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/resources/layer_tiling_data.h"
44 #include "cc/test/animation_test_common.h"
45 #include "cc/test/begin_frame_args_test.h"
46 #include "cc/test/fake_layer_tree_host_impl.h"
47 #include "cc/test/fake_output_surface.h"
48 #include "cc/test/fake_output_surface_client.h"
49 #include "cc/test/fake_picture_layer_impl.h"
50 #include "cc/test/fake_picture_pile_impl.h"
51 #include "cc/test/fake_proxy.h"
52 #include "cc/test/fake_video_frame_provider.h"
53 #include "cc/test/geometry_test_utils.h"
54 #include "cc/test/gpu_rasterization_enabled_settings.h"
55 #include "cc/test/layer_test_common.h"
56 #include "cc/test/layer_tree_test.h"
57 #include "cc/test/render_pass_test_common.h"
58 #include "cc/test/test_gpu_memory_buffer_manager.h"
59 #include "cc/test/test_shared_bitmap_manager.h"
60 #include "cc/test/test_task_graph_runner.h"
61 #include "cc/test/test_web_graphics_context_3d.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/frame_time.h"
69 #include "ui/gfx/geometry/rect_conversions.h"
70 #include "ui/gfx/geometry/size_conversions.h"
71 #include "ui/gfx/geometry/vector2d_conversions.h"
73 using ::testing::Mock
;
74 using ::testing::Return
;
75 using ::testing::AnyNumber
;
76 using ::testing::AtLeast
;
78 using media::VideoFrame
;
83 class LayerTreeHostImplTest
: public testing::Test
,
84 public LayerTreeHostImplClient
{
86 LayerTreeHostImplTest()
87 : proxy_(base::ThreadTaskRunnerHandle::Get(),
88 base::ThreadTaskRunnerHandle::Get()),
89 always_impl_thread_(&proxy_
),
90 always_main_thread_blocked_(&proxy_
),
91 shared_bitmap_manager_(new TestSharedBitmapManager
),
92 gpu_memory_buffer_manager_(new TestGpuMemoryBufferManager
),
93 task_graph_runner_(new TestTaskGraphRunner
),
94 on_can_draw_state_changed_called_(false),
95 did_notify_ready_to_activate_(false),
96 did_request_commit_(false),
97 did_request_redraw_(false),
98 did_request_animate_(false),
99 did_request_prepare_tiles_(false),
100 did_complete_page_scale_animation_(false),
101 reduce_memory_result_(true),
102 current_limit_bytes_(0),
103 current_priority_cutoff_value_(0) {
104 media::InitializeMediaLibraryForTesting();
107 LayerTreeSettings
DefaultSettings() {
108 LayerTreeSettings settings
;
109 settings
.minimum_occlusion_tracking_size
= gfx::Size();
110 settings
.impl_side_painting
= true;
111 settings
.renderer_settings
.texture_id_allocation_chunk_size
= 1;
112 settings
.report_overscroll_only_for_scrollable_axes
= true;
113 settings
.use_pinch_virtual_viewport
= true;
114 settings
.gpu_rasterization_enabled
= true;
118 void SetUp() override
{
119 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
122 void TearDown() override
{}
124 void UpdateRendererCapabilitiesOnImplThread() override
{}
125 void DidLoseOutputSurfaceOnImplThread() override
{}
126 void CommitVSyncParameters(base::TimeTicks timebase
,
127 base::TimeDelta interval
) override
{}
128 void SetEstimatedParentDrawTime(base::TimeDelta draw_time
) override
{}
129 void SetMaxSwapsPendingOnImplThread(int max
) override
{}
130 void DidSwapBuffersOnImplThread() override
{}
131 void DidSwapBuffersCompleteOnImplThread() override
{}
132 void OnCanDrawStateChanged(bool can_draw
) override
{
133 on_can_draw_state_changed_called_
= true;
135 void NotifyReadyToActivate() override
{
136 did_notify_ready_to_activate_
= true;
137 host_impl_
->ActivateSyncTree();
139 void NotifyReadyToDraw() override
{}
140 void SetNeedsRedrawOnImplThread() override
{ did_request_redraw_
= true; }
141 void SetNeedsRedrawRectOnImplThread(const gfx::Rect
& damage_rect
) override
{
142 did_request_redraw_
= true;
144 void SetNeedsAnimateOnImplThread() override
{ did_request_animate_
= true; }
145 void SetNeedsPrepareTilesOnImplThread() override
{
146 did_request_prepare_tiles_
= true;
148 void SetNeedsCommitOnImplThread() override
{ did_request_commit_
= true; }
149 void SetVideoNeedsBeginFrames(bool needs_begin_frames
) override
{}
150 void PostAnimationEventsToMainThreadOnImplThread(
151 scoped_ptr
<AnimationEventsVector
> events
) override
{}
152 bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes
,
153 int priority_cutoff
) override
{
154 current_limit_bytes_
= limit_bytes
;
155 current_priority_cutoff_value_
= priority_cutoff
;
156 return reduce_memory_result_
;
158 bool IsInsideDraw() override
{ return false; }
159 void RenewTreePriority() override
{}
160 void PostDelayedAnimationTaskOnImplThread(const base::Closure
& task
,
161 base::TimeDelta delay
) override
{
162 animation_task_
= task
;
163 requested_animation_delay_
= delay
;
165 void DidActivateSyncTree() override
{}
166 void DidPrepareTiles() override
{}
167 void DidCompletePageScaleAnimationOnImplThread() override
{
168 did_complete_page_scale_animation_
= true;
170 void OnDrawForOutputSurface() override
{}
172 void set_reduce_memory_result(bool reduce_memory_result
) {
173 reduce_memory_result_
= reduce_memory_result
;
176 virtual bool CreateHostImpl(const LayerTreeSettings
& settings
,
177 scoped_ptr
<OutputSurface
> output_surface
) {
178 host_impl_
= LayerTreeHostImpl::Create(
179 settings
, this, &proxy_
, &stats_instrumentation_
,
180 shared_bitmap_manager_
.get(), gpu_memory_buffer_manager_
.get(),
181 task_graph_runner_
.get(), 0);
182 bool init
= host_impl_
->InitializeRenderer(output_surface
.Pass());
183 host_impl_
->SetViewportSize(gfx::Size(10, 10));
184 // Set the BeginFrameArgs so that methods which use it are able to.
185 host_impl_
->WillBeginImplFrame(
186 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
190 void SetupRootLayerImpl(scoped_ptr
<LayerImpl
> root
) {
191 root
->SetPosition(gfx::PointF());
192 root
->SetBounds(gfx::Size(10, 10));
193 root
->SetContentBounds(gfx::Size(10, 10));
194 root
->SetDrawsContent(true);
195 root
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 10, 10);
196 root
->SetHasRenderSurface(true);
197 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
200 static void ExpectClearedScrollDeltasRecursive(LayerImpl
* layer
) {
201 ASSERT_EQ(layer
->ScrollDelta(), gfx::Vector2d());
202 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
203 ExpectClearedScrollDeltasRecursive(layer
->children()[i
]);
206 static void ExpectContains(const ScrollAndScaleSet
& scroll_info
,
208 const gfx::Vector2d
& scroll_delta
) {
209 int times_encountered
= 0;
211 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
212 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
214 EXPECT_VECTOR_EQ(scroll_delta
, scroll_info
.scrolls
[i
].scroll_delta
);
218 ASSERT_EQ(1, times_encountered
);
221 static void ExpectNone(const ScrollAndScaleSet
& scroll_info
, int id
) {
222 int times_encountered
= 0;
224 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
225 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
230 ASSERT_EQ(0, times_encountered
);
233 LayerImpl
* CreateScrollAndContentsLayers(LayerTreeImpl
* layer_tree_impl
,
234 const gfx::Size
& content_size
) {
235 // Create both an inner viewport scroll layer and an outer viewport scroll
236 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
237 // 0x0, so the scrolls will be applied directly to the inner viewport.
238 const int kOuterViewportClipLayerId
= 116;
239 const int kOuterViewportScrollLayerId
= 117;
240 const int kContentLayerId
= 118;
241 const int kInnerViewportScrollLayerId
= 2;
242 const int kInnerViewportClipLayerId
= 4;
243 const int kPageScaleLayerId
= 5;
245 scoped_ptr
<LayerImpl
> root
=
246 LayerImpl::Create(layer_tree_impl
, 1);
247 root
->SetBounds(content_size
);
248 root
->SetContentBounds(content_size
);
249 root
->SetPosition(gfx::PointF());
250 root
->SetHasRenderSurface(true);
252 scoped_ptr
<LayerImpl
> inner_scroll
=
253 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
254 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
255 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
257 scoped_ptr
<LayerImpl
> inner_clip
=
258 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
259 inner_clip
->SetBounds(
260 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
262 scoped_ptr
<LayerImpl
> page_scale
=
263 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
265 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
266 inner_scroll
->SetBounds(content_size
);
267 inner_scroll
->SetContentBounds(content_size
);
268 inner_scroll
->SetPosition(gfx::PointF());
270 scoped_ptr
<LayerImpl
> outer_clip
=
271 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
272 outer_clip
->SetBounds(content_size
);
273 outer_clip
->SetIsContainerForFixedPositionLayers(true);
275 scoped_ptr
<LayerImpl
> outer_scroll
=
276 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
277 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
278 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
279 outer_scroll
->SetBounds(content_size
);
280 outer_scroll
->SetContentBounds(content_size
);
281 outer_scroll
->SetPosition(gfx::PointF());
283 scoped_ptr
<LayerImpl
> contents
=
284 LayerImpl::Create(layer_tree_impl
, kContentLayerId
);
285 contents
->SetDrawsContent(true);
286 contents
->SetBounds(content_size
);
287 contents
->SetContentBounds(content_size
);
288 contents
->SetPosition(gfx::PointF());
290 outer_scroll
->AddChild(contents
.Pass());
291 outer_clip
->AddChild(outer_scroll
.Pass());
292 inner_scroll
->AddChild(outer_clip
.Pass());
293 page_scale
->AddChild(inner_scroll
.Pass());
294 inner_clip
->AddChild(page_scale
.Pass());
295 root
->AddChild(inner_clip
.Pass());
297 layer_tree_impl
->SetRootLayer(root
.Pass());
298 layer_tree_impl
->SetViewportLayersFromIds(
299 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
300 kOuterViewportScrollLayerId
);
302 layer_tree_impl
->DidBecomeActive();
303 return layer_tree_impl
->InnerViewportScrollLayer();
306 LayerImpl
* SetupScrollAndContentsLayers(const gfx::Size
& content_size
) {
307 LayerImpl
* scroll_layer
= CreateScrollAndContentsLayers(
308 host_impl_
->active_tree(), content_size
);
309 host_impl_
->active_tree()->DidBecomeActive();
313 // TODO(wjmaclean) Add clip-layer pointer to parameters.
314 scoped_ptr
<LayerImpl
> CreateScrollableLayer(int id
,
315 const gfx::Size
& size
,
316 LayerImpl
* clip_layer
) {
318 DCHECK(id
!= clip_layer
->id());
319 scoped_ptr
<LayerImpl
> layer
=
320 LayerImpl::Create(host_impl_
->active_tree(), id
);
321 layer
->SetScrollClipLayer(clip_layer
->id());
322 layer
->SetDrawsContent(true);
323 layer
->SetBounds(size
);
324 layer
->SetContentBounds(size
);
325 clip_layer
->SetBounds(gfx::Size(size
.width() / 2, size
.height() / 2));
330 LayerTreeHostImpl::FrameData frame
;
331 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
332 host_impl_
->DrawLayers(&frame
);
333 host_impl_
->DidDrawAllLayers(frame
);
336 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor
);
337 void pinch_zoom_pan_viewport_test(float device_scale_factor
);
338 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor
);
339 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
340 float device_scale_factor
);
342 void CheckNotifyCalledIfCanDrawChanged(bool always_draw
) {
343 // Note: It is not possible to disable the renderer once it has been set,
344 // so we do not need to test that disabling the renderer notifies us
345 // that can_draw changed.
346 EXPECT_FALSE(host_impl_
->CanDraw());
347 on_can_draw_state_changed_called_
= false;
349 // Set up the root layer, which allows us to draw.
350 SetupScrollAndContentsLayers(gfx::Size(100, 100));
351 EXPECT_TRUE(host_impl_
->CanDraw());
352 EXPECT_TRUE(on_can_draw_state_changed_called_
);
353 on_can_draw_state_changed_called_
= false;
355 // Toggle the root layer to make sure it toggles can_draw
356 host_impl_
->active_tree()->SetRootLayer(nullptr);
357 EXPECT_FALSE(host_impl_
->CanDraw());
358 EXPECT_TRUE(on_can_draw_state_changed_called_
);
359 on_can_draw_state_changed_called_
= false;
361 SetupScrollAndContentsLayers(gfx::Size(100, 100));
362 EXPECT_TRUE(host_impl_
->CanDraw());
363 EXPECT_TRUE(on_can_draw_state_changed_called_
);
364 on_can_draw_state_changed_called_
= false;
366 // Toggle the device viewport size to make sure it toggles can_draw.
367 host_impl_
->SetViewportSize(gfx::Size());
369 EXPECT_TRUE(host_impl_
->CanDraw());
371 EXPECT_FALSE(host_impl_
->CanDraw());
373 EXPECT_TRUE(on_can_draw_state_changed_called_
);
374 on_can_draw_state_changed_called_
= false;
376 host_impl_
->SetViewportSize(gfx::Size(100, 100));
377 EXPECT_TRUE(host_impl_
->CanDraw());
378 EXPECT_TRUE(on_can_draw_state_changed_called_
);
379 on_can_draw_state_changed_called_
= false;
381 // Toggle contents textures purged without causing any evictions,
382 // and make sure that it does not change can_draw.
383 set_reduce_memory_result(false);
384 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
385 host_impl_
->memory_allocation_limit_bytes() - 1));
386 EXPECT_TRUE(host_impl_
->CanDraw());
387 EXPECT_FALSE(on_can_draw_state_changed_called_
);
388 on_can_draw_state_changed_called_
= false;
390 // Toggle contents textures purged to make sure it toggles can_draw.
391 set_reduce_memory_result(true);
392 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
393 host_impl_
->memory_allocation_limit_bytes() - 1));
395 EXPECT_TRUE(host_impl_
->CanDraw());
397 EXPECT_FALSE(host_impl_
->CanDraw());
399 EXPECT_TRUE(on_can_draw_state_changed_called_
);
400 on_can_draw_state_changed_called_
= false;
402 host_impl_
->active_tree()->ResetContentsTexturesPurged();
403 EXPECT_TRUE(host_impl_
->CanDraw());
404 EXPECT_TRUE(on_can_draw_state_changed_called_
);
405 on_can_draw_state_changed_called_
= false;
408 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor
);
411 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() {
412 return FakeOutputSurface::Create3d();
415 void DrawOneFrame() {
416 LayerTreeHostImpl::FrameData frame_data
;
417 host_impl_
->PrepareToDraw(&frame_data
);
418 host_impl_
->DidDrawAllLayers(frame_data
);
422 DebugScopedSetImplThread always_impl_thread_
;
423 DebugScopedSetMainThreadBlocked always_main_thread_blocked_
;
425 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
426 scoped_ptr
<TestGpuMemoryBufferManager
> gpu_memory_buffer_manager_
;
427 scoped_ptr
<TestTaskGraphRunner
> task_graph_runner_
;
428 scoped_ptr
<LayerTreeHostImpl
> host_impl_
;
429 FakeRenderingStatsInstrumentation stats_instrumentation_
;
430 bool on_can_draw_state_changed_called_
;
431 bool did_notify_ready_to_activate_
;
432 bool did_request_commit_
;
433 bool did_request_redraw_
;
434 bool did_request_animate_
;
435 bool did_request_prepare_tiles_
;
436 bool did_complete_page_scale_animation_
;
437 bool reduce_memory_result_
;
438 base::Closure animation_task_
;
439 base::TimeDelta requested_animation_delay_
;
440 size_t current_limit_bytes_
;
441 int current_priority_cutoff_value_
;
444 TEST_F(LayerTreeHostImplTest
, NotifyIfCanDrawChanged
) {
445 bool always_draw
= false;
446 CheckNotifyCalledIfCanDrawChanged(always_draw
);
449 TEST_F(LayerTreeHostImplTest
, CanDrawIncompleteFrames
) {
450 CreateHostImpl(DefaultSettings(),
451 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
453 bool always_draw
= true;
454 CheckNotifyCalledIfCanDrawChanged(always_draw
);
457 TEST_F(LayerTreeHostImplTest
, ScrollDeltaNoLayers
) {
458 ASSERT_FALSE(host_impl_
->active_tree()->root_layer());
460 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
461 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
464 TEST_F(LayerTreeHostImplTest
, ScrollDeltaTreeButNoChanges
) {
466 scoped_ptr
<LayerImpl
> root
=
467 LayerImpl::Create(host_impl_
->active_tree(), 1);
468 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
469 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 3));
470 root
->children()[1]->AddChild(
471 LayerImpl::Create(host_impl_
->active_tree(), 4));
472 root
->children()[1]->AddChild(
473 LayerImpl::Create(host_impl_
->active_tree(), 5));
474 root
->children()[1]->children()[0]->AddChild(
475 LayerImpl::Create(host_impl_
->active_tree(), 6));
476 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
478 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
480 ExpectClearedScrollDeltasRecursive(root
);
482 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
484 scroll_info
= host_impl_
->ProcessScrollDeltas();
485 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
486 ExpectClearedScrollDeltasRecursive(root
);
488 scroll_info
= host_impl_
->ProcessScrollDeltas();
489 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
490 ExpectClearedScrollDeltasRecursive(root
);
493 TEST_F(LayerTreeHostImplTest
, ScrollDeltaRepeatedScrolls
) {
494 gfx::ScrollOffset
scroll_offset(20, 30);
495 gfx::Vector2d
scroll_delta(11, -15);
497 scoped_ptr
<LayerImpl
> root_clip
=
498 LayerImpl::Create(host_impl_
->active_tree(), 2);
499 scoped_ptr
<LayerImpl
> root
=
500 LayerImpl::Create(host_impl_
->active_tree(), 1);
501 root_clip
->SetBounds(gfx::Size(10, 10));
502 LayerImpl
* root_layer
= root
.get();
503 root_clip
->AddChild(root
.Pass());
504 root_layer
->SetBounds(gfx::Size(110, 110));
505 root_layer
->SetScrollClipLayer(root_clip
->id());
506 root_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
507 root_layer
->ScrollBy(scroll_delta
);
508 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
510 LayerImpl
* root
= host_impl_
->active_tree()->root_layer()->children()[0];
512 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
514 scroll_info
= host_impl_
->ProcessScrollDeltas();
515 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
516 ExpectContains(*scroll_info
, root
->id(), scroll_delta
);
518 gfx::Vector2d
scroll_delta2(-5, 27);
519 root
->ScrollBy(scroll_delta2
);
520 scroll_info
= host_impl_
->ProcessScrollDeltas();
521 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
522 ExpectContains(*scroll_info
, root
->id(), scroll_delta
+ scroll_delta2
);
524 root
->ScrollBy(gfx::Vector2d());
525 scroll_info
= host_impl_
->ProcessScrollDeltas();
526 ExpectContains(*scroll_info
, root
->id(), scroll_delta
+ scroll_delta2
);
529 TEST_F(LayerTreeHostImplTest
, ScrollRootCallsCommitAndRedraw
) {
530 SetupScrollAndContentsLayers(gfx::Size(100, 100));
531 host_impl_
->SetViewportSize(gfx::Size(50, 50));
534 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
535 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
536 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
537 InputHandler::WHEEL
));
538 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
539 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
540 InputHandler::WHEEL
));
541 host_impl_
->ScrollEnd();
542 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
543 InputHandler::WHEEL
));
544 EXPECT_TRUE(did_request_redraw_
);
545 EXPECT_TRUE(did_request_commit_
);
548 TEST_F(LayerTreeHostImplTest
, ScrollActiveOnlyAfterScrollMovement
) {
549 SetupScrollAndContentsLayers(gfx::Size(100, 100));
550 host_impl_
->SetViewportSize(gfx::Size(50, 50));
553 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
554 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
555 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
556 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
557 EXPECT_TRUE(host_impl_
->IsActivelyScrolling());
558 host_impl_
->ScrollEnd();
559 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
562 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRootLayer
) {
563 // We should not crash when trying to scroll an empty layer tree.
564 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
565 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
568 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRenderer
) {
569 scoped_ptr
<TestWebGraphicsContext3D
> context_owned
=
570 TestWebGraphicsContext3D::Create();
571 context_owned
->set_context_lost(true);
573 // Initialization will fail.
574 EXPECT_FALSE(CreateHostImpl(
575 DefaultSettings(), FakeOutputSurface::Create3d(context_owned
.Pass())));
577 SetupScrollAndContentsLayers(gfx::Size(100, 100));
579 // We should not crash when trying to scroll after the renderer initialization
581 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
582 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
585 TEST_F(LayerTreeHostImplTest
, ReplaceTreeWhileScrolling
) {
586 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
587 host_impl_
->SetViewportSize(gfx::Size(50, 50));
590 // We should not crash if the tree is replaced while we are scrolling.
591 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
592 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
593 host_impl_
->active_tree()->DetachLayerTree();
595 scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
597 // We should still be scrolling, because the scrolled layer also exists in the
599 gfx::Vector2d
scroll_delta(0, 10);
600 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
601 host_impl_
->ScrollEnd();
602 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
603 ExpectContains(*scroll_info
, scroll_layer
->id(), scroll_delta
);
606 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnWheelEventHandlers
) {
607 SetupScrollAndContentsLayers(gfx::Size(100, 100));
608 host_impl_
->SetViewportSize(gfx::Size(50, 50));
610 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
612 // With registered event handlers, wheel scrolls don't necessarily
613 // have to go to the main thread.
614 root
->SetHaveWheelEventHandlers(true);
615 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
616 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
617 host_impl_
->ScrollEnd();
619 // But typically the scroll-blocks-on mode will require them to.
620 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
621 SCROLL_BLOCKS_ON_START_TOUCH
);
622 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
623 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
625 // But gesture scrolls can still be handled.
626 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
627 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
628 host_impl_
->ScrollEnd();
630 // And if the handlers go away, wheel scrolls can again be processed
631 // on impl (despite the scroll-blocks-on mode).
632 root
->SetHaveWheelEventHandlers(false);
633 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
634 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
635 host_impl_
->ScrollEnd();
638 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnTouchEventHandlers
) {
639 LayerImpl
* scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
640 host_impl_
->SetViewportSize(gfx::Size(50, 50));
642 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
644 LayerImpl
* child
= 0;
646 scoped_ptr
<LayerImpl
> child_layer
=
647 LayerImpl::Create(host_impl_
->active_tree(), 6);
648 child
= child_layer
.get();
649 child_layer
->SetDrawsContent(true);
650 child_layer
->SetPosition(gfx::PointF(0, 20));
651 child_layer
->SetBounds(gfx::Size(50, 50));
652 child_layer
->SetContentBounds(gfx::Size(50, 50));
653 scroll
->AddChild(child_layer
.Pass());
656 // Touch handler regions determine whether touch events block scroll.
657 root
->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
658 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
659 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
|
660 SCROLL_BLOCKS_ON_WHEEL_EVENT
);
661 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
663 // But they don't influence the actual handling of the scroll gestures.
664 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
665 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
666 host_impl_
->ScrollEnd();
668 // It's the union of scroll-blocks-on mode bits across all layers in the
669 // scroll paret chain that matters.
670 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
671 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE
);
672 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
673 child
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
);
674 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
677 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnScrollEventHandlers
) {
678 SetupScrollAndContentsLayers(gfx::Size(100, 100));
679 host_impl_
->SetViewportSize(gfx::Size(50, 50));
681 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
683 // With registered scroll handlers, scrolls don't generally have to go
684 // to the main thread.
685 root
->SetHaveScrollEventHandlers(true);
686 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
687 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
688 host_impl_
->ScrollEnd();
690 // Even the default scroll blocks on mode doesn't require this.
691 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
692 SCROLL_BLOCKS_ON_START_TOUCH
);
693 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
694 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
695 host_impl_
->ScrollEnd();
697 // But the page can opt in to blocking on scroll event handlers.
698 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
699 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
700 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
702 // GESTURE and WHEEL scrolls behave identically in this regard.
703 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
704 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
706 // And if the handlers go away, scrolls can again be processed on impl
707 // (despite the scroll-blocks-on mode).
708 root
->SetHaveScrollEventHandlers(false);
709 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
710 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
711 host_impl_
->ScrollEnd();
714 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnLayerTopology
) {
715 host_impl_
->SetViewportSize(gfx::Size(50, 50));
717 // Create a normal scrollable root layer
718 LayerImpl
* root_scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
719 LayerImpl
* root_child
= root_scroll
->children()[0];
720 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
723 // Create two child scrollable layers
724 LayerImpl
* child1
= 0;
726 scoped_ptr
<LayerImpl
> scrollable_child_clip_1
=
727 LayerImpl::Create(host_impl_
->active_tree(), 6);
728 scoped_ptr
<LayerImpl
> scrollable_child_1
= CreateScrollableLayer(
729 7, gfx::Size(10, 10), scrollable_child_clip_1
.get());
730 child1
= scrollable_child_1
.get();
731 scrollable_child_1
->SetPosition(gfx::Point(5, 5));
732 scrollable_child_1
->SetHaveWheelEventHandlers(true);
733 scrollable_child_1
->SetHaveScrollEventHandlers(true);
734 scrollable_child_clip_1
->AddChild(scrollable_child_1
.Pass());
735 root_child
->AddChild(scrollable_child_clip_1
.Pass());
738 LayerImpl
* child2
= 0;
740 scoped_ptr
<LayerImpl
> scrollable_child_clip_2
=
741 LayerImpl::Create(host_impl_
->active_tree(), 8);
742 scoped_ptr
<LayerImpl
> scrollable_child_2
= CreateScrollableLayer(
743 9, gfx::Size(10, 10), scrollable_child_clip_2
.get());
744 child2
= scrollable_child_2
.get();
745 scrollable_child_2
->SetPosition(gfx::Point(5, 20));
746 scrollable_child_2
->SetHaveWheelEventHandlers(true);
747 scrollable_child_2
->SetHaveScrollEventHandlers(true);
748 scrollable_child_clip_2
->AddChild(scrollable_child_2
.Pass());
749 root_child
->AddChild(scrollable_child_clip_2
.Pass());
752 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
753 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
754 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
755 host_impl_
->ScrollEnd();
756 child1
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
757 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
758 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
760 // But not those that hit only other layers.
761 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
762 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
763 host_impl_
->ScrollEnd();
765 // It's the union of bits set across the scroll ancestor chain that matters.
766 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
767 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
768 host_impl_
->ScrollEnd();
769 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
770 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
771 host_impl_
->ScrollEnd();
772 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
);
773 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
774 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
775 host_impl_
->ScrollEnd();
776 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
777 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
778 child2
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
779 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
780 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
781 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
782 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
785 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchscreen
) {
786 SetupScrollAndContentsLayers(gfx::Size(100, 100));
787 host_impl_
->SetViewportSize(gfx::Size(50, 50));
790 // Ignore the fling since no layer is being scrolled
791 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
793 // Start scrolling a layer
794 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
795 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
797 // Now the fling should go ahead since we've started scrolling a layer
798 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
801 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchpad
) {
802 SetupScrollAndContentsLayers(gfx::Size(100, 100));
803 host_impl_
->SetViewportSize(gfx::Size(50, 50));
806 // Ignore the fling since no layer is being scrolled
807 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
809 // Start scrolling a layer
810 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
811 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
813 // Now the fling should go ahead since we've started scrolling a layer
814 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
817 TEST_F(LayerTreeHostImplTest
, NoFlingWhenScrollingOnMain
) {
818 SetupScrollAndContentsLayers(gfx::Size(100, 100));
819 host_impl_
->SetViewportSize(gfx::Size(50, 50));
821 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
823 root
->SetShouldScrollOnMainThread(true);
825 // Start scrolling a layer
826 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
827 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
829 // The fling should be ignored since there's no layer being scrolled impl-side
830 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
833 TEST_F(LayerTreeHostImplTest
, ShouldScrollOnMainThread
) {
834 SetupScrollAndContentsLayers(gfx::Size(100, 100));
835 host_impl_
->SetViewportSize(gfx::Size(50, 50));
837 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
839 root
->SetShouldScrollOnMainThread(true);
841 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
842 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
843 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
844 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
847 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionBasic
) {
848 SetupScrollAndContentsLayers(gfx::Size(200, 200));
849 host_impl_
->SetViewportSize(gfx::Size(100, 100));
851 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
852 root
->SetContentsScale(2.f
, 2.f
);
853 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
857 // All scroll types inside the non-fast scrollable region should fail.
858 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
859 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL
));
860 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
861 InputHandler::WHEEL
));
862 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
863 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE
));
864 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
865 InputHandler::GESTURE
));
867 // All scroll types outside this region should succeed.
868 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
869 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL
));
870 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
871 InputHandler::GESTURE
));
872 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
873 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
874 InputHandler::GESTURE
));
875 host_impl_
->ScrollEnd();
876 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
877 InputHandler::GESTURE
));
878 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
879 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE
));
880 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
881 InputHandler::GESTURE
));
882 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
883 host_impl_
->ScrollEnd();
884 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
885 InputHandler::GESTURE
));
888 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionWithOffset
) {
889 SetupScrollAndContentsLayers(gfx::Size(200, 200));
890 host_impl_
->SetViewportSize(gfx::Size(100, 100));
892 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
893 root
->SetContentsScale(2.f
, 2.f
);
894 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
895 root
->SetPosition(gfx::PointF(-25.f
, 0.f
));
899 // This point would fall into the non-fast scrollable region except that we've
900 // moved the layer down by 25 pixels.
901 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
902 host_impl_
->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL
));
903 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
904 InputHandler::WHEEL
));
905 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
906 host_impl_
->ScrollEnd();
908 // This point is still inside the non-fast region.
909 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
910 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL
));
913 TEST_F(LayerTreeHostImplTest
, ScrollHandlerNotPresent
) {
914 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
915 EXPECT_FALSE(scroll_layer
->have_scroll_event_handlers());
916 host_impl_
->SetViewportSize(gfx::Size(50, 50));
919 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
920 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
921 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
922 host_impl_
->ScrollEnd();
923 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
926 TEST_F(LayerTreeHostImplTest
, ScrollHandlerPresent
) {
927 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
928 scroll_layer
->SetHaveScrollEventHandlers(true);
929 host_impl_
->SetViewportSize(gfx::Size(50, 50));
932 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
933 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
934 EXPECT_TRUE(host_impl_
->scroll_affects_scroll_handler());
935 host_impl_
->ScrollEnd();
936 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
939 TEST_F(LayerTreeHostImplTest
, ScrollByReturnsCorrectValue
) {
940 SetupScrollAndContentsLayers(gfx::Size(200, 200));
941 host_impl_
->SetViewportSize(gfx::Size(100, 100));
945 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
946 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
948 // Trying to scroll to the left/top will not succeed.
950 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
952 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
954 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
956 // Scrolling to the right/bottom will succeed.
958 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll
);
960 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
962 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll
);
964 // Scrolling to left/top will now succeed.
966 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
968 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
970 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
972 // Scrolling diagonally against an edge will succeed.
974 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll
);
976 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
978 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll
);
980 // Trying to scroll more than the available space will also succeed.
982 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll
);
985 TEST_F(LayerTreeHostImplTest
, ScrollVerticallyByPageReturnsCorrectValue
) {
986 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
987 host_impl_
->SetViewportSize(gfx::Size(100, 1000));
991 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
992 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
994 // Trying to scroll without a vertical scrollbar will fail.
995 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
996 gfx::Point(), SCROLL_FORWARD
));
997 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
998 gfx::Point(), SCROLL_BACKWARD
));
1000 scoped_ptr
<PaintedScrollbarLayerImpl
> vertical_scrollbar(
1001 PaintedScrollbarLayerImpl::Create(
1002 host_impl_
->active_tree(),
1005 vertical_scrollbar
->SetBounds(gfx::Size(15, 1000));
1006 host_impl_
->InnerViewportScrollLayer()->AddScrollbar(
1007 vertical_scrollbar
.get());
1009 // Trying to scroll with a vertical scrollbar will succeed.
1010 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1011 gfx::Point(), SCROLL_FORWARD
));
1012 EXPECT_FLOAT_EQ(875.f
,
1013 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
1014 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1015 gfx::Point(), SCROLL_BACKWARD
));
1018 TEST_F(LayerTreeHostImplTest
, ScrollWithUserUnscrollableLayers
) {
1019 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
1020 host_impl_
->SetViewportSize(gfx::Size(100, 100));
1022 gfx::Size
overflow_size(400, 400);
1023 ASSERT_EQ(1u, scroll_layer
->children().size());
1024 LayerImpl
* overflow
= scroll_layer
->children()[0];
1025 overflow
->SetBounds(overflow_size
);
1026 overflow
->SetContentBounds(overflow_size
);
1027 overflow
->SetScrollClipLayer(scroll_layer
->parent()->id());
1028 overflow
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1029 overflow
->SetPosition(gfx::PointF());
1032 gfx::Point
scroll_position(10, 10);
1034 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1035 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1036 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1037 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow
->CurrentScrollOffset());
1039 gfx::Vector2dF
scroll_delta(10, 10);
1040 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1041 host_impl_
->ScrollEnd();
1042 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1043 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1045 overflow
->set_user_scrollable_horizontal(false);
1047 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1048 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1049 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1050 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1052 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1053 host_impl_
->ScrollEnd();
1054 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1055 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1057 overflow
->set_user_scrollable_vertical(false);
1059 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1060 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1061 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1062 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1064 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1065 host_impl_
->ScrollEnd();
1066 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer
->CurrentScrollOffset());
1067 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1070 TEST_F(LayerTreeHostImplTest
, ImplPinchZoom
) {
1071 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
1072 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1075 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
1076 LayerImpl
* container_layer
= scroll_layer
->scroll_clip_layer();
1077 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1079 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1080 float page_scale_factor
= 1.f
;
1082 // The impl-based pinch zoom should adjust the max scroll position.
1084 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1085 page_scale_factor
, min_page_scale
, max_page_scale
);
1086 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1087 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1089 float page_scale_delta
= 2.f
;
1091 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1092 host_impl_
->PinchGestureBegin();
1093 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1094 host_impl_
->PinchGestureEnd();
1095 host_impl_
->ScrollEnd();
1096 EXPECT_FALSE(did_request_animate_
);
1097 EXPECT_TRUE(did_request_redraw_
);
1098 EXPECT_TRUE(did_request_commit_
);
1099 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1101 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1102 host_impl_
->ProcessScrollDeltas();
1103 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1105 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1106 scroll_layer
->MaxScrollOffset().ToString());
1109 // Scrolling after a pinch gesture should always be in local space. The
1110 // scroll deltas have the page scale factor applied.
1112 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1113 page_scale_factor
, min_page_scale
, max_page_scale
);
1114 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1115 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1117 float page_scale_delta
= 2.f
;
1118 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1119 host_impl_
->PinchGestureBegin();
1120 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1121 host_impl_
->PinchGestureEnd();
1122 host_impl_
->ScrollEnd();
1124 gfx::Vector2d
scroll_delta(0, 10);
1125 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1126 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
1127 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1128 host_impl_
->ScrollEnd();
1130 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1131 host_impl_
->ProcessScrollDeltas();
1132 ExpectContains(*scroll_info
.get(), scroll_layer
->id(),
1133 gfx::Vector2d(0, scroll_delta
.y() / page_scale_delta
));
1137 TEST_F(LayerTreeHostImplTest
, ScrollWithSwapPromises
) {
1138 ui::LatencyInfo latency_info
;
1139 latency_info
.trace_id
= 1234;
1140 scoped_ptr
<SwapPromise
> swap_promise(
1141 new LatencyInfoSwapPromise(latency_info
));
1143 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1144 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1145 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
1146 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1147 host_impl_
->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise
.Pass());
1148 host_impl_
->ScrollEnd();
1150 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1151 EXPECT_EQ(1u, scroll_info
->swap_promises
.size());
1152 EXPECT_EQ(latency_info
.trace_id
, scroll_info
->swap_promises
[0]->TraceId());
1155 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
1156 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1157 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1160 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1161 DCHECK(scroll_layer
);
1163 float min_page_scale
= 1.f
;
1164 float max_page_scale
= 4.f
;
1166 // Basic pinch zoom in gesture
1168 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1170 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1172 float page_scale_delta
= 2.f
;
1173 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1174 host_impl_
->PinchGestureBegin();
1175 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1176 host_impl_
->PinchGestureEnd();
1177 host_impl_
->ScrollEnd();
1178 EXPECT_FALSE(did_request_animate_
);
1179 EXPECT_TRUE(did_request_redraw_
);
1180 EXPECT_TRUE(did_request_commit_
);
1182 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1183 host_impl_
->ProcessScrollDeltas();
1184 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1189 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1191 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1192 float page_scale_delta
= 10.f
;
1194 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1195 host_impl_
->PinchGestureBegin();
1196 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1197 host_impl_
->PinchGestureEnd();
1198 host_impl_
->ScrollEnd();
1200 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1201 host_impl_
->ProcessScrollDeltas();
1202 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
1205 // Zoom-out clamping
1207 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1209 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1210 scroll_layer
->PullDeltaForMainThread();
1211 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1213 float page_scale_delta
= 0.1f
;
1214 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1215 host_impl_
->PinchGestureBegin();
1216 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1217 host_impl_
->PinchGestureEnd();
1218 host_impl_
->ScrollEnd();
1220 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1221 host_impl_
->ProcessScrollDeltas();
1222 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1224 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1227 // Two-finger panning should not happen based on pinch events only
1229 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1231 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1232 scroll_layer
->PullDeltaForMainThread();
1233 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1235 float page_scale_delta
= 1.f
;
1236 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1237 host_impl_
->PinchGestureBegin();
1238 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1239 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1240 host_impl_
->PinchGestureEnd();
1241 host_impl_
->ScrollEnd();
1243 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1244 host_impl_
->ProcessScrollDeltas();
1245 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1246 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1249 // Two-finger panning should work with interleaved scroll events
1251 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1253 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1254 scroll_layer
->PullDeltaForMainThread();
1255 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1257 float page_scale_delta
= 1.f
;
1258 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1259 host_impl_
->PinchGestureBegin();
1260 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1261 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1262 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1263 host_impl_
->PinchGestureEnd();
1264 host_impl_
->ScrollEnd();
1266 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1267 host_impl_
->ProcessScrollDeltas();
1268 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1269 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-10, -10));
1272 // Two-finger panning should work when starting fully zoomed out.
1274 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.5f
, 0.5f
, 4.f
);
1275 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1276 scroll_layer
->PullDeltaForMainThread();
1277 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1279 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1280 host_impl_
->PinchGestureBegin();
1281 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1282 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(0, 0));
1283 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1284 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(10, 10));
1285 host_impl_
->PinchGestureEnd();
1286 host_impl_
->ScrollEnd();
1288 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1289 host_impl_
->ProcessScrollDeltas();
1290 EXPECT_EQ(scroll_info
->page_scale_delta
, 2.f
);
1291 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(20, 20));
1295 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
1296 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1297 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1300 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1301 DCHECK(scroll_layer
);
1303 float min_page_scale
= 0.5f
;
1304 float max_page_scale
= 4.f
;
1305 base::TimeTicks start_time
= base::TimeTicks() +
1306 base::TimeDelta::FromSeconds(1);
1307 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1308 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1309 base::TimeTicks end_time
= start_time
+ duration
;
1311 // Non-anchor zoom-in
1313 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1315 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1317 did_request_redraw_
= false;
1318 did_request_animate_
= false;
1319 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1320 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1325 host_impl_
->ActivateSyncTree();
1326 EXPECT_FALSE(did_request_redraw_
);
1327 EXPECT_TRUE(did_request_animate_
);
1329 did_request_redraw_
= false;
1330 did_request_animate_
= false;
1331 host_impl_
->Animate(start_time
);
1332 EXPECT_TRUE(did_request_redraw_
);
1333 EXPECT_TRUE(did_request_animate_
);
1335 did_request_redraw_
= false;
1336 did_request_animate_
= false;
1337 host_impl_
->Animate(halfway_through_animation
);
1338 EXPECT_TRUE(did_request_redraw_
);
1339 EXPECT_TRUE(did_request_animate_
);
1341 did_request_redraw_
= false;
1342 did_request_animate_
= false;
1343 did_request_commit_
= false;
1344 host_impl_
->Animate(end_time
);
1345 EXPECT_TRUE(did_request_commit_
);
1346 EXPECT_FALSE(did_request_animate_
);
1348 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1349 host_impl_
->ProcessScrollDeltas();
1350 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
1351 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1356 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1358 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1360 did_request_redraw_
= false;
1361 did_request_animate_
= false;
1362 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1363 scoped_ptr
<PendingPageScaleAnimation
> (new PendingPageScaleAnimation(
1364 gfx::Vector2d(25, 25),
1368 host_impl_
->ActivateSyncTree();
1369 EXPECT_FALSE(did_request_redraw_
);
1370 EXPECT_TRUE(did_request_animate_
);
1372 did_request_redraw_
= false;
1373 did_request_animate_
= false;
1374 host_impl_
->Animate(start_time
);
1375 EXPECT_TRUE(did_request_redraw_
);
1376 EXPECT_TRUE(did_request_animate_
);
1378 did_request_redraw_
= false;
1379 did_request_commit_
= false;
1380 did_request_animate_
= false;
1381 host_impl_
->Animate(end_time
);
1382 EXPECT_TRUE(did_request_redraw_
);
1383 EXPECT_FALSE(did_request_animate_
);
1384 EXPECT_TRUE(did_request_commit_
);
1386 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1387 host_impl_
->ProcessScrollDeltas();
1388 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1389 // Pushed to (0,0) via clamping against contents layer size.
1390 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1394 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
1395 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1396 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1399 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1400 DCHECK(scroll_layer
);
1402 float min_page_scale
= 0.5f
;
1403 float max_page_scale
= 4.f
;
1404 base::TimeTicks start_time
= base::TimeTicks() +
1405 base::TimeDelta::FromSeconds(1);
1406 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1407 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1408 base::TimeTicks end_time
= start_time
+ duration
;
1410 // Anchor zoom with unchanged page scale should not change scroll or scale.
1412 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1414 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1416 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1417 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1422 host_impl_
->ActivateSyncTree();
1423 host_impl_
->Animate(start_time
);
1424 host_impl_
->Animate(halfway_through_animation
);
1425 EXPECT_TRUE(did_request_redraw_
);
1426 host_impl_
->Animate(end_time
);
1427 EXPECT_TRUE(did_request_commit_
);
1429 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1430 host_impl_
->ProcessScrollDeltas();
1431 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
1432 ExpectNone(*scroll_info
, scroll_layer
->id());
1436 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationTransferedOnSyncTreeActivate
) {
1437 host_impl_
->CreatePendingTree();
1438 CreateScrollAndContentsLayers(
1439 host_impl_
->pending_tree(),
1440 gfx::Size(100, 100));
1441 host_impl_
->ActivateSyncTree();
1444 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1445 DCHECK(scroll_layer
);
1447 float min_page_scale
= 0.5f
;
1448 float max_page_scale
= 4.f
;
1449 host_impl_
->sync_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1451 host_impl_
->ActivateSyncTree();
1453 base::TimeTicks start_time
= base::TimeTicks() +
1454 base::TimeDelta::FromSeconds(1);
1455 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1456 base::TimeTicks third_through_animation
= start_time
+ duration
/ 3;
1457 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1458 base::TimeTicks end_time
= start_time
+ duration
;
1459 float target_scale
= 2.f
;
1461 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1463 // Make sure TakePageScaleAnimation works properly.
1465 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1466 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1471 scoped_ptr
<PendingPageScaleAnimation
> psa
=
1472 host_impl_
->sync_tree()->TakePendingPageScaleAnimation();
1473 EXPECT_EQ(target_scale
, psa
->scale
);
1474 EXPECT_EQ(duration
, psa
->duration
);
1475 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePendingPageScaleAnimation());
1477 // Recreate the PSA. Nothing should happen here since the tree containing the
1478 // PSA hasn't been activated yet.
1479 did_request_redraw_
= false;
1480 did_request_animate_
= false;
1481 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1482 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1487 host_impl_
->Animate(halfway_through_animation
);
1488 EXPECT_FALSE(did_request_animate_
);
1489 EXPECT_FALSE(did_request_redraw_
);
1491 // Activate the sync tree. This should cause the animation to become enabled.
1492 // It should also clear the pointer on the sync tree.
1493 host_impl_
->ActivateSyncTree();
1495 host_impl_
->sync_tree()->TakePendingPageScaleAnimation().get());
1496 EXPECT_FALSE(did_request_redraw_
);
1497 EXPECT_TRUE(did_request_animate_
);
1499 // From here on, make sure the animation runs as normal.
1500 did_request_redraw_
= false;
1501 did_request_animate_
= false;
1502 host_impl_
->Animate(start_time
);
1503 EXPECT_TRUE(did_request_redraw_
);
1504 EXPECT_TRUE(did_request_animate_
);
1506 did_request_redraw_
= false;
1507 did_request_animate_
= false;
1508 host_impl_
->Animate(third_through_animation
);
1509 EXPECT_TRUE(did_request_redraw_
);
1510 EXPECT_TRUE(did_request_animate_
);
1512 // Another activation shouldn't have any effect on the animation.
1513 host_impl_
->ActivateSyncTree();
1515 did_request_redraw_
= false;
1516 did_request_animate_
= false;
1517 host_impl_
->Animate(halfway_through_animation
);
1518 EXPECT_TRUE(did_request_redraw_
);
1519 EXPECT_TRUE(did_request_animate_
);
1521 did_request_redraw_
= false;
1522 did_request_animate_
= false;
1523 did_request_commit_
= false;
1524 host_impl_
->Animate(end_time
);
1525 EXPECT_TRUE(did_request_commit_
);
1526 EXPECT_FALSE(did_request_animate_
);
1528 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1529 host_impl_
->ProcessScrollDeltas();
1530 EXPECT_EQ(scroll_info
->page_scale_delta
, target_scale
);
1531 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1534 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationCompletedNotification
) {
1535 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1536 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1539 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1540 DCHECK(scroll_layer
);
1542 base::TimeTicks start_time
=
1543 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
1544 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1545 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1546 base::TimeTicks end_time
= start_time
+ duration
;
1548 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
1549 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1551 did_complete_page_scale_animation_
= false;
1552 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1553 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1554 gfx::Vector2d(), false, 2.f
, duration
)));
1555 host_impl_
->ActivateSyncTree();
1556 host_impl_
->Animate(start_time
);
1557 EXPECT_FALSE(did_complete_page_scale_animation_
);
1559 host_impl_
->Animate(halfway_through_animation
);
1560 EXPECT_FALSE(did_complete_page_scale_animation_
);
1562 host_impl_
->Animate(end_time
);
1563 EXPECT_TRUE(did_complete_page_scale_animation_
);
1566 class LayerTreeHostImplOverridePhysicalTime
: public LayerTreeHostImpl
{
1568 LayerTreeHostImplOverridePhysicalTime(
1569 const LayerTreeSettings
& settings
,
1570 LayerTreeHostImplClient
* client
,
1572 SharedBitmapManager
* manager
,
1573 RenderingStatsInstrumentation
* rendering_stats_instrumentation
)
1574 : LayerTreeHostImpl(settings
,
1577 rendering_stats_instrumentation
,
1583 BeginFrameArgs
CurrentBeginFrameArgs() const override
{
1584 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
,
1585 fake_current_physical_time_
);
1588 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now
) {
1589 fake_current_physical_time_
= fake_now
;
1593 base::TimeTicks fake_current_physical_time_
;
1596 class LayerTreeHostImplTestScrollbarAnimation
: public LayerTreeHostImplTest
{
1598 void SetupLayers(LayerTreeSettings settings
) {
1599 gfx::Size
viewport_size(10, 10);
1600 gfx::Size
content_size(100, 100);
1602 LayerTreeHostImplOverridePhysicalTime
* host_impl_override_time
=
1603 new LayerTreeHostImplOverridePhysicalTime(settings
, this, &proxy_
,
1604 shared_bitmap_manager_
.get(),
1605 &stats_instrumentation_
);
1606 host_impl_
= make_scoped_ptr(host_impl_override_time
);
1607 host_impl_
->InitializeRenderer(CreateOutputSurface());
1608 host_impl_
->SetViewportSize(viewport_size
);
1610 scoped_ptr
<LayerImpl
> root
=
1611 LayerImpl::Create(host_impl_
->active_tree(), 1);
1612 root
->SetBounds(viewport_size
);
1614 scoped_ptr
<LayerImpl
> scroll
=
1615 LayerImpl::Create(host_impl_
->active_tree(), 2);
1616 scroll
->SetScrollClipLayer(root
->id());
1617 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1618 root
->SetBounds(viewport_size
);
1619 scroll
->SetBounds(content_size
);
1620 scroll
->SetContentBounds(content_size
);
1621 scroll
->SetIsContainerForFixedPositionLayers(true);
1623 scoped_ptr
<LayerImpl
> contents
=
1624 LayerImpl::Create(host_impl_
->active_tree(), 3);
1625 contents
->SetDrawsContent(true);
1626 contents
->SetBounds(content_size
);
1627 contents
->SetContentBounds(content_size
);
1629 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar
=
1630 SolidColorScrollbarLayerImpl::Create(host_impl_
->active_tree(), 4,
1631 VERTICAL
, 10, 0, false, true);
1632 EXPECT_FLOAT_EQ(0.f
, scrollbar
->opacity());
1634 scroll
->AddChild(contents
.Pass());
1635 root
->AddChild(scroll
.Pass());
1636 root
->SetHasRenderSurface(true);
1637 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
1638 root
->AddChild(scrollbar
.Pass());
1640 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1641 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
1643 host_impl_
->active_tree()->DidBecomeActive();
1647 void RunTest(LayerTreeSettings::ScrollbarAnimator animator
) {
1648 LayerTreeSettings settings
;
1649 settings
.scrollbar_animator
= animator
;
1650 settings
.scrollbar_fade_delay_ms
= 20;
1651 settings
.scrollbar_fade_duration_ms
= 20;
1653 SetupLayers(settings
);
1655 base::TimeTicks fake_now
= gfx::FrameTime::Now();
1657 EXPECT_FALSE(did_request_animate_
);
1658 EXPECT_FALSE(did_request_redraw_
);
1659 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1660 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1662 // If no scroll happened during a scroll gesture, it should have no effect.
1663 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1664 host_impl_
->ScrollEnd();
1665 EXPECT_FALSE(did_request_animate_
);
1666 EXPECT_FALSE(did_request_redraw_
);
1667 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1668 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1670 // After a scroll, a scrollbar animation should be scheduled about 20ms from
1672 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1673 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1674 EXPECT_FALSE(did_request_animate_
);
1675 EXPECT_TRUE(did_request_redraw_
);
1676 did_request_redraw_
= false;
1677 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1678 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1680 host_impl_
->ScrollEnd();
1681 EXPECT_FALSE(did_request_animate_
);
1682 EXPECT_FALSE(did_request_redraw_
);
1683 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1684 requested_animation_delay_
);
1685 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1687 fake_now
+= requested_animation_delay_
;
1688 requested_animation_delay_
= base::TimeDelta();
1689 animation_task_
.Run();
1690 animation_task_
= base::Closure();
1691 EXPECT_TRUE(did_request_animate_
);
1692 did_request_animate_
= false;
1693 EXPECT_FALSE(did_request_redraw_
);
1695 // After the scrollbar animation begins, we should start getting redraws.
1696 host_impl_
->Animate(fake_now
);
1697 EXPECT_TRUE(did_request_animate_
);
1698 did_request_animate_
= false;
1699 EXPECT_TRUE(did_request_redraw_
);
1700 did_request_redraw_
= false;
1701 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1702 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1704 // Setting the scroll offset outside a scroll should also cause the
1705 // scrollbar to appear and to schedule a scrollbar animation.
1706 host_impl_
->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
1707 gfx::ScrollOffset(5, 5));
1708 EXPECT_FALSE(did_request_animate_
);
1709 EXPECT_FALSE(did_request_redraw_
);
1710 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1711 requested_animation_delay_
);
1712 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1713 requested_animation_delay_
= base::TimeDelta();
1714 animation_task_
= base::Closure();
1716 // Scrollbar animation is not triggered unnecessarily.
1717 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1718 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1719 EXPECT_FALSE(did_request_animate_
);
1720 EXPECT_TRUE(did_request_redraw_
);
1721 did_request_redraw_
= false;
1722 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1723 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1725 host_impl_
->ScrollEnd();
1726 EXPECT_FALSE(did_request_animate_
);
1727 EXPECT_FALSE(did_request_redraw_
);
1728 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1729 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1731 // Changing page scale triggers scrollbar animation.
1732 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
1733 host_impl_
->SetPageScaleOnActiveTree(1.1f
);
1734 EXPECT_FALSE(did_request_animate_
);
1735 EXPECT_FALSE(did_request_redraw_
);
1736 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1737 requested_animation_delay_
);
1738 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1739 requested_animation_delay_
= base::TimeDelta();
1740 animation_task_
= base::Closure();
1744 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, LinearFade
) {
1745 RunTest(LayerTreeSettings::LINEAR_FADE
);
1748 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, Thinning
) {
1749 RunTest(LayerTreeSettings::THINNING
);
1752 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1753 float device_scale_factor
) {
1754 LayerTreeSettings settings
;
1755 settings
.scrollbar_fade_delay_ms
= 500;
1756 settings
.scrollbar_fade_duration_ms
= 300;
1757 settings
.scrollbar_animator
= LayerTreeSettings::THINNING
;
1759 gfx::Size
viewport_size(300, 200);
1760 gfx::Size device_viewport_size
= gfx::ToFlooredSize(
1761 gfx::ScaleSize(viewport_size
, device_scale_factor
));
1762 gfx::Size
content_size(1000, 1000);
1764 CreateHostImpl(settings
, CreateOutputSurface());
1765 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
1766 host_impl_
->SetViewportSize(device_viewport_size
);
1768 scoped_ptr
<LayerImpl
> root
=
1769 LayerImpl::Create(host_impl_
->active_tree(), 1);
1770 root
->SetBounds(viewport_size
);
1771 root
->SetHasRenderSurface(true);
1773 scoped_ptr
<LayerImpl
> scroll
=
1774 LayerImpl::Create(host_impl_
->active_tree(), 2);
1775 scroll
->SetScrollClipLayer(root
->id());
1776 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1777 scroll
->SetBounds(content_size
);
1778 scroll
->SetContentBounds(content_size
);
1779 scroll
->SetIsContainerForFixedPositionLayers(true);
1781 scoped_ptr
<LayerImpl
> contents
=
1782 LayerImpl::Create(host_impl_
->active_tree(), 3);
1783 contents
->SetDrawsContent(true);
1784 contents
->SetBounds(content_size
);
1785 contents
->SetContentBounds(content_size
);
1787 // The scrollbar is on the right side.
1788 scoped_ptr
<PaintedScrollbarLayerImpl
> scrollbar
=
1789 PaintedScrollbarLayerImpl::Create(host_impl_
->active_tree(), 5, VERTICAL
);
1790 scrollbar
->SetDrawsContent(true);
1791 scrollbar
->SetBounds(gfx::Size(15, viewport_size
.height()));
1792 scrollbar
->SetContentBounds(gfx::Size(15, viewport_size
.height()));
1793 scrollbar
->SetPosition(gfx::Point(285, 0));
1795 scroll
->AddChild(contents
.Pass());
1796 root
->AddChild(scroll
.Pass());
1797 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
1798 root
->AddChild(scrollbar
.Pass());
1800 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1801 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
1803 host_impl_
->active_tree()->DidBecomeActive();
1806 LayerImpl
* root_scroll
=
1807 host_impl_
->active_tree()->InnerViewportScrollLayer();
1808 ASSERT_TRUE(root_scroll
->scrollbar_animation_controller());
1809 ScrollbarAnimationControllerThinning
* scrollbar_animation_controller
=
1810 static_cast<ScrollbarAnimationControllerThinning
*>(
1811 root_scroll
->scrollbar_animation_controller());
1812 scrollbar_animation_controller
->set_mouse_move_distance_for_test(100.f
);
1814 host_impl_
->MouseMoveAt(gfx::Point(1, 1));
1815 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1817 host_impl_
->MouseMoveAt(gfx::Point(200, 50));
1818 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1820 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
1821 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1823 scrollbar_animation_controller
->set_mouse_move_distance_for_test(102.f
);
1824 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
1825 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1827 did_request_redraw_
= false;
1828 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1829 host_impl_
->MouseMoveAt(gfx::Point(290, 100));
1830 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1831 host_impl_
->MouseMoveAt(gfx::Point(290, 120));
1832 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1833 host_impl_
->MouseMoveAt(gfx::Point(150, 120));
1834 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1837 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf1
) {
1838 SetupMouseMoveAtWithDeviceScale(1.f
);
1841 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf2
) {
1842 SetupMouseMoveAtWithDeviceScale(2.f
);
1845 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
1846 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1847 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1848 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
1851 CompositorFrameMetadata metadata
=
1852 host_impl_
->MakeCompositorFrameMetadata();
1853 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
1854 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
1855 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.scrollable_viewport_size
);
1856 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1857 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1858 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1859 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
1860 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
1863 // Scrolling should update metadata immediately.
1864 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1865 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
1866 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1868 CompositorFrameMetadata metadata
=
1869 host_impl_
->MakeCompositorFrameMetadata();
1870 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1872 host_impl_
->ScrollEnd();
1874 CompositorFrameMetadata metadata
=
1875 host_impl_
->MakeCompositorFrameMetadata();
1876 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1879 // Root "overflow: hidden" properties should be reflected on the outer
1880 // viewport scroll layer.
1882 host_impl_
->active_tree()
1883 ->OuterViewportScrollLayer()
1884 ->set_user_scrollable_horizontal(false);
1885 CompositorFrameMetadata metadata
=
1886 host_impl_
->MakeCompositorFrameMetadata();
1887 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
1888 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
1890 host_impl_
->active_tree()
1891 ->OuterViewportScrollLayer()
1892 ->set_user_scrollable_vertical(false);
1893 metadata
= host_impl_
->MakeCompositorFrameMetadata();
1894 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
1895 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
1898 // Page scale should update metadata correctly (shrinking only the viewport).
1899 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1900 host_impl_
->PinchGestureBegin();
1901 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
1902 host_impl_
->PinchGestureEnd();
1903 host_impl_
->ScrollEnd();
1905 CompositorFrameMetadata metadata
=
1906 host_impl_
->MakeCompositorFrameMetadata();
1907 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1908 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
1909 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.scrollable_viewport_size
);
1910 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1911 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1912 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1915 // Likewise if set from the main thread.
1916 host_impl_
->ProcessScrollDeltas();
1917 host_impl_
->active_tree()->PushPageScaleFromMainThread(4.f
, 0.5f
, 4.f
);
1918 host_impl_
->SetPageScaleOnActiveTree(4.f
);
1920 CompositorFrameMetadata metadata
=
1921 host_impl_
->MakeCompositorFrameMetadata();
1922 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1923 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
1924 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.scrollable_viewport_size
);
1925 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1926 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1927 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1931 class DidDrawCheckLayer
: public LayerImpl
{
1933 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
1934 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl
, id
));
1937 bool WillDraw(DrawMode draw_mode
, ResourceProvider
* provider
) override
{
1938 will_draw_called_
= true;
1939 if (will_draw_returns_false_
)
1941 return LayerImpl::WillDraw(draw_mode
, provider
);
1944 void AppendQuads(RenderPass
* render_pass
,
1945 AppendQuadsData
* append_quads_data
) override
{
1946 append_quads_called_
= true;
1947 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
1950 void DidDraw(ResourceProvider
* provider
) override
{
1951 did_draw_called_
= true;
1952 LayerImpl::DidDraw(provider
);
1955 bool will_draw_called() const { return will_draw_called_
; }
1956 bool append_quads_called() const { return append_quads_called_
; }
1957 bool did_draw_called() const { return did_draw_called_
; }
1959 void set_will_draw_returns_false() { will_draw_returns_false_
= true; }
1961 void ClearDidDrawCheck() {
1962 will_draw_called_
= false;
1963 append_quads_called_
= false;
1964 did_draw_called_
= false;
1967 static void IgnoreResult(scoped_ptr
<CopyOutputResult
> result
) {}
1969 void AddCopyRequest() {
1970 ScopedPtrVector
<CopyOutputRequest
> requests
;
1972 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult
)));
1973 SetHasRenderSurface(true);
1974 PassCopyRequests(&requests
);
1978 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
1979 : LayerImpl(tree_impl
, id
),
1980 will_draw_returns_false_(false),
1981 will_draw_called_(false),
1982 append_quads_called_(false),
1983 did_draw_called_(false) {
1984 SetBounds(gfx::Size(10, 10));
1985 SetContentBounds(gfx::Size(10, 10));
1986 SetDrawsContent(true);
1987 draw_properties().visible_content_rect
= gfx::Rect(0, 0, 10, 10);
1991 bool will_draw_returns_false_
;
1992 bool will_draw_called_
;
1993 bool append_quads_called_
;
1994 bool did_draw_called_
;
1997 TEST_F(LayerTreeHostImplTest
, WillDrawReturningFalseDoesNotCall
) {
1998 // The root layer is always drawn, so run this test on a child layer that
1999 // will be masked out by the root layer's bounds.
2000 host_impl_
->active_tree()->SetRootLayer(
2001 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2002 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2003 host_impl_
->active_tree()->root_layer());
2005 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2006 root
->SetHasRenderSurface(true);
2007 DidDrawCheckLayer
* layer
=
2008 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2011 LayerTreeHostImpl::FrameData frame
;
2012 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2013 host_impl_
->DrawLayers(&frame
);
2014 host_impl_
->DidDrawAllLayers(frame
);
2016 EXPECT_TRUE(layer
->will_draw_called());
2017 EXPECT_TRUE(layer
->append_quads_called());
2018 EXPECT_TRUE(layer
->did_draw_called());
2021 host_impl_
->SetViewportDamage(gfx::Rect(10, 10));
2024 LayerTreeHostImpl::FrameData frame
;
2026 layer
->set_will_draw_returns_false();
2027 layer
->ClearDidDrawCheck();
2029 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2030 host_impl_
->DrawLayers(&frame
);
2031 host_impl_
->DidDrawAllLayers(frame
);
2033 EXPECT_TRUE(layer
->will_draw_called());
2034 EXPECT_FALSE(layer
->append_quads_called());
2035 EXPECT_FALSE(layer
->did_draw_called());
2039 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
2040 // The root layer is always drawn, so run this test on a child layer that
2041 // will be masked out by the root layer's bounds.
2042 host_impl_
->active_tree()->SetRootLayer(
2043 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2044 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2045 host_impl_
->active_tree()->root_layer());
2046 root
->SetMasksToBounds(true);
2047 root
->SetHasRenderSurface(true);
2048 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2049 DidDrawCheckLayer
* layer
=
2050 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2051 // Ensure visible_content_rect for layer is empty.
2052 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
2053 layer
->SetBounds(gfx::Size(10, 10));
2054 layer
->SetContentBounds(gfx::Size(10, 10));
2056 LayerTreeHostImpl::FrameData frame
;
2058 EXPECT_FALSE(layer
->will_draw_called());
2059 EXPECT_FALSE(layer
->did_draw_called());
2061 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2062 host_impl_
->DrawLayers(&frame
);
2063 host_impl_
->DidDrawAllLayers(frame
);
2065 EXPECT_FALSE(layer
->will_draw_called());
2066 EXPECT_FALSE(layer
->did_draw_called());
2068 EXPECT_TRUE(layer
->visible_content_rect().IsEmpty());
2070 // Ensure visible_content_rect for layer is not empty
2071 layer
->SetPosition(gfx::PointF());
2073 EXPECT_FALSE(layer
->will_draw_called());
2074 EXPECT_FALSE(layer
->did_draw_called());
2076 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2077 host_impl_
->DrawLayers(&frame
);
2078 host_impl_
->DidDrawAllLayers(frame
);
2080 EXPECT_TRUE(layer
->will_draw_called());
2081 EXPECT_TRUE(layer
->did_draw_called());
2083 EXPECT_FALSE(layer
->visible_content_rect().IsEmpty());
2086 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
2087 gfx::Size
big_size(1000, 1000);
2088 host_impl_
->SetViewportSize(big_size
);
2090 host_impl_
->active_tree()->SetRootLayer(
2091 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2092 DidDrawCheckLayer
* root
=
2093 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2095 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2096 DidDrawCheckLayer
* occluded_layer
=
2097 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2099 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2100 root
->SetHasRenderSurface(true);
2101 DidDrawCheckLayer
* top_layer
=
2102 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
2103 // This layer covers the occluded_layer above. Make this layer large so it can
2105 top_layer
->SetBounds(big_size
);
2106 top_layer
->SetContentBounds(big_size
);
2107 top_layer
->SetContentsOpaque(true);
2109 LayerTreeHostImpl::FrameData frame
;
2111 EXPECT_FALSE(occluded_layer
->will_draw_called());
2112 EXPECT_FALSE(occluded_layer
->did_draw_called());
2113 EXPECT_FALSE(top_layer
->will_draw_called());
2114 EXPECT_FALSE(top_layer
->did_draw_called());
2116 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2117 host_impl_
->DrawLayers(&frame
);
2118 host_impl_
->DidDrawAllLayers(frame
);
2120 EXPECT_FALSE(occluded_layer
->will_draw_called());
2121 EXPECT_FALSE(occluded_layer
->did_draw_called());
2122 EXPECT_TRUE(top_layer
->will_draw_called());
2123 EXPECT_TRUE(top_layer
->did_draw_called());
2126 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
2127 host_impl_
->active_tree()->SetRootLayer(
2128 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2129 DidDrawCheckLayer
* root
=
2130 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2132 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2133 root
->SetHasRenderSurface(true);
2134 DidDrawCheckLayer
* layer1
=
2135 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2137 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2138 DidDrawCheckLayer
* layer2
=
2139 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
2141 layer1
->SetHasRenderSurface(true);
2142 layer1
->SetShouldFlattenTransform(true);
2144 EXPECT_FALSE(root
->did_draw_called());
2145 EXPECT_FALSE(layer1
->did_draw_called());
2146 EXPECT_FALSE(layer2
->did_draw_called());
2148 LayerTreeHostImpl::FrameData frame
;
2149 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2150 host_impl_
->active_tree()->root_layer());
2151 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2152 host_impl_
->DrawLayers(&frame
);
2153 host_impl_
->DidDrawAllLayers(frame
);
2155 EXPECT_TRUE(root
->did_draw_called());
2156 EXPECT_TRUE(layer1
->did_draw_called());
2157 EXPECT_TRUE(layer2
->did_draw_called());
2159 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
2160 EXPECT_TRUE(!!layer1
->render_surface());
2163 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
2165 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2168 bool had_incomplete_tile
,
2170 ResourceProvider
* resource_provider
) {
2171 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl
,
2174 had_incomplete_tile
,
2176 resource_provider
));
2179 void AppendQuads(RenderPass
* render_pass
,
2180 AppendQuadsData
* append_quads_data
) override
{
2181 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2182 if (had_incomplete_tile_
)
2183 append_quads_data
->num_incomplete_tiles
++;
2185 append_quads_data
->num_missing_tiles
++;
2189 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
2192 bool had_incomplete_tile
,
2194 ResourceProvider
* resource_provider
)
2195 : DidDrawCheckLayer(tree_impl
, id
),
2196 tile_missing_(tile_missing
),
2197 had_incomplete_tile_(had_incomplete_tile
) {
2199 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2203 bool had_incomplete_tile_
;
2206 struct PrepareToDrawSuccessTestCase
{
2208 bool has_missing_tile
= false;
2209 bool has_incomplete_tile
= false;
2210 bool is_animating
= false;
2211 bool has_copy_request
= false;
2213 bool high_res_required
= false;
2215 State layer_between
;
2217 DrawResult expected_result
;
2219 explicit PrepareToDrawSuccessTestCase(DrawResult result
)
2220 : expected_result(result
) {}
2223 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsAndFails
) {
2224 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2227 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2228 // 1. Animated layer first.
2229 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2230 cases
.back().layer_before
.is_animating
= true;
2231 // 2. Animated layer between.
2232 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2233 cases
.back().layer_between
.is_animating
= true;
2234 // 3. Animated layer last.
2235 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2236 cases
.back().layer_after
.is_animating
= true;
2237 // 4. Missing tile first.
2238 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2239 cases
.back().layer_before
.has_missing_tile
= true;
2240 // 5. Missing tile between.
2241 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2242 cases
.back().layer_between
.has_missing_tile
= true;
2243 // 6. Missing tile last.
2244 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2245 cases
.back().layer_after
.has_missing_tile
= true;
2246 // 7. Incomplete tile first.
2247 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2248 cases
.back().layer_before
.has_incomplete_tile
= true;
2249 // 8. Incomplete tile between.
2250 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2251 cases
.back().layer_between
.has_incomplete_tile
= true;
2252 // 9. Incomplete tile last.
2253 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2254 cases
.back().layer_after
.has_incomplete_tile
= true;
2255 // 10. Animation with missing tile.
2257 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
));
2258 cases
.back().layer_between
.has_missing_tile
= true;
2259 cases
.back().layer_between
.is_animating
= true;
2260 // 11. Animation with incomplete tile.
2261 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2262 cases
.back().layer_between
.has_incomplete_tile
= true;
2263 cases
.back().layer_between
.is_animating
= true;
2265 // 12. High res required.
2266 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2267 cases
.back().high_res_required
= true;
2268 // 13. High res required with incomplete tile.
2270 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2271 cases
.back().high_res_required
= true;
2272 cases
.back().layer_between
.has_incomplete_tile
= true;
2273 // 14. High res required with missing tile.
2275 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2276 cases
.back().high_res_required
= true;
2277 cases
.back().layer_between
.has_missing_tile
= true;
2279 // 15. High res required is higher priority than animating missing tiles.
2281 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2282 cases
.back().high_res_required
= true;
2283 cases
.back().layer_between
.has_missing_tile
= true;
2284 cases
.back().layer_after
.has_missing_tile
= true;
2285 cases
.back().layer_after
.is_animating
= true;
2286 // 16. High res required is higher priority than animating missing tiles.
2288 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2289 cases
.back().high_res_required
= true;
2290 cases
.back().layer_between
.has_missing_tile
= true;
2291 cases
.back().layer_before
.has_missing_tile
= true;
2292 cases
.back().layer_before
.is_animating
= true;
2294 host_impl_
->active_tree()->SetRootLayer(
2295 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2296 DidDrawCheckLayer
* root
=
2297 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2298 root
->SetHasRenderSurface(true);
2300 LayerTreeHostImpl::FrameData frame
;
2301 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2302 host_impl_
->DrawLayers(&frame
);
2303 host_impl_
->DidDrawAllLayers(frame
);
2304 host_impl_
->SwapBuffers(frame
);
2306 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2307 const auto& testcase
= cases
[i
];
2308 std::vector
<LayerImpl
*> to_remove
;
2309 for (auto* child
: root
->children())
2310 to_remove
.push_back(child
);
2311 for (auto* child
: to_remove
)
2312 root
->RemoveChild(child
);
2314 std::ostringstream scope
;
2315 scope
<< "Test case: " << i
;
2316 SCOPED_TRACE(scope
.str());
2318 root
->AddChild(MissingTextureAnimatingLayer::Create(
2319 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2320 testcase
.layer_before
.has_incomplete_tile
,
2321 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2322 DidDrawCheckLayer
* before
=
2323 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2324 if (testcase
.layer_before
.has_copy_request
)
2325 before
->AddCopyRequest();
2327 root
->AddChild(MissingTextureAnimatingLayer::Create(
2328 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2329 testcase
.layer_between
.has_incomplete_tile
,
2330 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2331 DidDrawCheckLayer
* between
=
2332 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2333 if (testcase
.layer_between
.has_copy_request
)
2334 between
->AddCopyRequest();
2336 root
->AddChild(MissingTextureAnimatingLayer::Create(
2337 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2338 testcase
.layer_after
.has_incomplete_tile
,
2339 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2340 DidDrawCheckLayer
* after
=
2341 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2342 if (testcase
.layer_after
.has_copy_request
)
2343 after
->AddCopyRequest();
2345 if (testcase
.high_res_required
)
2346 host_impl_
->SetRequiresHighResToDraw();
2348 LayerTreeHostImpl::FrameData frame
;
2349 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2350 host_impl_
->DrawLayers(&frame
);
2351 host_impl_
->DidDrawAllLayers(frame
);
2352 host_impl_
->SwapBuffers(frame
);
2356 TEST_F(LayerTreeHostImplTest
,
2357 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame
) {
2358 CreateHostImpl(DefaultSettings(),
2359 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2360 EXPECT_TRUE(host_impl_
->output_surface()
2362 .draw_and_swap_full_viewport_every_frame
);
2364 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2367 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2368 // 1. Animation with missing tile.
2369 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2370 cases
.back().layer_between
.has_missing_tile
= true;
2371 cases
.back().layer_between
.is_animating
= true;
2372 // 2. High res required with incomplete tile.
2373 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2374 cases
.back().high_res_required
= true;
2375 cases
.back().layer_between
.has_incomplete_tile
= true;
2376 // 3. High res required with missing tile.
2377 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2378 cases
.back().high_res_required
= true;
2379 cases
.back().layer_between
.has_missing_tile
= true;
2381 host_impl_
->active_tree()->SetRootLayer(
2382 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2383 DidDrawCheckLayer
* root
=
2384 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2385 root
->SetHasRenderSurface(true);
2387 LayerTreeHostImpl::FrameData frame
;
2388 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2389 host_impl_
->DrawLayers(&frame
);
2390 host_impl_
->DidDrawAllLayers(frame
);
2391 host_impl_
->SwapBuffers(frame
);
2393 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2394 const auto& testcase
= cases
[i
];
2395 std::vector
<LayerImpl
*> to_remove
;
2396 for (auto* child
: root
->children())
2397 to_remove
.push_back(child
);
2398 for (auto* child
: to_remove
)
2399 root
->RemoveChild(child
);
2401 std::ostringstream scope
;
2402 scope
<< "Test case: " << i
;
2403 SCOPED_TRACE(scope
.str());
2405 root
->AddChild(MissingTextureAnimatingLayer::Create(
2406 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2407 testcase
.layer_before
.has_incomplete_tile
,
2408 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2409 DidDrawCheckLayer
* before
=
2410 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2411 if (testcase
.layer_before
.has_copy_request
)
2412 before
->AddCopyRequest();
2414 root
->AddChild(MissingTextureAnimatingLayer::Create(
2415 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2416 testcase
.layer_between
.has_incomplete_tile
,
2417 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2418 DidDrawCheckLayer
* between
=
2419 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2420 if (testcase
.layer_between
.has_copy_request
)
2421 between
->AddCopyRequest();
2423 root
->AddChild(MissingTextureAnimatingLayer::Create(
2424 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2425 testcase
.layer_after
.has_incomplete_tile
,
2426 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2427 DidDrawCheckLayer
* after
=
2428 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2429 if (testcase
.layer_after
.has_copy_request
)
2430 after
->AddCopyRequest();
2432 if (testcase
.high_res_required
)
2433 host_impl_
->SetRequiresHighResToDraw();
2435 LayerTreeHostImpl::FrameData frame
;
2436 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2437 host_impl_
->DrawLayers(&frame
);
2438 host_impl_
->DidDrawAllLayers(frame
);
2439 host_impl_
->SwapBuffers(frame
);
2443 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
2444 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2445 root
->SetScrollClipLayer(Layer::INVALID_ID
);
2446 root
->SetHasRenderSurface(true);
2447 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2450 // Scroll event is ignored because layer is not scrollable.
2451 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
2452 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2453 EXPECT_FALSE(did_request_redraw_
);
2454 EXPECT_FALSE(did_request_commit_
);
2457 // TODO(bokan): Convert these tests to create inner and outer viewports.
2458 class LayerTreeHostImplTopControlsTest
: public LayerTreeHostImplTest
{
2460 LayerTreeHostImplTopControlsTest()
2461 // Make the clip size the same as the layer (content) size so the layer is
2463 : layer_size_(10, 10),
2464 clip_size_(layer_size_
),
2465 top_controls_height_(50) {
2466 settings_
.use_pinch_virtual_viewport
= true;
2468 viewport_size_
= gfx::Size(clip_size_
.width(),
2469 clip_size_
.height() + top_controls_height_
);
2472 bool CreateHostImpl(const LayerTreeSettings
& settings
,
2473 scoped_ptr
<OutputSurface
> output_surface
) override
{
2475 LayerTreeHostImplTest::CreateHostImpl(settings
, output_surface
.Pass());
2477 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
2478 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
2483 void SetupTopControlsAndScrollLayer() {
2484 scoped_ptr
<LayerImpl
> root
=
2485 LayerImpl::Create(host_impl_
->active_tree(), 1);
2486 scoped_ptr
<LayerImpl
> root_clip
=
2487 LayerImpl::Create(host_impl_
->active_tree(), 2);
2488 root_clip
->SetBounds(clip_size_
);
2489 root
->SetScrollClipLayer(root_clip
->id());
2490 root
->SetBounds(layer_size_
);
2491 root
->SetContentBounds(layer_size_
);
2492 root
->SetPosition(gfx::PointF());
2493 root
->SetDrawsContent(false);
2494 root
->SetIsContainerForFixedPositionLayers(true);
2495 int inner_viewport_scroll_layer_id
= root
->id();
2496 int page_scale_layer_id
= root_clip
->id();
2497 root_clip
->SetHasRenderSurface(true);
2498 root_clip
->AddChild(root
.Pass());
2499 root_clip
->SetHasRenderSurface(true);
2500 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
2501 host_impl_
->active_tree()->SetViewportLayersFromIds(
2502 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2504 // Set a viewport size that is large enough to contain both the top controls
2505 // and some content.
2506 host_impl_
->SetViewportSize(viewport_size_
);
2507 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2509 host_impl_
->DidChangeTopControlsPosition();
2511 host_impl_
->CreatePendingTree();
2512 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
2514 LayerImpl::Create(host_impl_
->sync_tree(), 1);
2516 LayerImpl::Create(host_impl_
->sync_tree(), 2);
2517 root_clip
->SetBounds(clip_size_
);
2518 root
->SetScrollClipLayer(root_clip
->id());
2519 root
->SetBounds(layer_size_
);
2520 root
->SetContentBounds(layer_size_
);
2521 root
->SetPosition(gfx::PointF());
2522 root
->SetDrawsContent(false);
2523 root
->SetIsContainerForFixedPositionLayers(true);
2524 inner_viewport_scroll_layer_id
= root
->id();
2525 page_scale_layer_id
= root_clip
->id();
2526 root_clip
->AddChild(root
.Pass());
2527 host_impl_
->sync_tree()->SetRootLayer(root_clip
.Pass());
2528 host_impl_
->sync_tree()->SetViewportLayersFromIds(
2529 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2531 // Set a viewport size that is large enough to contain both the top controls
2532 // and some content.
2533 host_impl_
->SetViewportSize(viewport_size_
);
2534 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2535 host_impl_
->DidChangeTopControlsPosition();
2538 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2539 const gfx::Size
& inner_viewport_size
,
2540 const gfx::Size
& outer_viewport_size
,
2541 const gfx::Size
& scroll_layer_size
) {
2542 CreateHostImpl(settings_
, CreateOutputSurface());
2543 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2544 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
2545 host_impl_
->DidChangeTopControlsPosition();
2547 scoped_ptr
<LayerImpl
> root
=
2548 LayerImpl::Create(host_impl_
->active_tree(), 1);
2549 scoped_ptr
<LayerImpl
> root_clip
=
2550 LayerImpl::Create(host_impl_
->active_tree(), 2);
2551 scoped_ptr
<LayerImpl
> page_scale
=
2552 LayerImpl::Create(host_impl_
->active_tree(), 3);
2554 scoped_ptr
<LayerImpl
> outer_scroll
=
2555 LayerImpl::Create(host_impl_
->active_tree(), 4);
2556 scoped_ptr
<LayerImpl
> outer_clip
=
2557 LayerImpl::Create(host_impl_
->active_tree(), 5);
2559 root_clip
->SetBounds(inner_viewport_size
);
2560 root
->SetScrollClipLayer(root_clip
->id());
2561 root
->SetBounds(outer_viewport_size
);
2562 root
->SetContentBounds(outer_viewport_size
);
2563 root
->SetPosition(gfx::PointF());
2564 root
->SetDrawsContent(false);
2565 root
->SetIsContainerForFixedPositionLayers(true);
2566 root_clip
->SetHasRenderSurface(true);
2567 outer_clip
->SetBounds(outer_viewport_size
);
2568 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
2569 outer_scroll
->SetBounds(scroll_layer_size
);
2570 outer_scroll
->SetContentBounds(scroll_layer_size
);
2571 outer_scroll
->SetPosition(gfx::PointF());
2572 outer_scroll
->SetDrawsContent(false);
2573 outer_scroll
->SetIsContainerForFixedPositionLayers(true);
2575 int inner_viewport_scroll_layer_id
= root
->id();
2576 int outer_viewport_scroll_layer_id
= outer_scroll
->id();
2577 int page_scale_layer_id
= page_scale
->id();
2579 outer_clip
->AddChild(outer_scroll
.Pass());
2580 root
->AddChild(outer_clip
.Pass());
2581 page_scale
->AddChild(root
.Pass());
2582 root_clip
->AddChild(page_scale
.Pass());
2584 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
2585 host_impl_
->active_tree()->SetViewportLayersFromIds(
2586 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2587 outer_viewport_scroll_layer_id
);
2589 host_impl_
->SetViewportSize(inner_viewport_size
);
2590 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2591 EXPECT_EQ(inner_viewport_size
, root_clip_ptr
->bounds());
2595 gfx::Size layer_size_
;
2596 gfx::Size clip_size_
;
2597 gfx::Size viewport_size_
;
2598 float top_controls_height_
;
2600 LayerTreeSettings settings_
;
2601 }; // class LayerTreeHostImplTopControlsTest
2603 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsByFractionalAmount
) {
2604 SetupTopControlsAndScrollLayerWithVirtualViewport(
2605 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2608 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2609 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2611 // Make the test scroll delta a fractional amount, to verify that the
2612 // fixed container size delta is (1) non-zero, and (2) fractional, and
2613 // (3) matches the movement of the top controls.
2614 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.25f
);
2615 host_impl_
->top_controls_manager()->ScrollBegin();
2616 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2617 host_impl_
->top_controls_manager()->ScrollEnd();
2619 LayerImpl
* inner_viewport_scroll_layer
=
2620 host_impl_
->active_tree()->InnerViewportScrollLayer();
2621 DCHECK(inner_viewport_scroll_layer
);
2622 host_impl_
->ScrollEnd();
2623 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
2624 inner_viewport_scroll_layer
->FixedContainerSizeDelta().y());
2627 // In this test, the outer viewport is initially unscrollable. We test that a
2628 // scroll initiated on the inner viewport, causing the top controls to show and
2629 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2630 TEST_F(LayerTreeHostImplTopControlsTest
,
2631 TopControlsOuterViewportBecomesScrollable
) {
2632 SetupTopControlsAndScrollLayerWithVirtualViewport(
2633 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2636 LayerImpl
*inner_scroll
=
2637 host_impl_
->active_tree()->InnerViewportScrollLayer();
2638 LayerImpl
*inner_container
=
2639 host_impl_
->active_tree()->InnerViewportContainerLayer();
2640 LayerImpl
*outer_scroll
=
2641 host_impl_
->active_tree()->OuterViewportScrollLayer();
2642 LayerImpl
*outer_container
=
2643 host_impl_
->active_tree()->OuterViewportContainerLayer();
2645 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2646 outer_scroll
->SetDrawsContent(true);
2647 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 1.f
, 2.f
);
2649 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2650 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2651 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 50.f
));
2653 // The entire scroll delta should have been used to hide the top controls.
2654 // The viewport layers should be resized back to their full sizes.
2655 EXPECT_EQ(0.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2656 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
2657 EXPECT_EQ(100.f
, inner_container
->BoundsForScrolling().height());
2658 EXPECT_EQ(100.f
, outer_container
->BoundsForScrolling().height());
2660 // The inner viewport should be scrollable by 50px * page_scale.
2661 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 100.f
));
2662 EXPECT_EQ(50.f
, inner_scroll
->CurrentScrollOffset().y());
2663 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2664 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll
->MaxScrollOffset());
2666 host_impl_
->ScrollEnd();
2668 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2669 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2670 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
2672 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
2674 // The entire scroll delta should have been used to show the top controls.
2675 // The outer viewport should be resized to accomodate and scrolled to the
2676 // bottom of the document to keep the viewport in place.
2677 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2678 EXPECT_EQ(50.f
, outer_container
->BoundsForScrolling().height());
2679 EXPECT_EQ(50.f
, inner_container
->BoundsForScrolling().height());
2680 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
2681 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2683 // Now when we continue scrolling, make sure the outer viewport gets scrolled
2684 // since it wasn't scrollable when the scroll began.
2685 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -20.f
));
2686 EXPECT_EQ(15.f
, outer_scroll
->CurrentScrollOffset().y());
2687 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2689 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -30.f
));
2690 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2691 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2693 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
2694 host_impl_
->ScrollEnd();
2696 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2697 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
2700 // Test that the fixed position container delta is appropriately adjusted
2701 // by the top controls showing/hiding and page scale doesn't affect it.
2702 TEST_F(LayerTreeHostImplTopControlsTest
, FixedContainerDelta
) {
2703 SetupTopControlsAndScrollLayerWithVirtualViewport(
2704 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
2707 float page_scale
= 1.5f
;
2708 LayerImpl
* outer_viewport_scroll_layer
=
2709 host_impl_
->active_tree()->OuterViewportScrollLayer();
2711 // Zoom in, since the fixed container is the outer viewport, the delta should
2713 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
2715 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2716 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2718 // Scroll down, the top controls hiding should expand the viewport size so
2719 // the delta should be equal to the scroll distance.
2720 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 20.f
);
2721 host_impl_
->top_controls_manager()->ScrollBegin();
2722 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2723 EXPECT_FLOAT_EQ(top_controls_height_
- top_controls_scroll_delta
.y(),
2724 host_impl_
->top_controls_manager()->ContentTopOffset());
2725 EXPECT_VECTOR_EQ(top_controls_scroll_delta
,
2726 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2727 host_impl_
->ScrollEnd();
2729 // Scroll past the maximum extent. The delta shouldn't be greater than the
2730 // top controls height.
2731 host_impl_
->top_controls_manager()->ScrollBegin();
2732 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2733 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2734 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2735 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2736 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_
),
2737 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2738 host_impl_
->ScrollEnd();
2740 // Scroll in the direction to make the top controls show.
2741 host_impl_
->top_controls_manager()->ScrollBegin();
2742 host_impl_
->top_controls_manager()->ScrollBy(-top_controls_scroll_delta
);
2743 EXPECT_EQ(top_controls_scroll_delta
.y(),
2744 host_impl_
->top_controls_manager()->ContentTopOffset());
2746 gfx::Vector2dF(0, top_controls_height_
- top_controls_scroll_delta
.y()),
2747 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2748 host_impl_
->top_controls_manager()->ScrollEnd();
2751 // Test that if a scrollable sublayer doesn't consume the scroll,
2752 // top controls should hide when scrolling down.
2753 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollableSublayer
) {
2754 gfx::Size
sub_content_size(100, 400);
2755 gfx::Size
sub_content_layer_size(100, 300);
2756 SetupTopControlsAndScrollLayerWithVirtualViewport(
2757 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
2760 // Show top controls
2761 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2763 LayerImpl
* outer_viewport_scroll_layer
=
2764 host_impl_
->active_tree()->OuterViewportScrollLayer();
2765 int id
= outer_viewport_scroll_layer
->id();
2767 scoped_ptr
<LayerImpl
> child
=
2768 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2);
2769 scoped_ptr
<LayerImpl
> child_clip
=
2770 LayerImpl::Create(host_impl_
->active_tree(), id
+ 3);
2772 child_clip
->SetBounds(sub_content_layer_size
);
2773 child
->SetScrollClipLayer(child_clip
->id());
2774 child
->SetBounds(sub_content_size
);
2775 child
->SetContentBounds(sub_content_size
);
2776 child
->SetPosition(gfx::PointF());
2777 child
->SetDrawsContent(true);
2778 child
->SetIsContainerForFixedPositionLayers(true);
2780 // scroll child to limit
2781 child
->SetScrollDelta(gfx::Vector2dF(0, 100.f
));
2782 child_clip
->AddChild(child
.Pass());
2783 outer_viewport_scroll_layer
->AddChild(child_clip
.Pass());
2785 // Scroll 25px to hide top controls
2786 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
2787 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2788 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2789 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2790 host_impl_
->ScrollEnd();
2792 // Top controls should be hidden
2793 EXPECT_EQ(scroll_delta
.y(),
2794 top_controls_height_
-
2795 host_impl_
->top_controls_manager()->ContentTopOffset());
2798 // Ensure setting the top controls position explicitly using the setters on the
2799 // TreeImpl correctly affects the top controls manager and viewport bounds.
2800 TEST_F(LayerTreeHostImplTopControlsTest
, PositionTopControlsExplicitly
) {
2801 CreateHostImpl(settings_
, CreateOutputSurface());
2802 SetupTopControlsAndScrollLayer();
2805 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2806 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2807 30.f
/ top_controls_height_
);
2808 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2809 EXPECT_FLOAT_EQ(30.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2810 EXPECT_FLOAT_EQ(-20.f
,
2811 host_impl_
->top_controls_manager()->ControlsTopOffset());
2813 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2814 EXPECT_FLOAT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2815 EXPECT_FLOAT_EQ(-50.f
,
2816 host_impl_
->top_controls_manager()->ControlsTopOffset());
2818 host_impl_
->DidChangeTopControlsPosition();
2820 // Now that top controls have moved, expect the clip to resize.
2821 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2822 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2825 // Test that the top_controls delta and sent delta are appropriately
2826 // applied on sync tree activation. The total top controls offset shouldn't
2827 // change after the activation.
2828 TEST_F(LayerTreeHostImplTopControlsTest
, ApplyDeltaOnTreeActivation
) {
2829 CreateHostImpl(settings_
, CreateOutputSurface());
2830 SetupTopControlsAndScrollLayer();
2833 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2834 20.f
/ top_controls_height_
);
2835 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2836 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(
2837 15.f
/ top_controls_height_
);
2838 host_impl_
->active_tree()
2839 ->top_controls_shown_ratio()
2840 ->PullDeltaForMainThread();
2841 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2842 host_impl_
->sync_tree()->PushTopControlsFromMainThread(15.f
/
2843 top_controls_height_
);
2845 host_impl_
->DidChangeTopControlsPosition();
2846 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2847 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2848 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2850 host_impl_
->ActivateSyncTree();
2852 root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2853 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2854 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2857 -15.f
, host_impl_
->active_tree()->top_controls_shown_ratio()->Delta() *
2858 top_controls_height_
);
2861 host_impl_
->active_tree()->top_controls_shown_ratio()->ActiveBase() *
2862 top_controls_height_
);
2865 // Test that changing the top controls layout height is correctly applied to
2866 // the inner viewport container bounds. That is, the top controls layout
2867 // height is the amount that the inner viewport container was shrunk outside
2868 // the compositor to accommodate the top controls.
2869 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsLayoutHeightChanged
) {
2870 CreateHostImpl(settings_
, CreateOutputSurface());
2871 SetupTopControlsAndScrollLayer();
2874 host_impl_
->sync_tree()->PushTopControlsFromMainThread(1.f
);
2875 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2877 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2879 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2880 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2882 host_impl_
->DidChangeTopControlsPosition();
2883 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2884 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2885 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2887 host_impl_
->sync_tree()->root_layer()->SetBounds(
2888 gfx::Size(root_clip_ptr
->bounds().width(),
2889 root_clip_ptr
->bounds().height() - 50.f
));
2891 host_impl_
->ActivateSyncTree();
2893 root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2894 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2896 // The total bounds should remain unchanged since the bounds delta should
2897 // account for the difference between the layout height and the current
2898 // top controls offset.
2899 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2900 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 50.f
), root_clip_ptr
->bounds_delta());
2902 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
2903 host_impl_
->DidChangeTopControlsPosition();
2905 EXPECT_EQ(1.f
, host_impl_
->top_controls_manager()->TopControlsShownRatio());
2906 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->TopControlsHeight());
2907 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2908 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 0.f
), root_clip_ptr
->bounds_delta());
2909 EXPECT_EQ(gfx::Size(viewport_size_
.width(), viewport_size_
.height() - 50.f
),
2910 root_clip_ptr
->bounds());
2913 // Test that showing/hiding the top controls when the viewport is fully scrolled
2914 // doesn't incorrectly change the viewport offset due to clamping from changing
2916 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsViewportOffsetClamping
) {
2917 SetupTopControlsAndScrollLayerWithVirtualViewport(
2918 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2921 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2923 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
2924 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
2926 // Scroll the viewports to max scroll offset.
2927 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
2928 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
2930 gfx::ScrollOffset viewport_offset
=
2931 host_impl_
->active_tree()->TotalScrollOffset();
2932 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(), viewport_offset
);
2934 // Hide the top controls by 25px.
2935 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
2936 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2937 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2938 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2940 // scrolling down at the max extents no longer hides the top controls
2941 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2943 // forcefully hide the top controls by 25px
2944 host_impl_
->top_controls_manager()->ScrollBy(scroll_delta
);
2945 host_impl_
->ScrollEnd();
2947 EXPECT_FLOAT_EQ(scroll_delta
.y(),
2948 top_controls_height_
-
2949 host_impl_
->top_controls_manager()->ContentTopOffset());
2951 inner_scroll
->ClampScrollToMaxScrollOffset();
2952 outer_scroll
->ClampScrollToMaxScrollOffset();
2954 // We should still be fully scrolled.
2955 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
2956 host_impl_
->active_tree()->TotalScrollOffset());
2958 viewport_offset
= host_impl_
->active_tree()->TotalScrollOffset();
2960 // Bring the top controls down by 25px.
2961 scroll_delta
= gfx::Vector2dF(0.f
, -25.f
);
2962 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2963 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2964 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2965 host_impl_
->ScrollEnd();
2967 // The viewport offset shouldn't have changed.
2968 EXPECT_EQ(viewport_offset
,
2969 host_impl_
->active_tree()->TotalScrollOffset());
2971 // Scroll the viewports to max scroll offset.
2972 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
2973 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
2974 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
2975 host_impl_
->active_tree()->TotalScrollOffset());
2978 // Test that the top controls coming in and out maintains the same aspect ratio
2979 // between the inner and outer viewports.
2980 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsAspectRatio
) {
2981 SetupTopControlsAndScrollLayerWithVirtualViewport(
2982 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2985 EXPECT_FLOAT_EQ(top_controls_height_
,
2986 host_impl_
->top_controls_manager()->ContentTopOffset());
2988 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
2989 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2990 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2991 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2992 host_impl_
->ScrollEnd();
2994 EXPECT_FLOAT_EQ(scroll_delta
.y(),
2995 top_controls_height_
-
2996 host_impl_
->top_controls_manager()->ContentTopOffset());
2998 // Top controls were hidden by 25px so the inner viewport should have expanded
3000 LayerImpl
* outer_container
=
3001 host_impl_
->active_tree()->OuterViewportContainerLayer();
3002 LayerImpl
* inner_container
=
3003 host_impl_
->active_tree()->InnerViewportContainerLayer();
3004 EXPECT_EQ(gfx::Size(100, 100+25), inner_container
->BoundsForScrolling());
3006 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3007 float aspect_ratio
= inner_container
->BoundsForScrolling().width() /
3008 inner_container
->BoundsForScrolling().height();
3009 gfx::Size expected
= gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio
));
3010 EXPECT_EQ(expected
, outer_container
->BoundsForScrolling());
3012 host_impl_
->InnerViewportScrollLayer()->BoundsForScrolling());
3015 // Test that scrolling the outer viewport affects the top controls.
3016 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollOuterViewport
) {
3017 SetupTopControlsAndScrollLayerWithVirtualViewport(
3018 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3021 EXPECT_EQ(top_controls_height_
,
3022 host_impl_
->top_controls_manager()->ContentTopOffset());
3024 // Send a gesture scroll that will scroll the outer viewport, make sure the
3025 // top controls get scrolled.
3026 gfx::Vector2dF
scroll_delta(0.f
, 15.f
);
3027 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3028 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3029 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3030 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3031 host_impl_
->CurrentlyScrollingLayer());
3032 host_impl_
->ScrollEnd();
3034 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3035 top_controls_height_
-
3036 host_impl_
->top_controls_manager()->ContentTopOffset());
3038 scroll_delta
= gfx::Vector2dF(0.f
, 50.f
);
3039 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3040 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3041 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3043 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ContentTopOffset());
3044 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3045 host_impl_
->CurrentlyScrollingLayer());
3047 host_impl_
->ScrollEnd();
3049 // Position the viewports such that the inner viewport will be scrolled.
3050 gfx::Vector2dF
inner_viewport_offset(0.f
, 25.f
);
3051 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3052 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset
);
3054 scroll_delta
= gfx::Vector2dF(0.f
, -65.f
);
3055 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3056 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3057 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3059 EXPECT_EQ(top_controls_height_
,
3060 host_impl_
->top_controls_manager()->ContentTopOffset());
3062 inner_viewport_offset
.y() + (scroll_delta
.y() + top_controls_height_
),
3063 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
3065 host_impl_
->ScrollEnd();
3068 TEST_F(LayerTreeHostImplTopControlsTest
,
3069 ScrollNonScrollableRootWithTopControls
) {
3070 CreateHostImpl(settings_
, CreateOutputSurface());
3071 SetupTopControlsAndScrollLayer();
3074 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3075 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3077 host_impl_
->top_controls_manager()->ScrollBegin();
3078 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
3079 host_impl_
->top_controls_manager()->ScrollEnd();
3080 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3081 // Now that top controls have moved, expect the clip to resize.
3082 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3083 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
3085 host_impl_
->ScrollEnd();
3087 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3088 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3090 float scroll_increment_y
= -25.f
;
3091 host_impl_
->top_controls_manager()->ScrollBegin();
3092 host_impl_
->top_controls_manager()->ScrollBy(
3093 gfx::Vector2dF(0.f
, scroll_increment_y
));
3094 EXPECT_FLOAT_EQ(-scroll_increment_y
,
3095 host_impl_
->top_controls_manager()->ContentTopOffset());
3096 // Now that top controls have moved, expect the clip to resize.
3097 EXPECT_EQ(gfx::Size(viewport_size_
.width(),
3098 viewport_size_
.height() + scroll_increment_y
),
3099 root_clip_ptr
->bounds());
3101 host_impl_
->top_controls_manager()->ScrollBy(
3102 gfx::Vector2dF(0.f
, scroll_increment_y
));
3103 host_impl_
->top_controls_manager()->ScrollEnd();
3104 EXPECT_FLOAT_EQ(-2 * scroll_increment_y
,
3105 host_impl_
->top_controls_manager()->ContentTopOffset());
3106 // Now that top controls have moved, expect the clip to resize.
3107 EXPECT_EQ(clip_size_
, root_clip_ptr
->bounds());
3109 host_impl_
->ScrollEnd();
3111 // Verify the layer is once-again non-scrollable.
3113 gfx::ScrollOffset(),
3114 host_impl_
->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3116 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3117 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3120 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
3121 // Test the configuration where a non-composited root layer is embedded in a
3122 // scrollable outer layer.
3123 gfx::Size
surface_size(10, 10);
3124 gfx::Size
contents_size(20, 20);
3126 scoped_ptr
<LayerImpl
> content_layer
=
3127 LayerImpl::Create(host_impl_
->active_tree(), 1);
3128 content_layer
->SetDrawsContent(true);
3129 content_layer
->SetPosition(gfx::PointF());
3130 content_layer
->SetBounds(contents_size
);
3131 content_layer
->SetContentBounds(contents_size
);
3132 content_layer
->SetContentsScale(2.f
, 2.f
);
3134 scoped_ptr
<LayerImpl
> scroll_clip_layer
=
3135 LayerImpl::Create(host_impl_
->active_tree(), 3);
3136 scroll_clip_layer
->SetBounds(surface_size
);
3138 scoped_ptr
<LayerImpl
> scroll_layer
=
3139 LayerImpl::Create(host_impl_
->active_tree(), 2);
3140 scroll_layer
->SetScrollClipLayer(3);
3141 scroll_layer
->SetBounds(contents_size
);
3142 scroll_layer
->SetContentBounds(contents_size
);
3143 scroll_layer
->SetPosition(gfx::PointF());
3144 scroll_layer
->AddChild(content_layer
.Pass());
3145 scroll_clip_layer
->AddChild(scroll_layer
.Pass());
3147 scroll_clip_layer
->SetHasRenderSurface(true);
3148 host_impl_
->active_tree()->SetRootLayer(scroll_clip_layer
.Pass());
3149 host_impl_
->SetViewportSize(surface_size
);
3152 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3153 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3154 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3155 host_impl_
->ScrollEnd();
3156 EXPECT_TRUE(did_request_redraw_
);
3157 EXPECT_TRUE(did_request_commit_
);
3160 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
3161 gfx::Size
surface_size(10, 10);
3162 gfx::Size
contents_size(20, 20);
3163 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3164 root
->SetBounds(surface_size
);
3165 root
->SetContentBounds(contents_size
);
3166 root
->AddChild(CreateScrollableLayer(2, contents_size
, root
.get()));
3167 root
->SetHasRenderSurface(true);
3168 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3169 host_impl_
->SetViewportSize(surface_size
);
3172 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3173 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3174 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3175 host_impl_
->ScrollEnd();
3176 EXPECT_TRUE(did_request_redraw_
);
3177 EXPECT_TRUE(did_request_commit_
);
3180 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
3181 gfx::Size
surface_size(10, 10);
3182 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3183 root
->AddChild(CreateScrollableLayer(2, surface_size
, root
.get()));
3184 root
->SetHasRenderSurface(true);
3185 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3186 host_impl_
->SetViewportSize(surface_size
);
3189 // Scroll event is ignored because the input coordinate is outside the layer
3191 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3192 host_impl_
->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL
));
3193 EXPECT_FALSE(did_request_redraw_
);
3194 EXPECT_FALSE(did_request_commit_
);
3197 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
3198 gfx::Size
surface_size(10, 10);
3199 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3200 root
->SetHasRenderSurface(true);
3201 scoped_ptr
<LayerImpl
> child
=
3202 CreateScrollableLayer(2, surface_size
, root
.get());
3203 host_impl_
->SetViewportSize(surface_size
);
3205 gfx::Transform matrix
;
3206 matrix
.RotateAboutXAxis(180.0);
3207 child
->SetTransform(matrix
);
3208 child
->SetDoubleSided(false);
3210 root
->AddChild(child
.Pass());
3211 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3214 // Scroll event is ignored because the scrollable layer is not facing the
3215 // viewer and there is nothing scrollable behind it.
3216 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3217 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3218 EXPECT_FALSE(did_request_redraw_
);
3219 EXPECT_FALSE(did_request_commit_
);
3222 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
3223 gfx::Size
surface_size(10, 10);
3224 scoped_ptr
<LayerImpl
> clip_layer
=
3225 LayerImpl::Create(host_impl_
->active_tree(), 3);
3226 scoped_ptr
<LayerImpl
> content_layer
=
3227 CreateScrollableLayer(1, surface_size
, clip_layer
.get());
3228 content_layer
->SetShouldScrollOnMainThread(true);
3229 content_layer
->SetScrollClipLayer(Layer::INVALID_ID
);
3231 // Note: we can use the same clip layer for both since both calls to
3232 // CreateScrollableLayer() use the same surface size.
3233 scoped_ptr
<LayerImpl
> scroll_layer
=
3234 CreateScrollableLayer(2, surface_size
, clip_layer
.get());
3235 scroll_layer
->AddChild(content_layer
.Pass());
3236 clip_layer
->AddChild(scroll_layer
.Pass());
3237 clip_layer
->SetHasRenderSurface(true);
3239 host_impl_
->active_tree()->SetRootLayer(clip_layer
.Pass());
3240 host_impl_
->SetViewportSize(surface_size
);
3243 // Scrolling fails because the content layer is asking to be scrolled on the
3245 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
3246 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3249 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
3250 gfx::Size
surface_size(20, 20);
3251 gfx::Size
viewport_size(10, 10);
3252 float page_scale
= 2.f
;
3253 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3254 scoped_ptr
<LayerImpl
> root_clip
=
3255 LayerImpl::Create(host_impl_
->active_tree(), 2);
3256 scoped_ptr
<LayerImpl
> root_scrolling
=
3257 CreateScrollableLayer(3, surface_size
, root_clip
.get());
3258 EXPECT_EQ(viewport_size
, root_clip
->bounds());
3259 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3260 root_clip
->AddChild(root_scrolling
.Pass());
3261 root
->AddChild(root_clip
.Pass());
3262 root
->SetHasRenderSurface(true);
3263 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3264 // The behaviour in this test assumes the page scale is applied at a layer
3265 // above the clip layer.
3266 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 3,
3268 host_impl_
->active_tree()->DidBecomeActive();
3269 host_impl_
->SetViewportSize(viewport_size
);
3272 LayerImpl
* root_scroll
=
3273 host_impl_
->active_tree()->InnerViewportScrollLayer();
3274 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3276 gfx::Vector2d
scroll_delta(0, 10);
3277 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3278 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3279 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3280 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3281 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3282 host_impl_
->ScrollEnd();
3284 // Set new page scale from main thread.
3285 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, page_scale
,
3288 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3289 ExpectContains(*scroll_info
.get(), root_scroll
->id(), expected_scroll_delta
);
3291 // The scroll range should also have been updated.
3292 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3294 // The page scale delta remains constant because the impl thread did not
3296 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3299 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
3300 gfx::Size
surface_size(20, 20);
3301 gfx::Size
viewport_size(10, 10);
3302 float page_scale
= 2.f
;
3303 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3304 scoped_ptr
<LayerImpl
> root_clip
=
3305 LayerImpl::Create(host_impl_
->active_tree(), 2);
3306 scoped_ptr
<LayerImpl
> root_scrolling
=
3307 CreateScrollableLayer(3, surface_size
, root_clip
.get());
3308 EXPECT_EQ(viewport_size
, root_clip
->bounds());
3309 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3310 root_clip
->AddChild(root_scrolling
.Pass());
3311 root
->AddChild(root_clip
.Pass());
3312 root
->SetHasRenderSurface(true);
3313 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3314 // The behaviour in this test assumes the page scale is applied at a layer
3315 // above the clip layer.
3316 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 3,
3318 host_impl_
->active_tree()->DidBecomeActive();
3319 host_impl_
->SetViewportSize(viewport_size
);
3320 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, page_scale
);
3323 LayerImpl
* root_scroll
=
3324 host_impl_
->active_tree()->InnerViewportScrollLayer();
3325 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3327 gfx::Vector2d
scroll_delta(0, 10);
3328 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3329 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3330 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3331 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3332 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3333 host_impl_
->ScrollEnd();
3335 // Set new page scale on impl thread by pinching.
3336 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3337 host_impl_
->PinchGestureBegin();
3338 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
3339 host_impl_
->PinchGestureEnd();
3340 host_impl_
->ScrollEnd();
3343 // The scroll delta is not scaled because the main thread did not scale.
3344 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3345 ExpectContains(*scroll_info
.get(), root_scroll
->id(), expected_scroll_delta
);
3347 // The scroll range should also have been updated.
3348 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3350 // The page scale delta should match the new scale on the impl side.
3351 EXPECT_EQ(page_scale
, host_impl_
->active_tree()->current_page_scale_factor());
3354 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
3355 gfx::Size
surface_size(10, 10);
3356 float default_page_scale
= 1.f
;
3357 gfx::Transform default_page_scale_matrix
;
3358 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
3360 float new_page_scale
= 2.f
;
3361 gfx::Transform new_page_scale_matrix
;
3362 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
3364 // Create a normal scrollable root layer and another scrollable child layer.
3365 LayerImpl
* scroll
= SetupScrollAndContentsLayers(surface_size
);
3366 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
3367 LayerImpl
* child
= scroll
->children()[0];
3369 scoped_ptr
<LayerImpl
> scrollable_child_clip
=
3370 LayerImpl::Create(host_impl_
->active_tree(), 6);
3371 scoped_ptr
<LayerImpl
> scrollable_child
=
3372 CreateScrollableLayer(7, surface_size
, scrollable_child_clip
.get());
3373 scrollable_child_clip
->AddChild(scrollable_child
.Pass());
3374 child
->AddChild(scrollable_child_clip
.Pass());
3375 LayerImpl
* grand_child
= child
->children()[0];
3377 // Set new page scale on impl thread by pinching.
3378 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3379 host_impl_
->PinchGestureBegin();
3380 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
3381 host_impl_
->PinchGestureEnd();
3382 host_impl_
->ScrollEnd();
3385 EXPECT_EQ(1.f
, root
->contents_scale_x());
3386 EXPECT_EQ(1.f
, root
->contents_scale_y());
3387 EXPECT_EQ(1.f
, scroll
->contents_scale_x());
3388 EXPECT_EQ(1.f
, scroll
->contents_scale_y());
3389 EXPECT_EQ(1.f
, child
->contents_scale_x());
3390 EXPECT_EQ(1.f
, child
->contents_scale_y());
3391 EXPECT_EQ(1.f
, grand_child
->contents_scale_x());
3392 EXPECT_EQ(1.f
, grand_child
->contents_scale_y());
3394 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3395 // the page scale delta on the root layer is applied hierarchically.
3396 LayerTreeHostImpl::FrameData frame
;
3397 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3398 host_impl_
->DrawLayers(&frame
);
3399 host_impl_
->DidDrawAllLayers(frame
);
3401 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(0, 0));
3402 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(1, 1));
3403 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(0, 0));
3404 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(1, 1));
3405 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
3406 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
3407 EXPECT_EQ(new_page_scale
,
3408 grand_child
->draw_transform().matrix().getDouble(0, 0));
3409 EXPECT_EQ(new_page_scale
,
3410 grand_child
->draw_transform().matrix().getDouble(1, 1));
3413 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
3414 gfx::Size
surface_size(30, 30);
3415 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3416 root
->SetBounds(gfx::Size(5, 5));
3417 root
->SetHasRenderSurface(true);
3418 scoped_ptr
<LayerImpl
> root_scrolling
=
3419 LayerImpl::Create(host_impl_
->active_tree(), 2);
3420 root_scrolling
->SetBounds(surface_size
);
3421 root_scrolling
->SetContentBounds(surface_size
);
3422 root_scrolling
->SetScrollClipLayer(root
->id());
3423 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3424 LayerImpl
* root_scrolling_ptr
= root_scrolling
.get();
3425 root
->AddChild(root_scrolling
.Pass());
3426 int child_scroll_layer_id
= 3;
3427 scoped_ptr
<LayerImpl
> child_scrolling
= CreateScrollableLayer(
3428 child_scroll_layer_id
, surface_size
, root_scrolling_ptr
);
3429 LayerImpl
* child
= child_scrolling
.get();
3430 root_scrolling_ptr
->AddChild(child_scrolling
.Pass());
3431 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3432 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3434 host_impl_
->active_tree()->DidBecomeActive();
3435 host_impl_
->SetViewportSize(surface_size
);
3438 gfx::Vector2d
scroll_delta(0, 10);
3439 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
3440 gfx::ScrollOffset
expected_max_scroll(child
->MaxScrollOffset());
3441 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3442 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3443 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3444 host_impl_
->ScrollEnd();
3446 float page_scale
= 2.f
;
3447 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
,
3452 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3454 *scroll_info
.get(), child_scroll_layer_id
, expected_scroll_delta
);
3456 // The scroll range should not have changed.
3457 EXPECT_EQ(child
->MaxScrollOffset(), expected_max_scroll
);
3459 // The page scale delta remains constant because the impl thread did not
3461 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3464 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
3465 // Scroll a child layer beyond its maximum scroll range and make sure the
3466 // parent layer is scrolled on the axis on which the child was unable to
3468 gfx::Size
surface_size(10, 10);
3469 gfx::Size
content_size(20, 20);
3470 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3471 root
->SetBounds(surface_size
);
3472 root
->SetHasRenderSurface(true);
3473 scoped_ptr
<LayerImpl
> grand_child
=
3474 CreateScrollableLayer(3, content_size
, root
.get());
3476 scoped_ptr
<LayerImpl
> child
=
3477 CreateScrollableLayer(2, content_size
, root
.get());
3478 LayerImpl
* grand_child_layer
= grand_child
.get();
3479 child
->AddChild(grand_child
.Pass());
3481 LayerImpl
* child_layer
= child
.get();
3482 root
->AddChild(child
.Pass());
3483 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3484 host_impl_
->active_tree()->DidBecomeActive();
3485 host_impl_
->SetViewportSize(surface_size
);
3486 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
3487 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
3491 gfx::Vector2d
scroll_delta(-8, -7);
3492 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3493 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3494 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3495 host_impl_
->ScrollEnd();
3497 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3498 host_impl_
->ProcessScrollDeltas();
3500 // The grand child should have scrolled up to its limit.
3501 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
3502 LayerImpl
* grand_child
= child
->children()[0];
3503 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -5));
3505 // The child should have only scrolled on the other axis.
3506 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(-3, 0));
3510 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
3511 // Scroll a child layer beyond its maximum scroll range and make sure the
3512 // the scroll doesn't bubble up to the parent layer.
3513 gfx::Size
surface_size(20, 20);
3514 gfx::Size
viewport_size(10, 10);
3515 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3516 root
->SetHasRenderSurface(true);
3517 scoped_ptr
<LayerImpl
> root_scrolling
=
3518 CreateScrollableLayer(2, surface_size
, root
.get());
3519 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3521 scoped_ptr
<LayerImpl
> grand_child
=
3522 CreateScrollableLayer(4, surface_size
, root
.get());
3524 scoped_ptr
<LayerImpl
> child
=
3525 CreateScrollableLayer(3, surface_size
, root
.get());
3526 LayerImpl
* grand_child_layer
= grand_child
.get();
3527 child
->AddChild(grand_child
.Pass());
3529 LayerImpl
* child_layer
= child
.get();
3530 root_scrolling
->AddChild(child
.Pass());
3531 root
->AddChild(root_scrolling
.Pass());
3532 EXPECT_EQ(viewport_size
, root
->bounds());
3533 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3534 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3536 host_impl_
->active_tree()->DidBecomeActive();
3537 host_impl_
->SetViewportSize(viewport_size
);
3539 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
3540 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
3544 gfx::Vector2d
scroll_delta(0, -10);
3545 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3546 host_impl_
->ScrollBegin(gfx::Point(),
3547 InputHandler::NON_BUBBLING_GESTURE
));
3548 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3549 host_impl_
->ScrollEnd();
3551 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3552 host_impl_
->ProcessScrollDeltas();
3554 // The grand child should have scrolled up to its limit.
3556 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
3557 LayerImpl
* grand_child
= child
->children()[0];
3558 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -2));
3560 // The child should not have scrolled.
3561 ExpectNone(*scroll_info
.get(), child
->id());
3563 // The next time we scroll we should only scroll the parent.
3564 scroll_delta
= gfx::Vector2d(0, -3);
3565 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3566 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3567 InputHandler::NON_BUBBLING_GESTURE
));
3568 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3569 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3570 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
3571 host_impl_
->ScrollEnd();
3573 scroll_info
= host_impl_
->ProcessScrollDeltas();
3575 // The child should have scrolled up to its limit.
3576 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(0, -3));
3578 // The grand child should not have scrolled.
3579 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -2));
3581 // After scrolling the parent, another scroll on the opposite direction
3582 // should still scroll the child.
3583 scroll_delta
= gfx::Vector2d(0, 7);
3584 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3585 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3586 InputHandler::NON_BUBBLING_GESTURE
));
3587 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3588 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3589 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3590 host_impl_
->ScrollEnd();
3592 scroll_info
= host_impl_
->ProcessScrollDeltas();
3594 // The grand child should have scrolled.
3595 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, 5));
3597 // The child should not have scrolled.
3598 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(0, -3));
3601 // Scrolling should be adjusted from viewport space.
3602 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 2.f
, 2.f
);
3603 host_impl_
->SetPageScaleOnActiveTree(2.f
);
3605 scroll_delta
= gfx::Vector2d(0, -2);
3606 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3607 host_impl_
->ScrollBegin(gfx::Point(1, 1),
3608 InputHandler::NON_BUBBLING_GESTURE
));
3609 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
3610 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3611 host_impl_
->ScrollEnd();
3613 scroll_info
= host_impl_
->ProcessScrollDeltas();
3615 // Should have scrolled by half the amount in layer space (5 - 2/2)
3616 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, 4));
3619 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
3620 // When we try to scroll a non-scrollable child layer, the scroll delta
3621 // should be applied to one of its ancestors if possible.
3622 gfx::Size
surface_size(10, 10);
3623 gfx::Size
content_size(20, 20);
3624 scoped_ptr
<LayerImpl
> root_clip
=
3625 LayerImpl::Create(host_impl_
->active_tree(), 3);
3626 root_clip
->SetHasRenderSurface(true);
3627 scoped_ptr
<LayerImpl
> root
=
3628 CreateScrollableLayer(1, content_size
, root_clip
.get());
3629 // Make 'root' the clip layer for child: since they have the same sizes the
3630 // child will have zero max_scroll_offset and scrolls will bubble.
3631 scoped_ptr
<LayerImpl
> child
=
3632 CreateScrollableLayer(2, content_size
, root
.get());
3633 child
->SetIsContainerForFixedPositionLayers(true);
3634 root
->SetBounds(content_size
);
3636 int root_scroll_id
= root
->id();
3637 root
->AddChild(child
.Pass());
3638 root_clip
->AddChild(root
.Pass());
3640 host_impl_
->SetViewportSize(surface_size
);
3641 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3642 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 2,
3644 host_impl_
->active_tree()->DidBecomeActive();
3647 gfx::Vector2d
scroll_delta(0, 4);
3648 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3649 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3650 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3651 host_impl_
->ScrollEnd();
3653 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3654 host_impl_
->ProcessScrollDeltas();
3656 // Only the root scroll should have scrolled.
3657 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
3658 ExpectContains(*scroll_info
.get(), root_scroll_id
, scroll_delta
);
3662 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
3663 gfx::Size
surface_size(10, 10);
3664 scoped_ptr
<LayerImpl
> root_clip
=
3665 LayerImpl::Create(host_impl_
->active_tree(), 1);
3666 scoped_ptr
<LayerImpl
> root_scroll
=
3667 CreateScrollableLayer(2, surface_size
, root_clip
.get());
3668 root_scroll
->SetIsContainerForFixedPositionLayers(true);
3669 root_clip
->SetHasRenderSurface(true);
3670 root_clip
->AddChild(root_scroll
.Pass());
3671 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3672 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3674 host_impl_
->active_tree()->DidBecomeActive();
3675 host_impl_
->SetViewportSize(surface_size
);
3677 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3680 host_impl_
->active_tree()->DetachLayerTree();
3681 scoped_ptr
<LayerImpl
> root_clip2
=
3682 LayerImpl::Create(host_impl_
->active_tree(), 3);
3683 scoped_ptr
<LayerImpl
> root_scroll2
=
3684 CreateScrollableLayer(4, surface_size
, root_clip2
.get());
3685 root_scroll2
->SetIsContainerForFixedPositionLayers(true);
3686 root_clip2
->AddChild(root_scroll2
.Pass());
3687 root_clip2
->SetHasRenderSurface(true);
3688 host_impl_
->active_tree()->SetRootLayer(root_clip2
.Pass());
3689 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 4,
3691 host_impl_
->active_tree()->DidBecomeActive();
3693 // Scrolling should still work even though we did not draw yet.
3694 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3695 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3698 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
3699 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3701 // Rotate the root layer 90 degrees counter-clockwise about its center.
3702 gfx::Transform rotate_transform
;
3703 rotate_transform
.Rotate(-90.0);
3704 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
3706 gfx::Size
surface_size(50, 50);
3707 host_impl_
->SetViewportSize(surface_size
);
3710 // Scroll to the right in screen coordinates with a gesture.
3711 gfx::Vector2d
gesture_scroll_delta(10, 0);
3712 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3713 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3714 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3715 host_impl_
->ScrollEnd();
3717 // The layer should have scrolled down in its local coordinates.
3718 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3719 ExpectContains(*scroll_info
.get(), scroll_layer
->id(),
3720 gfx::Vector2d(0, gesture_scroll_delta
.x()));
3722 // Reset and scroll down with the wheel.
3723 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
3724 gfx::Vector2d
wheel_scroll_delta(0, 10);
3725 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3726 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3727 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
3728 host_impl_
->ScrollEnd();
3730 // The layer should have scrolled down in its local coordinates.
3731 scroll_info
= host_impl_
->ProcessScrollDeltas();
3732 ExpectContains(*scroll_info
.get(),
3734 wheel_scroll_delta
);
3737 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
3738 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3739 int child_clip_layer_id
= 6;
3740 int child_layer_id
= 7;
3741 float child_layer_angle
= -20.f
;
3743 // Create a child layer that is rotated to a non-axis-aligned angle.
3744 scoped_ptr
<LayerImpl
> clip_layer
=
3745 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
3746 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
3747 child_layer_id
, scroll_layer
->content_bounds(), clip_layer
.get());
3748 gfx::Transform rotate_transform
;
3749 rotate_transform
.Translate(-50.0, -50.0);
3750 rotate_transform
.Rotate(child_layer_angle
);
3751 rotate_transform
.Translate(50.0, 50.0);
3752 clip_layer
->SetTransform(rotate_transform
);
3754 // Only allow vertical scrolling.
3755 clip_layer
->SetBounds(
3756 gfx::Size(child
->bounds().width(), child
->bounds().height() / 2));
3757 // The rotation depends on the layer's transform origin, and the child layer
3758 // is a different size than the clip, so make sure the clip layer's origin
3759 // lines up over the child.
3760 clip_layer
->SetTransformOrigin(gfx::Point3F(
3761 clip_layer
->bounds().width() * 0.5f
, clip_layer
->bounds().height(), 0.f
));
3762 LayerImpl
* child_ptr
= child
.get();
3763 clip_layer
->AddChild(child
.Pass());
3764 scroll_layer
->AddChild(clip_layer
.Pass());
3766 gfx::Size
surface_size(50, 50);
3767 host_impl_
->SetViewportSize(surface_size
);
3770 // Scroll down in screen coordinates with a gesture.
3771 gfx::Vector2d
gesture_scroll_delta(0, 10);
3772 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3773 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
3774 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3775 host_impl_
->ScrollEnd();
3777 // The child layer should have scrolled down in its local coordinates an
3778 // amount proportional to the angle between it and the input scroll delta.
3779 gfx::Vector2d
expected_scroll_delta(
3780 0, gesture_scroll_delta
.y() *
3781 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
3782 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3783 host_impl_
->ProcessScrollDeltas();
3784 ExpectContains(*scroll_info
.get(), child_layer_id
, expected_scroll_delta
);
3786 // The root scroll layer should not have scrolled, because the input delta
3787 // was close to the layer's axis of movement.
3788 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
3791 // Now reset and scroll the same amount horizontally.
3792 child_ptr
->SetScrollDelta(gfx::Vector2dF());
3793 gfx::Vector2d
gesture_scroll_delta(10, 0);
3794 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3795 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
3796 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3797 host_impl_
->ScrollEnd();
3799 // The child layer should have scrolled down in its local coordinates an
3800 // amount proportional to the angle between it and the input scroll delta.
3801 gfx::Vector2d
expected_scroll_delta(
3802 0, -gesture_scroll_delta
.x() *
3803 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
3804 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3805 host_impl_
->ProcessScrollDeltas();
3806 ExpectContains(*scroll_info
.get(), child_layer_id
, expected_scroll_delta
);
3808 // The root scroll layer should have scrolled more, since the input scroll
3809 // delta was mostly orthogonal to the child layer's vertical scroll axis.
3810 gfx::Vector2d
expected_root_scroll_delta(
3811 gesture_scroll_delta
.x() *
3812 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
3814 ExpectContains(*scroll_info
.get(),
3816 expected_root_scroll_delta
);
3820 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
3821 LayerImpl
* scroll_layer
=
3822 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3824 // Scale the layer to twice its normal size.
3826 gfx::Transform scale_transform
;
3827 scale_transform
.Scale(scale
, scale
);
3828 scroll_layer
->SetTransform(scale_transform
);
3830 gfx::Size
surface_size(50, 50);
3831 host_impl_
->SetViewportSize(surface_size
);
3834 // Scroll down in screen coordinates with a gesture.
3835 gfx::Vector2d
scroll_delta(0, 10);
3836 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3837 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3838 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3839 host_impl_
->ScrollEnd();
3841 // The layer should have scrolled down in its local coordinates, but half the
3843 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3844 ExpectContains(*scroll_info
.get(),
3846 gfx::Vector2d(0, scroll_delta
.y() / scale
));
3848 // Reset and scroll down with the wheel.
3849 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
3850 gfx::Vector2d
wheel_scroll_delta(0, 10);
3851 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3852 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3853 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
3854 host_impl_
->ScrollEnd();
3856 // It should apply the scale factor to the scroll delta for the wheel event.
3857 scroll_info
= host_impl_
->ProcessScrollDeltas();
3858 ExpectContains(*scroll_info
.get(),
3860 wheel_scroll_delta
);
3863 TEST_F(LayerTreeHostImplTest
, ScrollViewportRounding
) {
3867 SetupScrollAndContentsLayers(gfx::Size(width
, height
));
3868 host_impl_
->active_tree()->InnerViewportContainerLayer()->SetBounds(
3869 gfx::Size(width
* scale
- 1, height
* scale
));
3870 host_impl_
->SetDeviceScaleFactor(scale
);
3871 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
3873 LayerImpl
* inner_viewport_scroll_layer
=
3874 host_impl_
->active_tree()->InnerViewportScrollLayer();
3875 EXPECT_EQ(gfx::ScrollOffset(0, 0),
3876 inner_viewport_scroll_layer
->MaxScrollOffset());
3879 class TestScrollOffsetDelegate
: public LayerScrollOffsetDelegate
{
3881 TestScrollOffsetDelegate()
3882 : page_scale_factor_(0.f
),
3883 min_page_scale_factor_(-1.f
),
3884 max_page_scale_factor_(-1.f
) {}
3886 ~TestScrollOffsetDelegate() override
{}
3888 gfx::ScrollOffset
GetTotalScrollOffset() override
{
3889 return getter_return_value_
;
3892 bool IsExternalFlingActive() const override
{ return false; }
3894 void UpdateRootLayerState(const gfx::ScrollOffset
& total_scroll_offset
,
3895 const gfx::ScrollOffset
& max_scroll_offset
,
3896 const gfx::SizeF
& scrollable_size
,
3897 float page_scale_factor
,
3898 float min_page_scale_factor
,
3899 float max_page_scale_factor
) override
{
3900 DCHECK(total_scroll_offset
.x() <= max_scroll_offset
.x());
3901 DCHECK(total_scroll_offset
.y() <= max_scroll_offset
.y());
3902 last_set_scroll_offset_
= total_scroll_offset
;
3903 max_scroll_offset_
= max_scroll_offset
;
3904 scrollable_size_
= scrollable_size
;
3905 page_scale_factor_
= page_scale_factor
;
3906 min_page_scale_factor_
= min_page_scale_factor
;
3907 max_page_scale_factor_
= max_page_scale_factor
;
3909 set_getter_return_value(last_set_scroll_offset_
);
3912 gfx::ScrollOffset
last_set_scroll_offset() {
3913 return last_set_scroll_offset_
;
3916 void set_getter_return_value(const gfx::ScrollOffset
& value
) {
3917 getter_return_value_
= value
;
3920 gfx::ScrollOffset
max_scroll_offset() const {
3921 return max_scroll_offset_
;
3924 gfx::SizeF
scrollable_size() const {
3925 return scrollable_size_
;
3928 float page_scale_factor() const {
3929 return page_scale_factor_
;
3932 float min_page_scale_factor() const {
3933 return min_page_scale_factor_
;
3936 float max_page_scale_factor() const {
3937 return max_page_scale_factor_
;
3941 gfx::ScrollOffset last_set_scroll_offset_
;
3942 gfx::ScrollOffset getter_return_value_
;
3943 gfx::ScrollOffset max_scroll_offset_
;
3944 gfx::SizeF scrollable_size_
;
3945 float page_scale_factor_
;
3946 float min_page_scale_factor_
;
3947 float max_page_scale_factor_
;
3950 TEST_F(LayerTreeHostImplTest
, RootLayerScrollOffsetDelegation
) {
3951 TestScrollOffsetDelegate scroll_delegate
;
3952 host_impl_
->SetViewportSize(gfx::Size(10, 20));
3953 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3954 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
3955 clip_layer
->SetBounds(gfx::Size(10, 20));
3957 // Setting the delegate results in the current scroll offset being set.
3958 gfx::Vector2dF
initial_scroll_delta(10.f
, 10.f
);
3959 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
3960 scroll_layer
->SetScrollDelta(initial_scroll_delta
);
3961 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
3962 EXPECT_EQ(initial_scroll_delta
.ToString(),
3963 scroll_delegate
.last_set_scroll_offset().ToString());
3965 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3966 // page_scale_factor and {min|max}_page_scale_factor being set.
3967 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate
.scrollable_size());
3968 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate
.max_scroll_offset());
3969 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
3970 EXPECT_EQ(0.f
, scroll_delegate
.min_page_scale_factor());
3971 EXPECT_EQ(0.f
, scroll_delegate
.max_page_scale_factor());
3973 // Updating page scale immediately updates the delegate.
3974 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 0.5f
, 4.f
);
3975 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
3976 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
3977 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
3978 host_impl_
->SetPageScaleOnActiveTree(2.f
* 1.5f
);
3979 EXPECT_EQ(3.f
, scroll_delegate
.page_scale_factor());
3980 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
3981 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
3982 host_impl_
->SetPageScaleOnActiveTree(2.f
);
3983 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
3984 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
3985 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
3986 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
3988 // The pinch gesture doesn't put the delegate into a state where the scroll
3989 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3991 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3992 host_impl_
->PinchGestureBegin();
3993 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
3994 host_impl_
->PinchGestureUpdate(.5f
, gfx::Point());
3995 host_impl_
->PinchGestureEnd();
3996 host_impl_
->ScrollEnd();
3998 // Scrolling should be relative to the offset as returned by the delegate.
3999 gfx::Vector2dF
scroll_delta(0.f
, 10.f
);
4000 gfx::ScrollOffset
current_offset(7.f
, 8.f
);
4002 scroll_delegate
.set_getter_return_value(current_offset
);
4003 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4004 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4005 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4007 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4008 EXPECT_EQ(ScrollOffsetWithDelta(current_offset
, scroll_delta
),
4009 scroll_delegate
.last_set_scroll_offset());
4011 current_offset
= gfx::ScrollOffset(42.f
, 41.f
);
4012 scroll_delegate
.set_getter_return_value(current_offset
);
4013 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4014 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4015 EXPECT_EQ(current_offset
+ gfx::ScrollOffset(scroll_delta
),
4016 scroll_delegate
.last_set_scroll_offset());
4017 host_impl_
->ScrollEnd();
4018 scroll_delegate
.set_getter_return_value(gfx::ScrollOffset());
4019 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4021 // Forces a full tree synchronization and ensures that the scroll delegate
4022 // sees the correct size of the new tree.
4023 gfx::Size
new_size(42, 24);
4024 host_impl_
->CreatePendingTree();
4025 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), new_size
);
4026 host_impl_
->ActivateSyncTree();
4027 EXPECT_EQ(new_size
, scroll_delegate
.scrollable_size());
4029 // Un-setting the delegate should propagate the delegate's current offset to
4030 // the root scrollable layer.
4031 current_offset
= gfx::ScrollOffset(13.f
, 12.f
);
4032 scroll_delegate
.set_getter_return_value(current_offset
);
4033 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4034 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4036 EXPECT_EQ(current_offset
.ToString(),
4037 scroll_layer
->CurrentScrollOffset().ToString());
4040 void CheckLayerScrollDelta(LayerImpl
* layer
, gfx::Vector2dF scroll_delta
) {
4041 const gfx::Transform target_space_transform
=
4042 layer
->draw_properties().target_space_transform
;
4043 EXPECT_TRUE(target_space_transform
.IsScaleOrTranslation());
4044 gfx::Point translated_point
;
4045 target_space_transform
.TransformPoint(&translated_point
);
4046 gfx::Point expected_point
= gfx::Point() - ToRoundedVector2d(scroll_delta
);
4047 EXPECT_EQ(expected_point
.ToString(), translated_point
.ToString());
4050 TEST_F(LayerTreeHostImplTest
,
4051 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw
) {
4052 TestScrollOffsetDelegate scroll_delegate
;
4053 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4054 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4055 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4056 clip_layer
->SetBounds(gfx::Size(10, 20));
4057 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4059 // Draw first frame to clear any pending draws and check scroll.
4061 CheckLayerScrollDelta(scroll_layer
, gfx::Vector2dF(0.f
, 0.f
));
4062 EXPECT_FALSE(host_impl_
->active_tree()->needs_update_draw_properties());
4064 // Set external scroll delta on delegate and notify LayerTreeHost.
4065 gfx::ScrollOffset
scroll_offset(10.f
, 10.f
);
4066 scroll_delegate
.set_getter_return_value(scroll_offset
);
4067 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4069 // Check scroll delta reflected in layer.
4070 LayerTreeHostImpl::FrameData frame
;
4071 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4072 host_impl_
->DrawLayers(&frame
);
4073 host_impl_
->DidDrawAllLayers(frame
);
4074 EXPECT_FALSE(frame
.has_no_damage
);
4075 CheckLayerScrollDelta(scroll_layer
, ScrollOffsetToVector2dF(scroll_offset
));
4077 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4080 TEST_F(LayerTreeHostImplTest
, OverscrollRoot
) {
4081 InputHandlerScrollResult scroll_result
;
4082 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4083 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4084 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4086 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4088 // In-bounds scrolling does not affect overscroll.
4089 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4090 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4091 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4092 EXPECT_TRUE(scroll_result
.did_scroll
);
4093 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4094 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4095 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4097 // Overscroll events are reflected immediately.
4098 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4099 EXPECT_TRUE(scroll_result
.did_scroll
);
4100 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4101 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4102 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4103 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4104 host_impl_
->accumulated_root_overscroll());
4106 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4107 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4108 EXPECT_TRUE(scroll_result
.did_scroll
);
4109 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4110 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4111 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4112 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4113 host_impl_
->accumulated_root_overscroll());
4115 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4116 EXPECT_FALSE(scroll_result
.did_scroll
);
4117 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4118 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4119 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4120 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4121 host_impl_
->accumulated_root_overscroll());
4123 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4124 EXPECT_TRUE(scroll_result
.did_scroll
);
4125 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4126 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4127 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4128 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4129 host_impl_
->accumulated_root_overscroll());
4131 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4132 EXPECT_TRUE(scroll_result
.did_scroll
);
4133 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4134 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result
.unused_scroll_delta
);
4135 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_
->accumulated_root_overscroll());
4136 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4137 host_impl_
->accumulated_root_overscroll());
4139 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4140 EXPECT_TRUE(scroll_result
.did_scroll
);
4141 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4142 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4143 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_
->accumulated_root_overscroll());
4144 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4145 host_impl_
->accumulated_root_overscroll());
4147 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4148 EXPECT_TRUE(scroll_result
.did_scroll
);
4149 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4150 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4151 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4152 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4153 host_impl_
->accumulated_root_overscroll());
4155 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4156 // as no scroll occurs.
4157 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4158 EXPECT_FALSE(scroll_result
.did_scroll
);
4159 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4160 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4161 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_
->accumulated_root_overscroll());
4162 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4163 host_impl_
->accumulated_root_overscroll());
4165 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4166 EXPECT_FALSE(scroll_result
.did_scroll
);
4167 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4168 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4169 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_
->accumulated_root_overscroll());
4170 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4171 host_impl_
->accumulated_root_overscroll());
4173 // Overscroll resets on valid scroll.
4174 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4175 EXPECT_TRUE(scroll_result
.did_scroll
);
4176 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4177 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4178 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4179 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4180 host_impl_
->accumulated_root_overscroll());
4182 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4183 EXPECT_TRUE(scroll_result
.did_scroll
);
4184 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4185 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4186 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4187 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4188 host_impl_
->accumulated_root_overscroll());
4190 host_impl_
->ScrollEnd();
4194 TEST_F(LayerTreeHostImplTest
, OverscrollChildWithoutBubbling
) {
4195 // Scroll child layers beyond their maximum scroll range and make sure root
4196 // overscroll does not accumulate.
4197 gfx::Size
surface_size(10, 10);
4198 scoped_ptr
<LayerImpl
> root_clip
=
4199 LayerImpl::Create(host_impl_
->active_tree(), 4);
4200 root_clip
->SetHasRenderSurface(true);
4202 scoped_ptr
<LayerImpl
> root
=
4203 CreateScrollableLayer(1, surface_size
, root_clip
.get());
4205 scoped_ptr
<LayerImpl
> grand_child
=
4206 CreateScrollableLayer(3, surface_size
, root_clip
.get());
4208 scoped_ptr
<LayerImpl
> child
=
4209 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4210 LayerImpl
* grand_child_layer
= grand_child
.get();
4211 child
->AddChild(grand_child
.Pass());
4213 LayerImpl
* child_layer
= child
.get();
4214 root
->AddChild(child
.Pass());
4215 root_clip
->AddChild(root
.Pass());
4216 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4217 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4218 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4219 host_impl_
->active_tree()->DidBecomeActive();
4220 host_impl_
->SetViewportSize(surface_size
);
4223 gfx::Vector2d
scroll_delta(0, -10);
4224 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4225 host_impl_
->ScrollBegin(gfx::Point(),
4226 InputHandler::NON_BUBBLING_GESTURE
));
4227 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4228 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4229 host_impl_
->ScrollEnd();
4231 // The next time we scroll we should only scroll the parent, but overscroll
4232 // should still not reach the root layer.
4233 scroll_delta
= gfx::Vector2d(0, -30);
4234 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4235 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4236 InputHandler::NON_BUBBLING_GESTURE
));
4237 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4238 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4239 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4240 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_layer
);
4241 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4242 host_impl_
->ScrollEnd();
4244 // After scrolling the parent, another scroll on the opposite direction
4245 // should scroll the child.
4246 scroll_delta
= gfx::Vector2d(0, 70);
4247 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4248 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4249 InputHandler::NON_BUBBLING_GESTURE
));
4250 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4251 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4252 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4253 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4254 host_impl_
->ScrollEnd();
4258 TEST_F(LayerTreeHostImplTest
, OverscrollChildEventBubbling
) {
4259 // When we try to scroll a non-scrollable child layer, the scroll delta
4260 // should be applied to one of its ancestors if possible. Overscroll should
4261 // be reflected only when it has bubbled up to the root scrolling layer.
4262 gfx::Size
surface_size(10, 10);
4263 gfx::Size
content_size(20, 20);
4264 scoped_ptr
<LayerImpl
> root_clip
=
4265 LayerImpl::Create(host_impl_
->active_tree(), 3);
4266 root_clip
->SetHasRenderSurface(true);
4268 scoped_ptr
<LayerImpl
> root
=
4269 CreateScrollableLayer(1, content_size
, root_clip
.get());
4270 root
->SetIsContainerForFixedPositionLayers(true);
4271 scoped_ptr
<LayerImpl
> child
=
4272 CreateScrollableLayer(2, content_size
, root_clip
.get());
4274 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4275 root
->AddChild(child
.Pass());
4276 root_clip
->AddChild(root
.Pass());
4278 host_impl_
->SetViewportSize(surface_size
);
4279 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4280 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4282 host_impl_
->active_tree()->DidBecomeActive();
4285 gfx::Vector2d
scroll_delta(0, 8);
4286 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4287 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4288 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4289 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4290 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4291 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_
->accumulated_root_overscroll());
4292 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4293 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_
->accumulated_root_overscroll());
4294 host_impl_
->ScrollEnd();
4298 TEST_F(LayerTreeHostImplTest
, OverscrollAlways
) {
4299 LayerTreeSettings settings
;
4300 CreateHostImpl(settings
, CreateOutputSurface());
4302 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(50, 50));
4303 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4304 clip_layer
->SetBounds(gfx::Size(50, 50));
4305 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4306 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4308 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4310 // Even though the layer can't scroll the overscroll still happens.
4311 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4312 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4313 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4314 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4317 TEST_F(LayerTreeHostImplTest
, NoOverscrollOnFractionalDeviceScale
) {
4318 gfx::Size
surface_size(980, 1439);
4319 gfx::Size
content_size(980, 1438);
4320 float device_scale_factor
= 1.5f
;
4321 scoped_ptr
<LayerImpl
> root_clip
=
4322 LayerImpl::Create(host_impl_
->active_tree(), 3);
4323 root_clip
->SetHasRenderSurface(true);
4325 scoped_ptr
<LayerImpl
> root
=
4326 CreateScrollableLayer(1, content_size
, root_clip
.get());
4327 root
->SetIsContainerForFixedPositionLayers(true);
4328 scoped_ptr
<LayerImpl
> child
=
4329 CreateScrollableLayer(2, content_size
, root_clip
.get());
4330 root
->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
4331 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.326531f
, 0.326531f
,
4333 host_impl_
->SetPageScaleOnActiveTree(0.326531f
);
4334 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4335 root
->AddChild(child
.Pass());
4336 root_clip
->AddChild(root
.Pass());
4338 host_impl_
->SetViewportSize(surface_size
);
4339 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4340 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4341 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4343 host_impl_
->active_tree()->DidBecomeActive();
4346 // Horizontal & Vertical GlowEffect should not be applied when
4347 // content size is less then view port size. For Example Horizontal &
4348 // vertical GlowEffect should not be applied in about:blank page.
4349 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4350 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4351 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
4352 EXPECT_EQ(gfx::Vector2dF().ToString(),
4353 host_impl_
->accumulated_root_overscroll().ToString());
4355 host_impl_
->ScrollEnd();
4359 TEST_F(LayerTreeHostImplTest
, NoOverscrollWhenNotAtEdge
) {
4360 gfx::Size
surface_size(100, 100);
4361 gfx::Size
content_size(200, 200);
4362 scoped_ptr
<LayerImpl
> root_clip
=
4363 LayerImpl::Create(host_impl_
->active_tree(), 3);
4364 root_clip
->SetHasRenderSurface(true);
4366 scoped_ptr
<LayerImpl
> root
=
4367 CreateScrollableLayer(1, content_size
, root_clip
.get());
4368 root
->SetIsContainerForFixedPositionLayers(true);
4369 scoped_ptr
<LayerImpl
> child
=
4370 CreateScrollableLayer(2, content_size
, root_clip
.get());
4372 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4373 root
->AddChild(child
.Pass());
4374 root_clip
->AddChild(root
.Pass());
4376 host_impl_
->SetViewportSize(surface_size
);
4377 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4378 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4380 host_impl_
->active_tree()->DidBecomeActive();
4383 // Edge glow effect should be applicable only upon reaching Edges
4384 // of the content. unnecessary glow effect calls shouldn't be
4385 // called while scrolling up without reaching the edge of the content.
4386 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4387 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4388 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4389 EXPECT_EQ(gfx::Vector2dF().ToString(),
4390 host_impl_
->accumulated_root_overscroll().ToString());
4391 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f
));
4392 EXPECT_EQ(gfx::Vector2dF().ToString(),
4393 host_impl_
->accumulated_root_overscroll().ToString());
4394 host_impl_
->ScrollEnd();
4395 // unusedrootDelta should be subtracted from applied delta so that
4396 // unwanted glow effect calls are not called.
4397 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4398 host_impl_
->ScrollBegin(gfx::Point(0, 0),
4399 InputHandler::NON_BUBBLING_GESTURE
));
4400 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
4401 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4402 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4403 host_impl_
->accumulated_root_overscroll().ToString());
4405 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f
, -0.01f
));
4406 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4407 host_impl_
->accumulated_root_overscroll().ToString());
4408 host_impl_
->ScrollEnd();
4409 // TestCase to check kEpsilon, which prevents minute values to trigger
4410 // gloweffect without reaching edge.
4411 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4412 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4413 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f
, 0.1f
));
4414 EXPECT_EQ(gfx::Vector2dF().ToString(),
4415 host_impl_
->accumulated_root_overscroll().ToString());
4416 host_impl_
->ScrollEnd();
4420 class BlendStateCheckLayer
: public LayerImpl
{
4422 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
4424 ResourceProvider
* resource_provider
) {
4425 return make_scoped_ptr(
4426 new BlendStateCheckLayer(tree_impl
, id
, resource_provider
));
4429 void AppendQuads(RenderPass
* render_pass
,
4430 AppendQuadsData
* append_quads_data
) override
{
4431 quads_appended_
= true;
4433 gfx::Rect opaque_rect
;
4434 if (contents_opaque())
4435 opaque_rect
= quad_rect_
;
4437 opaque_rect
= opaque_content_rect_
;
4438 gfx::Rect visible_quad_rect
= quad_rect_
;
4440 SharedQuadState
* shared_quad_state
=
4441 render_pass
->CreateAndAppendSharedQuadState();
4442 PopulateSharedQuadState(shared_quad_state
);
4444 TileDrawQuad
* test_blending_draw_quad
=
4445 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
4446 test_blending_draw_quad
->SetNew(shared_quad_state
,
4451 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
4455 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
4456 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
4457 EXPECT_EQ(has_render_surface_
, !!render_surface());
4460 void SetExpectation(bool blend
, bool has_render_surface
) {
4462 has_render_surface_
= has_render_surface
;
4463 quads_appended_
= false;
4466 bool quads_appended() const { return quads_appended_
; }
4468 void SetQuadRect(const gfx::Rect
& rect
) { quad_rect_
= rect
; }
4469 void SetQuadVisibleRect(const gfx::Rect
& rect
) { quad_visible_rect_
= rect
; }
4470 void SetOpaqueContentRect(const gfx::Rect
& rect
) {
4471 opaque_content_rect_
= rect
;
4475 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
4477 ResourceProvider
* resource_provider
)
4478 : LayerImpl(tree_impl
, id
),
4480 has_render_surface_(false),
4481 quads_appended_(false),
4482 quad_rect_(5, 5, 5, 5),
4483 quad_visible_rect_(5, 5, 5, 5),
4484 resource_id_(resource_provider
->CreateResource(
4487 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
4489 resource_provider
->AllocateForTesting(resource_id_
);
4490 SetBounds(gfx::Size(10, 10));
4491 SetContentBounds(gfx::Size(10, 10));
4492 SetDrawsContent(true);
4496 bool has_render_surface_
;
4497 bool quads_appended_
;
4498 gfx::Rect quad_rect_
;
4499 gfx::Rect opaque_content_rect_
;
4500 gfx::Rect quad_visible_rect_
;
4501 ResourceProvider::ResourceId resource_id_
;
4504 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
4506 scoped_ptr
<LayerImpl
> root
=
4507 LayerImpl::Create(host_impl_
->active_tree(), 1);
4508 root
->SetBounds(gfx::Size(10, 10));
4509 root
->SetContentBounds(root
->bounds());
4510 root
->SetDrawsContent(false);
4511 root
->SetHasRenderSurface(true);
4512 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4514 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
4517 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4519 host_impl_
->resource_provider()));
4520 BlendStateCheckLayer
* layer1
=
4521 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
4522 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
4524 LayerTreeHostImpl::FrameData frame
;
4526 // Opaque layer, drawn without blending.
4527 layer1
->SetContentsOpaque(true);
4528 layer1
->SetExpectation(false, false);
4529 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4530 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4531 host_impl_
->DrawLayers(&frame
);
4532 EXPECT_TRUE(layer1
->quads_appended());
4533 host_impl_
->DidDrawAllLayers(frame
);
4535 // Layer with translucent content and painting, so drawn with blending.
4536 layer1
->SetContentsOpaque(false);
4537 layer1
->SetExpectation(true, false);
4538 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4539 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4540 host_impl_
->DrawLayers(&frame
);
4541 EXPECT_TRUE(layer1
->quads_appended());
4542 host_impl_
->DidDrawAllLayers(frame
);
4544 // Layer with translucent opacity, drawn with blending.
4545 layer1
->SetContentsOpaque(true);
4546 layer1
->SetOpacity(0.5f
);
4547 layer1
->SetExpectation(true, false);
4548 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4549 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4550 host_impl_
->DrawLayers(&frame
);
4551 EXPECT_TRUE(layer1
->quads_appended());
4552 host_impl_
->DidDrawAllLayers(frame
);
4554 // Layer with translucent opacity and painting, drawn with blending.
4555 layer1
->SetContentsOpaque(true);
4556 layer1
->SetOpacity(0.5f
);
4557 layer1
->SetExpectation(true, false);
4558 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4559 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4560 host_impl_
->DrawLayers(&frame
);
4561 EXPECT_TRUE(layer1
->quads_appended());
4562 host_impl_
->DidDrawAllLayers(frame
);
4565 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4567 host_impl_
->resource_provider()));
4568 BlendStateCheckLayer
* layer2
=
4569 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
4570 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
4572 // 2 opaque layers, drawn without blending.
4573 layer1
->SetContentsOpaque(true);
4574 layer1
->SetOpacity(1.f
);
4575 layer1
->SetExpectation(false, false);
4576 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4577 layer2
->SetContentsOpaque(true);
4578 layer2
->SetOpacity(1.f
);
4579 layer2
->SetExpectation(false, false);
4580 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4581 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4582 host_impl_
->DrawLayers(&frame
);
4583 EXPECT_TRUE(layer1
->quads_appended());
4584 EXPECT_TRUE(layer2
->quads_appended());
4585 host_impl_
->DidDrawAllLayers(frame
);
4587 // Parent layer with translucent content, drawn with blending.
4588 // Child layer with opaque content, drawn without blending.
4589 layer1
->SetContentsOpaque(false);
4590 layer1
->SetExpectation(true, false);
4591 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4592 layer2
->SetExpectation(false, false);
4593 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4594 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4595 host_impl_
->DrawLayers(&frame
);
4596 EXPECT_TRUE(layer1
->quads_appended());
4597 EXPECT_TRUE(layer2
->quads_appended());
4598 host_impl_
->DidDrawAllLayers(frame
);
4600 // Parent layer with translucent content but opaque painting, drawn without
4602 // Child layer with opaque content, drawn without blending.
4603 layer1
->SetContentsOpaque(true);
4604 layer1
->SetExpectation(false, false);
4605 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4606 layer2
->SetExpectation(false, false);
4607 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4608 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4609 host_impl_
->DrawLayers(&frame
);
4610 EXPECT_TRUE(layer1
->quads_appended());
4611 EXPECT_TRUE(layer2
->quads_appended());
4612 host_impl_
->DidDrawAllLayers(frame
);
4614 // Parent layer with translucent opacity and opaque content. Since it has a
4615 // drawing child, it's drawn to a render surface which carries the opacity,
4616 // so it's itself drawn without blending.
4617 // Child layer with opaque content, drawn without blending (parent surface
4618 // carries the inherited opacity).
4619 layer1
->SetContentsOpaque(true);
4620 layer1
->SetOpacity(0.5f
);
4621 layer1
->SetHasRenderSurface(true);
4622 layer1
->SetExpectation(false, true);
4623 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4624 layer2
->SetExpectation(false, false);
4625 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4626 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
4627 host_impl_
->active_tree()->root_layer());
4628 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4629 host_impl_
->DrawLayers(&frame
);
4630 EXPECT_TRUE(layer1
->quads_appended());
4631 EXPECT_TRUE(layer2
->quads_appended());
4632 host_impl_
->DidDrawAllLayers(frame
);
4633 layer1
->SetHasRenderSurface(false);
4635 // Draw again, but with child non-opaque, to make sure
4636 // layer1 not culled.
4637 layer1
->SetContentsOpaque(true);
4638 layer1
->SetOpacity(1.f
);
4639 layer1
->SetExpectation(false, false);
4640 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4641 layer2
->SetContentsOpaque(true);
4642 layer2
->SetOpacity(0.5f
);
4643 layer2
->SetExpectation(true, false);
4644 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4645 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4646 host_impl_
->DrawLayers(&frame
);
4647 EXPECT_TRUE(layer1
->quads_appended());
4648 EXPECT_TRUE(layer2
->quads_appended());
4649 host_impl_
->DidDrawAllLayers(frame
);
4651 // A second way of making the child non-opaque.
4652 layer1
->SetContentsOpaque(true);
4653 layer1
->SetOpacity(1.f
);
4654 layer1
->SetExpectation(false, false);
4655 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4656 layer2
->SetContentsOpaque(false);
4657 layer2
->SetOpacity(1.f
);
4658 layer2
->SetExpectation(true, false);
4659 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4660 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4661 host_impl_
->DrawLayers(&frame
);
4662 EXPECT_TRUE(layer1
->quads_appended());
4663 EXPECT_TRUE(layer2
->quads_appended());
4664 host_impl_
->DidDrawAllLayers(frame
);
4666 // And when the layer says its not opaque but is painted opaque, it is not
4668 layer1
->SetContentsOpaque(true);
4669 layer1
->SetOpacity(1.f
);
4670 layer1
->SetExpectation(false, false);
4671 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4672 layer2
->SetContentsOpaque(true);
4673 layer2
->SetOpacity(1.f
);
4674 layer2
->SetExpectation(false, false);
4675 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4676 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4677 host_impl_
->DrawLayers(&frame
);
4678 EXPECT_TRUE(layer1
->quads_appended());
4679 EXPECT_TRUE(layer2
->quads_appended());
4680 host_impl_
->DidDrawAllLayers(frame
);
4682 // Layer with partially opaque contents, drawn with blending.
4683 layer1
->SetContentsOpaque(false);
4684 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4685 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
4686 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4687 layer1
->SetExpectation(true, false);
4688 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4689 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4690 host_impl_
->DrawLayers(&frame
);
4691 EXPECT_TRUE(layer1
->quads_appended());
4692 host_impl_
->DidDrawAllLayers(frame
);
4694 // Layer with partially opaque contents partially culled, drawn with blending.
4695 layer1
->SetContentsOpaque(false);
4696 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4697 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
4698 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4699 layer1
->SetExpectation(true, false);
4700 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4701 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4702 host_impl_
->DrawLayers(&frame
);
4703 EXPECT_TRUE(layer1
->quads_appended());
4704 host_impl_
->DidDrawAllLayers(frame
);
4706 // Layer with partially opaque contents culled, drawn with blending.
4707 layer1
->SetContentsOpaque(false);
4708 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4709 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
4710 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4711 layer1
->SetExpectation(true, false);
4712 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4713 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4714 host_impl_
->DrawLayers(&frame
);
4715 EXPECT_TRUE(layer1
->quads_appended());
4716 host_impl_
->DidDrawAllLayers(frame
);
4718 // Layer with partially opaque contents and translucent contents culled, drawn
4719 // without blending.
4720 layer1
->SetContentsOpaque(false);
4721 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4722 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
4723 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4724 layer1
->SetExpectation(false, false);
4725 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4726 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4727 host_impl_
->DrawLayers(&frame
);
4728 EXPECT_TRUE(layer1
->quads_appended());
4729 host_impl_
->DidDrawAllLayers(frame
);
4732 class LayerTreeHostImplViewportCoveredTest
: public LayerTreeHostImplTest
{
4734 LayerTreeHostImplViewportCoveredTest() :
4735 gutter_quad_material_(DrawQuad::SOLID_COLOR
),
4737 did_activate_pending_tree_(false) {}
4739 scoped_ptr
<OutputSurface
> CreateFakeOutputSurface(bool always_draw
) {
4741 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
4743 return FakeOutputSurface::Create3d();
4746 void SetupActiveTreeLayers() {
4747 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
4748 host_impl_
->active_tree()->SetRootLayer(
4749 LayerImpl::Create(host_impl_
->active_tree(), 1));
4750 host_impl_
->active_tree()->root_layer()->SetHasRenderSurface(true);
4751 host_impl_
->active_tree()->root_layer()->AddChild(
4752 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4754 host_impl_
->resource_provider()));
4755 child_
= static_cast<BlendStateCheckLayer
*>(
4756 host_impl_
->active_tree()->root_layer()->children()[0]);
4757 child_
->SetExpectation(false, false);
4758 child_
->SetContentsOpaque(true);
4761 // Expect no gutter rects.
4762 void TestLayerCoversFullViewport() {
4763 gfx::Rect
layer_rect(viewport_size_
);
4764 child_
->SetPosition(layer_rect
.origin());
4765 child_
->SetBounds(layer_rect
.size());
4766 child_
->SetContentBounds(layer_rect
.size());
4767 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4768 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4770 LayerTreeHostImpl::FrameData frame
;
4771 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4772 ASSERT_EQ(1u, frame
.render_passes
.size());
4774 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4775 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4776 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4778 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4779 host_impl_
->DidDrawAllLayers(frame
);
4782 // Expect fullscreen gutter rect.
4783 void TestEmptyLayer() {
4784 gfx::Rect
layer_rect(0, 0, 0, 0);
4785 child_
->SetPosition(layer_rect
.origin());
4786 child_
->SetBounds(layer_rect
.size());
4787 child_
->SetContentBounds(layer_rect
.size());
4788 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4789 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4791 LayerTreeHostImpl::FrameData frame
;
4792 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4793 ASSERT_EQ(1u, frame
.render_passes
.size());
4795 EXPECT_EQ(1u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4796 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4797 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4799 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4800 host_impl_
->DidDrawAllLayers(frame
);
4803 // Expect four surrounding gutter rects.
4804 void TestLayerInMiddleOfViewport() {
4805 gfx::Rect
layer_rect(500, 500, 200, 200);
4806 child_
->SetPosition(layer_rect
.origin());
4807 child_
->SetBounds(layer_rect
.size());
4808 child_
->SetContentBounds(layer_rect
.size());
4809 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4810 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4812 LayerTreeHostImpl::FrameData frame
;
4813 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4814 ASSERT_EQ(1u, frame
.render_passes
.size());
4816 EXPECT_EQ(4u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4817 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
4818 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4820 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4821 host_impl_
->DidDrawAllLayers(frame
);
4824 // Expect no gutter rects.
4825 void TestLayerIsLargerThanViewport() {
4826 gfx::Rect
layer_rect(viewport_size_
.width() + 10,
4827 viewport_size_
.height() + 10);
4828 child_
->SetPosition(layer_rect
.origin());
4829 child_
->SetBounds(layer_rect
.size());
4830 child_
->SetContentBounds(layer_rect
.size());
4831 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4832 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4834 LayerTreeHostImpl::FrameData frame
;
4835 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4836 ASSERT_EQ(1u, frame
.render_passes
.size());
4838 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4839 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4840 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4842 host_impl_
->DidDrawAllLayers(frame
);
4845 void DidActivateSyncTree() override
{ did_activate_pending_tree_
= true; }
4847 void set_gutter_quad_material(DrawQuad::Material material
) {
4848 gutter_quad_material_
= material
;
4850 void set_gutter_texture_size(const gfx::Size
& gutter_texture_size
) {
4851 gutter_texture_size_
= gutter_texture_size
;
4855 size_t CountGutterQuads(const QuadList
& quad_list
) {
4856 size_t num_gutter_quads
= 0;
4857 for (const auto& quad
: quad_list
) {
4858 num_gutter_quads
+= (quad
->material
== gutter_quad_material_
) ? 1 : 0;
4860 return num_gutter_quads
;
4863 void VerifyQuadsExactlyCoverViewport(const QuadList
& quad_list
) {
4864 LayerTestCommon::VerifyQuadsExactlyCoverRect(
4865 quad_list
, gfx::Rect(DipSizeToPixelSize(viewport_size_
)));
4868 // Make sure that the texture coordinates match their expectations.
4869 void ValidateTextureDrawQuads(const QuadList
& quad_list
) {
4870 for (const auto& quad
: quad_list
) {
4871 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
)
4873 const TextureDrawQuad
* texture_quad
= TextureDrawQuad::MaterialCast(quad
);
4874 gfx::SizeF gutter_texture_size_pixels
= gfx::ScaleSize(
4875 gutter_texture_size_
, host_impl_
->device_scale_factor());
4876 EXPECT_EQ(texture_quad
->uv_top_left
.x(),
4877 texture_quad
->rect
.x() / gutter_texture_size_pixels
.width());
4878 EXPECT_EQ(texture_quad
->uv_top_left
.y(),
4879 texture_quad
->rect
.y() / gutter_texture_size_pixels
.height());
4881 texture_quad
->uv_bottom_right
.x(),
4882 texture_quad
->rect
.right() / gutter_texture_size_pixels
.width());
4884 texture_quad
->uv_bottom_right
.y(),
4885 texture_quad
->rect
.bottom() / gutter_texture_size_pixels
.height());
4889 gfx::Size
DipSizeToPixelSize(const gfx::Size
& size
) {
4890 return gfx::ToRoundedSize(
4891 gfx::ScaleSize(size
, host_impl_
->device_scale_factor()));
4894 DrawQuad::Material gutter_quad_material_
;
4895 gfx::Size gutter_texture_size_
;
4896 gfx::Size viewport_size_
;
4897 BlendStateCheckLayer
* child_
;
4898 bool did_activate_pending_tree_
;
4901 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCovered
) {
4902 viewport_size_
= gfx::Size(1000, 1000);
4904 bool always_draw
= false;
4905 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4907 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4908 SetupActiveTreeLayers();
4909 TestLayerCoversFullViewport();
4911 TestLayerInMiddleOfViewport();
4912 TestLayerIsLargerThanViewport();
4915 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredScaled
) {
4916 viewport_size_
= gfx::Size(1000, 1000);
4918 bool always_draw
= false;
4919 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4921 host_impl_
->SetDeviceScaleFactor(2.f
);
4922 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4923 SetupActiveTreeLayers();
4924 TestLayerCoversFullViewport();
4926 TestLayerInMiddleOfViewport();
4927 TestLayerIsLargerThanViewport();
4930 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeGrowViewportInvalid
) {
4931 viewport_size_
= gfx::Size(1000, 1000);
4933 bool always_draw
= true;
4934 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4936 // Pending tree to force active_tree size invalid. Not used otherwise.
4937 host_impl_
->CreatePendingTree();
4938 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4939 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
4941 SetupActiveTreeLayers();
4943 TestLayerInMiddleOfViewport();
4944 TestLayerIsLargerThanViewport();
4947 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeShrinkViewportInvalid
) {
4948 viewport_size_
= gfx::Size(1000, 1000);
4950 bool always_draw
= true;
4951 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4953 // Set larger viewport and activate it to active tree.
4954 host_impl_
->CreatePendingTree();
4955 gfx::Size
larger_viewport(viewport_size_
.width() + 100,
4956 viewport_size_
.height() + 100);
4957 host_impl_
->SetViewportSize(DipSizeToPixelSize(larger_viewport
));
4958 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
4959 host_impl_
->ActivateSyncTree();
4960 EXPECT_TRUE(did_activate_pending_tree_
);
4961 EXPECT_FALSE(host_impl_
->active_tree()->ViewportSizeInvalid());
4963 // Shrink pending tree viewport without activating.
4964 host_impl_
->CreatePendingTree();
4965 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4966 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
4968 SetupActiveTreeLayers();
4970 TestLayerInMiddleOfViewport();
4971 TestLayerIsLargerThanViewport();
4974 class FakeDrawableLayerImpl
: public LayerImpl
{
4976 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
4977 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl
, id
));
4980 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
4981 : LayerImpl(tree_impl
, id
) {}
4984 // Only reshape when we know we are going to draw. Otherwise, the reshape
4985 // can leave the window at the wrong size if we never draw and the proper
4986 // viewport size is never set.
4987 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
4988 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
4989 scoped_ptr
<OutputSurface
> output_surface(
4990 FakeOutputSurface::Create3d(provider
));
4991 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
4993 scoped_ptr
<LayerImpl
> root
=
4994 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
4995 root
->SetBounds(gfx::Size(10, 10));
4996 root
->SetContentBounds(gfx::Size(10, 10));
4997 root
->SetDrawsContent(true);
4998 root
->SetHasRenderSurface(true);
4999 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5000 EXPECT_FALSE(provider
->TestContext3d()->reshape_called());
5001 provider
->TestContext3d()->clear_reshape_called();
5003 LayerTreeHostImpl::FrameData frame
;
5004 host_impl_
->SetViewportSize(gfx::Size(10, 10));
5005 host_impl_
->SetDeviceScaleFactor(1.f
);
5006 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5007 host_impl_
->DrawLayers(&frame
);
5008 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5009 EXPECT_EQ(provider
->TestContext3d()->width(), 10);
5010 EXPECT_EQ(provider
->TestContext3d()->height(), 10);
5011 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5012 host_impl_
->DidDrawAllLayers(frame
);
5013 provider
->TestContext3d()->clear_reshape_called();
5015 host_impl_
->SetViewportSize(gfx::Size(20, 30));
5016 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5017 host_impl_
->DrawLayers(&frame
);
5018 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5019 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5020 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5021 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5022 host_impl_
->DidDrawAllLayers(frame
);
5023 provider
->TestContext3d()->clear_reshape_called();
5025 host_impl_
->SetDeviceScaleFactor(2.f
);
5026 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5027 host_impl_
->DrawLayers(&frame
);
5028 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5029 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5030 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5031 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 2.f
);
5032 host_impl_
->DidDrawAllLayers(frame
);
5033 provider
->TestContext3d()->clear_reshape_called();
5036 // Make sure damage tracking propagates all the way to the graphics context,
5037 // where it should request to swap only the sub-buffer that is damaged.
5038 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
5039 scoped_refptr
<TestContextProvider
> context_provider(
5040 TestContextProvider::Create());
5041 context_provider
->BindToCurrentThread();
5042 context_provider
->TestContext3d()->set_have_post_sub_buffer(true);
5044 scoped_ptr
<FakeOutputSurface
> output_surface(
5045 FakeOutputSurface::Create3d(context_provider
));
5046 FakeOutputSurface
* fake_output_surface
= output_surface
.get();
5048 // This test creates its own LayerTreeHostImpl, so
5049 // that we can force partial swap enabled.
5050 LayerTreeSettings settings
;
5051 settings
.renderer_settings
.partial_swap_enabled
= true;
5052 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
5053 LayerTreeHostImpl::Create(
5054 settings
, this, &proxy_
, &stats_instrumentation_
,
5055 shared_bitmap_manager_
.get(), NULL
, task_graph_runner_
.get(), 0);
5056 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
5057 layer_tree_host_impl
->WillBeginImplFrame(
5058 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5059 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
5061 scoped_ptr
<LayerImpl
> root
=
5062 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
5063 root
->SetHasRenderSurface(true);
5064 scoped_ptr
<LayerImpl
> child
=
5065 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
5066 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
5067 child
->SetBounds(gfx::Size(14, 15));
5068 child
->SetContentBounds(gfx::Size(14, 15));
5069 child
->SetDrawsContent(true);
5070 root
->SetBounds(gfx::Size(500, 500));
5071 root
->SetContentBounds(gfx::Size(500, 500));
5072 root
->SetDrawsContent(true);
5073 root
->AddChild(child
.Pass());
5074 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5076 LayerTreeHostImpl::FrameData frame
;
5078 // First frame, the entire screen should get swapped.
5079 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5080 layer_tree_host_impl
->DrawLayers(&frame
);
5081 layer_tree_host_impl
->DidDrawAllLayers(frame
);
5082 layer_tree_host_impl
->SwapBuffers(frame
);
5083 gfx::Rect
expected_swap_rect(0, 0, 500, 500);
5084 EXPECT_EQ(expected_swap_rect
.ToString(),
5085 fake_output_surface
->last_swap_rect().ToString());
5087 // Second frame, only the damaged area should get swapped. Damage should be
5088 // the union of old and new child rects.
5089 // expected damage rect: gfx::Rect(26, 28);
5090 // expected swap rect: vertically flipped, with origin at bottom left corner.
5091 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
5093 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5094 layer_tree_host_impl
->DrawLayers(&frame
);
5095 host_impl_
->DidDrawAllLayers(frame
);
5096 layer_tree_host_impl
->SwapBuffers(frame
);
5098 // Make sure that partial swap is constrained to the viewport dimensions
5099 // expected damage rect: gfx::Rect(500, 500);
5100 // expected swap rect: flipped damage rect, but also clamped to viewport
5101 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
5102 EXPECT_EQ(expected_swap_rect
.ToString(),
5103 fake_output_surface
->last_swap_rect().ToString());
5105 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
5106 // This will damage everything.
5107 layer_tree_host_impl
->active_tree()->root_layer()->SetBackgroundColor(
5109 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5110 layer_tree_host_impl
->DrawLayers(&frame
);
5111 host_impl_
->DidDrawAllLayers(frame
);
5112 layer_tree_host_impl
->SwapBuffers(frame
);
5114 expected_swap_rect
= gfx::Rect(0, 0, 10, 10);
5115 EXPECT_EQ(expected_swap_rect
.ToString(),
5116 fake_output_surface
->last_swap_rect().ToString());
5119 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
5120 scoped_ptr
<LayerImpl
> root
=
5121 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5122 scoped_ptr
<LayerImpl
> child
=
5123 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
5124 child
->SetBounds(gfx::Size(10, 10));
5125 child
->SetContentBounds(gfx::Size(10, 10));
5126 child
->SetDrawsContent(true);
5127 root
->SetBounds(gfx::Size(10, 10));
5128 root
->SetContentBounds(gfx::Size(10, 10));
5129 root
->SetDrawsContent(true);
5130 root
->SetHasRenderSurface(true);
5131 root
->AddChild(child
.Pass());
5133 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5135 LayerTreeHostImpl::FrameData frame
;
5137 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5138 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
5139 EXPECT_EQ(1u, frame
.render_passes
.size());
5140 host_impl_
->DidDrawAllLayers(frame
);
5143 class FakeLayerWithQuads
: public LayerImpl
{
5145 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5146 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl
, id
));
5149 void AppendQuads(RenderPass
* render_pass
,
5150 AppendQuadsData
* append_quads_data
) override
{
5151 SharedQuadState
* shared_quad_state
=
5152 render_pass
->CreateAndAppendSharedQuadState();
5153 PopulateSharedQuadState(shared_quad_state
);
5155 SkColor gray
= SkColorSetRGB(100, 100, 100);
5156 gfx::Rect
quad_rect(content_bounds());
5157 gfx::Rect
visible_quad_rect(quad_rect
);
5158 SolidColorDrawQuad
* my_quad
=
5159 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
5161 shared_quad_state
, quad_rect
, visible_quad_rect
, gray
, false);
5165 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
5166 : LayerImpl(tree_impl
, id
) {}
5169 class MockContext
: public TestWebGraphicsContext3D
{
5171 MOCK_METHOD1(useProgram
, void(GLuint program
));
5172 MOCK_METHOD5(uniform4f
, void(GLint location
,
5177 MOCK_METHOD4(uniformMatrix4fv
, void(GLint location
,
5179 GLboolean transpose
,
5180 const GLfloat
* value
));
5181 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5185 MOCK_METHOD1(enable
, void(GLenum cap
));
5186 MOCK_METHOD1(disable
, void(GLenum cap
));
5187 MOCK_METHOD4(scissor
, void(GLint x
,
5193 class MockContextHarness
{
5195 MockContext
* context_
;
5198 explicit MockContextHarness(MockContext
* context
)
5199 : context_(context
) {
5200 context_
->set_have_post_sub_buffer(true);
5202 // Catch "uninteresting" calls
5203 EXPECT_CALL(*context_
, useProgram(_
))
5206 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
5209 // These are not asserted
5210 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
5211 .WillRepeatedly(Return());
5213 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
5214 .WillRepeatedly(Return());
5216 // Any un-sanctioned calls to enable() are OK
5217 EXPECT_CALL(*context_
, enable(_
))
5218 .WillRepeatedly(Return());
5220 // Any un-sanctioned calls to disable() are OK
5221 EXPECT_CALL(*context_
, disable(_
))
5222 .WillRepeatedly(Return());
5225 void MustDrawSolidQuad() {
5226 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
5228 .RetiresOnSaturation();
5230 EXPECT_CALL(*context_
, useProgram(_
))
5232 .RetiresOnSaturation();
5235 void MustSetScissor(int x
, int y
, int width
, int height
) {
5236 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5237 .WillRepeatedly(Return());
5239 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
5241 .WillRepeatedly(Return());
5244 void MustSetNoScissor() {
5245 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
5246 .WillRepeatedly(Return());
5248 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5251 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
5256 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
5257 scoped_ptr
<MockContext
> mock_context_owned(new MockContext
);
5258 MockContext
* mock_context
= mock_context_owned
.get();
5259 MockContextHarness
harness(mock_context
);
5262 LayerTreeSettings settings
= DefaultSettings();
5263 settings
.renderer_settings
.partial_swap_enabled
= false;
5264 CreateHostImpl(settings
,
5265 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5266 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5268 // Without partial swap, and no clipping, no scissor is set.
5269 harness
.MustDrawSolidQuad();
5270 harness
.MustSetNoScissor();
5272 LayerTreeHostImpl::FrameData frame
;
5273 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5274 host_impl_
->DrawLayers(&frame
);
5275 host_impl_
->DidDrawAllLayers(frame
);
5277 Mock::VerifyAndClearExpectations(&mock_context
);
5279 // Without partial swap, but a layer does clip its subtree, one scissor is
5281 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
5282 harness
.MustDrawSolidQuad();
5283 harness
.MustSetScissor(0, 0, 10, 10);
5285 LayerTreeHostImpl::FrameData frame
;
5286 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5287 host_impl_
->DrawLayers(&frame
);
5288 host_impl_
->DidDrawAllLayers(frame
);
5290 Mock::VerifyAndClearExpectations(&mock_context
);
5293 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
5294 scoped_ptr
<MockContext
> context_owned(new MockContext
);
5295 MockContext
* mock_context
= context_owned
.get();
5296 MockContextHarness
harness(mock_context
);
5298 LayerTreeSettings settings
= DefaultSettings();
5299 settings
.renderer_settings
.partial_swap_enabled
= true;
5300 CreateHostImpl(settings
, FakeOutputSurface::Create3d(context_owned
.Pass()));
5301 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5303 // The first frame is not a partially-swapped one. No scissor should be set.
5304 harness
.MustSetNoScissor();
5305 harness
.MustDrawSolidQuad();
5307 LayerTreeHostImpl::FrameData frame
;
5308 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5309 host_impl_
->DrawLayers(&frame
);
5310 host_impl_
->DidDrawAllLayers(frame
);
5312 Mock::VerifyAndClearExpectations(&mock_context
);
5314 // Damage a portion of the frame.
5315 host_impl_
->active_tree()->root_layer()->SetUpdateRect(
5316 gfx::Rect(0, 0, 2, 3));
5318 // The second frame will be partially-swapped (the y coordinates are flipped).
5319 harness
.MustSetScissor(0, 7, 2, 3);
5320 harness
.MustDrawSolidQuad();
5322 LayerTreeHostImpl::FrameData frame
;
5323 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5324 host_impl_
->DrawLayers(&frame
);
5325 host_impl_
->DidDrawAllLayers(frame
);
5327 Mock::VerifyAndClearExpectations(&mock_context
);
5330 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
5332 LayerTreeHostImplClient
* client
,
5334 SharedBitmapManager
* manager
,
5335 RenderingStatsInstrumentation
* stats_instrumentation
) {
5336 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5337 scoped_ptr
<OutputSurface
> output_surface(
5338 FakeOutputSurface::Create3d(provider
));
5339 provider
->BindToCurrentThread();
5340 provider
->TestContext3d()->set_have_post_sub_buffer(true);
5342 LayerTreeSettings settings
;
5343 settings
.renderer_settings
.partial_swap_enabled
= partial_swap
;
5344 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
= LayerTreeHostImpl::Create(
5345 settings
, client
, proxy
, stats_instrumentation
, manager
, NULL
, NULL
, 0);
5346 my_host_impl
->InitializeRenderer(output_surface
.Pass());
5347 my_host_impl
->WillBeginImplFrame(
5348 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5349 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
5352 Layers are created as follows:
5354 +--------------------+
5358 | | +-------------------+
5360 | | +-------------------+
5365 +--------------------+
5367 Layers 1, 2 have render surfaces
5369 scoped_ptr
<LayerImpl
> root
=
5370 LayerImpl::Create(my_host_impl
->active_tree(), 1);
5371 scoped_ptr
<LayerImpl
> child
=
5372 LayerImpl::Create(my_host_impl
->active_tree(), 2);
5373 scoped_ptr
<LayerImpl
> grand_child
=
5374 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
5376 gfx::Rect
root_rect(0, 0, 100, 100);
5377 gfx::Rect
child_rect(10, 10, 50, 50);
5378 gfx::Rect
grand_child_rect(5, 5, 150, 150);
5380 root
->SetHasRenderSurface(true);
5381 root
->SetPosition(root_rect
.origin());
5382 root
->SetBounds(root_rect
.size());
5383 root
->SetContentBounds(root
->bounds());
5384 root
->draw_properties().visible_content_rect
= root_rect
;
5385 root
->SetDrawsContent(false);
5386 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
5388 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
5389 child
->SetOpacity(0.5f
);
5390 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
5391 child
->SetContentBounds(child
->bounds());
5392 child
->draw_properties().visible_content_rect
= child_rect
;
5393 child
->SetDrawsContent(false);
5394 child
->SetHasRenderSurface(true);
5396 grand_child
->SetPosition(grand_child_rect
.origin());
5397 grand_child
->SetBounds(grand_child_rect
.size());
5398 grand_child
->SetContentBounds(grand_child
->bounds());
5399 grand_child
->draw_properties().visible_content_rect
= grand_child_rect
;
5400 grand_child
->SetDrawsContent(true);
5402 child
->AddChild(grand_child
.Pass());
5403 root
->AddChild(child
.Pass());
5405 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5406 return my_host_impl
.Pass();
5409 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
5410 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
5411 new TestSharedBitmapManager());
5412 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5413 SetupLayersForOpacity(true,
5416 shared_bitmap_manager
.get(),
5417 &stats_instrumentation_
);
5419 LayerTreeHostImpl::FrameData frame
;
5420 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5422 // Verify all quads have been computed
5423 ASSERT_EQ(2U, frame
.render_passes
.size());
5424 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5425 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5426 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5427 frame
.render_passes
[0]->quad_list
.front()->material
);
5428 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5429 frame
.render_passes
[1]->quad_list
.front()->material
);
5431 my_host_impl
->DrawLayers(&frame
);
5432 my_host_impl
->DidDrawAllLayers(frame
);
5436 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
5437 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
5438 new TestSharedBitmapManager());
5439 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5440 SetupLayersForOpacity(false,
5443 shared_bitmap_manager
.get(),
5444 &stats_instrumentation_
);
5446 LayerTreeHostImpl::FrameData frame
;
5447 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5449 // Verify all quads have been computed
5450 ASSERT_EQ(2U, frame
.render_passes
.size());
5451 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5452 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5453 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5454 frame
.render_passes
[0]->quad_list
.front()->material
);
5455 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5456 frame
.render_passes
[1]->quad_list
.front()->material
);
5458 my_host_impl
->DrawLayers(&frame
);
5459 my_host_impl
->DidDrawAllLayers(frame
);
5463 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
5464 scoped_ptr
<TestWebGraphicsContext3D
> context
=
5465 TestWebGraphicsContext3D::Create();
5466 TestWebGraphicsContext3D
* context3d
= context
.get();
5467 scoped_ptr
<OutputSurface
> output_surface(
5468 FakeOutputSurface::Create3d(context
.Pass()));
5469 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5471 scoped_ptr
<LayerImpl
> root_layer
=
5472 LayerImpl::Create(host_impl_
->active_tree(), 1);
5473 root_layer
->SetBounds(gfx::Size(10, 10));
5474 root_layer
->SetHasRenderSurface(true);
5476 scoped_refptr
<VideoFrame
> softwareFrame
=
5477 media::VideoFrame::CreateColorFrame(
5478 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5479 FakeVideoFrameProvider provider
;
5480 provider
.set_frame(softwareFrame
);
5481 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
5482 host_impl_
->active_tree(), 4, &provider
, media::VIDEO_ROTATION_0
);
5483 video_layer
->SetBounds(gfx::Size(10, 10));
5484 video_layer
->SetContentBounds(gfx::Size(10, 10));
5485 video_layer
->SetDrawsContent(true);
5486 root_layer
->AddChild(video_layer
.Pass());
5488 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
5489 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
5490 io_surface_layer
->SetBounds(gfx::Size(10, 10));
5491 io_surface_layer
->SetContentBounds(gfx::Size(10, 10));
5492 io_surface_layer
->SetDrawsContent(true);
5493 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5494 root_layer
->AddChild(io_surface_layer
.Pass());
5496 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
5498 EXPECT_EQ(0u, context3d
->NumTextures());
5500 LayerTreeHostImpl::FrameData frame
;
5501 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5502 host_impl_
->DrawLayers(&frame
);
5503 host_impl_
->DidDrawAllLayers(frame
);
5504 host_impl_
->SwapBuffers(frame
);
5506 EXPECT_GT(context3d
->NumTextures(), 0u);
5508 // Kill the layer tree.
5509 host_impl_
->active_tree()->SetRootLayer(
5510 LayerImpl::Create(host_impl_
->active_tree(), 100));
5511 // There should be no textures left in use after.
5512 EXPECT_EQ(0u, context3d
->NumTextures());
5515 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
5517 MOCK_METHOD1(useProgram
, void(GLuint program
));
5518 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5524 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
5525 scoped_ptr
<MockDrawQuadsToFillScreenContext
> mock_context_owned(
5526 new MockDrawQuadsToFillScreenContext
);
5527 MockDrawQuadsToFillScreenContext
* mock_context
= mock_context_owned
.get();
5530 LayerTreeSettings settings
= DefaultSettings();
5531 settings
.renderer_settings
.partial_swap_enabled
= false;
5532 CreateHostImpl(settings
,
5533 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5534 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
5535 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
5537 // Verify one quad is drawn when transparent background set is not set.
5538 host_impl_
->active_tree()->set_has_transparent_background(false);
5539 EXPECT_CALL(*mock_context
, useProgram(_
))
5541 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
5543 LayerTreeHostImpl::FrameData frame
;
5544 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5545 host_impl_
->DrawLayers(&frame
);
5546 host_impl_
->DidDrawAllLayers(frame
);
5547 Mock::VerifyAndClearExpectations(&mock_context
);
5549 // Verify no quads are drawn when transparent background is set.
5550 host_impl_
->active_tree()->set_has_transparent_background(true);
5551 host_impl_
->SetFullRootLayerDamage();
5552 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5553 host_impl_
->DrawLayers(&frame
);
5554 host_impl_
->DidDrawAllLayers(frame
);
5555 Mock::VerifyAndClearExpectations(&mock_context
);
5558 TEST_F(LayerTreeHostImplTest
, ReleaseContentsTextureShouldTriggerCommit
) {
5559 set_reduce_memory_result(false);
5561 // If changing the memory limit wouldn't result in changing what was
5562 // committed, then no commit should be requested.
5563 set_reduce_memory_result(false);
5564 host_impl_
->set_max_memory_needed_bytes(
5565 host_impl_
->memory_allocation_limit_bytes() - 1);
5566 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5567 host_impl_
->memory_allocation_limit_bytes() - 1));
5568 EXPECT_FALSE(did_request_commit_
);
5569 did_request_commit_
= false;
5571 // If changing the memory limit would result in changing what was
5572 // committed, then a commit should be requested, even though nothing was
5574 set_reduce_memory_result(false);
5575 host_impl_
->set_max_memory_needed_bytes(
5576 host_impl_
->memory_allocation_limit_bytes());
5577 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5578 host_impl_
->memory_allocation_limit_bytes() - 1));
5579 EXPECT_TRUE(did_request_commit_
);
5580 did_request_commit_
= false;
5582 // Especially if changing the memory limit caused evictions, we need
5584 set_reduce_memory_result(true);
5585 host_impl_
->set_max_memory_needed_bytes(1);
5586 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5587 host_impl_
->memory_allocation_limit_bytes() - 1));
5588 EXPECT_TRUE(did_request_commit_
);
5589 did_request_commit_
= false;
5591 // But if we set it to the same value that it was before, we shouldn't
5593 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5594 host_impl_
->memory_allocation_limit_bytes()));
5595 EXPECT_FALSE(did_request_commit_
);
5598 class LayerTreeHostImplTestWithDelegatingRenderer
5599 : public LayerTreeHostImplTest
{
5601 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
5602 return FakeOutputSurface::CreateDelegating3d();
5605 void DrawFrameAndTestDamage(const gfx::RectF
& expected_damage
) {
5606 bool expect_to_draw
= !expected_damage
.IsEmpty();
5608 LayerTreeHostImpl::FrameData frame
;
5609 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5611 if (!expect_to_draw
) {
5612 // With no damage, we don't draw, and no quads are created.
5613 ASSERT_EQ(0u, frame
.render_passes
.size());
5615 ASSERT_EQ(1u, frame
.render_passes
.size());
5617 // Verify the damage rect for the root render pass.
5618 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
5619 EXPECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
5621 // Verify the root and child layers' quads are generated and not being
5623 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
5625 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
5626 gfx::RectF
expected_child_visible_rect(child
->content_bounds());
5627 EXPECT_EQ(expected_child_visible_rect
,
5628 root_render_pass
->quad_list
.front()->visible_rect
);
5630 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
5631 gfx::RectF
expected_root_visible_rect(root
->content_bounds());
5632 EXPECT_EQ(expected_root_visible_rect
,
5633 root_render_pass
->quad_list
.ElementAt(1)->visible_rect
);
5636 host_impl_
->DrawLayers(&frame
);
5637 host_impl_
->DidDrawAllLayers(frame
);
5638 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
5642 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
5643 scoped_ptr
<SolidColorLayerImpl
> root
=
5644 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
5645 root
->SetPosition(gfx::PointF());
5646 root
->SetBounds(gfx::Size(10, 10));
5647 root
->SetContentBounds(gfx::Size(10, 10));
5648 root
->SetDrawsContent(true);
5649 root
->SetHasRenderSurface(true);
5651 // Child layer is in the bottom right corner.
5652 scoped_ptr
<SolidColorLayerImpl
> child
=
5653 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
5654 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
5655 child
->SetBounds(gfx::Size(1, 1));
5656 child
->SetContentBounds(gfx::Size(1, 1));
5657 child
->SetDrawsContent(true);
5658 root
->AddChild(child
.Pass());
5660 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5662 // Draw a frame. In the first frame, the entire viewport should be damaged.
5663 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
5664 DrawFrameAndTestDamage(full_frame_damage
);
5666 // The second frame has damage that doesn't touch the child layer. Its quads
5667 // should still be generated.
5668 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
5669 host_impl_
->active_tree()->root_layer()->SetUpdateRect(small_damage
);
5670 DrawFrameAndTestDamage(small_damage
);
5672 // The third frame should have no damage, so no quads should be generated.
5673 gfx::Rect no_damage
;
5674 DrawFrameAndTestDamage(no_damage
);
5677 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5678 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5679 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, PreventRasterizeOnDemand
) {
5680 LayerTreeSettings settings
;
5681 CreateHostImpl(settings
, CreateOutputSurface());
5682 EXPECT_FALSE(host_impl_
->GetRendererCapabilities().allow_rasterize_on_demand
);
5685 class FakeMaskLayerImpl
: public LayerImpl
{
5687 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
5689 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
5692 void GetContentsResourceId(ResourceProvider::ResourceId
* resource_id
,
5693 gfx::Size
* resource_size
) const override
{
5698 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5699 : LayerImpl(tree_impl
, id
) {}
5702 class GLRendererWithSetupQuadForAntialiasing
: public GLRenderer
{
5704 using GLRenderer::ShouldAntialiasQuad
;
5707 TEST_F(LayerTreeHostImplTest
, FarAwayQuadsDontNeedAA
) {
5708 // Due to precision issues (especially on Android), sometimes far
5709 // away quads can end up thinking they need AA.
5710 float device_scale_factor
= 4.f
/ 3.f
;
5711 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5712 gfx::Size
root_size(2000, 1000);
5713 gfx::Size device_viewport_size
=
5714 gfx::ToCeiledSize(gfx::ScaleSize(root_size
, device_scale_factor
));
5715 host_impl_
->SetViewportSize(device_viewport_size
);
5717 host_impl_
->CreatePendingTree();
5718 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
/ 16.f
,
5721 scoped_ptr
<LayerImpl
> scoped_root
=
5722 LayerImpl::Create(host_impl_
->pending_tree(), 1);
5723 LayerImpl
* root
= scoped_root
.get();
5724 root
->SetHasRenderSurface(true);
5726 host_impl_
->pending_tree()->SetRootLayer(scoped_root
.Pass());
5728 scoped_ptr
<LayerImpl
> scoped_scrolling_layer
=
5729 LayerImpl::Create(host_impl_
->pending_tree(), 2);
5730 LayerImpl
* scrolling_layer
= scoped_scrolling_layer
.get();
5731 root
->AddChild(scoped_scrolling_layer
.Pass());
5733 gfx::Size
content_layer_bounds(100000, 100);
5734 gfx::Size
pile_tile_size(3000, 3000);
5735 scoped_refptr
<FakePicturePileImpl
> pile(FakePicturePileImpl::CreateFilledPile(
5736 pile_tile_size
, content_layer_bounds
));
5738 scoped_ptr
<FakePictureLayerImpl
> scoped_content_layer
=
5739 FakePictureLayerImpl::CreateWithRasterSource(host_impl_
->pending_tree(),
5741 LayerImpl
* content_layer
= scoped_content_layer
.get();
5742 scrolling_layer
->AddChild(scoped_content_layer
.Pass());
5743 content_layer
->SetBounds(content_layer_bounds
);
5744 content_layer
->SetDrawsContent(true);
5746 root
->SetBounds(root_size
);
5748 gfx::ScrollOffset
scroll_offset(100000, 0);
5749 scrolling_layer
->SetScrollClipLayer(root
->id());
5750 scrolling_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
5752 host_impl_
->ActivateSyncTree();
5754 bool update_lcd_text
= false;
5755 host_impl_
->active_tree()->UpdateDrawProperties(update_lcd_text
);
5756 ASSERT_EQ(1u, host_impl_
->active_tree()->RenderSurfaceLayerList().size());
5758 LayerTreeHostImpl::FrameData frame
;
5759 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5761 ASSERT_EQ(1u, frame
.render_passes
.size());
5762 ASSERT_LE(1u, frame
.render_passes
[0]->quad_list
.size());
5763 const DrawQuad
* quad
= frame
.render_passes
[0]->quad_list
.front();
5766 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
5767 quad
->quadTransform(), quad
, false);
5768 EXPECT_FALSE(antialiased
);
5770 host_impl_
->DrawLayers(&frame
);
5771 host_impl_
->DidDrawAllLayers(frame
);
5775 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
5777 CompositorFrameMetadataTest()
5778 : swap_buffers_complete_(0) {}
5780 void DidSwapBuffersCompleteOnImplThread() override
{
5781 swap_buffers_complete_
++;
5784 int swap_buffers_complete_
;
5787 TEST_F(CompositorFrameMetadataTest
, CompositorFrameAckCountsAsSwapComplete
) {
5788 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5790 LayerTreeHostImpl::FrameData frame
;
5791 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5792 host_impl_
->DrawLayers(&frame
);
5793 host_impl_
->DidDrawAllLayers(frame
);
5795 CompositorFrameAck ack
;
5796 host_impl_
->ReclaimResources(&ack
);
5797 host_impl_
->DidSwapBuffersComplete();
5798 EXPECT_EQ(swap_buffers_complete_
, 1);
5801 class CountingSoftwareDevice
: public SoftwareOutputDevice
{
5803 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5805 SkCanvas
* BeginPaint(const gfx::Rect
& damage_rect
) override
{
5807 return SoftwareOutputDevice::BeginPaint(damage_rect
);
5809 void EndPaint(SoftwareFrameData
* frame_data
) override
{
5811 SoftwareOutputDevice::EndPaint(frame_data
);
5814 int frames_began_
, frames_ended_
;
5817 TEST_F(LayerTreeHostImplTest
, ForcedDrawToSoftwareDeviceBasicRender
) {
5818 // No main thread evictions in resourceless software mode.
5819 set_reduce_memory_result(false);
5820 CountingSoftwareDevice
* software_device
= new CountingSoftwareDevice();
5821 EXPECT_TRUE(CreateHostImpl(
5823 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device
))));
5824 host_impl_
->SetViewportSize(gfx::Size(50, 50));
5826 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5828 const gfx::Transform external_transform
;
5829 const gfx::Rect external_viewport
;
5830 const gfx::Rect external_clip
;
5831 const bool resourceless_software_draw
= true;
5832 host_impl_
->SetExternalDrawConstraints(external_transform
,
5837 resourceless_software_draw
);
5839 EXPECT_EQ(0, software_device
->frames_began_
);
5840 EXPECT_EQ(0, software_device
->frames_ended_
);
5844 EXPECT_EQ(1, software_device
->frames_began_
);
5845 EXPECT_EQ(1, software_device
->frames_ended_
);
5847 // Call another API method that is likely to hit nullptr in this mode.
5848 scoped_refptr
<base::trace_event::TracedValue
> state
=
5849 make_scoped_refptr(new base::trace_event::TracedValue());
5850 host_impl_
->ActivationStateAsValueInto(state
.get());
5853 TEST_F(LayerTreeHostImplTest
,
5854 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers
) {
5855 set_reduce_memory_result(false);
5856 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5857 FakeOutputSurface::CreateSoftware(
5858 make_scoped_ptr(new CountingSoftwareDevice
))));
5860 const gfx::Transform external_transform
;
5861 const gfx::Rect external_viewport
;
5862 const gfx::Rect external_clip
;
5863 const bool resourceless_software_draw
= true;
5864 host_impl_
->SetExternalDrawConstraints(external_transform
,
5869 resourceless_software_draw
);
5871 // SolidColorLayerImpl will be drawn.
5872 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
5873 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
5875 // VideoLayerImpl will not be drawn.
5876 FakeVideoFrameProvider provider
;
5877 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
5878 host_impl_
->active_tree(), 2, &provider
, media::VIDEO_ROTATION_0
);
5879 video_layer
->SetBounds(gfx::Size(10, 10));
5880 video_layer
->SetContentBounds(gfx::Size(10, 10));
5881 video_layer
->SetDrawsContent(true);
5882 root_layer
->AddChild(video_layer
.Pass());
5883 SetupRootLayerImpl(root_layer
.Pass());
5885 LayerTreeHostImpl::FrameData frame
;
5886 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5887 host_impl_
->DrawLayers(&frame
);
5888 host_impl_
->DidDrawAllLayers(frame
);
5890 EXPECT_EQ(1u, frame
.will_draw_layers
.size());
5891 EXPECT_EQ(host_impl_
->active_tree()->root_layer(), frame
.will_draw_layers
[0]);
5894 // Checks that we have a non-0 default allocation if we pass a context that
5895 // doesn't support memory management extensions.
5896 TEST_F(LayerTreeHostImplTest
, DefaultMemoryAllocation
) {
5897 LayerTreeSettings settings
;
5898 host_impl_
= LayerTreeHostImpl::Create(
5899 settings
, this, &proxy_
, &stats_instrumentation_
,
5900 shared_bitmap_manager_
.get(), gpu_memory_buffer_manager_
.get(),
5901 task_graph_runner_
.get(), 0);
5903 scoped_ptr
<OutputSurface
> output_surface(
5904 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5905 host_impl_
->InitializeRenderer(output_surface
.Pass());
5906 EXPECT_LT(0ul, host_impl_
->memory_allocation_limit_bytes());
5909 TEST_F(LayerTreeHostImplTest
, MemoryPolicy
) {
5910 ManagedMemoryPolicy
policy1(
5911 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING
, 1000);
5912 int everything_cutoff_value
= ManagedMemoryPolicy::PriorityCutoffToValue(
5913 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING
);
5914 int allow_nice_to_have_cutoff_value
=
5915 ManagedMemoryPolicy::PriorityCutoffToValue(
5916 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE
);
5917 int nothing_cutoff_value
= ManagedMemoryPolicy::PriorityCutoffToValue(
5918 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING
);
5920 // GPU rasterization should be disabled by default on the tree(s)
5921 EXPECT_FALSE(host_impl_
->active_tree()->use_gpu_rasterization());
5922 EXPECT_TRUE(host_impl_
->pending_tree() == NULL
);
5924 host_impl_
->SetVisible(true);
5925 host_impl_
->SetMemoryPolicy(policy1
);
5926 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
5927 EXPECT_EQ(everything_cutoff_value
, current_priority_cutoff_value_
);
5929 host_impl_
->SetVisible(false);
5930 EXPECT_EQ(0u, current_limit_bytes_
);
5931 EXPECT_EQ(nothing_cutoff_value
, current_priority_cutoff_value_
);
5933 host_impl_
->SetVisible(true);
5934 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
5935 EXPECT_EQ(everything_cutoff_value
, current_priority_cutoff_value_
);
5937 // Now enable GPU rasterization and test if we get nice to have cutoff,
5939 LayerTreeSettings settings
;
5940 settings
.gpu_rasterization_enabled
= true;
5941 host_impl_
= LayerTreeHostImpl::Create(
5942 settings
, this, &proxy_
, &stats_instrumentation_
, NULL
, NULL
, NULL
, 0);
5943 host_impl_
->set_content_is_suitable_for_gpu_rasterization(true);
5944 host_impl_
->set_has_gpu_rasterization_trigger(true);
5945 host_impl_
->UpdateGpuRasterizationStatus();
5946 host_impl_
->SetVisible(true);
5947 host_impl_
->SetMemoryPolicy(policy1
);
5948 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
5949 EXPECT_EQ(allow_nice_to_have_cutoff_value
, current_priority_cutoff_value_
);
5951 host_impl_
->SetVisible(false);
5952 EXPECT_EQ(0u, current_limit_bytes_
);
5953 EXPECT_EQ(nothing_cutoff_value
, current_priority_cutoff_value_
);
5956 TEST_F(LayerTreeHostImplTest
, RequireHighResWhenVisible
) {
5957 ASSERT_TRUE(host_impl_
->active_tree());
5959 // RequiresHighResToDraw is set when new output surface is used.
5960 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5962 host_impl_
->ResetRequiresHighResToDraw();
5964 host_impl_
->SetVisible(false);
5965 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
5966 host_impl_
->SetVisible(true);
5967 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5968 host_impl_
->SetVisible(false);
5969 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5971 host_impl_
->ResetRequiresHighResToDraw();
5973 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
5974 host_impl_
->SetVisible(true);
5975 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5978 TEST_F(LayerTreeHostImplTest
, RequireHighResAfterGpuRasterizationToggles
) {
5979 ASSERT_TRUE(host_impl_
->active_tree());
5980 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
5982 // RequiresHighResToDraw is set when new output surface is used.
5983 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5985 host_impl_
->ResetRequiresHighResToDraw();
5987 host_impl_
->set_content_is_suitable_for_gpu_rasterization(true);
5988 host_impl_
->set_has_gpu_rasterization_trigger(false);
5989 host_impl_
->UpdateGpuRasterizationStatus();
5990 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
5991 host_impl_
->set_has_gpu_rasterization_trigger(true);
5992 host_impl_
->UpdateGpuRasterizationStatus();
5993 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5994 host_impl_
->set_has_gpu_rasterization_trigger(false);
5995 host_impl_
->UpdateGpuRasterizationStatus();
5996 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5998 host_impl_
->ResetRequiresHighResToDraw();
6000 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6001 host_impl_
->set_has_gpu_rasterization_trigger(true);
6002 host_impl_
->UpdateGpuRasterizationStatus();
6003 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6006 class LayerTreeHostImplTestPrepareTiles
: public LayerTreeHostImplTest
{
6008 void SetUp() override
{
6009 LayerTreeSettings settings
;
6010 settings
.impl_side_painting
= true;
6012 fake_host_impl_
= new FakeLayerTreeHostImpl(settings
, &proxy_
,
6013 shared_bitmap_manager_
.get(),
6014 task_graph_runner_
.get());
6015 host_impl_
.reset(fake_host_impl_
);
6016 host_impl_
->InitializeRenderer(CreateOutputSurface());
6017 host_impl_
->SetViewportSize(gfx::Size(10, 10));
6020 FakeLayerTreeHostImpl
* fake_host_impl_
;
6023 TEST_F(LayerTreeHostImplTestPrepareTiles
, PrepareTilesWhenInvisible
) {
6024 fake_host_impl_
->DidModifyTilePriorities();
6025 EXPECT_TRUE(fake_host_impl_
->prepare_tiles_needed());
6026 fake_host_impl_
->SetVisible(false);
6027 EXPECT_FALSE(fake_host_impl_
->prepare_tiles_needed());
6030 TEST_F(LayerTreeHostImplTest
, UIResourceManagement
) {
6031 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6032 TestWebGraphicsContext3D::Create();
6033 TestWebGraphicsContext3D
* context3d
= context
.get();
6034 scoped_ptr
<FakeOutputSurface
> output_surface
= FakeOutputSurface::Create3d();
6035 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6037 EXPECT_EQ(0u, context3d
->NumTextures());
6039 UIResourceId ui_resource_id
= 1;
6040 bool is_opaque
= false;
6041 UIResourceBitmap
bitmap(gfx::Size(1, 1), is_opaque
);
6042 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6043 EXPECT_EQ(1u, context3d
->NumTextures());
6044 ResourceProvider::ResourceId id1
=
6045 host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6048 // Multiple requests with the same id is allowed. The previous texture is
6050 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6051 EXPECT_EQ(1u, context3d
->NumTextures());
6052 ResourceProvider::ResourceId id2
=
6053 host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6055 EXPECT_NE(id1
, id2
);
6057 // Deleting invalid UIResourceId is allowed and does not change state.
6058 host_impl_
->DeleteUIResource(-1);
6059 EXPECT_EQ(1u, context3d
->NumTextures());
6061 // Should return zero for invalid UIResourceId. Number of textures should
6063 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(-1));
6064 EXPECT_EQ(1u, context3d
->NumTextures());
6066 host_impl_
->DeleteUIResource(ui_resource_id
);
6067 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(ui_resource_id
));
6068 EXPECT_EQ(0u, context3d
->NumTextures());
6070 // Should not change state for multiple deletion on one UIResourceId
6071 host_impl_
->DeleteUIResource(ui_resource_id
);
6072 EXPECT_EQ(0u, context3d
->NumTextures());
6075 TEST_F(LayerTreeHostImplTest
, CreateETC1UIResource
) {
6076 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6077 TestWebGraphicsContext3D::Create();
6078 TestWebGraphicsContext3D
* context3d
= context
.get();
6079 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6081 EXPECT_EQ(0u, context3d
->NumTextures());
6083 gfx::Size
size(4, 4);
6084 // SkImageInfo has no support for ETC1. The |info| below contains the right
6085 // total pixel size for the bitmap but not the right height and width. The
6086 // correct width/height are passed directly to UIResourceBitmap.
6088 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType
, kPremul_SkAlphaType
);
6089 skia::RefPtr
<SkPixelRef
> pixel_ref
=
6090 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info
, 0, 0));
6091 pixel_ref
->setImmutable();
6092 UIResourceBitmap
bitmap(pixel_ref
, size
);
6093 UIResourceId ui_resource_id
= 1;
6094 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6095 EXPECT_EQ(1u, context3d
->NumTextures());
6096 ResourceProvider::ResourceId id1
=
6097 host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6101 void ShutdownReleasesContext_Callback(scoped_ptr
<CopyOutputResult
> result
) {
6104 TEST_F(LayerTreeHostImplTest
, ShutdownReleasesContext
) {
6105 scoped_refptr
<TestContextProvider
> context_provider
=
6106 TestContextProvider::Create();
6108 CreateHostImpl(DefaultSettings(),
6109 FakeOutputSurface::Create3d(context_provider
));
6111 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6113 ScopedPtrVector
<CopyOutputRequest
> requests
;
6114 requests
.push_back(CopyOutputRequest::CreateRequest(
6115 base::Bind(&ShutdownReleasesContext_Callback
)));
6117 host_impl_
->active_tree()->root_layer()->PassCopyRequests(&requests
);
6119 LayerTreeHostImpl::FrameData frame
;
6120 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6121 host_impl_
->DrawLayers(&frame
);
6122 host_impl_
->DidDrawAllLayers(frame
);
6124 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6125 // texture in a texture mailbox.
6126 EXPECT_FALSE(context_provider
->HasOneRef());
6127 EXPECT_EQ(1u, context_provider
->TestContext3d()->NumTextures());
6129 host_impl_
= nullptr;
6131 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6132 // released, and the texture deleted.
6133 EXPECT_TRUE(context_provider
->HasOneRef());
6134 EXPECT_EQ(0u, context_provider
->TestContext3d()->NumTextures());
6137 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldNotBubble
) {
6138 // When flinging via touch, only the child should scroll (we should not
6140 gfx::Size
surface_size(10, 10);
6141 gfx::Size
content_size(20, 20);
6142 scoped_ptr
<LayerImpl
> root_clip
=
6143 LayerImpl::Create(host_impl_
->active_tree(), 3);
6144 root_clip
->SetHasRenderSurface(true);
6146 scoped_ptr
<LayerImpl
> root
=
6147 CreateScrollableLayer(1, content_size
, root_clip
.get());
6148 root
->SetIsContainerForFixedPositionLayers(true);
6149 scoped_ptr
<LayerImpl
> child
=
6150 CreateScrollableLayer(2, content_size
, root_clip
.get());
6152 root
->AddChild(child
.Pass());
6153 int root_id
= root
->id();
6154 root_clip
->AddChild(root
.Pass());
6156 host_impl_
->SetViewportSize(surface_size
);
6157 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6158 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
6160 host_impl_
->active_tree()->DidBecomeActive();
6163 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6164 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6166 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6168 gfx::Vector2d
scroll_delta(0, 100);
6169 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6170 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6172 host_impl_
->ScrollEnd();
6174 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6175 host_impl_
->ProcessScrollDeltas();
6177 // Only the child should have scrolled.
6178 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6179 ExpectNone(*scroll_info
.get(), root_id
);
6183 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldLockToFirstScrolledLayer
) {
6184 // Scroll a child layer beyond its maximum scroll range and make sure the
6185 // the scroll doesn't bubble up to the parent layer.
6186 gfx::Size
surface_size(10, 10);
6187 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
6188 root
->SetHasRenderSurface(true);
6189 scoped_ptr
<LayerImpl
> root_scrolling
=
6190 CreateScrollableLayer(2, surface_size
, root
.get());
6192 scoped_ptr
<LayerImpl
> grand_child
=
6193 CreateScrollableLayer(4, surface_size
, root
.get());
6194 grand_child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6196 scoped_ptr
<LayerImpl
> child
=
6197 CreateScrollableLayer(3, surface_size
, root
.get());
6198 child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6199 child
->AddChild(grand_child
.Pass());
6201 root_scrolling
->AddChild(child
.Pass());
6202 root
->AddChild(root_scrolling
.Pass());
6203 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6204 host_impl_
->active_tree()->DidBecomeActive();
6205 host_impl_
->SetViewportSize(surface_size
);
6208 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
6210 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
6211 LayerImpl
* grand_child
= child
->children()[0];
6213 gfx::Vector2d
scroll_delta(0, -2);
6214 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6215 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6216 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6218 // The grand child should have scrolled up to its limit.
6219 scroll_info
= host_impl_
->ProcessScrollDeltas();
6220 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6221 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6222 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6224 // The child should have received the bubbled delta, but the locked
6225 // scrolling layer should remain set as the grand child.
6226 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6227 scroll_info
= host_impl_
->ProcessScrollDeltas();
6228 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6229 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6230 ExpectContains(*scroll_info
, child
->id(), scroll_delta
);
6231 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6233 // The first |ScrollBy| after the fling should re-lock the scrolling
6234 // layer to the first layer that scrolled, which is the child.
6235 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6236 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6237 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6239 // The child should have scrolled up to its limit.
6240 scroll_info
= host_impl_
->ProcessScrollDeltas();
6241 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6242 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6243 ExpectContains(*scroll_info
, child
->id(), scroll_delta
+ scroll_delta
);
6245 // As the locked layer is at it's limit, no further scrolling can occur.
6246 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6247 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6248 host_impl_
->ScrollEnd();
6252 TEST_F(LayerTreeHostImplTest
, WheelFlingShouldBubble
) {
6253 // When flinging via wheel, the root should eventually scroll (we should
6255 gfx::Size
surface_size(10, 10);
6256 gfx::Size
content_size(20, 20);
6257 scoped_ptr
<LayerImpl
> root_clip
=
6258 LayerImpl::Create(host_impl_
->active_tree(), 3);
6259 root_clip
->SetHasRenderSurface(true);
6260 scoped_ptr
<LayerImpl
> root_scroll
=
6261 CreateScrollableLayer(1, content_size
, root_clip
.get());
6262 int root_scroll_id
= root_scroll
->id();
6263 scoped_ptr
<LayerImpl
> child
=
6264 CreateScrollableLayer(2, content_size
, root_clip
.get());
6266 root_scroll
->AddChild(child
.Pass());
6267 root_clip
->AddChild(root_scroll
.Pass());
6269 host_impl_
->SetViewportSize(surface_size
);
6270 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6271 host_impl_
->active_tree()->DidBecomeActive();
6274 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6275 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6277 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6279 gfx::Vector2d
scroll_delta(0, 100);
6280 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6281 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6283 host_impl_
->ScrollEnd();
6285 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6286 host_impl_
->ProcessScrollDeltas();
6288 // The root should have scrolled.
6289 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6290 ExpectContains(*scroll_info
.get(), root_scroll_id
, gfx::Vector2d(0, 10));
6294 TEST_F(LayerTreeHostImplTest
, ScrollUnknownNotOnAncestorChain
) {
6295 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6296 // we should return SCROLL_UNKNOWN.
6297 gfx::Size
content_size(100, 100);
6298 SetupScrollAndContentsLayers(content_size
);
6300 int scroll_layer_id
= 2;
6301 LayerImpl
* scroll_layer
=
6302 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6303 scroll_layer
->SetDrawsContent(true);
6305 int page_scale_layer_id
= 5;
6306 LayerImpl
* page_scale_layer
=
6307 host_impl_
->active_tree()->LayerById(page_scale_layer_id
);
6309 int occluder_layer_id
= 6;
6310 scoped_ptr
<LayerImpl
> occluder_layer
=
6311 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6312 occluder_layer
->SetDrawsContent(true);
6313 occluder_layer
->SetBounds(content_size
);
6314 occluder_layer
->SetContentBounds(content_size
);
6315 occluder_layer
->SetPosition(gfx::PointF());
6317 // The parent of the occluder is *above* the scroller.
6318 page_scale_layer
->AddChild(occluder_layer
.Pass());
6322 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6323 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6326 TEST_F(LayerTreeHostImplTest
, ScrollUnknownScrollAncestorMismatch
) {
6327 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6328 // is not the first scroller we encounter when walking up from the layer, we
6329 // should also return SCROLL_UNKNOWN.
6330 gfx::Size
content_size(100, 100);
6331 SetupScrollAndContentsLayers(content_size
);
6333 int scroll_layer_id
= 2;
6334 LayerImpl
* scroll_layer
=
6335 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6336 scroll_layer
->SetDrawsContent(true);
6338 int occluder_layer_id
= 6;
6339 scoped_ptr
<LayerImpl
> occluder_layer
=
6340 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6341 occluder_layer
->SetDrawsContent(true);
6342 occluder_layer
->SetBounds(content_size
);
6343 occluder_layer
->SetContentBounds(content_size
);
6344 occluder_layer
->SetPosition(gfx::PointF(-10.f
, -10.f
));
6346 int child_scroll_clip_layer_id
= 7;
6347 scoped_ptr
<LayerImpl
> child_scroll_clip
=
6348 LayerImpl::Create(host_impl_
->active_tree(), child_scroll_clip_layer_id
);
6350 int child_scroll_layer_id
= 8;
6351 scoped_ptr
<LayerImpl
> child_scroll
= CreateScrollableLayer(
6352 child_scroll_layer_id
, content_size
, child_scroll_clip
.get());
6354 child_scroll
->SetPosition(gfx::PointF(10.f
, 10.f
));
6356 child_scroll
->AddChild(occluder_layer
.Pass());
6357 scroll_layer
->AddChild(child_scroll
.Pass());
6361 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6362 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6365 TEST_F(LayerTreeHostImplTest
, NotScrollInvisibleScroller
) {
6366 gfx::Size
content_size(100, 100);
6367 SetupScrollAndContentsLayers(content_size
);
6369 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6371 int scroll_layer_id
= 2;
6372 LayerImpl
* scroll_layer
=
6373 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6375 int child_scroll_layer_id
= 7;
6376 scoped_ptr
<LayerImpl
> child_scroll
=
6377 CreateScrollableLayer(child_scroll_layer_id
, content_size
, root
);
6378 child_scroll
->SetDrawsContent(false);
6380 scroll_layer
->AddChild(child_scroll
.Pass());
6384 // We should not have scrolled |child_scroll| even though we technically "hit"
6385 // it. The reason for this is that if the scrolling the scroll would not move
6386 // any layer that is a drawn RSLL member, then we can ignore the hit.
6388 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6389 // started scrolling the inner viewport.
6390 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6391 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6393 EXPECT_EQ(2, host_impl_
->CurrentlyScrollingLayer()->id());
6396 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleDescendent
) {
6397 gfx::Size
content_size(100, 100);
6398 SetupScrollAndContentsLayers(content_size
);
6400 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6401 LayerImpl
* root_scroll_layer
= host_impl_
->active_tree()->LayerById(2);
6403 scoped_ptr
<LayerImpl
> invisible_scroll_layer
=
6404 CreateScrollableLayer(7, content_size
, root
);
6405 invisible_scroll_layer
->SetDrawsContent(false);
6407 scoped_ptr
<LayerImpl
> child_layer
=
6408 LayerImpl::Create(host_impl_
->active_tree(), 8);
6409 child_layer
->SetDrawsContent(false);
6411 scoped_ptr
<LayerImpl
> grand_child_layer
=
6412 LayerImpl::Create(host_impl_
->active_tree(), 9);
6413 grand_child_layer
->SetDrawsContent(true);
6414 grand_child_layer
->SetBounds(content_size
);
6415 grand_child_layer
->SetContentBounds(content_size
);
6416 // Move the grand child so it's not hit by our test point.
6417 grand_child_layer
->SetPosition(gfx::PointF(10.f
, 10.f
));
6419 child_layer
->AddChild(grand_child_layer
.Pass());
6420 invisible_scroll_layer
->AddChild(child_layer
.Pass());
6421 root_scroll_layer
->AddChild(invisible_scroll_layer
.Pass());
6425 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6426 // a descendant which is a drawn RSLL member.
6427 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6428 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6430 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6433 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleScrollChild
) {
6434 // This test case is very similar to the one above with one key difference:
6435 // the invisible scroller has a scroll child that is indeed draw contents.
6436 // If we attempt to initiate a gesture scroll off of the visible scroll child
6437 // we should still start the scroll child.
6438 gfx::Size
content_size(100, 100);
6439 SetupScrollAndContentsLayers(content_size
);
6441 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6443 int scroll_layer_id
= 2;
6444 LayerImpl
* scroll_layer
=
6445 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6447 int scroll_child_id
= 6;
6448 scoped_ptr
<LayerImpl
> scroll_child
=
6449 LayerImpl::Create(host_impl_
->active_tree(), scroll_child_id
);
6450 scroll_child
->SetDrawsContent(true);
6451 scroll_child
->SetBounds(content_size
);
6452 scroll_child
->SetContentBounds(content_size
);
6453 // Move the scroll child so it's not hit by our test point.
6454 scroll_child
->SetPosition(gfx::PointF(10.f
, 10.f
));
6456 int invisible_scroll_layer_id
= 7;
6457 scoped_ptr
<LayerImpl
> invisible_scroll
=
6458 CreateScrollableLayer(invisible_scroll_layer_id
, content_size
, root
);
6459 invisible_scroll
->SetDrawsContent(false);
6461 int container_id
= 8;
6462 scoped_ptr
<LayerImpl
> container
=
6463 LayerImpl::Create(host_impl_
->active_tree(), container_id
);
6465 scoped_ptr
<std::set
<LayerImpl
*>> scroll_children(new std::set
<LayerImpl
*>);
6466 scroll_children
->insert(scroll_child
.get());
6467 invisible_scroll
->SetScrollChildren(scroll_children
.release());
6469 scroll_child
->SetScrollParent(invisible_scroll
.get());
6471 container
->AddChild(invisible_scroll
.Pass());
6472 container
->AddChild(scroll_child
.Pass());
6474 scroll_layer
->AddChild(container
.Pass());
6478 // We should have scrolled |child_scroll| even though it is invisible.
6479 // The reason for this is that if the scrolling the scroll would move a layer
6480 // that is a drawn RSLL member, then we should accept this hit.
6481 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6482 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6484 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6487 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6488 // to CompositorFrameMetadata after SwapBuffers();
6489 TEST_F(LayerTreeHostImplTest
, LatencyInfoPassedToCompositorFrameMetadata
) {
6490 scoped_ptr
<SolidColorLayerImpl
> root
=
6491 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6492 root
->SetPosition(gfx::PointF());
6493 root
->SetBounds(gfx::Size(10, 10));
6494 root
->SetContentBounds(gfx::Size(10, 10));
6495 root
->SetDrawsContent(true);
6496 root
->SetHasRenderSurface(true);
6498 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6500 FakeOutputSurface
* fake_output_surface
=
6501 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6503 const std::vector
<ui::LatencyInfo
>& metadata_latency_before
=
6504 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6505 EXPECT_TRUE(metadata_latency_before
.empty());
6507 ui::LatencyInfo latency_info
;
6508 latency_info
.AddLatencyNumber(
6509 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, 0);
6510 scoped_ptr
<SwapPromise
> swap_promise(
6511 new LatencyInfoSwapPromise(latency_info
));
6512 host_impl_
->active_tree()->QueueSwapPromise(swap_promise
.Pass());
6513 host_impl_
->SetNeedsRedraw();
6515 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6516 LayerTreeHostImpl::FrameData frame
;
6517 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6518 host_impl_
->DrawLayers(&frame
);
6519 host_impl_
->DidDrawAllLayers(frame
);
6520 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6522 const std::vector
<ui::LatencyInfo
>& metadata_latency_after
=
6523 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6524 EXPECT_EQ(1u, metadata_latency_after
.size());
6525 EXPECT_TRUE(metadata_latency_after
[0].FindLatency(
6526 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, NULL
));
6529 TEST_F(LayerTreeHostImplTest
, SelectionBoundsPassedToCompositorFrameMetadata
) {
6530 int root_layer_id
= 1;
6531 scoped_ptr
<SolidColorLayerImpl
> root
=
6532 SolidColorLayerImpl::Create(host_impl_
->active_tree(), root_layer_id
);
6533 root
->SetPosition(gfx::PointF());
6534 root
->SetBounds(gfx::Size(10, 10));
6535 root
->SetContentBounds(gfx::Size(10, 10));
6536 root
->SetDrawsContent(true);
6537 root
->SetHasRenderSurface(true);
6539 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6541 // Ensure the default frame selection bounds are empty.
6542 FakeOutputSurface
* fake_output_surface
=
6543 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6544 const ViewportSelection
& selection_before
=
6545 fake_output_surface
->last_sent_frame().metadata
.selection
;
6546 EXPECT_EQ(ViewportSelectionBound(), selection_before
.start
);
6547 EXPECT_EQ(ViewportSelectionBound(), selection_before
.end
);
6549 // Plumb the layer-local selection bounds.
6550 gfx::PointF
selection_top(5, 0);
6551 gfx::PointF
selection_bottom(5, 5);
6552 LayerSelection selection
;
6553 selection
.start
.type
= SELECTION_BOUND_CENTER
;
6554 selection
.start
.layer_id
= root_layer_id
;
6555 selection
.start
.edge_bottom
= selection_bottom
;
6556 selection
.start
.edge_top
= selection_top
;
6557 selection
.end
= selection
.start
;
6558 host_impl_
->active_tree()->RegisterSelection(selection
);
6560 // Trigger a draw-swap sequence.
6561 host_impl_
->SetNeedsRedraw();
6563 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6564 LayerTreeHostImpl::FrameData frame
;
6565 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6566 host_impl_
->DrawLayers(&frame
);
6567 host_impl_
->DidDrawAllLayers(frame
);
6568 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6570 // Ensure the selection bounds have propagated to the frame metadata.
6571 const ViewportSelection
& selection_after
=
6572 fake_output_surface
->last_sent_frame().metadata
.selection
;
6573 EXPECT_EQ(selection
.start
.type
, selection_after
.start
.type
);
6574 EXPECT_EQ(selection
.end
.type
, selection_after
.end
.type
);
6575 EXPECT_EQ(selection_bottom
, selection_after
.start
.edge_bottom
);
6576 EXPECT_EQ(selection_top
, selection_after
.start
.edge_top
);
6577 EXPECT_TRUE(selection_after
.start
.visible
);
6578 EXPECT_TRUE(selection_after
.start
.visible
);
6581 class SimpleSwapPromiseMonitor
: public SwapPromiseMonitor
{
6583 SimpleSwapPromiseMonitor(LayerTreeHost
* layer_tree_host
,
6584 LayerTreeHostImpl
* layer_tree_host_impl
,
6585 int* set_needs_commit_count
,
6586 int* set_needs_redraw_count
,
6587 int* forward_to_main_count
)
6588 : SwapPromiseMonitor(layer_tree_host
, layer_tree_host_impl
),
6589 set_needs_commit_count_(set_needs_commit_count
),
6590 set_needs_redraw_count_(set_needs_redraw_count
),
6591 forward_to_main_count_(forward_to_main_count
) {}
6593 ~SimpleSwapPromiseMonitor() override
{}
6595 void OnSetNeedsCommitOnMain() override
{ (*set_needs_commit_count_
)++; }
6597 void OnSetNeedsRedrawOnImpl() override
{ (*set_needs_redraw_count_
)++; }
6599 void OnForwardScrollUpdateToMainThreadOnImpl() override
{
6600 (*forward_to_main_count_
)++;
6604 int* set_needs_commit_count_
;
6605 int* set_needs_redraw_count_
;
6606 int* forward_to_main_count_
;
6609 TEST_F(LayerTreeHostImplTest
, SimpleSwapPromiseMonitor
) {
6610 int set_needs_commit_count
= 0;
6611 int set_needs_redraw_count
= 0;
6612 int forward_to_main_count
= 0;
6615 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6616 new SimpleSwapPromiseMonitor(NULL
,
6618 &set_needs_commit_count
,
6619 &set_needs_redraw_count
,
6620 &forward_to_main_count
));
6621 host_impl_
->SetNeedsRedraw();
6622 EXPECT_EQ(0, set_needs_commit_count
);
6623 EXPECT_EQ(1, set_needs_redraw_count
);
6624 EXPECT_EQ(0, forward_to_main_count
);
6627 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6629 host_impl_
->SetNeedsRedraw();
6630 EXPECT_EQ(0, set_needs_commit_count
);
6631 EXPECT_EQ(1, set_needs_redraw_count
);
6632 EXPECT_EQ(0, forward_to_main_count
);
6635 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6636 new SimpleSwapPromiseMonitor(NULL
,
6638 &set_needs_commit_count
,
6639 &set_needs_redraw_count
,
6640 &forward_to_main_count
));
6641 host_impl_
->SetNeedsRedrawRect(gfx::Rect(10, 10));
6642 EXPECT_EQ(0, set_needs_commit_count
);
6643 EXPECT_EQ(2, set_needs_redraw_count
);
6644 EXPECT_EQ(0, forward_to_main_count
);
6648 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6649 new SimpleSwapPromiseMonitor(NULL
,
6651 &set_needs_commit_count
,
6652 &set_needs_redraw_count
,
6653 &forward_to_main_count
));
6654 // Empty damage rect won't signal the monitor.
6655 host_impl_
->SetNeedsRedrawRect(gfx::Rect());
6656 EXPECT_EQ(0, set_needs_commit_count
);
6657 EXPECT_EQ(2, set_needs_redraw_count
);
6658 EXPECT_EQ(0, forward_to_main_count
);
6662 set_needs_commit_count
= 0;
6663 set_needs_redraw_count
= 0;
6664 forward_to_main_count
= 0;
6665 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6666 new SimpleSwapPromiseMonitor(NULL
,
6668 &set_needs_commit_count
,
6669 &set_needs_redraw_count
,
6670 &forward_to_main_count
));
6671 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
6673 // Scrolling normally should not trigger any forwarding.
6674 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6675 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6677 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
6678 host_impl_
->ScrollEnd();
6680 EXPECT_EQ(0, set_needs_commit_count
);
6681 EXPECT_EQ(1, set_needs_redraw_count
);
6682 EXPECT_EQ(0, forward_to_main_count
);
6684 // Scrolling with a scroll handler should defer the swap to the main
6686 scroll_layer
->SetHaveScrollEventHandlers(true);
6687 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6688 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6690 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
6691 host_impl_
->ScrollEnd();
6693 EXPECT_EQ(0, set_needs_commit_count
);
6694 EXPECT_EQ(2, set_needs_redraw_count
);
6695 EXPECT_EQ(1, forward_to_main_count
);
6699 class LayerTreeHostImplWithTopControlsTest
: public LayerTreeHostImplTest
{
6701 void SetUp() override
{
6702 LayerTreeSettings settings
= DefaultSettings();
6703 CreateHostImpl(settings
, CreateOutputSurface());
6704 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
6705 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
6706 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
6710 static const int top_controls_height_
;
6713 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_
= 50;
6715 TEST_F(LayerTreeHostImplWithTopControlsTest
, NoIdleAnimations
) {
6716 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6717 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6718 host_impl_
->Animate(base::TimeTicks());
6719 EXPECT_FALSE(did_request_redraw_
);
6722 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsHeightIsCommitted
) {
6723 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6724 EXPECT_FALSE(did_request_redraw_
);
6725 host_impl_
->CreatePendingTree();
6726 host_impl_
->sync_tree()->set_top_controls_height(100);
6727 host_impl_
->ActivateSyncTree();
6728 EXPECT_EQ(100, host_impl_
->top_controls_manager()->TopControlsHeight());
6731 TEST_F(LayerTreeHostImplWithTopControlsTest
,
6732 TopControlsStayFullyVisibleOnHeightChange
) {
6733 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6734 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6736 host_impl_
->CreatePendingTree();
6737 host_impl_
->sync_tree()->set_top_controls_height(0);
6738 host_impl_
->ActivateSyncTree();
6739 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6741 host_impl_
->CreatePendingTree();
6742 host_impl_
->sync_tree()->set_top_controls_height(50);
6743 host_impl_
->ActivateSyncTree();
6744 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6747 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationScheduling
) {
6748 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6749 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6750 host_impl_
->DidChangeTopControlsPosition();
6751 EXPECT_TRUE(did_request_animate_
);
6752 EXPECT_TRUE(did_request_redraw_
);
6755 TEST_F(LayerTreeHostImplWithTopControlsTest
, ScrollHandledByTopControls
) {
6756 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6757 host_impl_
->SetViewportSize(gfx::Size(100, 100));
6758 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6759 BOTH
, SHOWN
, false);
6762 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6763 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6764 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6765 EXPECT_EQ(gfx::Vector2dF().ToString(),
6766 scroll_layer
->CurrentScrollOffset().ToString());
6768 // Scroll just the top controls and verify that the scroll succeeds.
6769 const float residue
= 10;
6770 float offset
= top_controls_height_
- residue
;
6772 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6773 EXPECT_FLOAT_EQ(-offset
,
6774 host_impl_
->top_controls_manager()->ControlsTopOffset());
6775 EXPECT_EQ(gfx::Vector2dF().ToString(),
6776 scroll_layer
->CurrentScrollOffset().ToString());
6778 // Scroll across the boundary
6779 const float content_scroll
= 20;
6780 offset
= residue
+ content_scroll
;
6782 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6783 EXPECT_EQ(-top_controls_height_
,
6784 host_impl_
->top_controls_manager()->ControlsTopOffset());
6785 EXPECT_EQ(gfx::Vector2dF(0, content_scroll
).ToString(),
6786 scroll_layer
->CurrentScrollOffset().ToString());
6788 // Now scroll back to the top of the content
6789 offset
= -content_scroll
;
6791 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6792 EXPECT_EQ(-top_controls_height_
,
6793 host_impl_
->top_controls_manager()->ControlsTopOffset());
6794 EXPECT_EQ(gfx::Vector2dF().ToString(),
6795 scroll_layer
->CurrentScrollOffset().ToString());
6797 // And scroll the top controls completely into view
6798 offset
= -top_controls_height_
;
6800 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6801 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6802 EXPECT_EQ(gfx::Vector2dF().ToString(),
6803 scroll_layer
->CurrentScrollOffset().ToString());
6805 // And attempt to scroll past the end
6807 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6808 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6809 EXPECT_EQ(gfx::Vector2dF().ToString(),
6810 scroll_layer
->CurrentScrollOffset().ToString());
6812 host_impl_
->ScrollEnd();
6815 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAtOrigin
) {
6816 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6817 host_impl_
->SetViewportSize(gfx::Size(100, 200));
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 the top controls partially.
6829 const float residue
= 35;
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 did_request_redraw_
= false;
6839 did_request_animate_
= false;
6840 did_request_commit_
= false;
6842 // End the scroll while the controls are still offset from their limit.
6843 host_impl_
->ScrollEnd();
6844 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
6845 EXPECT_TRUE(did_request_animate_
);
6846 EXPECT_TRUE(did_request_redraw_
);
6847 EXPECT_FALSE(did_request_commit_
);
6849 // The top controls should properly animate until finished, despite the scroll
6850 // offset being at the origin.
6851 base::TimeTicks animation_time
= gfx::FrameTime::Now();
6852 while (did_request_animate_
) {
6853 did_request_redraw_
= false;
6854 did_request_animate_
= false;
6855 did_request_commit_
= false;
6858 host_impl_
->top_controls_manager()->ControlsTopOffset();
6860 animation_time
+= base::TimeDelta::FromMilliseconds(5);
6861 host_impl_
->Animate(animation_time
);
6862 EXPECT_EQ(gfx::Vector2dF().ToString(),
6863 scroll_layer
->CurrentScrollOffset().ToString());
6866 host_impl_
->top_controls_manager()->ControlsTopOffset();
6868 // No commit is needed as the controls are animating the content offset,
6869 // not the scroll offset.
6870 EXPECT_FALSE(did_request_commit_
);
6872 if (new_offset
!= old_offset
)
6873 EXPECT_TRUE(did_request_redraw_
);
6875 if (new_offset
!= 0) {
6876 EXPECT_TRUE(host_impl_
->top_controls_manager()->animation());
6877 EXPECT_TRUE(did_request_animate_
);
6880 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
6883 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAfterScroll
) {
6884 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6885 host_impl_
->SetViewportSize(gfx::Size(100, 100));
6886 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6887 BOTH
, SHOWN
, false);
6888 float initial_scroll_offset
= 50;
6889 scroll_layer
->PushScrollOffsetFromMainThread(
6890 gfx::ScrollOffset(0, initial_scroll_offset
));
6893 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6894 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6895 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6896 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6897 scroll_layer
->CurrentScrollOffset().ToString());
6899 // Scroll the top controls partially.
6900 const float residue
= 15;
6901 float offset
= top_controls_height_
- residue
;
6903 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6904 EXPECT_FLOAT_EQ(-offset
,
6905 host_impl_
->top_controls_manager()->ControlsTopOffset());
6906 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6907 scroll_layer
->CurrentScrollOffset().ToString());
6909 did_request_redraw_
= false;
6910 did_request_animate_
= false;
6911 did_request_commit_
= false;
6913 // End the scroll while the controls are still offset from the limit.
6914 host_impl_
->ScrollEnd();
6915 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
6916 EXPECT_TRUE(did_request_animate_
);
6917 EXPECT_TRUE(did_request_redraw_
);
6918 EXPECT_FALSE(did_request_commit_
);
6920 // Animate the top controls to the limit.
6921 base::TimeTicks animation_time
= gfx::FrameTime::Now();
6922 while (did_request_animate_
) {
6923 did_request_redraw_
= false;
6924 did_request_animate_
= false;
6925 did_request_commit_
= false;
6928 host_impl_
->top_controls_manager()->ControlsTopOffset();
6930 animation_time
+= base::TimeDelta::FromMilliseconds(5);
6931 host_impl_
->Animate(animation_time
);
6934 host_impl_
->top_controls_manager()->ControlsTopOffset();
6936 if (new_offset
!= old_offset
) {
6937 EXPECT_TRUE(did_request_redraw_
);
6938 EXPECT_TRUE(did_request_commit_
);
6941 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
6942 EXPECT_EQ(-top_controls_height_
,
6943 host_impl_
->top_controls_manager()->ControlsTopOffset());
6946 TEST_F(LayerTreeHostImplWithTopControlsTest
,
6947 TopControlsAnimationAfterMainThreadFlingStopped
) {
6948 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6949 host_impl_
->SetViewportSize(gfx::Size(100, 100));
6950 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
6952 float initial_scroll_offset
= 50;
6953 scroll_layer
->PushScrollOffsetFromMainThread(
6954 gfx::ScrollOffset(0, initial_scroll_offset
));
6957 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6958 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6959 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6960 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6961 scroll_layer
->CurrentScrollOffset().ToString());
6963 // Scroll the top controls partially.
6964 const float residue
= 15;
6965 float offset
= top_controls_height_
- residue
;
6967 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6968 EXPECT_FLOAT_EQ(-offset
,
6969 host_impl_
->top_controls_manager()->ControlsTopOffset());
6970 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6971 scroll_layer
->CurrentScrollOffset().ToString());
6973 did_request_redraw_
= false;
6974 did_request_animate_
= false;
6975 did_request_commit_
= false;
6977 // End the fling while the controls are still offset from the limit.
6978 host_impl_
->MainThreadHasStoppedFlinging();
6979 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
6980 EXPECT_TRUE(did_request_animate_
);
6981 EXPECT_TRUE(did_request_redraw_
);
6982 EXPECT_FALSE(did_request_commit_
);
6984 // Animate the top controls to the limit.
6985 base::TimeTicks animation_time
= gfx::FrameTime::Now();
6986 while (did_request_animate_
) {
6987 did_request_redraw_
= false;
6988 did_request_animate_
= false;
6989 did_request_commit_
= false;
6991 float old_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
6993 animation_time
+= base::TimeDelta::FromMilliseconds(5);
6994 host_impl_
->Animate(animation_time
);
6996 float new_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
6998 if (new_offset
!= old_offset
) {
6999 EXPECT_TRUE(did_request_redraw_
);
7000 EXPECT_TRUE(did_request_commit_
);
7003 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7004 EXPECT_EQ(-top_controls_height_
,
7005 host_impl_
->top_controls_manager()->ControlsTopOffset());
7008 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7009 TopControlsScrollDeltaInOverScroll
) {
7010 // test varifies that the overscroll delta should not have accumulated in
7011 // the top controls if we do a hide and show without releasing finger.
7013 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7014 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7015 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7019 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7020 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7021 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7025 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7026 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7027 EXPECT_EQ(gfx::Vector2dF().ToString(),
7028 scroll_layer
->CurrentScrollOffset().ToString());
7031 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7032 EXPECT_EQ(gfx::Vector2dF(0, offset
).ToString(),
7033 scroll_layer
->CurrentScrollOffset().ToString());
7036 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7038 // Should have fully scrolled
7039 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer
->MaxScrollOffset().y()).ToString(),
7040 scroll_layer
->CurrentScrollOffset().ToString());
7042 float overscrollamount
= 10;
7044 // Overscroll the content
7046 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount
))
7048 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset
).ToString(),
7049 scroll_layer
->CurrentScrollOffset().ToString());
7050 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount
).ToString(),
7051 host_impl_
->accumulated_root_overscroll().ToString());
7053 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset
))
7055 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7056 scroll_layer
->CurrentScrollOffset().ToString());
7057 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7060 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset
)).did_scroll
);
7061 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7062 scroll_layer
->CurrentScrollOffset().ToString());
7064 // Top controls should be fully visible
7065 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7067 host_impl_
->ScrollEnd();
7070 class LayerTreeHostImplVirtualViewportTest
: public LayerTreeHostImplTest
{
7072 void SetupVirtualViewportLayers(const gfx::Size
& content_size
,
7073 const gfx::Size
& outer_viewport
,
7074 const gfx::Size
& inner_viewport
) {
7075 LayerTreeImpl
* layer_tree_impl
= host_impl_
->active_tree();
7076 const int kOuterViewportClipLayerId
= 6;
7077 const int kOuterViewportScrollLayerId
= 7;
7078 const int kInnerViewportScrollLayerId
= 2;
7079 const int kInnerViewportClipLayerId
= 4;
7080 const int kPageScaleLayerId
= 5;
7082 scoped_ptr
<LayerImpl
> inner_scroll
=
7083 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
7084 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
7085 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7087 scoped_ptr
<LayerImpl
> inner_clip
=
7088 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
7089 inner_clip
->SetBounds(inner_viewport
);
7091 scoped_ptr
<LayerImpl
> page_scale
=
7092 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
7094 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
7095 inner_scroll
->SetBounds(outer_viewport
);
7096 inner_scroll
->SetContentBounds(outer_viewport
);
7097 inner_scroll
->SetPosition(gfx::PointF());
7099 scoped_ptr
<LayerImpl
> outer_clip
=
7100 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
7101 outer_clip
->SetBounds(outer_viewport
);
7102 outer_clip
->SetIsContainerForFixedPositionLayers(true);
7104 scoped_ptr
<LayerImpl
> outer_scroll
=
7105 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
7106 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
7107 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7108 outer_scroll
->SetBounds(content_size
);
7109 outer_scroll
->SetContentBounds(content_size
);
7110 outer_scroll
->SetPosition(gfx::PointF());
7112 scoped_ptr
<LayerImpl
> contents
=
7113 LayerImpl::Create(layer_tree_impl
, 8);
7114 contents
->SetDrawsContent(true);
7115 contents
->SetBounds(content_size
);
7116 contents
->SetContentBounds(content_size
);
7117 contents
->SetPosition(gfx::PointF());
7119 outer_scroll
->AddChild(contents
.Pass());
7120 outer_clip
->AddChild(outer_scroll
.Pass());
7121 inner_scroll
->AddChild(outer_clip
.Pass());
7122 page_scale
->AddChild(inner_scroll
.Pass());
7123 inner_clip
->AddChild(page_scale
.Pass());
7125 inner_clip
->SetHasRenderSurface(true);
7126 layer_tree_impl
->SetRootLayer(inner_clip
.Pass());
7127 layer_tree_impl
->SetViewportLayersFromIds(
7128 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
7129 kOuterViewportScrollLayerId
);
7131 host_impl_
->active_tree()->DidBecomeActive();
7135 TEST_F(LayerTreeHostImplVirtualViewportTest
, ScrollBothInnerAndOuterLayer
) {
7136 gfx::Size content_size
= gfx::Size(100, 160);
7137 gfx::Size outer_viewport
= gfx::Size(50, 80);
7138 gfx::Size inner_viewport
= gfx::Size(25, 40);
7140 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7142 TestScrollOffsetDelegate scroll_delegate
;
7143 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
7145 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7146 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7149 gfx::ScrollOffset inner_expected
;
7150 gfx::ScrollOffset outer_expected
;
7151 EXPECT_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7152 EXPECT_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7154 gfx::ScrollOffset
current_offset(70.f
, 100.f
);
7156 scroll_delegate
.set_getter_return_value(current_offset
);
7157 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
7158 EXPECT_EQ(gfx::ScrollOffset(25.f
, 40.f
), inner_scroll
->MaxScrollOffset());
7159 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
), outer_scroll
->MaxScrollOffset());
7161 // Outer viewport scrolls first. Then the rest is applied to the inner
7163 EXPECT_EQ(gfx::ScrollOffset(20.f
, 20.f
),
7164 inner_scroll
->CurrentScrollOffset());
7165 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
),
7166 outer_scroll
->CurrentScrollOffset());
7170 TEST_F(LayerTreeHostImplVirtualViewportTest
, FlingScrollBubblesToInner
) {
7171 gfx::Size content_size
= gfx::Size(100, 160);
7172 gfx::Size outer_viewport
= gfx::Size(50, 80);
7173 gfx::Size inner_viewport
= gfx::Size(25, 40);
7175 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7177 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7178 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7181 gfx::Vector2dF inner_expected
;
7182 gfx::Vector2dF outer_expected
;
7183 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7184 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7186 // Make sure the fling goes to the outer viewport first
7187 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7188 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7189 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7191 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7192 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7193 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7195 host_impl_
->ScrollEnd();
7197 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7198 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7200 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7201 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7202 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7203 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7205 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7206 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7208 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7209 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7211 host_impl_
->ScrollEnd();
7213 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7214 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7218 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7219 DiagonalScrollBubblesPerfectlyToInner
) {
7220 gfx::Size content_size
= gfx::Size(100, 160);
7221 gfx::Size outer_viewport
= gfx::Size(50, 80);
7222 gfx::Size inner_viewport
= gfx::Size(25, 40);
7224 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7226 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7227 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7230 gfx::Vector2dF inner_expected
;
7231 gfx::Vector2dF outer_expected
;
7232 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7233 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7235 // Make sure the scroll goes to the outer viewport first.
7236 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7237 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7238 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7239 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7240 InputHandler::GESTURE
));
7242 // Scroll near the edge of the outer viewport.
7243 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7244 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7245 outer_expected
+= scroll_delta
;
7246 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7247 InputHandler::GESTURE
));
7249 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7250 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7252 // Now diagonal scroll across the outer viewport boundary in a single event.
7253 // The entirety of the scroll should be consumed, as bubbling between inner
7254 // and outer viewport layers is perfect.
7255 host_impl_
->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta
, 2));
7256 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7257 InputHandler::GESTURE
));
7258 outer_expected
+= scroll_delta
;
7259 inner_expected
+= scroll_delta
;
7260 host_impl_
->ScrollEnd();
7261 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7262 gfx::Point(), InputHandler::GESTURE
));
7264 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7265 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7269 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7270 TouchFlingCanLockToViewportLayerAfterBubbling
) {
7271 gfx::Size content_size
= gfx::Size(100, 160);
7272 gfx::Size outer_viewport
= gfx::Size(50, 80);
7273 gfx::Size inner_viewport
= gfx::Size(25, 40);
7275 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7277 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7278 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7280 scoped_ptr
<LayerImpl
> child
=
7281 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7282 LayerImpl
* child_scroll
= child
.get();
7283 outer_scroll
->children()[0]->AddChild(child
.Pass());
7287 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
7289 gfx::Vector2d
scroll_delta(0, inner_viewport
.height());
7290 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7291 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7292 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7293 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7294 InputHandler::GESTURE
));
7296 // The child should have scrolled up to its limit.
7297 scroll_info
= host_impl_
->ProcessScrollDeltas();
7298 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
7299 ExpectContains(*scroll_info
, child_scroll
->id(), scroll_delta
);
7300 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7302 // The first |ScrollBy| after the fling should re-lock the scrolling
7303 // layer to the first layer that scrolled, the inner viewport scroll layer.
7304 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7305 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7306 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7307 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7308 InputHandler::GESTURE
));
7310 // The inner viewport should have scrolled up to its limit.
7311 scroll_info
= host_impl_
->ProcessScrollDeltas();
7312 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
7313 ExpectContains(*scroll_info
, child_scroll
->id(), scroll_delta
);
7314 ExpectContains(*scroll_info
, inner_scroll
->id(), scroll_delta
);
7316 // As the locked layer is at its limit, no further scrolling can occur.
7317 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7318 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7319 host_impl_
->ScrollEnd();
7320 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7321 gfx::Point(), InputHandler::GESTURE
));
7325 class LayerTreeHostImplWithImplicitLimitsTest
: public LayerTreeHostImplTest
{
7327 void SetUp() override
{
7328 LayerTreeSettings settings
= DefaultSettings();
7329 settings
.max_memory_for_prepaint_percentage
= 50;
7330 CreateHostImpl(settings
, CreateOutputSurface());
7334 TEST_F(LayerTreeHostImplWithImplicitLimitsTest
, ImplicitMemoryLimits
) {
7335 // Set up a memory policy and percentages which could cause
7336 // 32-bit integer overflows.
7337 ManagedMemoryPolicy
mem_policy(300 * 1024 * 1024); // 300MB
7339 // Verify implicit limits are calculated correctly with no overflows
7340 host_impl_
->SetMemoryPolicy(mem_policy
);
7341 EXPECT_EQ(host_impl_
->global_tile_state().hard_memory_limit_in_bytes
,
7342 300u * 1024u * 1024u);
7343 EXPECT_EQ(host_impl_
->global_tile_state().soft_memory_limit_in_bytes
,
7344 150u * 1024u * 1024u);
7347 TEST_F(LayerTreeHostImplTest
, ExternalTransformReflectedInNextDraw
) {
7348 const gfx::Size
layer_size(100, 100);
7349 gfx::Transform external_transform
;
7350 const gfx::Rect
external_viewport(layer_size
);
7351 const gfx::Rect
external_clip(layer_size
);
7352 const bool resourceless_software_draw
= false;
7353 LayerImpl
* layer
= SetupScrollAndContentsLayers(layer_size
);
7355 host_impl_
->SetExternalDrawConstraints(external_transform
,
7360 resourceless_software_draw
);
7362 EXPECT_TRANSFORMATION_MATRIX_EQ(
7363 external_transform
, layer
->draw_properties().target_space_transform
);
7365 external_transform
.Translate(20, 20);
7366 host_impl_
->SetExternalDrawConstraints(external_transform
,
7371 resourceless_software_draw
);
7373 EXPECT_TRANSFORMATION_MATRIX_EQ(
7374 external_transform
, layer
->draw_properties().target_space_transform
);
7377 TEST_F(LayerTreeHostImplTest
, ScrollAnimated
) {
7378 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7381 base::TimeTicks start_time
=
7382 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7384 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7385 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7387 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7389 host_impl_
->Animate(start_time
);
7390 host_impl_
->UpdateAnimationState(true);
7392 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
7394 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(50));
7395 host_impl_
->UpdateAnimationState(true);
7397 float y
= scrolling_layer
->CurrentScrollOffset().y();
7398 EXPECT_TRUE(y
> 1 && y
< 49);
7401 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7402 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7404 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(200));
7405 host_impl_
->UpdateAnimationState(true);
7407 y
= scrolling_layer
->CurrentScrollOffset().y();
7408 EXPECT_TRUE(y
> 50 && y
< 100);
7409 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
7411 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(250));
7412 host_impl_
->UpdateAnimationState(true);
7414 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7415 scrolling_layer
->CurrentScrollOffset());
7416 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
7419 TEST_F(LayerTreeHostImplTest
, DidBecomeActive
) {
7420 host_impl_
->CreatePendingTree();
7421 host_impl_
->ActivateSyncTree();
7422 host_impl_
->CreatePendingTree();
7424 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
7426 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
7427 FakePictureLayerImpl::Create(pending_tree
, 10);
7428 FakePictureLayerImpl
* raw_pending_layer
= pending_layer
.get();
7429 pending_tree
->SetRootLayer(pending_layer
.Pass());
7430 ASSERT_EQ(raw_pending_layer
, pending_tree
->root_layer());
7432 EXPECT_EQ(0u, raw_pending_layer
->did_become_active_call_count());
7433 pending_tree
->DidBecomeActive();
7434 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7436 scoped_ptr
<FakePictureLayerImpl
> mask_layer
=
7437 FakePictureLayerImpl::Create(pending_tree
, 11);
7438 FakePictureLayerImpl
* raw_mask_layer
= mask_layer
.get();
7439 raw_pending_layer
->SetMaskLayer(mask_layer
.Pass());
7440 ASSERT_EQ(raw_mask_layer
, raw_pending_layer
->mask_layer());
7442 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7443 EXPECT_EQ(0u, raw_mask_layer
->did_become_active_call_count());
7444 pending_tree
->DidBecomeActive();
7445 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7446 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7448 scoped_ptr
<FakePictureLayerImpl
> replica_layer
=
7449 FakePictureLayerImpl::Create(pending_tree
, 12);
7450 scoped_ptr
<FakePictureLayerImpl
> replica_mask_layer
=
7451 FakePictureLayerImpl::Create(pending_tree
, 13);
7452 FakePictureLayerImpl
* raw_replica_mask_layer
= replica_mask_layer
.get();
7453 replica_layer
->SetMaskLayer(replica_mask_layer
.Pass());
7454 raw_pending_layer
->SetReplicaLayer(replica_layer
.Pass());
7455 ASSERT_EQ(raw_replica_mask_layer
,
7456 raw_pending_layer
->replica_layer()->mask_layer());
7458 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7459 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7460 EXPECT_EQ(0u, raw_replica_mask_layer
->did_become_active_call_count());
7461 pending_tree
->DidBecomeActive();
7462 EXPECT_EQ(3u, raw_pending_layer
->did_become_active_call_count());
7463 EXPECT_EQ(2u, raw_mask_layer
->did_become_active_call_count());
7464 EXPECT_EQ(1u, raw_replica_mask_layer
->did_become_active_call_count());
7467 TEST_F(LayerTreeHostImplTest
, WheelScrollWithPageScaleFactorOnInnerLayer
) {
7468 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
7469 host_impl_
->SetViewportSize(gfx::Size(50, 50));
7472 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
7474 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
7475 float page_scale_factor
= 1.f
;
7477 // The scroll deltas should have the page scale factor applied.
7479 host_impl_
->active_tree()->PushPageScaleFromMainThread(
7480 page_scale_factor
, min_page_scale
, max_page_scale
);
7481 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
7482 scroll_layer
->SetScrollDelta(gfx::Vector2d());
7484 float page_scale_delta
= 2.f
;
7485 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
7486 host_impl_
->PinchGestureBegin();
7487 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
7488 host_impl_
->PinchGestureEnd();
7489 host_impl_
->ScrollEnd();
7491 gfx::Vector2dF
scroll_delta(0, 5);
7492 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7493 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
7494 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
7496 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7497 host_impl_
->ScrollEnd();
7498 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
7499 scroll_layer
->CurrentScrollOffset());
7503 class LayerTreeHostImplCountingLostSurfaces
: public LayerTreeHostImplTest
{
7505 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7506 void DidLoseOutputSurfaceOnImplThread() override
{ num_lost_surfaces_
++; }
7509 int num_lost_surfaces_
;
7512 TEST_F(LayerTreeHostImplCountingLostSurfaces
, TwiceLostSurface
) {
7513 // Really we just need at least one client notification each time
7514 // we go from having a valid output surface to not having a valid output
7516 EXPECT_EQ(0, num_lost_surfaces_
);
7517 host_impl_
->DidLoseOutputSurface();
7518 EXPECT_EQ(1, num_lost_surfaces_
);
7519 host_impl_
->DidLoseOutputSurface();
7520 EXPECT_LE(1, num_lost_surfaces_
);
7523 TEST_F(LayerTreeHostImplTest
, RemoveUnreferencedRenderPass
) {
7524 LayerTreeHostImpl::FrameData frame
;
7525 frame
.render_passes
.push_back(RenderPass::Create());
7526 RenderPass
* pass3
= frame
.render_passes
.back();
7527 frame
.render_passes
.push_back(RenderPass::Create());
7528 RenderPass
* pass2
= frame
.render_passes
.back();
7529 frame
.render_passes
.push_back(RenderPass::Create());
7530 RenderPass
* pass1
= frame
.render_passes
.back();
7532 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7533 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7534 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7536 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7537 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7538 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7540 // Add a quad to each pass so they aren't empty.
7541 SolidColorDrawQuad
* color_quad
;
7542 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7543 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7544 color_quad
= pass2
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7545 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7546 color_quad
= pass3
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7547 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7549 // pass3 is referenced by pass2.
7550 RenderPassDrawQuad
* rpdq
=
7551 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7552 rpdq
->material
= DrawQuad::RENDER_PASS
;
7553 rpdq
->render_pass_id
= pass3
->id
;
7555 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
7556 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7557 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7558 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7559 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7560 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7561 EXPECT_EQ(1u, frame
.render_passes
.size());
7562 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7565 TEST_F(LayerTreeHostImplTest
, RemoveEmptyRenderPass
) {
7566 LayerTreeHostImpl::FrameData frame
;
7567 frame
.render_passes
.push_back(RenderPass::Create());
7568 RenderPass
* pass3
= frame
.render_passes
.back();
7569 frame
.render_passes
.push_back(RenderPass::Create());
7570 RenderPass
* pass2
= frame
.render_passes
.back();
7571 frame
.render_passes
.push_back(RenderPass::Create());
7572 RenderPass
* pass1
= frame
.render_passes
.back();
7574 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7575 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7576 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7578 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7579 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7580 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7582 // pass1 is not empty, but pass2 and pass3 are.
7583 SolidColorDrawQuad
* color_quad
;
7584 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7585 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7587 // pass3 is referenced by pass2.
7588 RenderPassDrawQuad
* rpdq
=
7589 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7590 rpdq
->material
= DrawQuad::RENDER_PASS
;
7591 rpdq
->render_pass_id
= pass3
->id
;
7593 // pass2 is referenced by pass1.
7594 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7595 rpdq
->material
= DrawQuad::RENDER_PASS
;
7596 rpdq
->render_pass_id
= pass2
->id
;
7598 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7599 // should be removed.
7600 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7601 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7602 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7603 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7604 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7605 EXPECT_EQ(1u, frame
.render_passes
.size());
7606 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7607 // The RenderPassDrawQuad should be removed from pass1.
7608 EXPECT_EQ(1u, pass1
->quad_list
.size());
7609 EXPECT_EQ(DrawQuad::SOLID_COLOR
, pass1
->quad_list
.ElementAt(0)->material
);
7612 TEST_F(LayerTreeHostImplTest
, DoNotRemoveEmptyRootRenderPass
) {
7613 LayerTreeHostImpl::FrameData frame
;
7614 frame
.render_passes
.push_back(RenderPass::Create());
7615 RenderPass
* pass3
= frame
.render_passes
.back();
7616 frame
.render_passes
.push_back(RenderPass::Create());
7617 RenderPass
* pass2
= frame
.render_passes
.back();
7618 frame
.render_passes
.push_back(RenderPass::Create());
7619 RenderPass
* pass1
= frame
.render_passes
.back();
7621 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7622 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7623 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7625 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7626 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7627 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7629 // pass3 is referenced by pass2.
7630 RenderPassDrawQuad
* rpdq
=
7631 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7632 rpdq
->material
= DrawQuad::RENDER_PASS
;
7633 rpdq
->render_pass_id
= pass3
->id
;
7635 // pass2 is referenced by pass1.
7636 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7637 rpdq
->material
= DrawQuad::RENDER_PASS
;
7638 rpdq
->render_pass_id
= pass2
->id
;
7640 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7641 // should be removed. Then pass1 is empty too, but it's the root so it should
7643 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7644 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7645 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7646 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7647 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7648 EXPECT_EQ(1u, frame
.render_passes
.size());
7649 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7650 // The RenderPassDrawQuad should be removed from pass1.
7651 EXPECT_EQ(0u, pass1
->quad_list
.size());
7654 class FakeVideoFrameController
: public VideoFrameController
{
7656 void OnBeginFrame(const BeginFrameArgs
& args
) override
{
7657 begin_frame_args_
= args
;
7660 const BeginFrameArgs
& begin_frame_args() { return begin_frame_args_
; }
7663 BeginFrameArgs begin_frame_args_
;
7666 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerInsideFrame
) {
7667 host_impl_
->DidFinishImplFrame();
7669 BeginFrameArgs begin_frame_args
=
7670 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7671 FakeVideoFrameController controller
;
7673 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7674 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7675 host_impl_
->AddVideoFrameController(&controller
);
7676 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
7677 host_impl_
->DidFinishImplFrame();
7680 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerOutsideFrame
) {
7681 host_impl_
->DidFinishImplFrame();
7683 BeginFrameArgs begin_frame_args
=
7684 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7685 FakeVideoFrameController controller
;
7687 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7688 host_impl_
->DidFinishImplFrame();
7690 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7691 host_impl_
->AddVideoFrameController(&controller
);
7692 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7694 begin_frame_args
= CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7695 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7696 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7697 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
7700 TEST_F(LayerTreeHostImplTest
, GpuRasterizationStatusModes
) {
7701 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7703 host_impl_
->set_has_gpu_rasterization_trigger(true);
7704 host_impl_
->set_content_is_suitable_for_gpu_rasterization(true);
7705 host_impl_
->UpdateGpuRasterizationStatus();
7706 EXPECT_EQ(GpuRasterizationStatus::ON
, host_impl_
->gpu_rasterization_status());
7707 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
7709 host_impl_
->set_has_gpu_rasterization_trigger(false);
7710 host_impl_
->set_content_is_suitable_for_gpu_rasterization(true);
7711 host_impl_
->UpdateGpuRasterizationStatus();
7712 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT
,
7713 host_impl_
->gpu_rasterization_status());
7714 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7716 host_impl_
->set_has_gpu_rasterization_trigger(true);
7717 host_impl_
->set_content_is_suitable_for_gpu_rasterization(false);
7718 host_impl_
->UpdateGpuRasterizationStatus();
7719 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT
,
7720 host_impl_
->gpu_rasterization_status());
7721 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7722 EXPECT_FALSE(host_impl_
->use_msaa());
7724 scoped_ptr
<TestWebGraphicsContext3D
> context_with_msaa
=
7725 TestWebGraphicsContext3D::Create();
7726 context_with_msaa
->SetMaxSamples(8);
7728 LayerTreeSettings msaaSettings
= GpuRasterizationEnabledSettings();
7729 msaaSettings
.gpu_rasterization_msaa_sample_count
= 4;
7730 EXPECT_TRUE(CreateHostImpl(
7731 msaaSettings
, FakeOutputSurface::Create3d(context_with_msaa
.Pass())));
7732 host_impl_
->set_has_gpu_rasterization_trigger(true);
7733 host_impl_
->set_content_is_suitable_for_gpu_rasterization(false);
7734 host_impl_
->UpdateGpuRasterizationStatus();
7735 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT
,
7736 host_impl_
->gpu_rasterization_status());
7737 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
7738 EXPECT_TRUE(host_impl_
->use_msaa());
7740 LayerTreeSettings settings
= DefaultSettings();
7741 settings
.gpu_rasterization_enabled
= false;
7742 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
7743 host_impl_
->set_has_gpu_rasterization_trigger(true);
7744 host_impl_
->set_content_is_suitable_for_gpu_rasterization(true);
7745 host_impl_
->UpdateGpuRasterizationStatus();
7746 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE
,
7747 host_impl_
->gpu_rasterization_status());
7748 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7750 settings
.gpu_rasterization_forced
= true;
7751 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
7753 host_impl_
->set_has_gpu_rasterization_trigger(false);
7754 host_impl_
->set_content_is_suitable_for_gpu_rasterization(false);
7755 host_impl_
->UpdateGpuRasterizationStatus();
7756 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED
,
7757 host_impl_
->gpu_rasterization_status());
7758 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());