1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host_impl.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/containers/scoped_ptr_hash_map.h"
14 #include "base/location.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "cc/animation/scrollbar_animation_controller_thinning.h"
17 #include "cc/base/math_util.h"
18 #include "cc/input/page_scale_animation.h"
19 #include "cc/input/top_controls_manager.h"
20 #include "cc/layers/append_quads_data.h"
21 #include "cc/layers/delegated_renderer_layer_impl.h"
22 #include "cc/layers/heads_up_display_layer_impl.h"
23 #include "cc/layers/io_surface_layer_impl.h"
24 #include "cc/layers/layer_impl.h"
25 #include "cc/layers/painted_scrollbar_layer_impl.h"
26 #include "cc/layers/render_surface_impl.h"
27 #include "cc/layers/solid_color_layer_impl.h"
28 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
29 #include "cc/layers/texture_layer_impl.h"
30 #include "cc/layers/tiled_layer_impl.h"
31 #include "cc/layers/video_layer_impl.h"
32 #include "cc/output/begin_frame_args.h"
33 #include "cc/output/compositor_frame_ack.h"
34 #include "cc/output/compositor_frame_metadata.h"
35 #include "cc/output/copy_output_request.h"
36 #include "cc/output/copy_output_result.h"
37 #include "cc/output/gl_renderer.h"
38 #include "cc/output/latency_info_swap_promise.h"
39 #include "cc/quads/render_pass_draw_quad.h"
40 #include "cc/quads/solid_color_draw_quad.h"
41 #include "cc/quads/texture_draw_quad.h"
42 #include "cc/quads/tile_draw_quad.h"
43 #include "cc/test/animation_test_common.h"
44 #include "cc/test/begin_frame_args_test.h"
45 #include "cc/test/fake_layer_tree_host_impl.h"
46 #include "cc/test/fake_output_surface.h"
47 #include "cc/test/fake_output_surface_client.h"
48 #include "cc/test/fake_picture_layer_impl.h"
49 #include "cc/test/fake_picture_pile_impl.h"
50 #include "cc/test/fake_proxy.h"
51 #include "cc/test/fake_video_frame_provider.h"
52 #include "cc/test/geometry_test_utils.h"
53 #include "cc/test/gpu_rasterization_enabled_settings.h"
54 #include "cc/test/layer_test_common.h"
55 #include "cc/test/layer_tree_test.h"
56 #include "cc/test/render_pass_test_common.h"
57 #include "cc/test/test_gpu_memory_buffer_manager.h"
58 #include "cc/test/test_shared_bitmap_manager.h"
59 #include "cc/test/test_task_graph_runner.h"
60 #include "cc/test/test_web_graphics_context_3d.h"
61 #include "cc/tiles/layer_tiling_data.h"
62 #include "cc/trees/layer_tree_impl.h"
63 #include "cc/trees/single_thread_proxy.h"
64 #include "media/base/media.h"
65 #include "testing/gmock/include/gmock/gmock.h"
66 #include "testing/gtest/include/gtest/gtest.h"
67 #include "third_party/skia/include/core/SkMallocPixelRef.h"
68 #include "ui/gfx/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));
187 void SetupRootLayerImpl(scoped_ptr
<LayerImpl
> root
) {
188 root
->SetPosition(gfx::PointF());
189 root
->SetBounds(gfx::Size(10, 10));
190 root
->SetContentBounds(gfx::Size(10, 10));
191 root
->SetDrawsContent(true);
192 root
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 10, 10);
193 root
->SetHasRenderSurface(true);
194 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
197 static void ExpectClearedScrollDeltasRecursive(LayerImpl
* layer
) {
198 ASSERT_EQ(layer
->ScrollDelta(), gfx::Vector2d());
199 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
200 ExpectClearedScrollDeltasRecursive(layer
->children()[i
]);
203 static void ExpectContains(const ScrollAndScaleSet
& scroll_info
,
205 const gfx::Vector2d
& scroll_delta
) {
206 int times_encountered
= 0;
208 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
209 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
211 EXPECT_VECTOR_EQ(scroll_delta
, scroll_info
.scrolls
[i
].scroll_delta
);
215 ASSERT_EQ(1, times_encountered
);
218 static void ExpectNone(const ScrollAndScaleSet
& scroll_info
, int id
) {
219 int times_encountered
= 0;
221 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
222 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
227 ASSERT_EQ(0, times_encountered
);
230 LayerImpl
* CreateScrollAndContentsLayers(LayerTreeImpl
* layer_tree_impl
,
231 const gfx::Size
& content_size
) {
232 // Create both an inner viewport scroll layer and an outer viewport scroll
233 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
234 // 0x0, so the scrolls will be applied directly to the inner viewport.
235 const int kOuterViewportClipLayerId
= 116;
236 const int kOuterViewportScrollLayerId
= 117;
237 const int kContentLayerId
= 118;
238 const int kInnerViewportScrollLayerId
= 2;
239 const int kInnerViewportClipLayerId
= 4;
240 const int kPageScaleLayerId
= 5;
242 scoped_ptr
<LayerImpl
> root
=
243 LayerImpl::Create(layer_tree_impl
, 1);
244 root
->SetBounds(content_size
);
245 root
->SetContentBounds(content_size
);
246 root
->SetPosition(gfx::PointF());
247 root
->SetHasRenderSurface(true);
249 scoped_ptr
<LayerImpl
> inner_scroll
=
250 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
251 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
252 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
254 scoped_ptr
<LayerImpl
> inner_clip
=
255 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
256 inner_clip
->SetBounds(
257 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
259 scoped_ptr
<LayerImpl
> page_scale
=
260 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
262 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
263 inner_scroll
->SetBounds(content_size
);
264 inner_scroll
->SetContentBounds(content_size
);
265 inner_scroll
->SetPosition(gfx::PointF());
267 scoped_ptr
<LayerImpl
> outer_clip
=
268 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
269 outer_clip
->SetBounds(content_size
);
270 outer_clip
->SetIsContainerForFixedPositionLayers(true);
272 scoped_ptr
<LayerImpl
> outer_scroll
=
273 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
274 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
275 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
276 outer_scroll
->SetBounds(content_size
);
277 outer_scroll
->SetContentBounds(content_size
);
278 outer_scroll
->SetPosition(gfx::PointF());
280 scoped_ptr
<LayerImpl
> contents
=
281 LayerImpl::Create(layer_tree_impl
, kContentLayerId
);
282 contents
->SetDrawsContent(true);
283 contents
->SetBounds(content_size
);
284 contents
->SetContentBounds(content_size
);
285 contents
->SetPosition(gfx::PointF());
287 outer_scroll
->AddChild(contents
.Pass());
288 outer_clip
->AddChild(outer_scroll
.Pass());
289 inner_scroll
->AddChild(outer_clip
.Pass());
290 page_scale
->AddChild(inner_scroll
.Pass());
291 inner_clip
->AddChild(page_scale
.Pass());
292 root
->AddChild(inner_clip
.Pass());
294 layer_tree_impl
->SetRootLayer(root
.Pass());
295 layer_tree_impl
->SetViewportLayersFromIds(
296 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
297 kOuterViewportScrollLayerId
);
299 layer_tree_impl
->DidBecomeActive();
300 return layer_tree_impl
->InnerViewportScrollLayer();
303 LayerImpl
* SetupScrollAndContentsLayers(const gfx::Size
& content_size
) {
304 LayerImpl
* scroll_layer
= CreateScrollAndContentsLayers(
305 host_impl_
->active_tree(), content_size
);
306 host_impl_
->active_tree()->DidBecomeActive();
310 // TODO(wjmaclean) Add clip-layer pointer to parameters.
311 scoped_ptr
<LayerImpl
> CreateScrollableLayer(int id
,
312 const gfx::Size
& size
,
313 LayerImpl
* clip_layer
) {
315 DCHECK(id
!= clip_layer
->id());
316 scoped_ptr
<LayerImpl
> layer
=
317 LayerImpl::Create(host_impl_
->active_tree(), id
);
318 layer
->SetScrollClipLayer(clip_layer
->id());
319 layer
->SetDrawsContent(true);
320 layer
->SetBounds(size
);
321 layer
->SetContentBounds(size
);
322 clip_layer
->SetBounds(gfx::Size(size
.width() / 2, size
.height() / 2));
327 LayerTreeHostImpl::FrameData frame
;
328 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
329 host_impl_
->DrawLayers(&frame
);
330 host_impl_
->DidDrawAllLayers(frame
);
333 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor
);
334 void pinch_zoom_pan_viewport_test(float device_scale_factor
);
335 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor
);
336 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
337 float device_scale_factor
);
339 void CheckNotifyCalledIfCanDrawChanged(bool always_draw
) {
340 // Note: It is not possible to disable the renderer once it has been set,
341 // so we do not need to test that disabling the renderer notifies us
342 // that can_draw changed.
343 EXPECT_FALSE(host_impl_
->CanDraw());
344 on_can_draw_state_changed_called_
= false;
346 // Set up the root layer, which allows us to draw.
347 SetupScrollAndContentsLayers(gfx::Size(100, 100));
348 EXPECT_TRUE(host_impl_
->CanDraw());
349 EXPECT_TRUE(on_can_draw_state_changed_called_
);
350 on_can_draw_state_changed_called_
= false;
352 // Toggle the root layer to make sure it toggles can_draw
353 host_impl_
->active_tree()->SetRootLayer(nullptr);
354 EXPECT_FALSE(host_impl_
->CanDraw());
355 EXPECT_TRUE(on_can_draw_state_changed_called_
);
356 on_can_draw_state_changed_called_
= false;
358 SetupScrollAndContentsLayers(gfx::Size(100, 100));
359 EXPECT_TRUE(host_impl_
->CanDraw());
360 EXPECT_TRUE(on_can_draw_state_changed_called_
);
361 on_can_draw_state_changed_called_
= false;
363 // Toggle the device viewport size to make sure it toggles can_draw.
364 host_impl_
->SetViewportSize(gfx::Size());
366 EXPECT_TRUE(host_impl_
->CanDraw());
368 EXPECT_FALSE(host_impl_
->CanDraw());
370 EXPECT_TRUE(on_can_draw_state_changed_called_
);
371 on_can_draw_state_changed_called_
= false;
373 host_impl_
->SetViewportSize(gfx::Size(100, 100));
374 EXPECT_TRUE(host_impl_
->CanDraw());
375 EXPECT_TRUE(on_can_draw_state_changed_called_
);
376 on_can_draw_state_changed_called_
= false;
378 // Toggle contents textures purged without causing any evictions,
379 // and make sure that it does not change can_draw.
380 set_reduce_memory_result(false);
381 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
382 host_impl_
->memory_allocation_limit_bytes() - 1));
383 EXPECT_TRUE(host_impl_
->CanDraw());
384 EXPECT_FALSE(on_can_draw_state_changed_called_
);
385 on_can_draw_state_changed_called_
= false;
387 // Toggle contents textures purged to make sure it toggles can_draw.
388 set_reduce_memory_result(true);
389 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
390 host_impl_
->memory_allocation_limit_bytes() - 1));
392 EXPECT_TRUE(host_impl_
->CanDraw());
394 EXPECT_FALSE(host_impl_
->CanDraw());
396 EXPECT_TRUE(on_can_draw_state_changed_called_
);
397 on_can_draw_state_changed_called_
= false;
399 host_impl_
->active_tree()->ResetContentsTexturesPurged();
400 EXPECT_TRUE(host_impl_
->CanDraw());
401 EXPECT_TRUE(on_can_draw_state_changed_called_
);
402 on_can_draw_state_changed_called_
= false;
405 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor
);
408 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() {
409 return FakeOutputSurface::Create3d();
412 void DrawOneFrame() {
413 LayerTreeHostImpl::FrameData frame_data
;
414 host_impl_
->PrepareToDraw(&frame_data
);
415 host_impl_
->DidDrawAllLayers(frame_data
);
419 DebugScopedSetImplThread always_impl_thread_
;
420 DebugScopedSetMainThreadBlocked always_main_thread_blocked_
;
422 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
423 scoped_ptr
<TestGpuMemoryBufferManager
> gpu_memory_buffer_manager_
;
424 scoped_ptr
<TestTaskGraphRunner
> task_graph_runner_
;
425 scoped_ptr
<LayerTreeHostImpl
> host_impl_
;
426 FakeRenderingStatsInstrumentation stats_instrumentation_
;
427 bool on_can_draw_state_changed_called_
;
428 bool did_notify_ready_to_activate_
;
429 bool did_request_commit_
;
430 bool did_request_redraw_
;
431 bool did_request_animate_
;
432 bool did_request_prepare_tiles_
;
433 bool did_complete_page_scale_animation_
;
434 bool reduce_memory_result_
;
435 base::Closure animation_task_
;
436 base::TimeDelta requested_animation_delay_
;
437 size_t current_limit_bytes_
;
438 int current_priority_cutoff_value_
;
441 TEST_F(LayerTreeHostImplTest
, NotifyIfCanDrawChanged
) {
442 bool always_draw
= false;
443 CheckNotifyCalledIfCanDrawChanged(always_draw
);
446 TEST_F(LayerTreeHostImplTest
, CanDrawIncompleteFrames
) {
447 CreateHostImpl(DefaultSettings(),
448 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
450 bool always_draw
= true;
451 CheckNotifyCalledIfCanDrawChanged(always_draw
);
454 TEST_F(LayerTreeHostImplTest
, ScrollDeltaNoLayers
) {
455 ASSERT_FALSE(host_impl_
->active_tree()->root_layer());
457 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
458 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
461 TEST_F(LayerTreeHostImplTest
, ScrollDeltaTreeButNoChanges
) {
463 scoped_ptr
<LayerImpl
> root
=
464 LayerImpl::Create(host_impl_
->active_tree(), 1);
465 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
466 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 3));
467 root
->children()[1]->AddChild(
468 LayerImpl::Create(host_impl_
->active_tree(), 4));
469 root
->children()[1]->AddChild(
470 LayerImpl::Create(host_impl_
->active_tree(), 5));
471 root
->children()[1]->children()[0]->AddChild(
472 LayerImpl::Create(host_impl_
->active_tree(), 6));
473 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
475 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
477 ExpectClearedScrollDeltasRecursive(root
);
479 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
481 scroll_info
= host_impl_
->ProcessScrollDeltas();
482 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
483 ExpectClearedScrollDeltasRecursive(root
);
485 scroll_info
= host_impl_
->ProcessScrollDeltas();
486 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
487 ExpectClearedScrollDeltasRecursive(root
);
490 TEST_F(LayerTreeHostImplTest
, ScrollDeltaRepeatedScrolls
) {
491 gfx::ScrollOffset
scroll_offset(20, 30);
492 gfx::Vector2d
scroll_delta(11, -15);
494 scoped_ptr
<LayerImpl
> root_clip
=
495 LayerImpl::Create(host_impl_
->active_tree(), 2);
496 scoped_ptr
<LayerImpl
> root
=
497 LayerImpl::Create(host_impl_
->active_tree(), 1);
498 root_clip
->SetBounds(gfx::Size(10, 10));
499 LayerImpl
* root_layer
= root
.get();
500 root_clip
->AddChild(root
.Pass());
501 root_layer
->SetBounds(gfx::Size(110, 110));
502 root_layer
->SetScrollClipLayer(root_clip
->id());
503 root_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
504 root_layer
->ScrollBy(scroll_delta
);
505 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
507 LayerImpl
* root
= host_impl_
->active_tree()->root_layer()->children()[0];
509 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
511 scroll_info
= host_impl_
->ProcessScrollDeltas();
512 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
513 ExpectContains(*scroll_info
, root
->id(), scroll_delta
);
515 gfx::Vector2d
scroll_delta2(-5, 27);
516 root
->ScrollBy(scroll_delta2
);
517 scroll_info
= host_impl_
->ProcessScrollDeltas();
518 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
519 ExpectContains(*scroll_info
, root
->id(), scroll_delta
+ scroll_delta2
);
521 root
->ScrollBy(gfx::Vector2d());
522 scroll_info
= host_impl_
->ProcessScrollDeltas();
523 ExpectContains(*scroll_info
, root
->id(), scroll_delta
+ scroll_delta2
);
526 TEST_F(LayerTreeHostImplTest
, ScrollRootCallsCommitAndRedraw
) {
527 SetupScrollAndContentsLayers(gfx::Size(100, 100));
528 host_impl_
->SetViewportSize(gfx::Size(50, 50));
531 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
532 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
533 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
534 InputHandler::WHEEL
));
535 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
536 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
537 InputHandler::WHEEL
));
538 host_impl_
->ScrollEnd();
539 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
540 InputHandler::WHEEL
));
541 EXPECT_TRUE(did_request_redraw_
);
542 EXPECT_TRUE(did_request_commit_
);
545 TEST_F(LayerTreeHostImplTest
, ScrollActiveOnlyAfterScrollMovement
) {
546 SetupScrollAndContentsLayers(gfx::Size(100, 100));
547 host_impl_
->SetViewportSize(gfx::Size(50, 50));
550 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
551 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
552 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
553 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
554 EXPECT_TRUE(host_impl_
->IsActivelyScrolling());
555 host_impl_
->ScrollEnd();
556 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
559 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRootLayer
) {
560 // We should not crash when trying to scroll an empty layer tree.
561 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
562 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
565 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRenderer
) {
566 scoped_ptr
<TestWebGraphicsContext3D
> context_owned
=
567 TestWebGraphicsContext3D::Create();
568 context_owned
->set_context_lost(true);
570 // Initialization will fail.
571 EXPECT_FALSE(CreateHostImpl(
572 DefaultSettings(), FakeOutputSurface::Create3d(context_owned
.Pass())));
574 SetupScrollAndContentsLayers(gfx::Size(100, 100));
576 // We should not crash when trying to scroll after the renderer initialization
578 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
579 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
582 TEST_F(LayerTreeHostImplTest
, ReplaceTreeWhileScrolling
) {
583 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
584 host_impl_
->SetViewportSize(gfx::Size(50, 50));
587 // We should not crash if the tree is replaced while we are scrolling.
588 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
589 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
590 host_impl_
->active_tree()->DetachLayerTree();
592 scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
594 // We should still be scrolling, because the scrolled layer also exists in the
596 gfx::Vector2d
scroll_delta(0, 10);
597 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
598 host_impl_
->ScrollEnd();
599 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
600 ExpectContains(*scroll_info
, scroll_layer
->id(), scroll_delta
);
603 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnWheelEventHandlers
) {
604 SetupScrollAndContentsLayers(gfx::Size(100, 100));
605 host_impl_
->SetViewportSize(gfx::Size(50, 50));
607 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
609 // With registered event handlers, wheel scrolls don't necessarily
610 // have to go to the main thread.
611 root
->SetHaveWheelEventHandlers(true);
612 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
613 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
614 host_impl_
->ScrollEnd();
616 // But typically the scroll-blocks-on mode will require them to.
617 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
618 SCROLL_BLOCKS_ON_START_TOUCH
);
619 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
620 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
622 // But gesture scrolls can still be handled.
623 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
624 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
625 host_impl_
->ScrollEnd();
627 // And if the handlers go away, wheel scrolls can again be processed
628 // on impl (despite the scroll-blocks-on mode).
629 root
->SetHaveWheelEventHandlers(false);
630 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
631 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
632 host_impl_
->ScrollEnd();
635 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnTouchEventHandlers
) {
636 LayerImpl
* scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
637 host_impl_
->SetViewportSize(gfx::Size(50, 50));
639 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
641 LayerImpl
* child
= 0;
643 scoped_ptr
<LayerImpl
> child_layer
=
644 LayerImpl::Create(host_impl_
->active_tree(), 6);
645 child
= child_layer
.get();
646 child_layer
->SetDrawsContent(true);
647 child_layer
->SetPosition(gfx::PointF(0, 20));
648 child_layer
->SetBounds(gfx::Size(50, 50));
649 child_layer
->SetContentBounds(gfx::Size(50, 50));
650 scroll
->AddChild(child_layer
.Pass());
653 // Touch handler regions determine whether touch events block scroll.
654 root
->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
655 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
656 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
|
657 SCROLL_BLOCKS_ON_WHEEL_EVENT
);
658 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
660 // But they don't influence the actual handling of the scroll gestures.
661 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
662 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
663 host_impl_
->ScrollEnd();
665 // It's the union of scroll-blocks-on mode bits across all layers in the
666 // scroll paret chain that matters.
667 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
668 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE
);
669 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
670 child
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
);
671 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
674 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnScrollEventHandlers
) {
675 SetupScrollAndContentsLayers(gfx::Size(100, 100));
676 host_impl_
->SetViewportSize(gfx::Size(50, 50));
678 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
680 // With registered scroll handlers, scrolls don't generally have to go
681 // to the main thread.
682 root
->SetHaveScrollEventHandlers(true);
683 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
684 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
685 host_impl_
->ScrollEnd();
687 // Even the default scroll blocks on mode doesn't require this.
688 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
689 SCROLL_BLOCKS_ON_START_TOUCH
);
690 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
691 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
692 host_impl_
->ScrollEnd();
694 // But the page can opt in to blocking on scroll event handlers.
695 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
696 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
697 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
699 // GESTURE and WHEEL scrolls behave identically in this regard.
700 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
701 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
703 // And if the handlers go away, scrolls can again be processed on impl
704 // (despite the scroll-blocks-on mode).
705 root
->SetHaveScrollEventHandlers(false);
706 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
707 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
708 host_impl_
->ScrollEnd();
711 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnLayerTopology
) {
712 host_impl_
->SetViewportSize(gfx::Size(50, 50));
714 // Create a normal scrollable root layer
715 LayerImpl
* root_scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
716 LayerImpl
* root_child
= root_scroll
->children()[0];
717 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
720 // Create two child scrollable layers
721 LayerImpl
* child1
= 0;
723 scoped_ptr
<LayerImpl
> scrollable_child_clip_1
=
724 LayerImpl::Create(host_impl_
->active_tree(), 6);
725 scoped_ptr
<LayerImpl
> scrollable_child_1
= CreateScrollableLayer(
726 7, gfx::Size(10, 10), scrollable_child_clip_1
.get());
727 child1
= scrollable_child_1
.get();
728 scrollable_child_1
->SetPosition(gfx::Point(5, 5));
729 scrollable_child_1
->SetHaveWheelEventHandlers(true);
730 scrollable_child_1
->SetHaveScrollEventHandlers(true);
731 scrollable_child_clip_1
->AddChild(scrollable_child_1
.Pass());
732 root_child
->AddChild(scrollable_child_clip_1
.Pass());
735 LayerImpl
* child2
= 0;
737 scoped_ptr
<LayerImpl
> scrollable_child_clip_2
=
738 LayerImpl::Create(host_impl_
->active_tree(), 8);
739 scoped_ptr
<LayerImpl
> scrollable_child_2
= CreateScrollableLayer(
740 9, gfx::Size(10, 10), scrollable_child_clip_2
.get());
741 child2
= scrollable_child_2
.get();
742 scrollable_child_2
->SetPosition(gfx::Point(5, 20));
743 scrollable_child_2
->SetHaveWheelEventHandlers(true);
744 scrollable_child_2
->SetHaveScrollEventHandlers(true);
745 scrollable_child_clip_2
->AddChild(scrollable_child_2
.Pass());
746 root_child
->AddChild(scrollable_child_clip_2
.Pass());
749 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
750 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
751 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
752 host_impl_
->ScrollEnd();
753 child1
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
754 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
755 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
757 // But not those that hit only other layers.
758 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
759 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
760 host_impl_
->ScrollEnd();
762 // It's the union of bits set across the scroll ancestor chain that matters.
763 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
764 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
765 host_impl_
->ScrollEnd();
766 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
767 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
768 host_impl_
->ScrollEnd();
769 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
);
770 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
771 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
772 host_impl_
->ScrollEnd();
773 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
774 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
775 child2
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
776 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
777 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
778 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
779 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
782 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchscreen
) {
783 SetupScrollAndContentsLayers(gfx::Size(100, 100));
784 host_impl_
->SetViewportSize(gfx::Size(50, 50));
787 // Ignore the fling since no layer is being scrolled
788 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
790 // Start scrolling a layer
791 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
792 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
794 // Now the fling should go ahead since we've started scrolling a layer
795 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
798 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchpad
) {
799 SetupScrollAndContentsLayers(gfx::Size(100, 100));
800 host_impl_
->SetViewportSize(gfx::Size(50, 50));
803 // Ignore the fling since no layer is being scrolled
804 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
806 // Start scrolling a layer
807 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
808 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
810 // Now the fling should go ahead since we've started scrolling a layer
811 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
814 TEST_F(LayerTreeHostImplTest
, NoFlingWhenScrollingOnMain
) {
815 SetupScrollAndContentsLayers(gfx::Size(100, 100));
816 host_impl_
->SetViewportSize(gfx::Size(50, 50));
818 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
820 root
->SetShouldScrollOnMainThread(true);
822 // Start scrolling a layer
823 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
824 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
826 // The fling should be ignored since there's no layer being scrolled impl-side
827 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
830 TEST_F(LayerTreeHostImplTest
, ShouldScrollOnMainThread
) {
831 SetupScrollAndContentsLayers(gfx::Size(100, 100));
832 host_impl_
->SetViewportSize(gfx::Size(50, 50));
834 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
836 root
->SetShouldScrollOnMainThread(true);
838 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
839 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
840 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
841 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
844 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionBasic
) {
845 SetupScrollAndContentsLayers(gfx::Size(200, 200));
846 host_impl_
->SetViewportSize(gfx::Size(100, 100));
848 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
849 root
->SetContentsScale(2.f
, 2.f
);
850 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
854 // All scroll types inside the non-fast scrollable region should fail.
855 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
856 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL
));
857 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
858 InputHandler::WHEEL
));
859 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
860 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE
));
861 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
862 InputHandler::GESTURE
));
864 // All scroll types outside this region should succeed.
865 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
866 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL
));
867 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
868 InputHandler::GESTURE
));
869 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
870 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
871 InputHandler::GESTURE
));
872 host_impl_
->ScrollEnd();
873 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
874 InputHandler::GESTURE
));
875 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
876 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE
));
877 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
878 InputHandler::GESTURE
));
879 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
880 host_impl_
->ScrollEnd();
881 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
882 InputHandler::GESTURE
));
885 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionWithOffset
) {
886 SetupScrollAndContentsLayers(gfx::Size(200, 200));
887 host_impl_
->SetViewportSize(gfx::Size(100, 100));
889 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
890 root
->SetContentsScale(2.f
, 2.f
);
891 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
892 root
->SetPosition(gfx::PointF(-25.f
, 0.f
));
896 // This point would fall into the non-fast scrollable region except that we've
897 // moved the layer down by 25 pixels.
898 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
899 host_impl_
->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL
));
900 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
901 InputHandler::WHEEL
));
902 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
903 host_impl_
->ScrollEnd();
905 // This point is still inside the non-fast region.
906 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
907 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL
));
910 TEST_F(LayerTreeHostImplTest
, ScrollHandlerNotPresent
) {
911 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
912 EXPECT_FALSE(scroll_layer
->have_scroll_event_handlers());
913 host_impl_
->SetViewportSize(gfx::Size(50, 50));
916 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
917 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
918 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
919 host_impl_
->ScrollEnd();
920 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
923 TEST_F(LayerTreeHostImplTest
, ScrollHandlerPresent
) {
924 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
925 scroll_layer
->SetHaveScrollEventHandlers(true);
926 host_impl_
->SetViewportSize(gfx::Size(50, 50));
929 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
930 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
931 EXPECT_TRUE(host_impl_
->scroll_affects_scroll_handler());
932 host_impl_
->ScrollEnd();
933 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
936 TEST_F(LayerTreeHostImplTest
, ScrollByReturnsCorrectValue
) {
937 SetupScrollAndContentsLayers(gfx::Size(200, 200));
938 host_impl_
->SetViewportSize(gfx::Size(100, 100));
942 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
943 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
945 // Trying to scroll to the left/top will not succeed.
947 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
949 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
951 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
953 // Scrolling to the right/bottom will succeed.
955 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll
);
957 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
959 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll
);
961 // Scrolling to left/top will now succeed.
963 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
965 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
967 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
969 // Scrolling diagonally against an edge will succeed.
971 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll
);
973 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
975 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll
);
977 // Trying to scroll more than the available space will also succeed.
979 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll
);
982 TEST_F(LayerTreeHostImplTest
, ScrollVerticallyByPageReturnsCorrectValue
) {
983 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
984 host_impl_
->SetViewportSize(gfx::Size(100, 1000));
988 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
989 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
991 // Trying to scroll without a vertical scrollbar will fail.
992 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
993 gfx::Point(), SCROLL_FORWARD
));
994 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
995 gfx::Point(), SCROLL_BACKWARD
));
997 scoped_ptr
<PaintedScrollbarLayerImpl
> vertical_scrollbar(
998 PaintedScrollbarLayerImpl::Create(
999 host_impl_
->active_tree(),
1002 vertical_scrollbar
->SetBounds(gfx::Size(15, 1000));
1003 host_impl_
->InnerViewportScrollLayer()->AddScrollbar(
1004 vertical_scrollbar
.get());
1006 // Trying to scroll with a vertical scrollbar will succeed.
1007 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1008 gfx::Point(), SCROLL_FORWARD
));
1009 EXPECT_FLOAT_EQ(875.f
,
1010 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
1011 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1012 gfx::Point(), SCROLL_BACKWARD
));
1015 TEST_F(LayerTreeHostImplTest
, ScrollWithUserUnscrollableLayers
) {
1016 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
1017 host_impl_
->SetViewportSize(gfx::Size(100, 100));
1019 gfx::Size
overflow_size(400, 400);
1020 ASSERT_EQ(1u, scroll_layer
->children().size());
1021 LayerImpl
* overflow
= scroll_layer
->children()[0];
1022 overflow
->SetBounds(overflow_size
);
1023 overflow
->SetContentBounds(overflow_size
);
1024 overflow
->SetScrollClipLayer(scroll_layer
->parent()->id());
1025 overflow
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1026 overflow
->SetPosition(gfx::PointF());
1029 gfx::Point
scroll_position(10, 10);
1031 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1032 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1033 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1034 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow
->CurrentScrollOffset());
1036 gfx::Vector2dF
scroll_delta(10, 10);
1037 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1038 host_impl_
->ScrollEnd();
1039 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1040 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1042 overflow
->set_user_scrollable_horizontal(false);
1044 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1045 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1046 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1047 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1049 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1050 host_impl_
->ScrollEnd();
1051 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1052 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1054 overflow
->set_user_scrollable_vertical(false);
1056 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1057 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1058 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1059 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1061 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1062 host_impl_
->ScrollEnd();
1063 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer
->CurrentScrollOffset());
1064 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1067 TEST_F(LayerTreeHostImplTest
, ImplPinchZoom
) {
1068 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
1069 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1072 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
1073 LayerImpl
* container_layer
= scroll_layer
->scroll_clip_layer();
1074 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1076 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1077 float page_scale_factor
= 1.f
;
1079 // The impl-based pinch zoom should adjust the max scroll position.
1081 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1082 page_scale_factor
, min_page_scale
, max_page_scale
);
1083 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1084 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1086 float page_scale_delta
= 2.f
;
1088 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1089 host_impl_
->PinchGestureBegin();
1090 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1091 host_impl_
->PinchGestureEnd();
1092 host_impl_
->ScrollEnd();
1093 EXPECT_FALSE(did_request_animate_
);
1094 EXPECT_TRUE(did_request_redraw_
);
1095 EXPECT_TRUE(did_request_commit_
);
1096 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1098 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1099 host_impl_
->ProcessScrollDeltas();
1100 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1102 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1103 scroll_layer
->MaxScrollOffset().ToString());
1106 // Scrolling after a pinch gesture should always be in local space. The
1107 // scroll deltas have the page scale factor applied.
1109 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1110 page_scale_factor
, min_page_scale
, max_page_scale
);
1111 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1112 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1114 float page_scale_delta
= 2.f
;
1115 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1116 host_impl_
->PinchGestureBegin();
1117 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1118 host_impl_
->PinchGestureEnd();
1119 host_impl_
->ScrollEnd();
1121 gfx::Vector2d
scroll_delta(0, 10);
1122 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1123 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
1124 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1125 host_impl_
->ScrollEnd();
1127 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1128 host_impl_
->ProcessScrollDeltas();
1129 ExpectContains(*scroll_info
.get(), scroll_layer
->id(),
1130 gfx::Vector2d(0, scroll_delta
.y() / page_scale_delta
));
1134 TEST_F(LayerTreeHostImplTest
, ScrollWithSwapPromises
) {
1135 ui::LatencyInfo latency_info
;
1136 latency_info
.trace_id
= 1234;
1137 scoped_ptr
<SwapPromise
> swap_promise(
1138 new LatencyInfoSwapPromise(latency_info
));
1140 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1141 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1142 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
1143 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1144 host_impl_
->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise
.Pass());
1145 host_impl_
->ScrollEnd();
1147 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1148 EXPECT_EQ(1u, scroll_info
->swap_promises
.size());
1149 EXPECT_EQ(latency_info
.trace_id
, scroll_info
->swap_promises
[0]->TraceId());
1152 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
1153 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1154 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1157 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1158 DCHECK(scroll_layer
);
1160 float min_page_scale
= 1.f
;
1161 float max_page_scale
= 4.f
;
1163 // Basic pinch zoom in gesture
1165 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1167 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1169 float page_scale_delta
= 2.f
;
1170 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1171 host_impl_
->PinchGestureBegin();
1172 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1173 host_impl_
->PinchGestureEnd();
1174 host_impl_
->ScrollEnd();
1175 EXPECT_FALSE(did_request_animate_
);
1176 EXPECT_TRUE(did_request_redraw_
);
1177 EXPECT_TRUE(did_request_commit_
);
1179 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1180 host_impl_
->ProcessScrollDeltas();
1181 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1186 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1188 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1189 float page_scale_delta
= 10.f
;
1191 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1192 host_impl_
->PinchGestureBegin();
1193 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1194 host_impl_
->PinchGestureEnd();
1195 host_impl_
->ScrollEnd();
1197 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1198 host_impl_
->ProcessScrollDeltas();
1199 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
1202 // Zoom-out clamping
1204 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1206 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1207 scroll_layer
->PullDeltaForMainThread();
1208 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1210 float page_scale_delta
= 0.1f
;
1211 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1212 host_impl_
->PinchGestureBegin();
1213 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1214 host_impl_
->PinchGestureEnd();
1215 host_impl_
->ScrollEnd();
1217 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1218 host_impl_
->ProcessScrollDeltas();
1219 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1221 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1224 // Two-finger panning should not happen based on pinch events only
1226 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1228 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1229 scroll_layer
->PullDeltaForMainThread();
1230 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1232 float page_scale_delta
= 1.f
;
1233 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1234 host_impl_
->PinchGestureBegin();
1235 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1236 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1237 host_impl_
->PinchGestureEnd();
1238 host_impl_
->ScrollEnd();
1240 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1241 host_impl_
->ProcessScrollDeltas();
1242 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1243 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1246 // Two-finger panning should work with interleaved scroll events
1248 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1250 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1251 scroll_layer
->PullDeltaForMainThread();
1252 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1254 float page_scale_delta
= 1.f
;
1255 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1256 host_impl_
->PinchGestureBegin();
1257 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1258 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1259 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1260 host_impl_
->PinchGestureEnd();
1261 host_impl_
->ScrollEnd();
1263 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1264 host_impl_
->ProcessScrollDeltas();
1265 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1266 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-10, -10));
1269 // Two-finger panning should work when starting fully zoomed out.
1271 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.5f
, 0.5f
, 4.f
);
1272 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1273 scroll_layer
->PullDeltaForMainThread();
1274 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1276 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1277 host_impl_
->PinchGestureBegin();
1278 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1279 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(0, 0));
1280 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1281 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(10, 10));
1282 host_impl_
->PinchGestureEnd();
1283 host_impl_
->ScrollEnd();
1285 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1286 host_impl_
->ProcessScrollDeltas();
1287 EXPECT_EQ(scroll_info
->page_scale_delta
, 2.f
);
1288 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(20, 20));
1292 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
1293 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1294 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1297 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1298 DCHECK(scroll_layer
);
1300 float min_page_scale
= 0.5f
;
1301 float max_page_scale
= 4.f
;
1302 base::TimeTicks start_time
= base::TimeTicks() +
1303 base::TimeDelta::FromSeconds(1);
1304 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1305 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1306 base::TimeTicks end_time
= start_time
+ duration
;
1308 // Non-anchor zoom-in
1310 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1312 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1314 did_request_redraw_
= false;
1315 did_request_animate_
= false;
1316 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1317 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1322 host_impl_
->ActivateSyncTree();
1323 EXPECT_FALSE(did_request_redraw_
);
1324 EXPECT_TRUE(did_request_animate_
);
1326 did_request_redraw_
= false;
1327 did_request_animate_
= false;
1328 host_impl_
->Animate(start_time
);
1329 EXPECT_TRUE(did_request_redraw_
);
1330 EXPECT_TRUE(did_request_animate_
);
1332 did_request_redraw_
= false;
1333 did_request_animate_
= false;
1334 host_impl_
->Animate(halfway_through_animation
);
1335 EXPECT_TRUE(did_request_redraw_
);
1336 EXPECT_TRUE(did_request_animate_
);
1338 did_request_redraw_
= false;
1339 did_request_animate_
= false;
1340 did_request_commit_
= false;
1341 host_impl_
->Animate(end_time
);
1342 EXPECT_TRUE(did_request_commit_
);
1343 EXPECT_FALSE(did_request_animate_
);
1345 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1346 host_impl_
->ProcessScrollDeltas();
1347 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
1348 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1353 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1355 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1357 did_request_redraw_
= false;
1358 did_request_animate_
= false;
1359 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1360 scoped_ptr
<PendingPageScaleAnimation
> (new PendingPageScaleAnimation(
1361 gfx::Vector2d(25, 25),
1365 host_impl_
->ActivateSyncTree();
1366 EXPECT_FALSE(did_request_redraw_
);
1367 EXPECT_TRUE(did_request_animate_
);
1369 did_request_redraw_
= false;
1370 did_request_animate_
= false;
1371 host_impl_
->Animate(start_time
);
1372 EXPECT_TRUE(did_request_redraw_
);
1373 EXPECT_TRUE(did_request_animate_
);
1375 did_request_redraw_
= false;
1376 did_request_commit_
= false;
1377 did_request_animate_
= false;
1378 host_impl_
->Animate(end_time
);
1379 EXPECT_TRUE(did_request_redraw_
);
1380 EXPECT_FALSE(did_request_animate_
);
1381 EXPECT_TRUE(did_request_commit_
);
1383 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1384 host_impl_
->ProcessScrollDeltas();
1385 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1386 // Pushed to (0,0) via clamping against contents layer size.
1387 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1391 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
1392 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1393 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1396 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1397 DCHECK(scroll_layer
);
1399 float min_page_scale
= 0.5f
;
1400 float max_page_scale
= 4.f
;
1401 base::TimeTicks start_time
= base::TimeTicks() +
1402 base::TimeDelta::FromSeconds(1);
1403 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1404 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1405 base::TimeTicks end_time
= start_time
+ duration
;
1407 // Anchor zoom with unchanged page scale should not change scroll or scale.
1409 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1411 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1413 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1414 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1419 host_impl_
->ActivateSyncTree();
1420 host_impl_
->Animate(start_time
);
1421 host_impl_
->Animate(halfway_through_animation
);
1422 EXPECT_TRUE(did_request_redraw_
);
1423 host_impl_
->Animate(end_time
);
1424 EXPECT_TRUE(did_request_commit_
);
1426 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1427 host_impl_
->ProcessScrollDeltas();
1428 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
1429 ExpectNone(*scroll_info
, scroll_layer
->id());
1433 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationTransferedOnSyncTreeActivate
) {
1434 host_impl_
->CreatePendingTree();
1435 CreateScrollAndContentsLayers(
1436 host_impl_
->pending_tree(),
1437 gfx::Size(100, 100));
1438 host_impl_
->ActivateSyncTree();
1441 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1442 DCHECK(scroll_layer
);
1444 float min_page_scale
= 0.5f
;
1445 float max_page_scale
= 4.f
;
1446 host_impl_
->sync_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1448 host_impl_
->ActivateSyncTree();
1450 base::TimeTicks start_time
= base::TimeTicks() +
1451 base::TimeDelta::FromSeconds(1);
1452 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1453 base::TimeTicks third_through_animation
= start_time
+ duration
/ 3;
1454 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1455 base::TimeTicks end_time
= start_time
+ duration
;
1456 float target_scale
= 2.f
;
1458 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1460 // Make sure TakePageScaleAnimation works properly.
1462 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1463 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1468 scoped_ptr
<PendingPageScaleAnimation
> psa
=
1469 host_impl_
->sync_tree()->TakePendingPageScaleAnimation();
1470 EXPECT_EQ(target_scale
, psa
->scale
);
1471 EXPECT_EQ(duration
, psa
->duration
);
1472 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePendingPageScaleAnimation());
1474 // Recreate the PSA. Nothing should happen here since the tree containing the
1475 // PSA hasn't been activated yet.
1476 did_request_redraw_
= false;
1477 did_request_animate_
= false;
1478 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1479 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1484 host_impl_
->Animate(halfway_through_animation
);
1485 EXPECT_FALSE(did_request_animate_
);
1486 EXPECT_FALSE(did_request_redraw_
);
1488 // Activate the sync tree. This should cause the animation to become enabled.
1489 // It should also clear the pointer on the sync tree.
1490 host_impl_
->ActivateSyncTree();
1492 host_impl_
->sync_tree()->TakePendingPageScaleAnimation().get());
1493 EXPECT_FALSE(did_request_redraw_
);
1494 EXPECT_TRUE(did_request_animate_
);
1496 // From here on, make sure the animation runs as normal.
1497 did_request_redraw_
= false;
1498 did_request_animate_
= false;
1499 host_impl_
->Animate(start_time
);
1500 EXPECT_TRUE(did_request_redraw_
);
1501 EXPECT_TRUE(did_request_animate_
);
1503 did_request_redraw_
= false;
1504 did_request_animate_
= false;
1505 host_impl_
->Animate(third_through_animation
);
1506 EXPECT_TRUE(did_request_redraw_
);
1507 EXPECT_TRUE(did_request_animate_
);
1509 // Another activation shouldn't have any effect on the animation.
1510 host_impl_
->ActivateSyncTree();
1512 did_request_redraw_
= false;
1513 did_request_animate_
= false;
1514 host_impl_
->Animate(halfway_through_animation
);
1515 EXPECT_TRUE(did_request_redraw_
);
1516 EXPECT_TRUE(did_request_animate_
);
1518 did_request_redraw_
= false;
1519 did_request_animate_
= false;
1520 did_request_commit_
= false;
1521 host_impl_
->Animate(end_time
);
1522 EXPECT_TRUE(did_request_commit_
);
1523 EXPECT_FALSE(did_request_animate_
);
1525 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1526 host_impl_
->ProcessScrollDeltas();
1527 EXPECT_EQ(scroll_info
->page_scale_delta
, target_scale
);
1528 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1531 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationCompletedNotification
) {
1532 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1533 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1536 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1537 DCHECK(scroll_layer
);
1539 base::TimeTicks start_time
=
1540 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
1541 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1542 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1543 base::TimeTicks end_time
= start_time
+ duration
;
1545 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
1546 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1548 did_complete_page_scale_animation_
= false;
1549 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1550 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1551 gfx::Vector2d(), false, 2.f
, duration
)));
1552 host_impl_
->ActivateSyncTree();
1553 host_impl_
->Animate(start_time
);
1554 EXPECT_FALSE(did_complete_page_scale_animation_
);
1556 host_impl_
->Animate(halfway_through_animation
);
1557 EXPECT_FALSE(did_complete_page_scale_animation_
);
1559 host_impl_
->Animate(end_time
);
1560 EXPECT_TRUE(did_complete_page_scale_animation_
);
1563 class LayerTreeHostImplOverridePhysicalTime
: public LayerTreeHostImpl
{
1565 LayerTreeHostImplOverridePhysicalTime(
1566 const LayerTreeSettings
& settings
,
1567 LayerTreeHostImplClient
* client
,
1569 SharedBitmapManager
* manager
,
1570 RenderingStatsInstrumentation
* rendering_stats_instrumentation
)
1571 : LayerTreeHostImpl(settings
,
1574 rendering_stats_instrumentation
,
1580 BeginFrameArgs
CurrentBeginFrameArgs() const override
{
1581 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
,
1582 fake_current_physical_time_
);
1585 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now
) {
1586 fake_current_physical_time_
= fake_now
;
1590 base::TimeTicks fake_current_physical_time_
;
1593 class LayerTreeHostImplTestScrollbarAnimation
: public LayerTreeHostImplTest
{
1595 void SetupLayers(LayerTreeSettings settings
) {
1596 gfx::Size
viewport_size(10, 10);
1597 gfx::Size
content_size(100, 100);
1599 LayerTreeHostImplOverridePhysicalTime
* host_impl_override_time
=
1600 new LayerTreeHostImplOverridePhysicalTime(settings
, this, &proxy_
,
1601 shared_bitmap_manager_
.get(),
1602 &stats_instrumentation_
);
1603 host_impl_
= make_scoped_ptr(host_impl_override_time
);
1604 host_impl_
->InitializeRenderer(CreateOutputSurface());
1605 host_impl_
->SetViewportSize(viewport_size
);
1607 scoped_ptr
<LayerImpl
> root
=
1608 LayerImpl::Create(host_impl_
->active_tree(), 1);
1609 root
->SetBounds(viewport_size
);
1611 scoped_ptr
<LayerImpl
> scroll
=
1612 LayerImpl::Create(host_impl_
->active_tree(), 2);
1613 scroll
->SetScrollClipLayer(root
->id());
1614 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1615 root
->SetBounds(viewport_size
);
1616 scroll
->SetBounds(content_size
);
1617 scroll
->SetContentBounds(content_size
);
1618 scroll
->SetIsContainerForFixedPositionLayers(true);
1620 scoped_ptr
<LayerImpl
> contents
=
1621 LayerImpl::Create(host_impl_
->active_tree(), 3);
1622 contents
->SetDrawsContent(true);
1623 contents
->SetBounds(content_size
);
1624 contents
->SetContentBounds(content_size
);
1626 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar
=
1627 SolidColorScrollbarLayerImpl::Create(host_impl_
->active_tree(), 4,
1628 VERTICAL
, 10, 0, false, true);
1629 EXPECT_FLOAT_EQ(0.f
, scrollbar
->opacity());
1631 scroll
->AddChild(contents
.Pass());
1632 root
->AddChild(scroll
.Pass());
1633 root
->SetHasRenderSurface(true);
1634 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
1635 root
->AddChild(scrollbar
.Pass());
1637 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1638 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
1640 host_impl_
->active_tree()->DidBecomeActive();
1644 void RunTest(LayerTreeSettings::ScrollbarAnimator animator
) {
1645 LayerTreeSettings settings
;
1646 settings
.scrollbar_animator
= animator
;
1647 settings
.scrollbar_fade_delay_ms
= 20;
1648 settings
.scrollbar_fade_duration_ms
= 20;
1650 SetupLayers(settings
);
1652 base::TimeTicks fake_now
= gfx::FrameTime::Now();
1654 EXPECT_FALSE(did_request_animate_
);
1655 EXPECT_FALSE(did_request_redraw_
);
1656 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1657 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1659 // If no scroll happened during a scroll gesture, it should have no effect.
1660 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1661 host_impl_
->ScrollEnd();
1662 EXPECT_FALSE(did_request_animate_
);
1663 EXPECT_FALSE(did_request_redraw_
);
1664 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1665 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1667 // After a scroll, a scrollbar animation should be scheduled about 20ms from
1669 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1670 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1671 EXPECT_FALSE(did_request_animate_
);
1672 EXPECT_TRUE(did_request_redraw_
);
1673 did_request_redraw_
= false;
1674 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1675 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1677 host_impl_
->ScrollEnd();
1678 EXPECT_FALSE(did_request_animate_
);
1679 EXPECT_FALSE(did_request_redraw_
);
1680 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1681 requested_animation_delay_
);
1682 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1684 fake_now
+= requested_animation_delay_
;
1685 requested_animation_delay_
= base::TimeDelta();
1686 animation_task_
.Run();
1687 animation_task_
= base::Closure();
1688 EXPECT_TRUE(did_request_animate_
);
1689 did_request_animate_
= false;
1690 EXPECT_FALSE(did_request_redraw_
);
1692 // After the scrollbar animation begins, we should start getting redraws.
1693 host_impl_
->Animate(fake_now
);
1694 EXPECT_TRUE(did_request_animate_
);
1695 did_request_animate_
= false;
1696 EXPECT_TRUE(did_request_redraw_
);
1697 did_request_redraw_
= false;
1698 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1699 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1701 // Setting the scroll offset outside a scroll should also cause the
1702 // scrollbar to appear and to schedule a scrollbar animation.
1703 host_impl_
->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
1704 gfx::ScrollOffset(5, 5));
1705 EXPECT_FALSE(did_request_animate_
);
1706 EXPECT_FALSE(did_request_redraw_
);
1707 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1708 requested_animation_delay_
);
1709 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1710 requested_animation_delay_
= base::TimeDelta();
1711 animation_task_
= base::Closure();
1713 // Scrollbar animation is not triggered unnecessarily.
1714 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1715 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1716 EXPECT_FALSE(did_request_animate_
);
1717 EXPECT_TRUE(did_request_redraw_
);
1718 did_request_redraw_
= false;
1719 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1720 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1722 host_impl_
->ScrollEnd();
1723 EXPECT_FALSE(did_request_animate_
);
1724 EXPECT_FALSE(did_request_redraw_
);
1725 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1726 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1728 // Changing page scale triggers scrollbar animation.
1729 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
1730 host_impl_
->SetPageScaleOnActiveTree(1.1f
);
1731 EXPECT_FALSE(did_request_animate_
);
1732 EXPECT_FALSE(did_request_redraw_
);
1733 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1734 requested_animation_delay_
);
1735 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1736 requested_animation_delay_
= base::TimeDelta();
1737 animation_task_
= base::Closure();
1741 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, LinearFade
) {
1742 RunTest(LayerTreeSettings::LINEAR_FADE
);
1745 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, Thinning
) {
1746 RunTest(LayerTreeSettings::THINNING
);
1749 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1750 float device_scale_factor
) {
1751 LayerTreeSettings settings
;
1752 settings
.scrollbar_fade_delay_ms
= 500;
1753 settings
.scrollbar_fade_duration_ms
= 300;
1754 settings
.scrollbar_animator
= LayerTreeSettings::THINNING
;
1756 gfx::Size
viewport_size(300, 200);
1757 gfx::Size device_viewport_size
= gfx::ToFlooredSize(
1758 gfx::ScaleSize(viewport_size
, device_scale_factor
));
1759 gfx::Size
content_size(1000, 1000);
1761 CreateHostImpl(settings
, CreateOutputSurface());
1762 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
1763 host_impl_
->SetViewportSize(device_viewport_size
);
1765 scoped_ptr
<LayerImpl
> root
=
1766 LayerImpl::Create(host_impl_
->active_tree(), 1);
1767 root
->SetBounds(viewport_size
);
1768 root
->SetHasRenderSurface(true);
1770 scoped_ptr
<LayerImpl
> scroll
=
1771 LayerImpl::Create(host_impl_
->active_tree(), 2);
1772 scroll
->SetScrollClipLayer(root
->id());
1773 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1774 scroll
->SetBounds(content_size
);
1775 scroll
->SetContentBounds(content_size
);
1776 scroll
->SetIsContainerForFixedPositionLayers(true);
1778 scoped_ptr
<LayerImpl
> contents
=
1779 LayerImpl::Create(host_impl_
->active_tree(), 3);
1780 contents
->SetDrawsContent(true);
1781 contents
->SetBounds(content_size
);
1782 contents
->SetContentBounds(content_size
);
1784 // The scrollbar is on the right side.
1785 scoped_ptr
<PaintedScrollbarLayerImpl
> scrollbar
=
1786 PaintedScrollbarLayerImpl::Create(host_impl_
->active_tree(), 5, VERTICAL
);
1787 scrollbar
->SetDrawsContent(true);
1788 scrollbar
->SetBounds(gfx::Size(15, viewport_size
.height()));
1789 scrollbar
->SetContentBounds(gfx::Size(15, viewport_size
.height()));
1790 scrollbar
->SetPosition(gfx::Point(285, 0));
1792 scroll
->AddChild(contents
.Pass());
1793 root
->AddChild(scroll
.Pass());
1794 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
1795 root
->AddChild(scrollbar
.Pass());
1797 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1798 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
1800 host_impl_
->active_tree()->DidBecomeActive();
1803 LayerImpl
* root_scroll
=
1804 host_impl_
->active_tree()->InnerViewportScrollLayer();
1805 ASSERT_TRUE(root_scroll
->scrollbar_animation_controller());
1806 ScrollbarAnimationControllerThinning
* scrollbar_animation_controller
=
1807 static_cast<ScrollbarAnimationControllerThinning
*>(
1808 root_scroll
->scrollbar_animation_controller());
1809 scrollbar_animation_controller
->set_mouse_move_distance_for_test(100.f
);
1811 host_impl_
->MouseMoveAt(gfx::Point(1, 1));
1812 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1814 host_impl_
->MouseMoveAt(gfx::Point(200, 50));
1815 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1817 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
1818 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1820 scrollbar_animation_controller
->set_mouse_move_distance_for_test(102.f
);
1821 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
1822 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1824 did_request_redraw_
= false;
1825 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1826 host_impl_
->MouseMoveAt(gfx::Point(290, 100));
1827 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1828 host_impl_
->MouseMoveAt(gfx::Point(290, 120));
1829 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1830 host_impl_
->MouseMoveAt(gfx::Point(150, 120));
1831 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1834 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf1
) {
1835 SetupMouseMoveAtWithDeviceScale(1.f
);
1838 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf2
) {
1839 SetupMouseMoveAtWithDeviceScale(2.f
);
1842 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
1843 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1844 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1845 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
1848 CompositorFrameMetadata metadata
=
1849 host_impl_
->MakeCompositorFrameMetadata();
1850 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
1851 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
1852 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.scrollable_viewport_size
);
1853 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1854 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1855 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1856 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
1857 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
1860 // Scrolling should update metadata immediately.
1861 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1862 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
1863 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1865 CompositorFrameMetadata metadata
=
1866 host_impl_
->MakeCompositorFrameMetadata();
1867 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1869 host_impl_
->ScrollEnd();
1871 CompositorFrameMetadata metadata
=
1872 host_impl_
->MakeCompositorFrameMetadata();
1873 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1876 // Root "overflow: hidden" properties should be reflected on the outer
1877 // viewport scroll layer.
1879 host_impl_
->active_tree()
1880 ->OuterViewportScrollLayer()
1881 ->set_user_scrollable_horizontal(false);
1882 CompositorFrameMetadata metadata
=
1883 host_impl_
->MakeCompositorFrameMetadata();
1884 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
1885 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
1887 host_impl_
->active_tree()
1888 ->OuterViewportScrollLayer()
1889 ->set_user_scrollable_vertical(false);
1890 metadata
= host_impl_
->MakeCompositorFrameMetadata();
1891 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
1892 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
1895 // Page scale should update metadata correctly (shrinking only the viewport).
1896 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1897 host_impl_
->PinchGestureBegin();
1898 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
1899 host_impl_
->PinchGestureEnd();
1900 host_impl_
->ScrollEnd();
1902 CompositorFrameMetadata metadata
=
1903 host_impl_
->MakeCompositorFrameMetadata();
1904 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1905 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
1906 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.scrollable_viewport_size
);
1907 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1908 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1909 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1912 // Likewise if set from the main thread.
1913 host_impl_
->ProcessScrollDeltas();
1914 host_impl_
->active_tree()->PushPageScaleFromMainThread(4.f
, 0.5f
, 4.f
);
1915 host_impl_
->SetPageScaleOnActiveTree(4.f
);
1917 CompositorFrameMetadata metadata
=
1918 host_impl_
->MakeCompositorFrameMetadata();
1919 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1920 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
1921 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.scrollable_viewport_size
);
1922 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1923 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1924 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1928 class DidDrawCheckLayer
: public LayerImpl
{
1930 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
1931 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl
, id
));
1934 bool WillDraw(DrawMode draw_mode
, ResourceProvider
* provider
) override
{
1935 will_draw_called_
= true;
1936 if (will_draw_returns_false_
)
1938 return LayerImpl::WillDraw(draw_mode
, provider
);
1941 void AppendQuads(RenderPass
* render_pass
,
1942 AppendQuadsData
* append_quads_data
) override
{
1943 append_quads_called_
= true;
1944 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
1947 void DidDraw(ResourceProvider
* provider
) override
{
1948 did_draw_called_
= true;
1949 LayerImpl::DidDraw(provider
);
1952 bool will_draw_called() const { return will_draw_called_
; }
1953 bool append_quads_called() const { return append_quads_called_
; }
1954 bool did_draw_called() const { return did_draw_called_
; }
1956 void set_will_draw_returns_false() { will_draw_returns_false_
= true; }
1958 void ClearDidDrawCheck() {
1959 will_draw_called_
= false;
1960 append_quads_called_
= false;
1961 did_draw_called_
= false;
1964 static void IgnoreResult(scoped_ptr
<CopyOutputResult
> result
) {}
1966 void AddCopyRequest() {
1967 ScopedPtrVector
<CopyOutputRequest
> requests
;
1969 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult
)));
1970 SetHasRenderSurface(true);
1971 PassCopyRequests(&requests
);
1975 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
1976 : LayerImpl(tree_impl
, id
),
1977 will_draw_returns_false_(false),
1978 will_draw_called_(false),
1979 append_quads_called_(false),
1980 did_draw_called_(false) {
1981 SetBounds(gfx::Size(10, 10));
1982 SetContentBounds(gfx::Size(10, 10));
1983 SetDrawsContent(true);
1984 draw_properties().visible_content_rect
= gfx::Rect(0, 0, 10, 10);
1988 bool will_draw_returns_false_
;
1989 bool will_draw_called_
;
1990 bool append_quads_called_
;
1991 bool did_draw_called_
;
1994 TEST_F(LayerTreeHostImplTest
, WillDrawReturningFalseDoesNotCall
) {
1995 // The root layer is always drawn, so run this test on a child layer that
1996 // will be masked out by the root layer's bounds.
1997 host_impl_
->active_tree()->SetRootLayer(
1998 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
1999 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2000 host_impl_
->active_tree()->root_layer());
2002 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2003 root
->SetHasRenderSurface(true);
2004 DidDrawCheckLayer
* layer
=
2005 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2008 LayerTreeHostImpl::FrameData frame
;
2009 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2010 host_impl_
->DrawLayers(&frame
);
2011 host_impl_
->DidDrawAllLayers(frame
);
2013 EXPECT_TRUE(layer
->will_draw_called());
2014 EXPECT_TRUE(layer
->append_quads_called());
2015 EXPECT_TRUE(layer
->did_draw_called());
2018 host_impl_
->SetViewportDamage(gfx::Rect(10, 10));
2021 LayerTreeHostImpl::FrameData frame
;
2023 layer
->set_will_draw_returns_false();
2024 layer
->ClearDidDrawCheck();
2026 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2027 host_impl_
->DrawLayers(&frame
);
2028 host_impl_
->DidDrawAllLayers(frame
);
2030 EXPECT_TRUE(layer
->will_draw_called());
2031 EXPECT_FALSE(layer
->append_quads_called());
2032 EXPECT_FALSE(layer
->did_draw_called());
2036 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
2037 // The root layer is always drawn, so run this test on a child layer that
2038 // will be masked out by the root layer's bounds.
2039 host_impl_
->active_tree()->SetRootLayer(
2040 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2041 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2042 host_impl_
->active_tree()->root_layer());
2043 root
->SetMasksToBounds(true);
2044 root
->SetHasRenderSurface(true);
2045 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2046 DidDrawCheckLayer
* layer
=
2047 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2048 // Ensure visible_content_rect for layer is empty.
2049 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
2050 layer
->SetBounds(gfx::Size(10, 10));
2051 layer
->SetContentBounds(gfx::Size(10, 10));
2053 LayerTreeHostImpl::FrameData frame
;
2055 EXPECT_FALSE(layer
->will_draw_called());
2056 EXPECT_FALSE(layer
->did_draw_called());
2058 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2059 host_impl_
->DrawLayers(&frame
);
2060 host_impl_
->DidDrawAllLayers(frame
);
2062 EXPECT_FALSE(layer
->will_draw_called());
2063 EXPECT_FALSE(layer
->did_draw_called());
2065 EXPECT_TRUE(layer
->visible_content_rect().IsEmpty());
2067 // Ensure visible_content_rect for layer is not empty
2068 layer
->SetPosition(gfx::PointF());
2070 EXPECT_FALSE(layer
->will_draw_called());
2071 EXPECT_FALSE(layer
->did_draw_called());
2073 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2074 host_impl_
->DrawLayers(&frame
);
2075 host_impl_
->DidDrawAllLayers(frame
);
2077 EXPECT_TRUE(layer
->will_draw_called());
2078 EXPECT_TRUE(layer
->did_draw_called());
2080 EXPECT_FALSE(layer
->visible_content_rect().IsEmpty());
2083 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
2084 gfx::Size
big_size(1000, 1000);
2085 host_impl_
->SetViewportSize(big_size
);
2087 host_impl_
->active_tree()->SetRootLayer(
2088 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2089 DidDrawCheckLayer
* root
=
2090 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2092 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2093 DidDrawCheckLayer
* occluded_layer
=
2094 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2096 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2097 root
->SetHasRenderSurface(true);
2098 DidDrawCheckLayer
* top_layer
=
2099 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
2100 // This layer covers the occluded_layer above. Make this layer large so it can
2102 top_layer
->SetBounds(big_size
);
2103 top_layer
->SetContentBounds(big_size
);
2104 top_layer
->SetContentsOpaque(true);
2106 LayerTreeHostImpl::FrameData frame
;
2108 EXPECT_FALSE(occluded_layer
->will_draw_called());
2109 EXPECT_FALSE(occluded_layer
->did_draw_called());
2110 EXPECT_FALSE(top_layer
->will_draw_called());
2111 EXPECT_FALSE(top_layer
->did_draw_called());
2113 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2114 host_impl_
->DrawLayers(&frame
);
2115 host_impl_
->DidDrawAllLayers(frame
);
2117 EXPECT_FALSE(occluded_layer
->will_draw_called());
2118 EXPECT_FALSE(occluded_layer
->did_draw_called());
2119 EXPECT_TRUE(top_layer
->will_draw_called());
2120 EXPECT_TRUE(top_layer
->did_draw_called());
2123 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
2124 host_impl_
->active_tree()->SetRootLayer(
2125 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2126 DidDrawCheckLayer
* root
=
2127 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2129 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2130 root
->SetHasRenderSurface(true);
2131 DidDrawCheckLayer
* layer1
=
2132 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2134 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2135 DidDrawCheckLayer
* layer2
=
2136 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
2138 layer1
->SetHasRenderSurface(true);
2139 layer1
->SetShouldFlattenTransform(true);
2141 EXPECT_FALSE(root
->did_draw_called());
2142 EXPECT_FALSE(layer1
->did_draw_called());
2143 EXPECT_FALSE(layer2
->did_draw_called());
2145 LayerTreeHostImpl::FrameData frame
;
2146 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2147 host_impl_
->active_tree()->root_layer());
2148 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2149 host_impl_
->DrawLayers(&frame
);
2150 host_impl_
->DidDrawAllLayers(frame
);
2152 EXPECT_TRUE(root
->did_draw_called());
2153 EXPECT_TRUE(layer1
->did_draw_called());
2154 EXPECT_TRUE(layer2
->did_draw_called());
2156 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
2157 EXPECT_TRUE(layer1
->render_surface());
2160 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
2162 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2165 bool had_incomplete_tile
,
2167 ResourceProvider
* resource_provider
) {
2168 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl
,
2171 had_incomplete_tile
,
2173 resource_provider
));
2176 void AppendQuads(RenderPass
* render_pass
,
2177 AppendQuadsData
* append_quads_data
) override
{
2178 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2179 if (had_incomplete_tile_
)
2180 append_quads_data
->num_incomplete_tiles
++;
2182 append_quads_data
->num_missing_tiles
++;
2186 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
2189 bool had_incomplete_tile
,
2191 ResourceProvider
* resource_provider
)
2192 : DidDrawCheckLayer(tree_impl
, id
),
2193 tile_missing_(tile_missing
),
2194 had_incomplete_tile_(had_incomplete_tile
) {
2196 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2200 bool had_incomplete_tile_
;
2203 struct PrepareToDrawSuccessTestCase
{
2205 bool has_missing_tile
= false;
2206 bool has_incomplete_tile
= false;
2207 bool is_animating
= false;
2208 bool has_copy_request
= false;
2210 bool high_res_required
= false;
2212 State layer_between
;
2214 DrawResult expected_result
;
2216 explicit PrepareToDrawSuccessTestCase(DrawResult result
)
2217 : expected_result(result
) {}
2220 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsAndFails
) {
2221 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2224 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2225 // 1. Animated layer first.
2226 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2227 cases
.back().layer_before
.is_animating
= true;
2228 // 2. Animated layer between.
2229 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2230 cases
.back().layer_between
.is_animating
= true;
2231 // 3. Animated layer last.
2232 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2233 cases
.back().layer_after
.is_animating
= true;
2234 // 4. Missing tile first.
2235 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2236 cases
.back().layer_before
.has_missing_tile
= true;
2237 // 5. Missing tile between.
2238 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2239 cases
.back().layer_between
.has_missing_tile
= true;
2240 // 6. Missing tile last.
2241 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2242 cases
.back().layer_after
.has_missing_tile
= true;
2243 // 7. Incomplete tile first.
2244 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2245 cases
.back().layer_before
.has_incomplete_tile
= true;
2246 // 8. Incomplete tile between.
2247 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2248 cases
.back().layer_between
.has_incomplete_tile
= true;
2249 // 9. Incomplete tile last.
2250 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2251 cases
.back().layer_after
.has_incomplete_tile
= true;
2252 // 10. Animation with missing tile.
2254 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
));
2255 cases
.back().layer_between
.has_missing_tile
= true;
2256 cases
.back().layer_between
.is_animating
= true;
2257 // 11. Animation with incomplete tile.
2258 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2259 cases
.back().layer_between
.has_incomplete_tile
= true;
2260 cases
.back().layer_between
.is_animating
= true;
2262 // 12. High res required.
2263 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2264 cases
.back().high_res_required
= true;
2265 // 13. High res required with incomplete tile.
2267 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2268 cases
.back().high_res_required
= true;
2269 cases
.back().layer_between
.has_incomplete_tile
= true;
2270 // 14. High res required with missing tile.
2272 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2273 cases
.back().high_res_required
= true;
2274 cases
.back().layer_between
.has_missing_tile
= true;
2276 // 15. High res required is higher priority than animating missing tiles.
2278 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2279 cases
.back().high_res_required
= true;
2280 cases
.back().layer_between
.has_missing_tile
= true;
2281 cases
.back().layer_after
.has_missing_tile
= true;
2282 cases
.back().layer_after
.is_animating
= true;
2283 // 16. High res required is higher priority than animating missing tiles.
2285 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2286 cases
.back().high_res_required
= true;
2287 cases
.back().layer_between
.has_missing_tile
= true;
2288 cases
.back().layer_before
.has_missing_tile
= true;
2289 cases
.back().layer_before
.is_animating
= true;
2291 host_impl_
->active_tree()->SetRootLayer(
2292 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2293 DidDrawCheckLayer
* root
=
2294 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2295 root
->SetHasRenderSurface(true);
2297 LayerTreeHostImpl::FrameData frame
;
2298 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2299 host_impl_
->DrawLayers(&frame
);
2300 host_impl_
->DidDrawAllLayers(frame
);
2301 host_impl_
->SwapBuffers(frame
);
2303 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2304 const auto& testcase
= cases
[i
];
2305 std::vector
<LayerImpl
*> to_remove
;
2306 for (auto* child
: root
->children())
2307 to_remove
.push_back(child
);
2308 for (auto* child
: to_remove
)
2309 root
->RemoveChild(child
);
2311 std::ostringstream scope
;
2312 scope
<< "Test case: " << i
;
2313 SCOPED_TRACE(scope
.str());
2315 root
->AddChild(MissingTextureAnimatingLayer::Create(
2316 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2317 testcase
.layer_before
.has_incomplete_tile
,
2318 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2319 DidDrawCheckLayer
* before
=
2320 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2321 if (testcase
.layer_before
.has_copy_request
)
2322 before
->AddCopyRequest();
2324 root
->AddChild(MissingTextureAnimatingLayer::Create(
2325 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2326 testcase
.layer_between
.has_incomplete_tile
,
2327 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2328 DidDrawCheckLayer
* between
=
2329 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2330 if (testcase
.layer_between
.has_copy_request
)
2331 between
->AddCopyRequest();
2333 root
->AddChild(MissingTextureAnimatingLayer::Create(
2334 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2335 testcase
.layer_after
.has_incomplete_tile
,
2336 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2337 DidDrawCheckLayer
* after
=
2338 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2339 if (testcase
.layer_after
.has_copy_request
)
2340 after
->AddCopyRequest();
2342 if (testcase
.high_res_required
)
2343 host_impl_
->SetRequiresHighResToDraw();
2345 LayerTreeHostImpl::FrameData frame
;
2346 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2347 host_impl_
->DrawLayers(&frame
);
2348 host_impl_
->DidDrawAllLayers(frame
);
2349 host_impl_
->SwapBuffers(frame
);
2353 TEST_F(LayerTreeHostImplTest
,
2354 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame
) {
2355 CreateHostImpl(DefaultSettings(),
2356 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2357 EXPECT_TRUE(host_impl_
->output_surface()
2359 .draw_and_swap_full_viewport_every_frame
);
2361 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2364 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2365 // 1. Animation with missing tile.
2366 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2367 cases
.back().layer_between
.has_missing_tile
= true;
2368 cases
.back().layer_between
.is_animating
= true;
2369 // 2. High res required with incomplete tile.
2370 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2371 cases
.back().high_res_required
= true;
2372 cases
.back().layer_between
.has_incomplete_tile
= true;
2373 // 3. High res required with missing tile.
2374 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2375 cases
.back().high_res_required
= true;
2376 cases
.back().layer_between
.has_missing_tile
= true;
2378 host_impl_
->active_tree()->SetRootLayer(
2379 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2380 DidDrawCheckLayer
* root
=
2381 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2382 root
->SetHasRenderSurface(true);
2384 LayerTreeHostImpl::FrameData frame
;
2385 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2386 host_impl_
->DrawLayers(&frame
);
2387 host_impl_
->DidDrawAllLayers(frame
);
2388 host_impl_
->SwapBuffers(frame
);
2390 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2391 const auto& testcase
= cases
[i
];
2392 std::vector
<LayerImpl
*> to_remove
;
2393 for (auto* child
: root
->children())
2394 to_remove
.push_back(child
);
2395 for (auto* child
: to_remove
)
2396 root
->RemoveChild(child
);
2398 std::ostringstream scope
;
2399 scope
<< "Test case: " << i
;
2400 SCOPED_TRACE(scope
.str());
2402 root
->AddChild(MissingTextureAnimatingLayer::Create(
2403 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2404 testcase
.layer_before
.has_incomplete_tile
,
2405 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2406 DidDrawCheckLayer
* before
=
2407 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2408 if (testcase
.layer_before
.has_copy_request
)
2409 before
->AddCopyRequest();
2411 root
->AddChild(MissingTextureAnimatingLayer::Create(
2412 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2413 testcase
.layer_between
.has_incomplete_tile
,
2414 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2415 DidDrawCheckLayer
* between
=
2416 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2417 if (testcase
.layer_between
.has_copy_request
)
2418 between
->AddCopyRequest();
2420 root
->AddChild(MissingTextureAnimatingLayer::Create(
2421 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2422 testcase
.layer_after
.has_incomplete_tile
,
2423 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2424 DidDrawCheckLayer
* after
=
2425 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2426 if (testcase
.layer_after
.has_copy_request
)
2427 after
->AddCopyRequest();
2429 if (testcase
.high_res_required
)
2430 host_impl_
->SetRequiresHighResToDraw();
2432 LayerTreeHostImpl::FrameData frame
;
2433 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2434 host_impl_
->DrawLayers(&frame
);
2435 host_impl_
->DidDrawAllLayers(frame
);
2436 host_impl_
->SwapBuffers(frame
);
2440 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
2441 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2442 root
->SetScrollClipLayer(Layer::INVALID_ID
);
2443 root
->SetHasRenderSurface(true);
2444 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2447 // Scroll event is ignored because layer is not scrollable.
2448 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
2449 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2450 EXPECT_FALSE(did_request_redraw_
);
2451 EXPECT_FALSE(did_request_commit_
);
2454 // TODO(bokan): Convert these tests to create inner and outer viewports.
2455 class LayerTreeHostImplTopControlsTest
: public LayerTreeHostImplTest
{
2457 LayerTreeHostImplTopControlsTest()
2458 // Make the clip size the same as the layer (content) size so the layer is
2460 : layer_size_(10, 10),
2461 clip_size_(layer_size_
),
2462 top_controls_height_(50) {
2463 settings_
.use_pinch_virtual_viewport
= true;
2465 viewport_size_
= gfx::Size(clip_size_
.width(),
2466 clip_size_
.height() + top_controls_height_
);
2469 bool CreateHostImpl(const LayerTreeSettings
& settings
,
2470 scoped_ptr
<OutputSurface
> output_surface
) override
{
2472 LayerTreeHostImplTest::CreateHostImpl(settings
, output_surface
.Pass());
2474 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
2475 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
2480 void SetupTopControlsAndScrollLayer() {
2481 scoped_ptr
<LayerImpl
> root
=
2482 LayerImpl::Create(host_impl_
->active_tree(), 1);
2483 scoped_ptr
<LayerImpl
> root_clip
=
2484 LayerImpl::Create(host_impl_
->active_tree(), 2);
2485 root_clip
->SetBounds(clip_size_
);
2486 root
->SetScrollClipLayer(root_clip
->id());
2487 root
->SetBounds(layer_size_
);
2488 root
->SetContentBounds(layer_size_
);
2489 root
->SetPosition(gfx::PointF());
2490 root
->SetDrawsContent(false);
2491 root
->SetIsContainerForFixedPositionLayers(true);
2492 int inner_viewport_scroll_layer_id
= root
->id();
2493 int page_scale_layer_id
= root_clip
->id();
2494 root_clip
->SetHasRenderSurface(true);
2495 root_clip
->AddChild(root
.Pass());
2496 root_clip
->SetHasRenderSurface(true);
2497 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
2498 host_impl_
->active_tree()->SetViewportLayersFromIds(
2499 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2501 // Set a viewport size that is large enough to contain both the top controls
2502 // and some content.
2503 host_impl_
->SetViewportSize(viewport_size_
);
2504 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2506 host_impl_
->DidChangeTopControlsPosition();
2508 host_impl_
->CreatePendingTree();
2509 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
2511 LayerImpl::Create(host_impl_
->sync_tree(), 1);
2513 LayerImpl::Create(host_impl_
->sync_tree(), 2);
2514 root_clip
->SetBounds(clip_size_
);
2515 root
->SetScrollClipLayer(root_clip
->id());
2516 root
->SetBounds(layer_size_
);
2517 root
->SetContentBounds(layer_size_
);
2518 root
->SetPosition(gfx::PointF());
2519 root
->SetDrawsContent(false);
2520 root
->SetIsContainerForFixedPositionLayers(true);
2521 inner_viewport_scroll_layer_id
= root
->id();
2522 page_scale_layer_id
= root_clip
->id();
2523 root_clip
->AddChild(root
.Pass());
2524 host_impl_
->sync_tree()->SetRootLayer(root_clip
.Pass());
2525 host_impl_
->sync_tree()->SetViewportLayersFromIds(
2526 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2528 // Set a viewport size that is large enough to contain both the top controls
2529 // and some content.
2530 host_impl_
->SetViewportSize(viewport_size_
);
2531 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2532 host_impl_
->DidChangeTopControlsPosition();
2535 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2536 const gfx::Size
& inner_viewport_size
,
2537 const gfx::Size
& outer_viewport_size
,
2538 const gfx::Size
& scroll_layer_size
) {
2539 CreateHostImpl(settings_
, CreateOutputSurface());
2540 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2541 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
2542 host_impl_
->DidChangeTopControlsPosition();
2544 scoped_ptr
<LayerImpl
> root
=
2545 LayerImpl::Create(host_impl_
->active_tree(), 1);
2546 scoped_ptr
<LayerImpl
> root_clip
=
2547 LayerImpl::Create(host_impl_
->active_tree(), 2);
2548 scoped_ptr
<LayerImpl
> page_scale
=
2549 LayerImpl::Create(host_impl_
->active_tree(), 3);
2551 scoped_ptr
<LayerImpl
> outer_scroll
=
2552 LayerImpl::Create(host_impl_
->active_tree(), 4);
2553 scoped_ptr
<LayerImpl
> outer_clip
=
2554 LayerImpl::Create(host_impl_
->active_tree(), 5);
2556 root_clip
->SetBounds(inner_viewport_size
);
2557 root
->SetScrollClipLayer(root_clip
->id());
2558 root
->SetBounds(outer_viewport_size
);
2559 root
->SetContentBounds(outer_viewport_size
);
2560 root
->SetPosition(gfx::PointF());
2561 root
->SetDrawsContent(false);
2562 root
->SetIsContainerForFixedPositionLayers(true);
2563 root_clip
->SetHasRenderSurface(true);
2564 outer_clip
->SetBounds(outer_viewport_size
);
2565 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
2566 outer_scroll
->SetBounds(scroll_layer_size
);
2567 outer_scroll
->SetContentBounds(scroll_layer_size
);
2568 outer_scroll
->SetPosition(gfx::PointF());
2569 outer_scroll
->SetDrawsContent(false);
2570 outer_scroll
->SetIsContainerForFixedPositionLayers(true);
2572 int inner_viewport_scroll_layer_id
= root
->id();
2573 int outer_viewport_scroll_layer_id
= outer_scroll
->id();
2574 int page_scale_layer_id
= page_scale
->id();
2576 outer_clip
->AddChild(outer_scroll
.Pass());
2577 root
->AddChild(outer_clip
.Pass());
2578 page_scale
->AddChild(root
.Pass());
2579 root_clip
->AddChild(page_scale
.Pass());
2581 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
2582 host_impl_
->active_tree()->SetViewportLayersFromIds(
2583 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2584 outer_viewport_scroll_layer_id
);
2586 host_impl_
->SetViewportSize(inner_viewport_size
);
2587 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2588 EXPECT_EQ(inner_viewport_size
, root_clip_ptr
->bounds());
2592 gfx::Size layer_size_
;
2593 gfx::Size clip_size_
;
2594 gfx::Size viewport_size_
;
2595 float top_controls_height_
;
2597 LayerTreeSettings settings_
;
2598 }; // class LayerTreeHostImplTopControlsTest
2600 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsByFractionalAmount
) {
2601 SetupTopControlsAndScrollLayerWithVirtualViewport(
2602 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2605 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2606 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2608 // Make the test scroll delta a fractional amount, to verify that the
2609 // fixed container size delta is (1) non-zero, and (2) fractional, and
2610 // (3) matches the movement of the top controls.
2611 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.25f
);
2612 host_impl_
->top_controls_manager()->ScrollBegin();
2613 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2614 host_impl_
->top_controls_manager()->ScrollEnd();
2616 LayerImpl
* inner_viewport_scroll_layer
=
2617 host_impl_
->active_tree()->InnerViewportScrollLayer();
2618 DCHECK(inner_viewport_scroll_layer
);
2619 host_impl_
->ScrollEnd();
2620 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
2621 inner_viewport_scroll_layer
->FixedContainerSizeDelta().y());
2624 // In this test, the outer viewport is initially unscrollable. We test that a
2625 // scroll initiated on the inner viewport, causing the top controls to show and
2626 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2627 TEST_F(LayerTreeHostImplTopControlsTest
,
2628 TopControlsOuterViewportBecomesScrollable
) {
2629 SetupTopControlsAndScrollLayerWithVirtualViewport(
2630 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2633 LayerImpl
* inner_scroll
=
2634 host_impl_
->active_tree()->InnerViewportScrollLayer();
2635 LayerImpl
* inner_container
=
2636 host_impl_
->active_tree()->InnerViewportContainerLayer();
2637 LayerImpl
* outer_scroll
=
2638 host_impl_
->active_tree()->OuterViewportScrollLayer();
2639 LayerImpl
* outer_container
=
2640 host_impl_
->active_tree()->OuterViewportContainerLayer();
2642 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2643 outer_scroll
->SetDrawsContent(true);
2644 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 1.f
, 2.f
);
2646 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2647 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2648 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 50.f
));
2650 // The entire scroll delta should have been used to hide the top controls.
2651 // The viewport layers should be resized back to their full sizes.
2652 EXPECT_EQ(0.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2653 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
2654 EXPECT_EQ(100.f
, inner_container
->BoundsForScrolling().height());
2655 EXPECT_EQ(100.f
, outer_container
->BoundsForScrolling().height());
2657 // The inner viewport should be scrollable by 50px * page_scale.
2658 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 100.f
));
2659 EXPECT_EQ(50.f
, inner_scroll
->CurrentScrollOffset().y());
2660 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2661 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll
->MaxScrollOffset());
2663 host_impl_
->ScrollEnd();
2665 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2666 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2667 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
2669 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
2671 // The entire scroll delta should have been used to show the top controls.
2672 // The outer viewport should be resized to accomodate and scrolled to the
2673 // bottom of the document to keep the viewport in place.
2674 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2675 EXPECT_EQ(50.f
, outer_container
->BoundsForScrolling().height());
2676 EXPECT_EQ(50.f
, inner_container
->BoundsForScrolling().height());
2677 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
2678 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2680 // Now when we continue scrolling, make sure the outer viewport gets scrolled
2681 // since it wasn't scrollable when the scroll began.
2682 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -20.f
));
2683 EXPECT_EQ(15.f
, outer_scroll
->CurrentScrollOffset().y());
2684 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2686 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -30.f
));
2687 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2688 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2690 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
2691 host_impl_
->ScrollEnd();
2693 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2694 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
2697 // Test that the fixed position container delta is appropriately adjusted
2698 // by the top controls showing/hiding and page scale doesn't affect it.
2699 TEST_F(LayerTreeHostImplTopControlsTest
, FixedContainerDelta
) {
2700 SetupTopControlsAndScrollLayerWithVirtualViewport(
2701 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
2704 float page_scale
= 1.5f
;
2705 LayerImpl
* outer_viewport_scroll_layer
=
2706 host_impl_
->active_tree()->OuterViewportScrollLayer();
2708 // Zoom in, since the fixed container is the outer viewport, the delta should
2710 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
2712 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2713 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2715 // Scroll down, the top controls hiding should expand the viewport size so
2716 // the delta should be equal to the scroll distance.
2717 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 20.f
);
2718 host_impl_
->top_controls_manager()->ScrollBegin();
2719 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2720 EXPECT_FLOAT_EQ(top_controls_height_
- top_controls_scroll_delta
.y(),
2721 host_impl_
->top_controls_manager()->ContentTopOffset());
2722 EXPECT_VECTOR_EQ(top_controls_scroll_delta
,
2723 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2724 host_impl_
->ScrollEnd();
2726 // Scroll past the maximum extent. The delta shouldn't be greater than the
2727 // top controls height.
2728 host_impl_
->top_controls_manager()->ScrollBegin();
2729 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2730 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2731 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2732 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2733 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_
),
2734 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2735 host_impl_
->ScrollEnd();
2737 // Scroll in the direction to make the top controls show.
2738 host_impl_
->top_controls_manager()->ScrollBegin();
2739 host_impl_
->top_controls_manager()->ScrollBy(-top_controls_scroll_delta
);
2740 EXPECT_EQ(top_controls_scroll_delta
.y(),
2741 host_impl_
->top_controls_manager()->ContentTopOffset());
2743 gfx::Vector2dF(0, top_controls_height_
- top_controls_scroll_delta
.y()),
2744 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2745 host_impl_
->top_controls_manager()->ScrollEnd();
2748 // Test that if a scrollable sublayer doesn't consume the scroll,
2749 // top controls should hide when scrolling down.
2750 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollableSublayer
) {
2751 gfx::Size
sub_content_size(100, 400);
2752 gfx::Size
sub_content_layer_size(100, 300);
2753 SetupTopControlsAndScrollLayerWithVirtualViewport(
2754 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
2757 // Show top controls
2758 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2760 LayerImpl
* outer_viewport_scroll_layer
=
2761 host_impl_
->active_tree()->OuterViewportScrollLayer();
2762 int id
= outer_viewport_scroll_layer
->id();
2764 scoped_ptr
<LayerImpl
> child
=
2765 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2);
2766 scoped_ptr
<LayerImpl
> child_clip
=
2767 LayerImpl::Create(host_impl_
->active_tree(), id
+ 3);
2769 child_clip
->SetBounds(sub_content_layer_size
);
2770 child
->SetScrollClipLayer(child_clip
->id());
2771 child
->SetBounds(sub_content_size
);
2772 child
->SetContentBounds(sub_content_size
);
2773 child
->SetPosition(gfx::PointF());
2774 child
->SetDrawsContent(true);
2775 child
->SetIsContainerForFixedPositionLayers(true);
2777 // scroll child to limit
2778 child
->SetScrollDelta(gfx::Vector2dF(0, 100.f
));
2779 child_clip
->AddChild(child
.Pass());
2780 outer_viewport_scroll_layer
->AddChild(child_clip
.Pass());
2782 // Scroll 25px to hide top controls
2783 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
2784 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2785 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2786 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2787 host_impl_
->ScrollEnd();
2789 // Top controls should be hidden
2790 EXPECT_EQ(scroll_delta
.y(),
2791 top_controls_height_
-
2792 host_impl_
->top_controls_manager()->ContentTopOffset());
2795 // Ensure setting the top controls position explicitly using the setters on the
2796 // TreeImpl correctly affects the top controls manager and viewport bounds.
2797 TEST_F(LayerTreeHostImplTopControlsTest
, PositionTopControlsExplicitly
) {
2798 CreateHostImpl(settings_
, CreateOutputSurface());
2799 SetupTopControlsAndScrollLayer();
2802 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2803 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2804 30.f
/ top_controls_height_
);
2805 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2806 EXPECT_FLOAT_EQ(30.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2807 EXPECT_FLOAT_EQ(-20.f
,
2808 host_impl_
->top_controls_manager()->ControlsTopOffset());
2810 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2811 EXPECT_FLOAT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2812 EXPECT_FLOAT_EQ(-50.f
,
2813 host_impl_
->top_controls_manager()->ControlsTopOffset());
2815 host_impl_
->DidChangeTopControlsPosition();
2817 // Now that top controls have moved, expect the clip to resize.
2818 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2819 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2822 // Test that the top_controls delta and sent delta are appropriately
2823 // applied on sync tree activation. The total top controls offset shouldn't
2824 // change after the activation.
2825 TEST_F(LayerTreeHostImplTopControlsTest
, ApplyDeltaOnTreeActivation
) {
2826 CreateHostImpl(settings_
, CreateOutputSurface());
2827 SetupTopControlsAndScrollLayer();
2830 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2831 20.f
/ top_controls_height_
);
2832 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2833 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(
2834 15.f
/ top_controls_height_
);
2835 host_impl_
->active_tree()
2836 ->top_controls_shown_ratio()
2837 ->PullDeltaForMainThread();
2838 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2839 host_impl_
->sync_tree()->PushTopControlsFromMainThread(15.f
/
2840 top_controls_height_
);
2842 host_impl_
->DidChangeTopControlsPosition();
2843 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2844 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2845 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2847 host_impl_
->ActivateSyncTree();
2849 root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2850 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2851 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2854 -15.f
, host_impl_
->active_tree()->top_controls_shown_ratio()->Delta() *
2855 top_controls_height_
);
2858 host_impl_
->active_tree()->top_controls_shown_ratio()->ActiveBase() *
2859 top_controls_height_
);
2862 // Test that changing the top controls layout height is correctly applied to
2863 // the inner viewport container bounds. That is, the top controls layout
2864 // height is the amount that the inner viewport container was shrunk outside
2865 // the compositor to accommodate the top controls.
2866 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsLayoutHeightChanged
) {
2867 CreateHostImpl(settings_
, CreateOutputSurface());
2868 SetupTopControlsAndScrollLayer();
2871 host_impl_
->sync_tree()->PushTopControlsFromMainThread(1.f
);
2872 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2874 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2876 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2877 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2879 host_impl_
->DidChangeTopControlsPosition();
2880 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2881 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2882 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2884 host_impl_
->sync_tree()->root_layer()->SetBounds(
2885 gfx::Size(root_clip_ptr
->bounds().width(),
2886 root_clip_ptr
->bounds().height() - 50.f
));
2888 host_impl_
->ActivateSyncTree();
2890 root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2891 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2893 // The total bounds should remain unchanged since the bounds delta should
2894 // account for the difference between the layout height and the current
2895 // top controls offset.
2896 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2897 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 50.f
), root_clip_ptr
->bounds_delta());
2899 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
2900 host_impl_
->DidChangeTopControlsPosition();
2902 EXPECT_EQ(1.f
, host_impl_
->top_controls_manager()->TopControlsShownRatio());
2903 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->TopControlsHeight());
2904 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2905 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 0.f
), root_clip_ptr
->bounds_delta());
2906 EXPECT_EQ(gfx::Size(viewport_size_
.width(), viewport_size_
.height() - 50.f
),
2907 root_clip_ptr
->bounds());
2910 // Test that showing/hiding the top controls when the viewport is fully scrolled
2911 // doesn't incorrectly change the viewport offset due to clamping from changing
2913 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsViewportOffsetClamping
) {
2914 SetupTopControlsAndScrollLayerWithVirtualViewport(
2915 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2918 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2920 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
2921 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
2923 // Scroll the viewports to max scroll offset.
2924 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
2925 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
2927 gfx::ScrollOffset viewport_offset
=
2928 host_impl_
->active_tree()->TotalScrollOffset();
2929 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(), viewport_offset
);
2931 // Hide the top controls by 25px.
2932 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
2933 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2934 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2935 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2937 // scrolling down at the max extents no longer hides the top controls
2938 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2940 // forcefully hide the top controls by 25px
2941 host_impl_
->top_controls_manager()->ScrollBy(scroll_delta
);
2942 host_impl_
->ScrollEnd();
2944 EXPECT_FLOAT_EQ(scroll_delta
.y(),
2945 top_controls_height_
-
2946 host_impl_
->top_controls_manager()->ContentTopOffset());
2948 inner_scroll
->ClampScrollToMaxScrollOffset();
2949 outer_scroll
->ClampScrollToMaxScrollOffset();
2951 // We should still be fully scrolled.
2952 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
2953 host_impl_
->active_tree()->TotalScrollOffset());
2955 viewport_offset
= host_impl_
->active_tree()->TotalScrollOffset();
2957 // Bring the top controls down by 25px.
2958 scroll_delta
= gfx::Vector2dF(0.f
, -25.f
);
2959 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2960 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2961 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2962 host_impl_
->ScrollEnd();
2964 // The viewport offset shouldn't have changed.
2965 EXPECT_EQ(viewport_offset
,
2966 host_impl_
->active_tree()->TotalScrollOffset());
2968 // Scroll the viewports to max scroll offset.
2969 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
2970 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
2971 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
2972 host_impl_
->active_tree()->TotalScrollOffset());
2975 // Test that the top controls coming in and out maintains the same aspect ratio
2976 // between the inner and outer viewports.
2977 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsAspectRatio
) {
2978 SetupTopControlsAndScrollLayerWithVirtualViewport(
2979 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2982 EXPECT_FLOAT_EQ(top_controls_height_
,
2983 host_impl_
->top_controls_manager()->ContentTopOffset());
2985 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
2986 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2987 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2988 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2989 host_impl_
->ScrollEnd();
2991 EXPECT_FLOAT_EQ(scroll_delta
.y(),
2992 top_controls_height_
-
2993 host_impl_
->top_controls_manager()->ContentTopOffset());
2995 // Top controls were hidden by 25px so the inner viewport should have expanded
2997 LayerImpl
* outer_container
=
2998 host_impl_
->active_tree()->OuterViewportContainerLayer();
2999 LayerImpl
* inner_container
=
3000 host_impl_
->active_tree()->InnerViewportContainerLayer();
3001 EXPECT_EQ(gfx::Size(100, 100+25), inner_container
->BoundsForScrolling());
3003 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3004 float aspect_ratio
= inner_container
->BoundsForScrolling().width() /
3005 inner_container
->BoundsForScrolling().height();
3006 gfx::Size expected
= gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio
));
3007 EXPECT_EQ(expected
, outer_container
->BoundsForScrolling());
3009 host_impl_
->InnerViewportScrollLayer()->BoundsForScrolling());
3012 // Test that scrolling the outer viewport affects the top controls.
3013 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollOuterViewport
) {
3014 SetupTopControlsAndScrollLayerWithVirtualViewport(
3015 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3018 EXPECT_EQ(top_controls_height_
,
3019 host_impl_
->top_controls_manager()->ContentTopOffset());
3021 // Send a gesture scroll that will scroll the outer viewport, make sure the
3022 // top controls get scrolled.
3023 gfx::Vector2dF
scroll_delta(0.f
, 15.f
);
3024 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3025 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3026 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3027 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3028 host_impl_
->CurrentlyScrollingLayer());
3029 host_impl_
->ScrollEnd();
3031 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3032 top_controls_height_
-
3033 host_impl_
->top_controls_manager()->ContentTopOffset());
3035 scroll_delta
= gfx::Vector2dF(0.f
, 50.f
);
3036 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3037 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3038 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3040 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ContentTopOffset());
3041 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3042 host_impl_
->CurrentlyScrollingLayer());
3044 host_impl_
->ScrollEnd();
3046 // Position the viewports such that the inner viewport will be scrolled.
3047 gfx::Vector2dF
inner_viewport_offset(0.f
, 25.f
);
3048 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3049 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset
);
3051 scroll_delta
= gfx::Vector2dF(0.f
, -65.f
);
3052 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3053 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3054 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3056 EXPECT_EQ(top_controls_height_
,
3057 host_impl_
->top_controls_manager()->ContentTopOffset());
3059 inner_viewport_offset
.y() + (scroll_delta
.y() + top_controls_height_
),
3060 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
3062 host_impl_
->ScrollEnd();
3065 TEST_F(LayerTreeHostImplTopControlsTest
,
3066 ScrollNonScrollableRootWithTopControls
) {
3067 CreateHostImpl(settings_
, CreateOutputSurface());
3068 SetupTopControlsAndScrollLayer();
3071 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3072 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3074 host_impl_
->top_controls_manager()->ScrollBegin();
3075 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
3076 host_impl_
->top_controls_manager()->ScrollEnd();
3077 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3078 // Now that top controls have moved, expect the clip to resize.
3079 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3080 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
3082 host_impl_
->ScrollEnd();
3084 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3085 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3087 float scroll_increment_y
= -25.f
;
3088 host_impl_
->top_controls_manager()->ScrollBegin();
3089 host_impl_
->top_controls_manager()->ScrollBy(
3090 gfx::Vector2dF(0.f
, scroll_increment_y
));
3091 EXPECT_FLOAT_EQ(-scroll_increment_y
,
3092 host_impl_
->top_controls_manager()->ContentTopOffset());
3093 // Now that top controls have moved, expect the clip to resize.
3094 EXPECT_EQ(gfx::Size(viewport_size_
.width(),
3095 viewport_size_
.height() + scroll_increment_y
),
3096 root_clip_ptr
->bounds());
3098 host_impl_
->top_controls_manager()->ScrollBy(
3099 gfx::Vector2dF(0.f
, scroll_increment_y
));
3100 host_impl_
->top_controls_manager()->ScrollEnd();
3101 EXPECT_FLOAT_EQ(-2 * scroll_increment_y
,
3102 host_impl_
->top_controls_manager()->ContentTopOffset());
3103 // Now that top controls have moved, expect the clip to resize.
3104 EXPECT_EQ(clip_size_
, root_clip_ptr
->bounds());
3106 host_impl_
->ScrollEnd();
3108 // Verify the layer is once-again non-scrollable.
3110 gfx::ScrollOffset(),
3111 host_impl_
->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3113 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3114 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3117 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
3118 // Test the configuration where a non-composited root layer is embedded in a
3119 // scrollable outer layer.
3120 gfx::Size
surface_size(10, 10);
3121 gfx::Size
contents_size(20, 20);
3123 scoped_ptr
<LayerImpl
> content_layer
=
3124 LayerImpl::Create(host_impl_
->active_tree(), 1);
3125 content_layer
->SetDrawsContent(true);
3126 content_layer
->SetPosition(gfx::PointF());
3127 content_layer
->SetBounds(contents_size
);
3128 content_layer
->SetContentBounds(contents_size
);
3129 content_layer
->SetContentsScale(2.f
, 2.f
);
3131 scoped_ptr
<LayerImpl
> scroll_clip_layer
=
3132 LayerImpl::Create(host_impl_
->active_tree(), 3);
3133 scroll_clip_layer
->SetBounds(surface_size
);
3135 scoped_ptr
<LayerImpl
> scroll_layer
=
3136 LayerImpl::Create(host_impl_
->active_tree(), 2);
3137 scroll_layer
->SetScrollClipLayer(3);
3138 scroll_layer
->SetBounds(contents_size
);
3139 scroll_layer
->SetContentBounds(contents_size
);
3140 scroll_layer
->SetPosition(gfx::PointF());
3141 scroll_layer
->AddChild(content_layer
.Pass());
3142 scroll_clip_layer
->AddChild(scroll_layer
.Pass());
3144 scroll_clip_layer
->SetHasRenderSurface(true);
3145 host_impl_
->active_tree()->SetRootLayer(scroll_clip_layer
.Pass());
3146 host_impl_
->SetViewportSize(surface_size
);
3149 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3150 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3151 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3152 host_impl_
->ScrollEnd();
3153 EXPECT_TRUE(did_request_redraw_
);
3154 EXPECT_TRUE(did_request_commit_
);
3157 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
3158 gfx::Size
surface_size(10, 10);
3159 gfx::Size
contents_size(20, 20);
3160 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3161 root
->SetBounds(surface_size
);
3162 root
->SetContentBounds(contents_size
);
3163 root
->AddChild(CreateScrollableLayer(2, contents_size
, root
.get()));
3164 root
->SetHasRenderSurface(true);
3165 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3166 host_impl_
->SetViewportSize(surface_size
);
3169 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3170 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3171 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3172 host_impl_
->ScrollEnd();
3173 EXPECT_TRUE(did_request_redraw_
);
3174 EXPECT_TRUE(did_request_commit_
);
3177 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
3178 gfx::Size
surface_size(10, 10);
3179 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3180 root
->AddChild(CreateScrollableLayer(2, surface_size
, root
.get()));
3181 root
->SetHasRenderSurface(true);
3182 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3183 host_impl_
->SetViewportSize(surface_size
);
3186 // Scroll event is ignored because the input coordinate is outside the layer
3188 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3189 host_impl_
->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL
));
3190 EXPECT_FALSE(did_request_redraw_
);
3191 EXPECT_FALSE(did_request_commit_
);
3194 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
3195 gfx::Size
surface_size(10, 10);
3196 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3197 root
->SetHasRenderSurface(true);
3198 scoped_ptr
<LayerImpl
> child
=
3199 CreateScrollableLayer(2, surface_size
, root
.get());
3200 host_impl_
->SetViewportSize(surface_size
);
3202 gfx::Transform matrix
;
3203 matrix
.RotateAboutXAxis(180.0);
3204 child
->SetTransform(matrix
);
3205 child
->SetDoubleSided(false);
3207 root
->AddChild(child
.Pass());
3208 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3211 // Scroll event is ignored because the scrollable layer is not facing the
3212 // viewer and there is nothing scrollable behind it.
3213 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3214 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3215 EXPECT_FALSE(did_request_redraw_
);
3216 EXPECT_FALSE(did_request_commit_
);
3219 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
3220 gfx::Size
surface_size(10, 10);
3221 scoped_ptr
<LayerImpl
> clip_layer
=
3222 LayerImpl::Create(host_impl_
->active_tree(), 3);
3223 scoped_ptr
<LayerImpl
> content_layer
=
3224 CreateScrollableLayer(1, surface_size
, clip_layer
.get());
3225 content_layer
->SetShouldScrollOnMainThread(true);
3226 content_layer
->SetScrollClipLayer(Layer::INVALID_ID
);
3228 // Note: we can use the same clip layer for both since both calls to
3229 // CreateScrollableLayer() use the same surface size.
3230 scoped_ptr
<LayerImpl
> scroll_layer
=
3231 CreateScrollableLayer(2, surface_size
, clip_layer
.get());
3232 scroll_layer
->AddChild(content_layer
.Pass());
3233 clip_layer
->AddChild(scroll_layer
.Pass());
3234 clip_layer
->SetHasRenderSurface(true);
3236 host_impl_
->active_tree()->SetRootLayer(clip_layer
.Pass());
3237 host_impl_
->SetViewportSize(surface_size
);
3240 // Scrolling fails because the content layer is asking to be scrolled on the
3242 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
3243 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3246 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
3247 gfx::Size
surface_size(20, 20);
3248 gfx::Size
viewport_size(10, 10);
3249 float page_scale
= 2.f
;
3250 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3251 scoped_ptr
<LayerImpl
> root_clip
=
3252 LayerImpl::Create(host_impl_
->active_tree(), 2);
3253 scoped_ptr
<LayerImpl
> root_scrolling
=
3254 CreateScrollableLayer(3, surface_size
, root_clip
.get());
3255 EXPECT_EQ(viewport_size
, root_clip
->bounds());
3256 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3257 root_clip
->AddChild(root_scrolling
.Pass());
3258 root
->AddChild(root_clip
.Pass());
3259 root
->SetHasRenderSurface(true);
3260 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3261 // The behaviour in this test assumes the page scale is applied at a layer
3262 // above the clip layer.
3263 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 3,
3265 host_impl_
->active_tree()->DidBecomeActive();
3266 host_impl_
->SetViewportSize(viewport_size
);
3269 LayerImpl
* root_scroll
=
3270 host_impl_
->active_tree()->InnerViewportScrollLayer();
3271 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3273 gfx::Vector2d
scroll_delta(0, 10);
3274 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3275 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3276 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3277 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3278 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3279 host_impl_
->ScrollEnd();
3281 // Set new page scale from main thread.
3282 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, page_scale
,
3285 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3286 ExpectContains(*scroll_info
.get(), root_scroll
->id(), expected_scroll_delta
);
3288 // The scroll range should also have been updated.
3289 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3291 // The page scale delta remains constant because the impl thread did not
3293 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3296 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
3297 gfx::Size
surface_size(20, 20);
3298 gfx::Size
viewport_size(10, 10);
3299 float page_scale
= 2.f
;
3300 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3301 scoped_ptr
<LayerImpl
> root_clip
=
3302 LayerImpl::Create(host_impl_
->active_tree(), 2);
3303 scoped_ptr
<LayerImpl
> root_scrolling
=
3304 CreateScrollableLayer(3, surface_size
, root_clip
.get());
3305 EXPECT_EQ(viewport_size
, root_clip
->bounds());
3306 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3307 root_clip
->AddChild(root_scrolling
.Pass());
3308 root
->AddChild(root_clip
.Pass());
3309 root
->SetHasRenderSurface(true);
3310 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3311 // The behaviour in this test assumes the page scale is applied at a layer
3312 // above the clip layer.
3313 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 3,
3315 host_impl_
->active_tree()->DidBecomeActive();
3316 host_impl_
->SetViewportSize(viewport_size
);
3317 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, page_scale
);
3320 LayerImpl
* root_scroll
=
3321 host_impl_
->active_tree()->InnerViewportScrollLayer();
3322 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3324 gfx::Vector2d
scroll_delta(0, 10);
3325 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3326 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3327 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3328 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3329 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3330 host_impl_
->ScrollEnd();
3332 // Set new page scale on impl thread by pinching.
3333 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3334 host_impl_
->PinchGestureBegin();
3335 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
3336 host_impl_
->PinchGestureEnd();
3337 host_impl_
->ScrollEnd();
3340 // The scroll delta is not scaled because the main thread did not scale.
3341 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3342 ExpectContains(*scroll_info
.get(), root_scroll
->id(), expected_scroll_delta
);
3344 // The scroll range should also have been updated.
3345 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3347 // The page scale delta should match the new scale on the impl side.
3348 EXPECT_EQ(page_scale
, host_impl_
->active_tree()->current_page_scale_factor());
3351 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
3352 gfx::Size
surface_size(10, 10);
3353 float default_page_scale
= 1.f
;
3354 gfx::Transform default_page_scale_matrix
;
3355 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
3357 float new_page_scale
= 2.f
;
3358 gfx::Transform new_page_scale_matrix
;
3359 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
3361 // Create a normal scrollable root layer and another scrollable child layer.
3362 LayerImpl
* scroll
= SetupScrollAndContentsLayers(surface_size
);
3363 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
3364 LayerImpl
* child
= scroll
->children()[0];
3366 scoped_ptr
<LayerImpl
> scrollable_child_clip
=
3367 LayerImpl::Create(host_impl_
->active_tree(), 6);
3368 scoped_ptr
<LayerImpl
> scrollable_child
=
3369 CreateScrollableLayer(7, surface_size
, scrollable_child_clip
.get());
3370 scrollable_child_clip
->AddChild(scrollable_child
.Pass());
3371 child
->AddChild(scrollable_child_clip
.Pass());
3372 LayerImpl
* grand_child
= child
->children()[0];
3374 // Set new page scale on impl thread by pinching.
3375 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3376 host_impl_
->PinchGestureBegin();
3377 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
3378 host_impl_
->PinchGestureEnd();
3379 host_impl_
->ScrollEnd();
3382 EXPECT_EQ(1.f
, root
->contents_scale_x());
3383 EXPECT_EQ(1.f
, root
->contents_scale_y());
3384 EXPECT_EQ(1.f
, scroll
->contents_scale_x());
3385 EXPECT_EQ(1.f
, scroll
->contents_scale_y());
3386 EXPECT_EQ(1.f
, child
->contents_scale_x());
3387 EXPECT_EQ(1.f
, child
->contents_scale_y());
3388 EXPECT_EQ(1.f
, grand_child
->contents_scale_x());
3389 EXPECT_EQ(1.f
, grand_child
->contents_scale_y());
3391 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3392 // the page scale delta on the root layer is applied hierarchically.
3393 LayerTreeHostImpl::FrameData frame
;
3394 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3395 host_impl_
->DrawLayers(&frame
);
3396 host_impl_
->DidDrawAllLayers(frame
);
3398 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(0, 0));
3399 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(1, 1));
3400 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(0, 0));
3401 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(1, 1));
3402 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
3403 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
3404 EXPECT_EQ(new_page_scale
,
3405 grand_child
->draw_transform().matrix().getDouble(0, 0));
3406 EXPECT_EQ(new_page_scale
,
3407 grand_child
->draw_transform().matrix().getDouble(1, 1));
3410 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
3411 gfx::Size
surface_size(30, 30);
3412 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3413 root
->SetBounds(gfx::Size(5, 5));
3414 root
->SetHasRenderSurface(true);
3415 scoped_ptr
<LayerImpl
> root_scrolling
=
3416 LayerImpl::Create(host_impl_
->active_tree(), 2);
3417 root_scrolling
->SetBounds(surface_size
);
3418 root_scrolling
->SetContentBounds(surface_size
);
3419 root_scrolling
->SetScrollClipLayer(root
->id());
3420 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3421 LayerImpl
* root_scrolling_ptr
= root_scrolling
.get();
3422 root
->AddChild(root_scrolling
.Pass());
3423 int child_scroll_layer_id
= 3;
3424 scoped_ptr
<LayerImpl
> child_scrolling
= CreateScrollableLayer(
3425 child_scroll_layer_id
, surface_size
, root_scrolling_ptr
);
3426 LayerImpl
* child
= child_scrolling
.get();
3427 root_scrolling_ptr
->AddChild(child_scrolling
.Pass());
3428 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3429 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3431 host_impl_
->active_tree()->DidBecomeActive();
3432 host_impl_
->SetViewportSize(surface_size
);
3435 gfx::Vector2d
scroll_delta(0, 10);
3436 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
3437 gfx::ScrollOffset
expected_max_scroll(child
->MaxScrollOffset());
3438 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3439 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3440 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3441 host_impl_
->ScrollEnd();
3443 float page_scale
= 2.f
;
3444 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
,
3449 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3451 *scroll_info
.get(), child_scroll_layer_id
, expected_scroll_delta
);
3453 // The scroll range should not have changed.
3454 EXPECT_EQ(child
->MaxScrollOffset(), expected_max_scroll
);
3456 // The page scale delta remains constant because the impl thread did not
3458 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3461 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
3462 // Scroll a child layer beyond its maximum scroll range and make sure the
3463 // parent layer is scrolled on the axis on which the child was unable to
3465 gfx::Size
surface_size(10, 10);
3466 gfx::Size
content_size(20, 20);
3467 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3468 root
->SetBounds(surface_size
);
3469 root
->SetHasRenderSurface(true);
3470 scoped_ptr
<LayerImpl
> grand_child
=
3471 CreateScrollableLayer(3, content_size
, root
.get());
3473 scoped_ptr
<LayerImpl
> child
=
3474 CreateScrollableLayer(2, content_size
, root
.get());
3475 LayerImpl
* grand_child_layer
= grand_child
.get();
3476 child
->AddChild(grand_child
.Pass());
3478 LayerImpl
* child_layer
= child
.get();
3479 root
->AddChild(child
.Pass());
3480 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3481 host_impl_
->active_tree()->DidBecomeActive();
3482 host_impl_
->SetViewportSize(surface_size
);
3483 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
3484 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
3488 gfx::Vector2d
scroll_delta(-8, -7);
3489 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3490 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3491 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3492 host_impl_
->ScrollEnd();
3494 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3495 host_impl_
->ProcessScrollDeltas();
3497 // The grand child should have scrolled up to its limit.
3498 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
3499 LayerImpl
* grand_child
= child
->children()[0];
3500 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -5));
3502 // The child should have only scrolled on the other axis.
3503 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(-3, 0));
3507 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
3508 // Scroll a child layer beyond its maximum scroll range and make sure the
3509 // the scroll doesn't bubble up to the parent layer.
3510 gfx::Size
surface_size(20, 20);
3511 gfx::Size
viewport_size(10, 10);
3512 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3513 root
->SetHasRenderSurface(true);
3514 scoped_ptr
<LayerImpl
> root_scrolling
=
3515 CreateScrollableLayer(2, surface_size
, root
.get());
3516 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3518 scoped_ptr
<LayerImpl
> grand_child
=
3519 CreateScrollableLayer(4, surface_size
, root
.get());
3521 scoped_ptr
<LayerImpl
> child
=
3522 CreateScrollableLayer(3, surface_size
, root
.get());
3523 LayerImpl
* grand_child_layer
= grand_child
.get();
3524 child
->AddChild(grand_child
.Pass());
3526 LayerImpl
* child_layer
= child
.get();
3527 root_scrolling
->AddChild(child
.Pass());
3528 root
->AddChild(root_scrolling
.Pass());
3529 EXPECT_EQ(viewport_size
, root
->bounds());
3530 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3531 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3533 host_impl_
->active_tree()->DidBecomeActive();
3534 host_impl_
->SetViewportSize(viewport_size
);
3536 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
3537 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
3541 gfx::Vector2d
scroll_delta(0, -10);
3542 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3543 host_impl_
->ScrollBegin(gfx::Point(),
3544 InputHandler::NON_BUBBLING_GESTURE
));
3545 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3546 host_impl_
->ScrollEnd();
3548 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3549 host_impl_
->ProcessScrollDeltas();
3551 // The grand child should have scrolled up to its limit.
3553 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
3554 LayerImpl
* grand_child
= child
->children()[0];
3555 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -2));
3557 // The child should not have scrolled.
3558 ExpectNone(*scroll_info
.get(), child
->id());
3560 // The next time we scroll we should only scroll the parent.
3561 scroll_delta
= gfx::Vector2d(0, -3);
3562 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3563 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3564 InputHandler::NON_BUBBLING_GESTURE
));
3565 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3566 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3567 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
3568 host_impl_
->ScrollEnd();
3570 scroll_info
= host_impl_
->ProcessScrollDeltas();
3572 // The child should have scrolled up to its limit.
3573 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(0, -3));
3575 // The grand child should not have scrolled.
3576 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -2));
3578 // After scrolling the parent, another scroll on the opposite direction
3579 // should still scroll the child.
3580 scroll_delta
= gfx::Vector2d(0, 7);
3581 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3582 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3583 InputHandler::NON_BUBBLING_GESTURE
));
3584 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3585 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3586 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3587 host_impl_
->ScrollEnd();
3589 scroll_info
= host_impl_
->ProcessScrollDeltas();
3591 // The grand child should have scrolled.
3592 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, 5));
3594 // The child should not have scrolled.
3595 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(0, -3));
3598 // Scrolling should be adjusted from viewport space.
3599 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 2.f
, 2.f
);
3600 host_impl_
->SetPageScaleOnActiveTree(2.f
);
3602 scroll_delta
= gfx::Vector2d(0, -2);
3603 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3604 host_impl_
->ScrollBegin(gfx::Point(1, 1),
3605 InputHandler::NON_BUBBLING_GESTURE
));
3606 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
3607 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3608 host_impl_
->ScrollEnd();
3610 scroll_info
= host_impl_
->ProcessScrollDeltas();
3612 // Should have scrolled by half the amount in layer space (5 - 2/2)
3613 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, 4));
3616 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
3617 // When we try to scroll a non-scrollable child layer, the scroll delta
3618 // should be applied to one of its ancestors if possible.
3619 gfx::Size
surface_size(10, 10);
3620 gfx::Size
content_size(20, 20);
3621 scoped_ptr
<LayerImpl
> root_clip
=
3622 LayerImpl::Create(host_impl_
->active_tree(), 3);
3623 root_clip
->SetHasRenderSurface(true);
3624 scoped_ptr
<LayerImpl
> root
=
3625 CreateScrollableLayer(1, content_size
, root_clip
.get());
3626 // Make 'root' the clip layer for child: since they have the same sizes the
3627 // child will have zero max_scroll_offset and scrolls will bubble.
3628 scoped_ptr
<LayerImpl
> child
=
3629 CreateScrollableLayer(2, content_size
, root
.get());
3630 child
->SetIsContainerForFixedPositionLayers(true);
3631 root
->SetBounds(content_size
);
3633 int root_scroll_id
= root
->id();
3634 root
->AddChild(child
.Pass());
3635 root_clip
->AddChild(root
.Pass());
3637 host_impl_
->SetViewportSize(surface_size
);
3638 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3639 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 2,
3641 host_impl_
->active_tree()->DidBecomeActive();
3644 gfx::Vector2d
scroll_delta(0, 4);
3645 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3646 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3647 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3648 host_impl_
->ScrollEnd();
3650 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3651 host_impl_
->ProcessScrollDeltas();
3653 // Only the root scroll should have scrolled.
3654 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
3655 ExpectContains(*scroll_info
.get(), root_scroll_id
, scroll_delta
);
3659 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
3660 gfx::Size
surface_size(10, 10);
3661 scoped_ptr
<LayerImpl
> root_clip
=
3662 LayerImpl::Create(host_impl_
->active_tree(), 1);
3663 scoped_ptr
<LayerImpl
> root_scroll
=
3664 CreateScrollableLayer(2, surface_size
, root_clip
.get());
3665 root_scroll
->SetIsContainerForFixedPositionLayers(true);
3666 root_clip
->SetHasRenderSurface(true);
3667 root_clip
->AddChild(root_scroll
.Pass());
3668 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3669 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3671 host_impl_
->active_tree()->DidBecomeActive();
3672 host_impl_
->SetViewportSize(surface_size
);
3674 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3677 host_impl_
->active_tree()->DetachLayerTree();
3678 scoped_ptr
<LayerImpl
> root_clip2
=
3679 LayerImpl::Create(host_impl_
->active_tree(), 3);
3680 scoped_ptr
<LayerImpl
> root_scroll2
=
3681 CreateScrollableLayer(4, surface_size
, root_clip2
.get());
3682 root_scroll2
->SetIsContainerForFixedPositionLayers(true);
3683 root_clip2
->AddChild(root_scroll2
.Pass());
3684 root_clip2
->SetHasRenderSurface(true);
3685 host_impl_
->active_tree()->SetRootLayer(root_clip2
.Pass());
3686 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 4,
3688 host_impl_
->active_tree()->DidBecomeActive();
3690 // Scrolling should still work even though we did not draw yet.
3691 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3692 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3695 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
3696 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3698 // Rotate the root layer 90 degrees counter-clockwise about its center.
3699 gfx::Transform rotate_transform
;
3700 rotate_transform
.Rotate(-90.0);
3701 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
3703 gfx::Size
surface_size(50, 50);
3704 host_impl_
->SetViewportSize(surface_size
);
3707 // Scroll to the right in screen coordinates with a gesture.
3708 gfx::Vector2d
gesture_scroll_delta(10, 0);
3709 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3710 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3711 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3712 host_impl_
->ScrollEnd();
3714 // The layer should have scrolled down in its local coordinates.
3715 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3716 ExpectContains(*scroll_info
.get(), scroll_layer
->id(),
3717 gfx::Vector2d(0, gesture_scroll_delta
.x()));
3719 // Reset and scroll down with the wheel.
3720 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
3721 gfx::Vector2d
wheel_scroll_delta(0, 10);
3722 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3723 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3724 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
3725 host_impl_
->ScrollEnd();
3727 // The layer should have scrolled down in its local coordinates.
3728 scroll_info
= host_impl_
->ProcessScrollDeltas();
3729 ExpectContains(*scroll_info
.get(),
3731 wheel_scroll_delta
);
3734 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
3735 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3736 int child_clip_layer_id
= 6;
3737 int child_layer_id
= 7;
3738 float child_layer_angle
= -20.f
;
3740 // Create a child layer that is rotated to a non-axis-aligned angle.
3741 scoped_ptr
<LayerImpl
> clip_layer
=
3742 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
3743 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
3744 child_layer_id
, scroll_layer
->content_bounds(), clip_layer
.get());
3745 gfx::Transform rotate_transform
;
3746 rotate_transform
.Translate(-50.0, -50.0);
3747 rotate_transform
.Rotate(child_layer_angle
);
3748 rotate_transform
.Translate(50.0, 50.0);
3749 clip_layer
->SetTransform(rotate_transform
);
3751 // Only allow vertical scrolling.
3752 clip_layer
->SetBounds(
3753 gfx::Size(child
->bounds().width(), child
->bounds().height() / 2));
3754 // The rotation depends on the layer's transform origin, and the child layer
3755 // is a different size than the clip, so make sure the clip layer's origin
3756 // lines up over the child.
3757 clip_layer
->SetTransformOrigin(gfx::Point3F(
3758 clip_layer
->bounds().width() * 0.5f
, clip_layer
->bounds().height(), 0.f
));
3759 LayerImpl
* child_ptr
= child
.get();
3760 clip_layer
->AddChild(child
.Pass());
3761 scroll_layer
->AddChild(clip_layer
.Pass());
3763 gfx::Size
surface_size(50, 50);
3764 host_impl_
->SetViewportSize(surface_size
);
3767 // Scroll down in screen coordinates with a gesture.
3768 gfx::Vector2d
gesture_scroll_delta(0, 10);
3769 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3770 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
3771 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3772 host_impl_
->ScrollEnd();
3774 // The child layer should have scrolled down in its local coordinates an
3775 // amount proportional to the angle between it and the input scroll delta.
3776 gfx::Vector2d
expected_scroll_delta(
3777 0, gesture_scroll_delta
.y() *
3778 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
3779 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3780 host_impl_
->ProcessScrollDeltas();
3781 ExpectContains(*scroll_info
.get(), child_layer_id
, expected_scroll_delta
);
3783 // The root scroll layer should not have scrolled, because the input delta
3784 // was close to the layer's axis of movement.
3785 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
3788 // Now reset and scroll the same amount horizontally.
3789 child_ptr
->SetScrollDelta(gfx::Vector2dF());
3790 gfx::Vector2d
gesture_scroll_delta(10, 0);
3791 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3792 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
3793 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3794 host_impl_
->ScrollEnd();
3796 // The child layer should have scrolled down in its local coordinates an
3797 // amount proportional to the angle between it and the input scroll delta.
3798 gfx::Vector2d
expected_scroll_delta(
3799 0, -gesture_scroll_delta
.x() *
3800 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
3801 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3802 host_impl_
->ProcessScrollDeltas();
3803 ExpectContains(*scroll_info
.get(), child_layer_id
, expected_scroll_delta
);
3805 // The root scroll layer should have scrolled more, since the input scroll
3806 // delta was mostly orthogonal to the child layer's vertical scroll axis.
3807 gfx::Vector2d
expected_root_scroll_delta(
3808 gesture_scroll_delta
.x() *
3809 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
3811 ExpectContains(*scroll_info
.get(),
3813 expected_root_scroll_delta
);
3817 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
3818 LayerImpl
* scroll_layer
=
3819 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3821 // Scale the layer to twice its normal size.
3823 gfx::Transform scale_transform
;
3824 scale_transform
.Scale(scale
, scale
);
3825 scroll_layer
->SetTransform(scale_transform
);
3827 gfx::Size
surface_size(50, 50);
3828 host_impl_
->SetViewportSize(surface_size
);
3831 // Scroll down in screen coordinates with a gesture.
3832 gfx::Vector2d
scroll_delta(0, 10);
3833 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3834 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3835 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3836 host_impl_
->ScrollEnd();
3838 // The layer should have scrolled down in its local coordinates, but half the
3840 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3841 ExpectContains(*scroll_info
.get(),
3843 gfx::Vector2d(0, scroll_delta
.y() / scale
));
3845 // Reset and scroll down with the wheel.
3846 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
3847 gfx::Vector2d
wheel_scroll_delta(0, 10);
3848 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3849 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3850 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
3851 host_impl_
->ScrollEnd();
3853 // It should apply the scale factor to the scroll delta for the wheel event.
3854 scroll_info
= host_impl_
->ProcessScrollDeltas();
3855 ExpectContains(*scroll_info
.get(),
3857 wheel_scroll_delta
);
3860 TEST_F(LayerTreeHostImplTest
, ScrollViewportRounding
) {
3864 SetupScrollAndContentsLayers(gfx::Size(width
, height
));
3865 host_impl_
->active_tree()->InnerViewportContainerLayer()->SetBounds(
3866 gfx::Size(width
* scale
- 1, height
* scale
));
3867 host_impl_
->SetDeviceScaleFactor(scale
);
3868 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
3870 LayerImpl
* inner_viewport_scroll_layer
=
3871 host_impl_
->active_tree()->InnerViewportScrollLayer();
3872 EXPECT_EQ(gfx::ScrollOffset(0, 0),
3873 inner_viewport_scroll_layer
->MaxScrollOffset());
3876 class TestScrollOffsetDelegate
: public LayerScrollOffsetDelegate
{
3878 TestScrollOffsetDelegate()
3879 : page_scale_factor_(0.f
),
3880 min_page_scale_factor_(-1.f
),
3881 max_page_scale_factor_(-1.f
) {}
3883 ~TestScrollOffsetDelegate() override
{}
3885 gfx::ScrollOffset
GetTotalScrollOffset() override
{
3886 return getter_return_value_
;
3889 bool IsExternalFlingActive() const override
{ return false; }
3891 void UpdateRootLayerState(const gfx::ScrollOffset
& total_scroll_offset
,
3892 const gfx::ScrollOffset
& max_scroll_offset
,
3893 const gfx::SizeF
& scrollable_size
,
3894 float page_scale_factor
,
3895 float min_page_scale_factor
,
3896 float max_page_scale_factor
) override
{
3897 DCHECK(total_scroll_offset
.x() <= max_scroll_offset
.x());
3898 DCHECK(total_scroll_offset
.y() <= max_scroll_offset
.y());
3899 last_set_scroll_offset_
= total_scroll_offset
;
3900 max_scroll_offset_
= max_scroll_offset
;
3901 scrollable_size_
= scrollable_size
;
3902 page_scale_factor_
= page_scale_factor
;
3903 min_page_scale_factor_
= min_page_scale_factor
;
3904 max_page_scale_factor_
= max_page_scale_factor
;
3906 set_getter_return_value(last_set_scroll_offset_
);
3909 gfx::ScrollOffset
last_set_scroll_offset() {
3910 return last_set_scroll_offset_
;
3913 void set_getter_return_value(const gfx::ScrollOffset
& value
) {
3914 getter_return_value_
= value
;
3917 gfx::ScrollOffset
max_scroll_offset() const {
3918 return max_scroll_offset_
;
3921 gfx::SizeF
scrollable_size() const {
3922 return scrollable_size_
;
3925 float page_scale_factor() const {
3926 return page_scale_factor_
;
3929 float min_page_scale_factor() const {
3930 return min_page_scale_factor_
;
3933 float max_page_scale_factor() const {
3934 return max_page_scale_factor_
;
3938 gfx::ScrollOffset last_set_scroll_offset_
;
3939 gfx::ScrollOffset getter_return_value_
;
3940 gfx::ScrollOffset max_scroll_offset_
;
3941 gfx::SizeF scrollable_size_
;
3942 float page_scale_factor_
;
3943 float min_page_scale_factor_
;
3944 float max_page_scale_factor_
;
3947 TEST_F(LayerTreeHostImplTest
, RootLayerScrollOffsetDelegation
) {
3948 TestScrollOffsetDelegate scroll_delegate
;
3949 host_impl_
->SetViewportSize(gfx::Size(10, 20));
3950 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3951 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
3952 clip_layer
->SetBounds(gfx::Size(10, 20));
3954 // Setting the delegate results in the current scroll offset being set.
3955 gfx::Vector2dF
initial_scroll_delta(10.f
, 10.f
);
3956 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
3957 scroll_layer
->SetScrollDelta(initial_scroll_delta
);
3958 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
3959 EXPECT_EQ(initial_scroll_delta
.ToString(),
3960 scroll_delegate
.last_set_scroll_offset().ToString());
3962 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3963 // page_scale_factor and {min|max}_page_scale_factor being set.
3964 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate
.scrollable_size());
3965 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate
.max_scroll_offset());
3966 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
3967 EXPECT_EQ(0.f
, scroll_delegate
.min_page_scale_factor());
3968 EXPECT_EQ(0.f
, scroll_delegate
.max_page_scale_factor());
3970 // Updating page scale immediately updates the delegate.
3971 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 0.5f
, 4.f
);
3972 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
3973 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
3974 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
3975 host_impl_
->SetPageScaleOnActiveTree(2.f
* 1.5f
);
3976 EXPECT_EQ(3.f
, scroll_delegate
.page_scale_factor());
3977 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
3978 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
3979 host_impl_
->SetPageScaleOnActiveTree(2.f
);
3980 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
3981 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
3982 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
3983 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
3985 // The pinch gesture doesn't put the delegate into a state where the scroll
3986 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3988 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3989 host_impl_
->PinchGestureBegin();
3990 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
3991 host_impl_
->PinchGestureUpdate(.5f
, gfx::Point());
3992 host_impl_
->PinchGestureEnd();
3993 host_impl_
->ScrollEnd();
3995 // Scrolling should be relative to the offset as returned by the delegate.
3996 gfx::Vector2dF
scroll_delta(0.f
, 10.f
);
3997 gfx::ScrollOffset
current_offset(7.f
, 8.f
);
3999 scroll_delegate
.set_getter_return_value(current_offset
);
4000 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4001 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4002 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4004 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4005 EXPECT_EQ(ScrollOffsetWithDelta(current_offset
, scroll_delta
),
4006 scroll_delegate
.last_set_scroll_offset());
4008 current_offset
= gfx::ScrollOffset(42.f
, 41.f
);
4009 scroll_delegate
.set_getter_return_value(current_offset
);
4010 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4011 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4012 EXPECT_EQ(current_offset
+ gfx::ScrollOffset(scroll_delta
),
4013 scroll_delegate
.last_set_scroll_offset());
4014 host_impl_
->ScrollEnd();
4015 scroll_delegate
.set_getter_return_value(gfx::ScrollOffset());
4016 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4018 // Forces a full tree synchronization and ensures that the scroll delegate
4019 // sees the correct size of the new tree.
4020 gfx::Size
new_size(42, 24);
4021 host_impl_
->CreatePendingTree();
4022 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), new_size
);
4023 host_impl_
->ActivateSyncTree();
4024 EXPECT_EQ(new_size
, scroll_delegate
.scrollable_size());
4026 // Un-setting the delegate should propagate the delegate's current offset to
4027 // the root scrollable layer.
4028 current_offset
= gfx::ScrollOffset(13.f
, 12.f
);
4029 scroll_delegate
.set_getter_return_value(current_offset
);
4030 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4031 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4033 EXPECT_EQ(current_offset
.ToString(),
4034 scroll_layer
->CurrentScrollOffset().ToString());
4037 void CheckLayerScrollDelta(LayerImpl
* layer
, gfx::Vector2dF scroll_delta
) {
4038 const gfx::Transform target_space_transform
=
4039 layer
->draw_properties().target_space_transform
;
4040 EXPECT_TRUE(target_space_transform
.IsScaleOrTranslation());
4041 gfx::Point translated_point
;
4042 target_space_transform
.TransformPoint(&translated_point
);
4043 gfx::Point expected_point
= gfx::Point() - ToRoundedVector2d(scroll_delta
);
4044 EXPECT_EQ(expected_point
.ToString(), translated_point
.ToString());
4047 TEST_F(LayerTreeHostImplTest
,
4048 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw
) {
4049 TestScrollOffsetDelegate scroll_delegate
;
4050 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4051 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4052 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4053 clip_layer
->SetBounds(gfx::Size(10, 20));
4054 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4056 // Draw first frame to clear any pending draws and check scroll.
4058 CheckLayerScrollDelta(scroll_layer
, gfx::Vector2dF(0.f
, 0.f
));
4059 EXPECT_FALSE(host_impl_
->active_tree()->needs_update_draw_properties());
4061 // Set external scroll delta on delegate and notify LayerTreeHost.
4062 gfx::ScrollOffset
scroll_offset(10.f
, 10.f
);
4063 scroll_delegate
.set_getter_return_value(scroll_offset
);
4064 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4066 // Check scroll delta reflected in layer.
4067 LayerTreeHostImpl::FrameData frame
;
4068 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4069 host_impl_
->DrawLayers(&frame
);
4070 host_impl_
->DidDrawAllLayers(frame
);
4071 EXPECT_FALSE(frame
.has_no_damage
);
4072 CheckLayerScrollDelta(scroll_layer
, ScrollOffsetToVector2dF(scroll_offset
));
4074 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4077 TEST_F(LayerTreeHostImplTest
, OverscrollRoot
) {
4078 InputHandlerScrollResult scroll_result
;
4079 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4080 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4081 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4083 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4085 // In-bounds scrolling does not affect overscroll.
4086 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4087 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4088 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4089 EXPECT_TRUE(scroll_result
.did_scroll
);
4090 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4091 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4092 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4094 // Overscroll events are reflected immediately.
4095 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4096 EXPECT_TRUE(scroll_result
.did_scroll
);
4097 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4098 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4099 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4100 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4101 host_impl_
->accumulated_root_overscroll());
4103 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4104 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4105 EXPECT_TRUE(scroll_result
.did_scroll
);
4106 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4107 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4108 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4109 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4110 host_impl_
->accumulated_root_overscroll());
4112 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4113 EXPECT_FALSE(scroll_result
.did_scroll
);
4114 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4115 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4116 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4117 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4118 host_impl_
->accumulated_root_overscroll());
4120 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4121 EXPECT_TRUE(scroll_result
.did_scroll
);
4122 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4123 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4124 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4125 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4126 host_impl_
->accumulated_root_overscroll());
4128 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4129 EXPECT_TRUE(scroll_result
.did_scroll
);
4130 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4131 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result
.unused_scroll_delta
);
4132 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_
->accumulated_root_overscroll());
4133 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4134 host_impl_
->accumulated_root_overscroll());
4136 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4137 EXPECT_TRUE(scroll_result
.did_scroll
);
4138 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4139 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4140 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_
->accumulated_root_overscroll());
4141 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4142 host_impl_
->accumulated_root_overscroll());
4144 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4145 EXPECT_TRUE(scroll_result
.did_scroll
);
4146 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4147 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4148 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4149 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4150 host_impl_
->accumulated_root_overscroll());
4152 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4153 // as no scroll occurs.
4154 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4155 EXPECT_FALSE(scroll_result
.did_scroll
);
4156 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4157 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4158 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_
->accumulated_root_overscroll());
4159 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4160 host_impl_
->accumulated_root_overscroll());
4162 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4163 EXPECT_FALSE(scroll_result
.did_scroll
);
4164 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4165 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4166 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_
->accumulated_root_overscroll());
4167 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4168 host_impl_
->accumulated_root_overscroll());
4170 // Overscroll resets on valid scroll.
4171 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4172 EXPECT_TRUE(scroll_result
.did_scroll
);
4173 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4174 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4175 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4176 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4177 host_impl_
->accumulated_root_overscroll());
4179 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4180 EXPECT_TRUE(scroll_result
.did_scroll
);
4181 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4182 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4183 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4184 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4185 host_impl_
->accumulated_root_overscroll());
4187 host_impl_
->ScrollEnd();
4191 TEST_F(LayerTreeHostImplTest
, OverscrollChildWithoutBubbling
) {
4192 // Scroll child layers beyond their maximum scroll range and make sure root
4193 // overscroll does not accumulate.
4194 gfx::Size
surface_size(10, 10);
4195 scoped_ptr
<LayerImpl
> root_clip
=
4196 LayerImpl::Create(host_impl_
->active_tree(), 4);
4197 root_clip
->SetHasRenderSurface(true);
4199 scoped_ptr
<LayerImpl
> root
=
4200 CreateScrollableLayer(1, surface_size
, root_clip
.get());
4202 scoped_ptr
<LayerImpl
> grand_child
=
4203 CreateScrollableLayer(3, surface_size
, root_clip
.get());
4205 scoped_ptr
<LayerImpl
> child
=
4206 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4207 LayerImpl
* grand_child_layer
= grand_child
.get();
4208 child
->AddChild(grand_child
.Pass());
4210 LayerImpl
* child_layer
= child
.get();
4211 root
->AddChild(child
.Pass());
4212 root_clip
->AddChild(root
.Pass());
4213 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4214 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4215 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4216 host_impl_
->active_tree()->DidBecomeActive();
4217 host_impl_
->SetViewportSize(surface_size
);
4220 gfx::Vector2d
scroll_delta(0, -10);
4221 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4222 host_impl_
->ScrollBegin(gfx::Point(),
4223 InputHandler::NON_BUBBLING_GESTURE
));
4224 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4225 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4226 host_impl_
->ScrollEnd();
4228 // The next time we scroll we should only scroll the parent, but overscroll
4229 // should still not reach the root layer.
4230 scroll_delta
= gfx::Vector2d(0, -30);
4231 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4232 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4233 InputHandler::NON_BUBBLING_GESTURE
));
4234 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4235 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4236 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4237 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_layer
);
4238 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4239 host_impl_
->ScrollEnd();
4241 // After scrolling the parent, another scroll on the opposite direction
4242 // should scroll the child.
4243 scroll_delta
= gfx::Vector2d(0, 70);
4244 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4245 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4246 InputHandler::NON_BUBBLING_GESTURE
));
4247 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4248 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4249 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4250 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4251 host_impl_
->ScrollEnd();
4255 TEST_F(LayerTreeHostImplTest
, OverscrollChildEventBubbling
) {
4256 // When we try to scroll a non-scrollable child layer, the scroll delta
4257 // should be applied to one of its ancestors if possible. Overscroll should
4258 // be reflected only when it has bubbled up to the root scrolling layer.
4259 gfx::Size
surface_size(10, 10);
4260 gfx::Size
content_size(20, 20);
4261 scoped_ptr
<LayerImpl
> root_clip
=
4262 LayerImpl::Create(host_impl_
->active_tree(), 3);
4263 root_clip
->SetHasRenderSurface(true);
4265 scoped_ptr
<LayerImpl
> root
=
4266 CreateScrollableLayer(1, content_size
, root_clip
.get());
4267 root
->SetIsContainerForFixedPositionLayers(true);
4268 scoped_ptr
<LayerImpl
> child
=
4269 CreateScrollableLayer(2, content_size
, root_clip
.get());
4271 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4272 root
->AddChild(child
.Pass());
4273 root_clip
->AddChild(root
.Pass());
4275 host_impl_
->SetViewportSize(surface_size
);
4276 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4277 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4279 host_impl_
->active_tree()->DidBecomeActive();
4282 gfx::Vector2d
scroll_delta(0, 8);
4283 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4284 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4285 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4286 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4287 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4288 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_
->accumulated_root_overscroll());
4289 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4290 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_
->accumulated_root_overscroll());
4291 host_impl_
->ScrollEnd();
4295 TEST_F(LayerTreeHostImplTest
, OverscrollAlways
) {
4296 LayerTreeSettings settings
;
4297 CreateHostImpl(settings
, CreateOutputSurface());
4299 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(50, 50));
4300 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4301 clip_layer
->SetBounds(gfx::Size(50, 50));
4302 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4303 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4305 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4307 // Even though the layer can't scroll the overscroll still happens.
4308 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4309 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4310 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4311 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4314 TEST_F(LayerTreeHostImplTest
, NoOverscrollOnFractionalDeviceScale
) {
4315 gfx::Size
surface_size(980, 1439);
4316 gfx::Size
content_size(980, 1438);
4317 float device_scale_factor
= 1.5f
;
4318 scoped_ptr
<LayerImpl
> root_clip
=
4319 LayerImpl::Create(host_impl_
->active_tree(), 3);
4320 root_clip
->SetHasRenderSurface(true);
4322 scoped_ptr
<LayerImpl
> root
=
4323 CreateScrollableLayer(1, content_size
, root_clip
.get());
4324 root
->SetIsContainerForFixedPositionLayers(true);
4325 scoped_ptr
<LayerImpl
> child
=
4326 CreateScrollableLayer(2, content_size
, root_clip
.get());
4327 root
->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
4328 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.326531f
, 0.326531f
,
4330 host_impl_
->SetPageScaleOnActiveTree(0.326531f
);
4331 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4332 root
->AddChild(child
.Pass());
4333 root_clip
->AddChild(root
.Pass());
4335 host_impl_
->SetViewportSize(surface_size
);
4336 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4337 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4338 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4340 host_impl_
->active_tree()->DidBecomeActive();
4343 // Horizontal & Vertical GlowEffect should not be applied when
4344 // content size is less then view port size. For Example Horizontal &
4345 // vertical GlowEffect should not be applied in about:blank page.
4346 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4347 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4348 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
4349 EXPECT_EQ(gfx::Vector2dF().ToString(),
4350 host_impl_
->accumulated_root_overscroll().ToString());
4352 host_impl_
->ScrollEnd();
4356 TEST_F(LayerTreeHostImplTest
, NoOverscrollWhenNotAtEdge
) {
4357 gfx::Size
surface_size(100, 100);
4358 gfx::Size
content_size(200, 200);
4359 scoped_ptr
<LayerImpl
> root_clip
=
4360 LayerImpl::Create(host_impl_
->active_tree(), 3);
4361 root_clip
->SetHasRenderSurface(true);
4363 scoped_ptr
<LayerImpl
> root
=
4364 CreateScrollableLayer(1, content_size
, root_clip
.get());
4365 root
->SetIsContainerForFixedPositionLayers(true);
4366 scoped_ptr
<LayerImpl
> child
=
4367 CreateScrollableLayer(2, content_size
, root_clip
.get());
4369 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4370 root
->AddChild(child
.Pass());
4371 root_clip
->AddChild(root
.Pass());
4373 host_impl_
->SetViewportSize(surface_size
);
4374 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4375 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4377 host_impl_
->active_tree()->DidBecomeActive();
4380 // Edge glow effect should be applicable only upon reaching Edges
4381 // of the content. unnecessary glow effect calls shouldn't be
4382 // called while scrolling up without reaching the edge of the content.
4383 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4384 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4385 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4386 EXPECT_EQ(gfx::Vector2dF().ToString(),
4387 host_impl_
->accumulated_root_overscroll().ToString());
4388 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f
));
4389 EXPECT_EQ(gfx::Vector2dF().ToString(),
4390 host_impl_
->accumulated_root_overscroll().ToString());
4391 host_impl_
->ScrollEnd();
4392 // unusedrootDelta should be subtracted from applied delta so that
4393 // unwanted glow effect calls are not called.
4394 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4395 host_impl_
->ScrollBegin(gfx::Point(0, 0),
4396 InputHandler::NON_BUBBLING_GESTURE
));
4397 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
4398 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4399 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4400 host_impl_
->accumulated_root_overscroll().ToString());
4402 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f
, -0.01f
));
4403 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4404 host_impl_
->accumulated_root_overscroll().ToString());
4405 host_impl_
->ScrollEnd();
4406 // TestCase to check kEpsilon, which prevents minute values to trigger
4407 // gloweffect without reaching edge.
4408 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4409 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4410 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f
, 0.1f
));
4411 EXPECT_EQ(gfx::Vector2dF().ToString(),
4412 host_impl_
->accumulated_root_overscroll().ToString());
4413 host_impl_
->ScrollEnd();
4417 class BlendStateCheckLayer
: public LayerImpl
{
4419 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
4421 ResourceProvider
* resource_provider
) {
4422 return make_scoped_ptr(
4423 new BlendStateCheckLayer(tree_impl
, id
, resource_provider
));
4426 void AppendQuads(RenderPass
* render_pass
,
4427 AppendQuadsData
* append_quads_data
) override
{
4428 quads_appended_
= true;
4430 gfx::Rect opaque_rect
;
4431 if (contents_opaque())
4432 opaque_rect
= quad_rect_
;
4434 opaque_rect
= opaque_content_rect_
;
4435 gfx::Rect visible_quad_rect
= quad_rect_
;
4437 SharedQuadState
* shared_quad_state
=
4438 render_pass
->CreateAndAppendSharedQuadState();
4439 PopulateSharedQuadState(shared_quad_state
);
4441 TileDrawQuad
* test_blending_draw_quad
=
4442 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
4443 test_blending_draw_quad
->SetNew(shared_quad_state
,
4448 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
4452 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
4453 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
4454 EXPECT_EQ(has_render_surface_
, !!render_surface());
4457 void SetExpectation(bool blend
, bool has_render_surface
) {
4459 has_render_surface_
= has_render_surface
;
4460 quads_appended_
= false;
4463 bool quads_appended() const { return quads_appended_
; }
4465 void SetQuadRect(const gfx::Rect
& rect
) { quad_rect_
= rect
; }
4466 void SetQuadVisibleRect(const gfx::Rect
& rect
) { quad_visible_rect_
= rect
; }
4467 void SetOpaqueContentRect(const gfx::Rect
& rect
) {
4468 opaque_content_rect_
= rect
;
4472 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
4474 ResourceProvider
* resource_provider
)
4475 : LayerImpl(tree_impl
, id
),
4477 has_render_surface_(false),
4478 quads_appended_(false),
4479 quad_rect_(5, 5, 5, 5),
4480 quad_visible_rect_(5, 5, 5, 5),
4481 resource_id_(resource_provider
->CreateResource(
4484 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
4486 resource_provider
->AllocateForTesting(resource_id_
);
4487 SetBounds(gfx::Size(10, 10));
4488 SetContentBounds(gfx::Size(10, 10));
4489 SetDrawsContent(true);
4493 bool has_render_surface_
;
4494 bool quads_appended_
;
4495 gfx::Rect quad_rect_
;
4496 gfx::Rect opaque_content_rect_
;
4497 gfx::Rect quad_visible_rect_
;
4498 ResourceId resource_id_
;
4501 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
4503 scoped_ptr
<LayerImpl
> root
=
4504 LayerImpl::Create(host_impl_
->active_tree(), 1);
4505 root
->SetBounds(gfx::Size(10, 10));
4506 root
->SetContentBounds(root
->bounds());
4507 root
->SetDrawsContent(false);
4508 root
->SetHasRenderSurface(true);
4509 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4511 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
4514 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4516 host_impl_
->resource_provider()));
4517 BlendStateCheckLayer
* layer1
=
4518 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
4519 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
4521 LayerTreeHostImpl::FrameData frame
;
4523 // Opaque layer, drawn without blending.
4524 layer1
->SetContentsOpaque(true);
4525 layer1
->SetExpectation(false, false);
4526 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4527 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4528 host_impl_
->DrawLayers(&frame
);
4529 EXPECT_TRUE(layer1
->quads_appended());
4530 host_impl_
->DidDrawAllLayers(frame
);
4532 // Layer with translucent content and painting, so drawn with blending.
4533 layer1
->SetContentsOpaque(false);
4534 layer1
->SetExpectation(true, false);
4535 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4536 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4537 host_impl_
->DrawLayers(&frame
);
4538 EXPECT_TRUE(layer1
->quads_appended());
4539 host_impl_
->DidDrawAllLayers(frame
);
4541 // Layer with translucent opacity, drawn with blending.
4542 layer1
->SetContentsOpaque(true);
4543 layer1
->SetOpacity(0.5f
);
4544 layer1
->SetExpectation(true, false);
4545 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4546 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4547 host_impl_
->DrawLayers(&frame
);
4548 EXPECT_TRUE(layer1
->quads_appended());
4549 host_impl_
->DidDrawAllLayers(frame
);
4551 // Layer with translucent opacity and painting, drawn with blending.
4552 layer1
->SetContentsOpaque(true);
4553 layer1
->SetOpacity(0.5f
);
4554 layer1
->SetExpectation(true, false);
4555 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4556 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4557 host_impl_
->DrawLayers(&frame
);
4558 EXPECT_TRUE(layer1
->quads_appended());
4559 host_impl_
->DidDrawAllLayers(frame
);
4562 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4564 host_impl_
->resource_provider()));
4565 BlendStateCheckLayer
* layer2
=
4566 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
4567 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
4569 // 2 opaque layers, drawn without blending.
4570 layer1
->SetContentsOpaque(true);
4571 layer1
->SetOpacity(1.f
);
4572 layer1
->SetExpectation(false, false);
4573 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4574 layer2
->SetContentsOpaque(true);
4575 layer2
->SetOpacity(1.f
);
4576 layer2
->SetExpectation(false, false);
4577 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4578 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4579 host_impl_
->DrawLayers(&frame
);
4580 EXPECT_TRUE(layer1
->quads_appended());
4581 EXPECT_TRUE(layer2
->quads_appended());
4582 host_impl_
->DidDrawAllLayers(frame
);
4584 // Parent layer with translucent content, drawn with blending.
4585 // Child layer with opaque content, drawn without blending.
4586 layer1
->SetContentsOpaque(false);
4587 layer1
->SetExpectation(true, false);
4588 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4589 layer2
->SetExpectation(false, false);
4590 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4591 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4592 host_impl_
->DrawLayers(&frame
);
4593 EXPECT_TRUE(layer1
->quads_appended());
4594 EXPECT_TRUE(layer2
->quads_appended());
4595 host_impl_
->DidDrawAllLayers(frame
);
4597 // Parent layer with translucent content but opaque painting, drawn without
4599 // Child layer with opaque content, drawn without blending.
4600 layer1
->SetContentsOpaque(true);
4601 layer1
->SetExpectation(false, false);
4602 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4603 layer2
->SetExpectation(false, false);
4604 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4605 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4606 host_impl_
->DrawLayers(&frame
);
4607 EXPECT_TRUE(layer1
->quads_appended());
4608 EXPECT_TRUE(layer2
->quads_appended());
4609 host_impl_
->DidDrawAllLayers(frame
);
4611 // Parent layer with translucent opacity and opaque content. Since it has a
4612 // drawing child, it's drawn to a render surface which carries the opacity,
4613 // so it's itself drawn without blending.
4614 // Child layer with opaque content, drawn without blending (parent surface
4615 // carries the inherited opacity).
4616 layer1
->SetContentsOpaque(true);
4617 layer1
->SetOpacity(0.5f
);
4618 layer1
->SetHasRenderSurface(true);
4619 layer1
->SetExpectation(false, true);
4620 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4621 layer2
->SetExpectation(false, false);
4622 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4623 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
4624 host_impl_
->active_tree()->root_layer());
4625 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4626 host_impl_
->DrawLayers(&frame
);
4627 EXPECT_TRUE(layer1
->quads_appended());
4628 EXPECT_TRUE(layer2
->quads_appended());
4629 host_impl_
->DidDrawAllLayers(frame
);
4630 layer1
->SetHasRenderSurface(false);
4632 // Draw again, but with child non-opaque, to make sure
4633 // layer1 not culled.
4634 layer1
->SetContentsOpaque(true);
4635 layer1
->SetOpacity(1.f
);
4636 layer1
->SetExpectation(false, false);
4637 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4638 layer2
->SetContentsOpaque(true);
4639 layer2
->SetOpacity(0.5f
);
4640 layer2
->SetExpectation(true, false);
4641 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4642 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4643 host_impl_
->DrawLayers(&frame
);
4644 EXPECT_TRUE(layer1
->quads_appended());
4645 EXPECT_TRUE(layer2
->quads_appended());
4646 host_impl_
->DidDrawAllLayers(frame
);
4648 // A second way of making the child non-opaque.
4649 layer1
->SetContentsOpaque(true);
4650 layer1
->SetOpacity(1.f
);
4651 layer1
->SetExpectation(false, false);
4652 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4653 layer2
->SetContentsOpaque(false);
4654 layer2
->SetOpacity(1.f
);
4655 layer2
->SetExpectation(true, false);
4656 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4657 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4658 host_impl_
->DrawLayers(&frame
);
4659 EXPECT_TRUE(layer1
->quads_appended());
4660 EXPECT_TRUE(layer2
->quads_appended());
4661 host_impl_
->DidDrawAllLayers(frame
);
4663 // And when the layer says its not opaque but is painted opaque, it is not
4665 layer1
->SetContentsOpaque(true);
4666 layer1
->SetOpacity(1.f
);
4667 layer1
->SetExpectation(false, false);
4668 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4669 layer2
->SetContentsOpaque(true);
4670 layer2
->SetOpacity(1.f
);
4671 layer2
->SetExpectation(false, false);
4672 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4673 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4674 host_impl_
->DrawLayers(&frame
);
4675 EXPECT_TRUE(layer1
->quads_appended());
4676 EXPECT_TRUE(layer2
->quads_appended());
4677 host_impl_
->DidDrawAllLayers(frame
);
4679 // Layer with partially opaque contents, drawn with blending.
4680 layer1
->SetContentsOpaque(false);
4681 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4682 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
4683 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4684 layer1
->SetExpectation(true, false);
4685 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4686 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4687 host_impl_
->DrawLayers(&frame
);
4688 EXPECT_TRUE(layer1
->quads_appended());
4689 host_impl_
->DidDrawAllLayers(frame
);
4691 // Layer with partially opaque contents partially culled, drawn with blending.
4692 layer1
->SetContentsOpaque(false);
4693 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4694 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
4695 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4696 layer1
->SetExpectation(true, false);
4697 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4698 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4699 host_impl_
->DrawLayers(&frame
);
4700 EXPECT_TRUE(layer1
->quads_appended());
4701 host_impl_
->DidDrawAllLayers(frame
);
4703 // Layer with partially opaque contents culled, drawn with blending.
4704 layer1
->SetContentsOpaque(false);
4705 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4706 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
4707 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4708 layer1
->SetExpectation(true, false);
4709 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4710 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4711 host_impl_
->DrawLayers(&frame
);
4712 EXPECT_TRUE(layer1
->quads_appended());
4713 host_impl_
->DidDrawAllLayers(frame
);
4715 // Layer with partially opaque contents and translucent contents culled, drawn
4716 // without blending.
4717 layer1
->SetContentsOpaque(false);
4718 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4719 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
4720 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4721 layer1
->SetExpectation(false, false);
4722 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4723 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4724 host_impl_
->DrawLayers(&frame
);
4725 EXPECT_TRUE(layer1
->quads_appended());
4726 host_impl_
->DidDrawAllLayers(frame
);
4729 class LayerTreeHostImplViewportCoveredTest
: public LayerTreeHostImplTest
{
4731 LayerTreeHostImplViewportCoveredTest() :
4732 gutter_quad_material_(DrawQuad::SOLID_COLOR
),
4734 did_activate_pending_tree_(false) {}
4736 scoped_ptr
<OutputSurface
> CreateFakeOutputSurface(bool always_draw
) {
4738 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
4740 return FakeOutputSurface::Create3d();
4743 void SetupActiveTreeLayers() {
4744 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
4745 host_impl_
->active_tree()->SetRootLayer(
4746 LayerImpl::Create(host_impl_
->active_tree(), 1));
4747 host_impl_
->active_tree()->root_layer()->SetHasRenderSurface(true);
4748 host_impl_
->active_tree()->root_layer()->AddChild(
4749 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4751 host_impl_
->resource_provider()));
4752 child_
= static_cast<BlendStateCheckLayer
*>(
4753 host_impl_
->active_tree()->root_layer()->children()[0]);
4754 child_
->SetExpectation(false, false);
4755 child_
->SetContentsOpaque(true);
4758 // Expect no gutter rects.
4759 void TestLayerCoversFullViewport() {
4760 gfx::Rect
layer_rect(viewport_size_
);
4761 child_
->SetPosition(layer_rect
.origin());
4762 child_
->SetBounds(layer_rect
.size());
4763 child_
->SetContentBounds(layer_rect
.size());
4764 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4765 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4767 LayerTreeHostImpl::FrameData frame
;
4768 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4769 ASSERT_EQ(1u, frame
.render_passes
.size());
4771 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4772 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4773 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4775 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4776 host_impl_
->DidDrawAllLayers(frame
);
4779 // Expect fullscreen gutter rect.
4780 void TestEmptyLayer() {
4781 gfx::Rect
layer_rect(0, 0, 0, 0);
4782 child_
->SetPosition(layer_rect
.origin());
4783 child_
->SetBounds(layer_rect
.size());
4784 child_
->SetContentBounds(layer_rect
.size());
4785 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4786 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4788 LayerTreeHostImpl::FrameData frame
;
4789 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4790 ASSERT_EQ(1u, frame
.render_passes
.size());
4792 EXPECT_EQ(1u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4793 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4794 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4796 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4797 host_impl_
->DidDrawAllLayers(frame
);
4800 // Expect four surrounding gutter rects.
4801 void TestLayerInMiddleOfViewport() {
4802 gfx::Rect
layer_rect(500, 500, 200, 200);
4803 child_
->SetPosition(layer_rect
.origin());
4804 child_
->SetBounds(layer_rect
.size());
4805 child_
->SetContentBounds(layer_rect
.size());
4806 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4807 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4809 LayerTreeHostImpl::FrameData frame
;
4810 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4811 ASSERT_EQ(1u, frame
.render_passes
.size());
4813 EXPECT_EQ(4u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4814 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
4815 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4817 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4818 host_impl_
->DidDrawAllLayers(frame
);
4821 // Expect no gutter rects.
4822 void TestLayerIsLargerThanViewport() {
4823 gfx::Rect
layer_rect(viewport_size_
.width() + 10,
4824 viewport_size_
.height() + 10);
4825 child_
->SetPosition(layer_rect
.origin());
4826 child_
->SetBounds(layer_rect
.size());
4827 child_
->SetContentBounds(layer_rect
.size());
4828 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4829 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4831 LayerTreeHostImpl::FrameData frame
;
4832 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4833 ASSERT_EQ(1u, frame
.render_passes
.size());
4835 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4836 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4837 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4839 host_impl_
->DidDrawAllLayers(frame
);
4842 void DidActivateSyncTree() override
{ did_activate_pending_tree_
= true; }
4844 void set_gutter_quad_material(DrawQuad::Material material
) {
4845 gutter_quad_material_
= material
;
4847 void set_gutter_texture_size(const gfx::Size
& gutter_texture_size
) {
4848 gutter_texture_size_
= gutter_texture_size
;
4852 size_t CountGutterQuads(const QuadList
& quad_list
) {
4853 size_t num_gutter_quads
= 0;
4854 for (const auto& quad
: quad_list
) {
4855 num_gutter_quads
+= (quad
->material
== gutter_quad_material_
) ? 1 : 0;
4857 return num_gutter_quads
;
4860 void VerifyQuadsExactlyCoverViewport(const QuadList
& quad_list
) {
4861 LayerTestCommon::VerifyQuadsExactlyCoverRect(
4862 quad_list
, gfx::Rect(DipSizeToPixelSize(viewport_size_
)));
4865 // Make sure that the texture coordinates match their expectations.
4866 void ValidateTextureDrawQuads(const QuadList
& quad_list
) {
4867 for (const auto& quad
: quad_list
) {
4868 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
)
4870 const TextureDrawQuad
* texture_quad
= TextureDrawQuad::MaterialCast(quad
);
4871 gfx::SizeF gutter_texture_size_pixels
= gfx::ScaleSize(
4872 gutter_texture_size_
, host_impl_
->device_scale_factor());
4873 EXPECT_EQ(texture_quad
->uv_top_left
.x(),
4874 texture_quad
->rect
.x() / gutter_texture_size_pixels
.width());
4875 EXPECT_EQ(texture_quad
->uv_top_left
.y(),
4876 texture_quad
->rect
.y() / gutter_texture_size_pixels
.height());
4878 texture_quad
->uv_bottom_right
.x(),
4879 texture_quad
->rect
.right() / gutter_texture_size_pixels
.width());
4881 texture_quad
->uv_bottom_right
.y(),
4882 texture_quad
->rect
.bottom() / gutter_texture_size_pixels
.height());
4886 gfx::Size
DipSizeToPixelSize(const gfx::Size
& size
) {
4887 return gfx::ToRoundedSize(
4888 gfx::ScaleSize(size
, host_impl_
->device_scale_factor()));
4891 DrawQuad::Material gutter_quad_material_
;
4892 gfx::Size gutter_texture_size_
;
4893 gfx::Size viewport_size_
;
4894 BlendStateCheckLayer
* child_
;
4895 bool did_activate_pending_tree_
;
4898 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCovered
) {
4899 viewport_size_
= gfx::Size(1000, 1000);
4901 bool always_draw
= false;
4902 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4904 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4905 SetupActiveTreeLayers();
4906 TestLayerCoversFullViewport();
4908 TestLayerInMiddleOfViewport();
4909 TestLayerIsLargerThanViewport();
4912 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredScaled
) {
4913 viewport_size_
= gfx::Size(1000, 1000);
4915 bool always_draw
= false;
4916 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4918 host_impl_
->SetDeviceScaleFactor(2.f
);
4919 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4920 SetupActiveTreeLayers();
4921 TestLayerCoversFullViewport();
4923 TestLayerInMiddleOfViewport();
4924 TestLayerIsLargerThanViewport();
4927 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeGrowViewportInvalid
) {
4928 viewport_size_
= gfx::Size(1000, 1000);
4930 bool always_draw
= true;
4931 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4933 // Pending tree to force active_tree size invalid. Not used otherwise.
4934 host_impl_
->CreatePendingTree();
4935 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4936 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
4938 SetupActiveTreeLayers();
4940 TestLayerInMiddleOfViewport();
4941 TestLayerIsLargerThanViewport();
4944 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeShrinkViewportInvalid
) {
4945 viewport_size_
= gfx::Size(1000, 1000);
4947 bool always_draw
= true;
4948 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4950 // Set larger viewport and activate it to active tree.
4951 host_impl_
->CreatePendingTree();
4952 gfx::Size
larger_viewport(viewport_size_
.width() + 100,
4953 viewport_size_
.height() + 100);
4954 host_impl_
->SetViewportSize(DipSizeToPixelSize(larger_viewport
));
4955 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
4956 host_impl_
->ActivateSyncTree();
4957 EXPECT_TRUE(did_activate_pending_tree_
);
4958 EXPECT_FALSE(host_impl_
->active_tree()->ViewportSizeInvalid());
4960 // Shrink pending tree viewport without activating.
4961 host_impl_
->CreatePendingTree();
4962 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4963 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
4965 SetupActiveTreeLayers();
4967 TestLayerInMiddleOfViewport();
4968 TestLayerIsLargerThanViewport();
4971 class FakeDrawableLayerImpl
: public LayerImpl
{
4973 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
4974 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl
, id
));
4977 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
4978 : LayerImpl(tree_impl
, id
) {}
4981 // Only reshape when we know we are going to draw. Otherwise, the reshape
4982 // can leave the window at the wrong size if we never draw and the proper
4983 // viewport size is never set.
4984 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
4985 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
4986 scoped_ptr
<OutputSurface
> output_surface(
4987 FakeOutputSurface::Create3d(provider
));
4988 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
4990 scoped_ptr
<LayerImpl
> root
=
4991 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
4992 root
->SetBounds(gfx::Size(10, 10));
4993 root
->SetContentBounds(gfx::Size(10, 10));
4994 root
->SetDrawsContent(true);
4995 root
->SetHasRenderSurface(true);
4996 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4997 EXPECT_FALSE(provider
->TestContext3d()->reshape_called());
4998 provider
->TestContext3d()->clear_reshape_called();
5000 LayerTreeHostImpl::FrameData frame
;
5001 host_impl_
->SetViewportSize(gfx::Size(10, 10));
5002 host_impl_
->SetDeviceScaleFactor(1.f
);
5003 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5004 host_impl_
->DrawLayers(&frame
);
5005 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5006 EXPECT_EQ(provider
->TestContext3d()->width(), 10);
5007 EXPECT_EQ(provider
->TestContext3d()->height(), 10);
5008 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5009 host_impl_
->DidDrawAllLayers(frame
);
5010 provider
->TestContext3d()->clear_reshape_called();
5012 host_impl_
->SetViewportSize(gfx::Size(20, 30));
5013 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5014 host_impl_
->DrawLayers(&frame
);
5015 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5016 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5017 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5018 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5019 host_impl_
->DidDrawAllLayers(frame
);
5020 provider
->TestContext3d()->clear_reshape_called();
5022 host_impl_
->SetDeviceScaleFactor(2.f
);
5023 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5024 host_impl_
->DrawLayers(&frame
);
5025 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5026 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5027 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5028 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 2.f
);
5029 host_impl_
->DidDrawAllLayers(frame
);
5030 provider
->TestContext3d()->clear_reshape_called();
5033 // Make sure damage tracking propagates all the way to the graphics context,
5034 // where it should request to swap only the sub-buffer that is damaged.
5035 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
5036 scoped_refptr
<TestContextProvider
> context_provider(
5037 TestContextProvider::Create());
5038 context_provider
->BindToCurrentThread();
5039 context_provider
->TestContext3d()->set_have_post_sub_buffer(true);
5041 scoped_ptr
<FakeOutputSurface
> output_surface(
5042 FakeOutputSurface::Create3d(context_provider
));
5043 FakeOutputSurface
* fake_output_surface
= output_surface
.get();
5045 // This test creates its own LayerTreeHostImpl, so
5046 // that we can force partial swap enabled.
5047 LayerTreeSettings settings
;
5048 settings
.renderer_settings
.partial_swap_enabled
= true;
5049 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
5050 LayerTreeHostImpl::Create(
5051 settings
, this, &proxy_
, &stats_instrumentation_
,
5052 shared_bitmap_manager_
.get(), NULL
, task_graph_runner_
.get(), 0);
5053 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
5054 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
5056 scoped_ptr
<LayerImpl
> root
=
5057 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
5058 root
->SetHasRenderSurface(true);
5059 scoped_ptr
<LayerImpl
> child
=
5060 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
5061 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
5062 child
->SetBounds(gfx::Size(14, 15));
5063 child
->SetContentBounds(gfx::Size(14, 15));
5064 child
->SetDrawsContent(true);
5065 root
->SetBounds(gfx::Size(500, 500));
5066 root
->SetContentBounds(gfx::Size(500, 500));
5067 root
->SetDrawsContent(true);
5068 root
->AddChild(child
.Pass());
5069 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5071 LayerTreeHostImpl::FrameData frame
;
5073 // First frame, the entire screen should get swapped.
5074 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5075 layer_tree_host_impl
->DrawLayers(&frame
);
5076 layer_tree_host_impl
->DidDrawAllLayers(frame
);
5077 layer_tree_host_impl
->SwapBuffers(frame
);
5078 gfx::Rect
expected_swap_rect(0, 0, 500, 500);
5079 EXPECT_EQ(expected_swap_rect
.ToString(),
5080 fake_output_surface
->last_swap_rect().ToString());
5082 // Second frame, only the damaged area should get swapped. Damage should be
5083 // the union of old and new child rects.
5084 // expected damage rect: gfx::Rect(26, 28);
5085 // expected swap rect: vertically flipped, with origin at bottom left corner.
5086 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
5088 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5089 layer_tree_host_impl
->DrawLayers(&frame
);
5090 host_impl_
->DidDrawAllLayers(frame
);
5091 layer_tree_host_impl
->SwapBuffers(frame
);
5093 // Make sure that partial swap is constrained to the viewport dimensions
5094 // expected damage rect: gfx::Rect(500, 500);
5095 // expected swap rect: flipped damage rect, but also clamped to viewport
5096 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
5097 EXPECT_EQ(expected_swap_rect
.ToString(),
5098 fake_output_surface
->last_swap_rect().ToString());
5100 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
5101 // This will damage everything.
5102 layer_tree_host_impl
->active_tree()->root_layer()->SetBackgroundColor(
5104 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5105 layer_tree_host_impl
->DrawLayers(&frame
);
5106 host_impl_
->DidDrawAllLayers(frame
);
5107 layer_tree_host_impl
->SwapBuffers(frame
);
5109 expected_swap_rect
= gfx::Rect(0, 0, 10, 10);
5110 EXPECT_EQ(expected_swap_rect
.ToString(),
5111 fake_output_surface
->last_swap_rect().ToString());
5114 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
5115 scoped_ptr
<LayerImpl
> root
=
5116 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5117 scoped_ptr
<LayerImpl
> child
=
5118 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
5119 child
->SetBounds(gfx::Size(10, 10));
5120 child
->SetContentBounds(gfx::Size(10, 10));
5121 child
->SetDrawsContent(true);
5122 root
->SetBounds(gfx::Size(10, 10));
5123 root
->SetContentBounds(gfx::Size(10, 10));
5124 root
->SetDrawsContent(true);
5125 root
->SetHasRenderSurface(true);
5126 root
->AddChild(child
.Pass());
5128 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5130 LayerTreeHostImpl::FrameData frame
;
5132 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5133 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
5134 EXPECT_EQ(1u, frame
.render_passes
.size());
5135 host_impl_
->DidDrawAllLayers(frame
);
5138 class FakeLayerWithQuads
: public LayerImpl
{
5140 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5141 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl
, id
));
5144 void AppendQuads(RenderPass
* render_pass
,
5145 AppendQuadsData
* append_quads_data
) override
{
5146 SharedQuadState
* shared_quad_state
=
5147 render_pass
->CreateAndAppendSharedQuadState();
5148 PopulateSharedQuadState(shared_quad_state
);
5150 SkColor gray
= SkColorSetRGB(100, 100, 100);
5151 gfx::Rect
quad_rect(content_bounds());
5152 gfx::Rect
visible_quad_rect(quad_rect
);
5153 SolidColorDrawQuad
* my_quad
=
5154 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
5156 shared_quad_state
, quad_rect
, visible_quad_rect
, gray
, false);
5160 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
5161 : LayerImpl(tree_impl
, id
) {}
5164 class MockContext
: public TestWebGraphicsContext3D
{
5166 MOCK_METHOD1(useProgram
, void(GLuint program
));
5167 MOCK_METHOD5(uniform4f
, void(GLint location
,
5172 MOCK_METHOD4(uniformMatrix4fv
, void(GLint location
,
5174 GLboolean transpose
,
5175 const GLfloat
* value
));
5176 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5180 MOCK_METHOD1(enable
, void(GLenum cap
));
5181 MOCK_METHOD1(disable
, void(GLenum cap
));
5182 MOCK_METHOD4(scissor
, void(GLint x
,
5188 class MockContextHarness
{
5190 MockContext
* context_
;
5193 explicit MockContextHarness(MockContext
* context
)
5194 : context_(context
) {
5195 context_
->set_have_post_sub_buffer(true);
5197 // Catch "uninteresting" calls
5198 EXPECT_CALL(*context_
, useProgram(_
))
5201 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
5204 // These are not asserted
5205 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
5206 .WillRepeatedly(Return());
5208 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
5209 .WillRepeatedly(Return());
5211 // Any un-sanctioned calls to enable() are OK
5212 EXPECT_CALL(*context_
, enable(_
))
5213 .WillRepeatedly(Return());
5215 // Any un-sanctioned calls to disable() are OK
5216 EXPECT_CALL(*context_
, disable(_
))
5217 .WillRepeatedly(Return());
5220 void MustDrawSolidQuad() {
5221 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
5223 .RetiresOnSaturation();
5225 EXPECT_CALL(*context_
, useProgram(_
))
5227 .RetiresOnSaturation();
5230 void MustSetScissor(int x
, int y
, int width
, int height
) {
5231 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5232 .WillRepeatedly(Return());
5234 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
5236 .WillRepeatedly(Return());
5239 void MustSetNoScissor() {
5240 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
5241 .WillRepeatedly(Return());
5243 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5246 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
5251 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
5252 scoped_ptr
<MockContext
> mock_context_owned(new MockContext
);
5253 MockContext
* mock_context
= mock_context_owned
.get();
5254 MockContextHarness
harness(mock_context
);
5257 LayerTreeSettings settings
= DefaultSettings();
5258 settings
.renderer_settings
.partial_swap_enabled
= false;
5259 CreateHostImpl(settings
,
5260 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5261 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5263 // Without partial swap, and no clipping, no scissor is set.
5264 harness
.MustDrawSolidQuad();
5265 harness
.MustSetNoScissor();
5267 LayerTreeHostImpl::FrameData frame
;
5268 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5269 host_impl_
->DrawLayers(&frame
);
5270 host_impl_
->DidDrawAllLayers(frame
);
5272 Mock::VerifyAndClearExpectations(&mock_context
);
5274 // Without partial swap, but a layer does clip its subtree, one scissor is
5276 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
5277 harness
.MustDrawSolidQuad();
5278 harness
.MustSetScissor(0, 0, 10, 10);
5280 LayerTreeHostImpl::FrameData frame
;
5281 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5282 host_impl_
->DrawLayers(&frame
);
5283 host_impl_
->DidDrawAllLayers(frame
);
5285 Mock::VerifyAndClearExpectations(&mock_context
);
5288 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
5289 scoped_ptr
<MockContext
> context_owned(new MockContext
);
5290 MockContext
* mock_context
= context_owned
.get();
5291 MockContextHarness
harness(mock_context
);
5293 LayerTreeSettings settings
= DefaultSettings();
5294 settings
.renderer_settings
.partial_swap_enabled
= true;
5295 CreateHostImpl(settings
, FakeOutputSurface::Create3d(context_owned
.Pass()));
5296 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5298 // The first frame is not a partially-swapped one. No scissor should be set.
5299 harness
.MustSetNoScissor();
5300 harness
.MustDrawSolidQuad();
5302 LayerTreeHostImpl::FrameData frame
;
5303 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5304 host_impl_
->DrawLayers(&frame
);
5305 host_impl_
->DidDrawAllLayers(frame
);
5307 Mock::VerifyAndClearExpectations(&mock_context
);
5309 // Damage a portion of the frame.
5310 host_impl_
->active_tree()->root_layer()->SetUpdateRect(
5311 gfx::Rect(0, 0, 2, 3));
5313 // The second frame will be partially-swapped (the y coordinates are flipped).
5314 harness
.MustSetScissor(0, 7, 2, 3);
5315 harness
.MustDrawSolidQuad();
5317 LayerTreeHostImpl::FrameData frame
;
5318 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5319 host_impl_
->DrawLayers(&frame
);
5320 host_impl_
->DidDrawAllLayers(frame
);
5322 Mock::VerifyAndClearExpectations(&mock_context
);
5325 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
5327 LayerTreeHostImplClient
* client
,
5329 SharedBitmapManager
* manager
,
5330 RenderingStatsInstrumentation
* stats_instrumentation
) {
5331 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5332 scoped_ptr
<OutputSurface
> output_surface(
5333 FakeOutputSurface::Create3d(provider
));
5334 provider
->BindToCurrentThread();
5335 provider
->TestContext3d()->set_have_post_sub_buffer(true);
5337 LayerTreeSettings settings
;
5338 settings
.renderer_settings
.partial_swap_enabled
= partial_swap
;
5339 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
= LayerTreeHostImpl::Create(
5340 settings
, client
, proxy
, stats_instrumentation
, manager
, NULL
, NULL
, 0);
5341 my_host_impl
->InitializeRenderer(output_surface
.Pass());
5342 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
5345 Layers are created as follows:
5347 +--------------------+
5351 | | +-------------------+
5353 | | +-------------------+
5358 +--------------------+
5360 Layers 1, 2 have render surfaces
5362 scoped_ptr
<LayerImpl
> root
=
5363 LayerImpl::Create(my_host_impl
->active_tree(), 1);
5364 scoped_ptr
<LayerImpl
> child
=
5365 LayerImpl::Create(my_host_impl
->active_tree(), 2);
5366 scoped_ptr
<LayerImpl
> grand_child
=
5367 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
5369 gfx::Rect
root_rect(0, 0, 100, 100);
5370 gfx::Rect
child_rect(10, 10, 50, 50);
5371 gfx::Rect
grand_child_rect(5, 5, 150, 150);
5373 root
->SetHasRenderSurface(true);
5374 root
->SetPosition(root_rect
.origin());
5375 root
->SetBounds(root_rect
.size());
5376 root
->SetContentBounds(root
->bounds());
5377 root
->draw_properties().visible_content_rect
= root_rect
;
5378 root
->SetDrawsContent(false);
5379 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
5381 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
5382 child
->SetOpacity(0.5f
);
5383 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
5384 child
->SetContentBounds(child
->bounds());
5385 child
->draw_properties().visible_content_rect
= child_rect
;
5386 child
->SetDrawsContent(false);
5387 child
->SetHasRenderSurface(true);
5389 grand_child
->SetPosition(grand_child_rect
.origin());
5390 grand_child
->SetBounds(grand_child_rect
.size());
5391 grand_child
->SetContentBounds(grand_child
->bounds());
5392 grand_child
->draw_properties().visible_content_rect
= grand_child_rect
;
5393 grand_child
->SetDrawsContent(true);
5395 child
->AddChild(grand_child
.Pass());
5396 root
->AddChild(child
.Pass());
5398 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5399 return my_host_impl
.Pass();
5402 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
5403 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
5404 new TestSharedBitmapManager());
5405 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5406 SetupLayersForOpacity(true,
5409 shared_bitmap_manager
.get(),
5410 &stats_instrumentation_
);
5412 LayerTreeHostImpl::FrameData frame
;
5413 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5415 // Verify all quads have been computed
5416 ASSERT_EQ(2U, frame
.render_passes
.size());
5417 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5418 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5419 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5420 frame
.render_passes
[0]->quad_list
.front()->material
);
5421 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5422 frame
.render_passes
[1]->quad_list
.front()->material
);
5424 my_host_impl
->DrawLayers(&frame
);
5425 my_host_impl
->DidDrawAllLayers(frame
);
5429 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
5430 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
5431 new TestSharedBitmapManager());
5432 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5433 SetupLayersForOpacity(false,
5436 shared_bitmap_manager
.get(),
5437 &stats_instrumentation_
);
5439 LayerTreeHostImpl::FrameData frame
;
5440 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5442 // Verify all quads have been computed
5443 ASSERT_EQ(2U, frame
.render_passes
.size());
5444 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5445 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5446 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5447 frame
.render_passes
[0]->quad_list
.front()->material
);
5448 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5449 frame
.render_passes
[1]->quad_list
.front()->material
);
5451 my_host_impl
->DrawLayers(&frame
);
5452 my_host_impl
->DidDrawAllLayers(frame
);
5456 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
5457 scoped_ptr
<TestWebGraphicsContext3D
> context
=
5458 TestWebGraphicsContext3D::Create();
5459 TestWebGraphicsContext3D
* context3d
= context
.get();
5460 scoped_ptr
<OutputSurface
> output_surface(
5461 FakeOutputSurface::Create3d(context
.Pass()));
5462 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5464 scoped_ptr
<LayerImpl
> root_layer
=
5465 LayerImpl::Create(host_impl_
->active_tree(), 1);
5466 root_layer
->SetBounds(gfx::Size(10, 10));
5467 root_layer
->SetHasRenderSurface(true);
5469 scoped_refptr
<VideoFrame
> softwareFrame
=
5470 media::VideoFrame::CreateColorFrame(
5471 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5472 FakeVideoFrameProvider provider
;
5473 provider
.set_frame(softwareFrame
);
5474 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
5475 host_impl_
->active_tree(), 4, &provider
, media::VIDEO_ROTATION_0
);
5476 video_layer
->SetBounds(gfx::Size(10, 10));
5477 video_layer
->SetContentBounds(gfx::Size(10, 10));
5478 video_layer
->SetDrawsContent(true);
5479 root_layer
->AddChild(video_layer
.Pass());
5481 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
5482 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
5483 io_surface_layer
->SetBounds(gfx::Size(10, 10));
5484 io_surface_layer
->SetContentBounds(gfx::Size(10, 10));
5485 io_surface_layer
->SetDrawsContent(true);
5486 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5487 root_layer
->AddChild(io_surface_layer
.Pass());
5489 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
5491 EXPECT_EQ(0u, context3d
->NumTextures());
5493 LayerTreeHostImpl::FrameData frame
;
5494 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5495 host_impl_
->DrawLayers(&frame
);
5496 host_impl_
->DidDrawAllLayers(frame
);
5497 host_impl_
->SwapBuffers(frame
);
5499 EXPECT_GT(context3d
->NumTextures(), 0u);
5501 // Kill the layer tree.
5502 host_impl_
->active_tree()->SetRootLayer(
5503 LayerImpl::Create(host_impl_
->active_tree(), 100));
5504 // There should be no textures left in use after.
5505 EXPECT_EQ(0u, context3d
->NumTextures());
5508 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
5510 MOCK_METHOD1(useProgram
, void(GLuint program
));
5511 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5517 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
5518 scoped_ptr
<MockDrawQuadsToFillScreenContext
> mock_context_owned(
5519 new MockDrawQuadsToFillScreenContext
);
5520 MockDrawQuadsToFillScreenContext
* mock_context
= mock_context_owned
.get();
5523 LayerTreeSettings settings
= DefaultSettings();
5524 settings
.renderer_settings
.partial_swap_enabled
= false;
5525 CreateHostImpl(settings
,
5526 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5527 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
5528 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
5530 // Verify one quad is drawn when transparent background set is not set.
5531 host_impl_
->active_tree()->set_has_transparent_background(false);
5532 EXPECT_CALL(*mock_context
, useProgram(_
))
5534 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
5536 LayerTreeHostImpl::FrameData frame
;
5537 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5538 host_impl_
->DrawLayers(&frame
);
5539 host_impl_
->DidDrawAllLayers(frame
);
5540 Mock::VerifyAndClearExpectations(&mock_context
);
5542 // Verify no quads are drawn when transparent background is set.
5543 host_impl_
->active_tree()->set_has_transparent_background(true);
5544 host_impl_
->SetFullRootLayerDamage();
5545 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5546 host_impl_
->DrawLayers(&frame
);
5547 host_impl_
->DidDrawAllLayers(frame
);
5548 Mock::VerifyAndClearExpectations(&mock_context
);
5551 TEST_F(LayerTreeHostImplTest
, ReleaseContentsTextureShouldTriggerCommit
) {
5552 set_reduce_memory_result(false);
5554 // If changing the memory limit wouldn't result in changing what was
5555 // committed, then no commit should be requested.
5556 set_reduce_memory_result(false);
5557 host_impl_
->set_max_memory_needed_bytes(
5558 host_impl_
->memory_allocation_limit_bytes() - 1);
5559 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5560 host_impl_
->memory_allocation_limit_bytes() - 1));
5561 EXPECT_FALSE(did_request_commit_
);
5562 did_request_commit_
= false;
5564 // If changing the memory limit would result in changing what was
5565 // committed, then a commit should be requested, even though nothing was
5567 set_reduce_memory_result(false);
5568 host_impl_
->set_max_memory_needed_bytes(
5569 host_impl_
->memory_allocation_limit_bytes());
5570 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5571 host_impl_
->memory_allocation_limit_bytes() - 1));
5572 EXPECT_TRUE(did_request_commit_
);
5573 did_request_commit_
= false;
5575 // Especially if changing the memory limit caused evictions, we need
5577 set_reduce_memory_result(true);
5578 host_impl_
->set_max_memory_needed_bytes(1);
5579 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5580 host_impl_
->memory_allocation_limit_bytes() - 1));
5581 EXPECT_TRUE(did_request_commit_
);
5582 did_request_commit_
= false;
5584 // But if we set it to the same value that it was before, we shouldn't
5586 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5587 host_impl_
->memory_allocation_limit_bytes()));
5588 EXPECT_FALSE(did_request_commit_
);
5591 class LayerTreeHostImplTestWithDelegatingRenderer
5592 : public LayerTreeHostImplTest
{
5594 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
5595 return FakeOutputSurface::CreateDelegating3d();
5598 void DrawFrameAndTestDamage(const gfx::RectF
& expected_damage
) {
5599 bool expect_to_draw
= !expected_damage
.IsEmpty();
5601 LayerTreeHostImpl::FrameData frame
;
5602 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5604 if (!expect_to_draw
) {
5605 // With no damage, we don't draw, and no quads are created.
5606 ASSERT_EQ(0u, frame
.render_passes
.size());
5608 ASSERT_EQ(1u, frame
.render_passes
.size());
5610 // Verify the damage rect for the root render pass.
5611 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
5612 EXPECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
5614 // Verify the root and child layers' quads are generated and not being
5616 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
5618 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
5619 gfx::RectF
expected_child_visible_rect(child
->content_bounds());
5620 EXPECT_EQ(expected_child_visible_rect
,
5621 root_render_pass
->quad_list
.front()->visible_rect
);
5623 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
5624 gfx::RectF
expected_root_visible_rect(root
->content_bounds());
5625 EXPECT_EQ(expected_root_visible_rect
,
5626 root_render_pass
->quad_list
.ElementAt(1)->visible_rect
);
5629 host_impl_
->DrawLayers(&frame
);
5630 host_impl_
->DidDrawAllLayers(frame
);
5631 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
5635 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
5636 scoped_ptr
<SolidColorLayerImpl
> root
=
5637 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
5638 root
->SetPosition(gfx::PointF());
5639 root
->SetBounds(gfx::Size(10, 10));
5640 root
->SetContentBounds(gfx::Size(10, 10));
5641 root
->SetDrawsContent(true);
5642 root
->SetHasRenderSurface(true);
5644 // Child layer is in the bottom right corner.
5645 scoped_ptr
<SolidColorLayerImpl
> child
=
5646 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
5647 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
5648 child
->SetBounds(gfx::Size(1, 1));
5649 child
->SetContentBounds(gfx::Size(1, 1));
5650 child
->SetDrawsContent(true);
5651 root
->AddChild(child
.Pass());
5653 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5655 // Draw a frame. In the first frame, the entire viewport should be damaged.
5656 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
5657 DrawFrameAndTestDamage(full_frame_damage
);
5659 // The second frame has damage that doesn't touch the child layer. Its quads
5660 // should still be generated.
5661 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
5662 host_impl_
->active_tree()->root_layer()->SetUpdateRect(small_damage
);
5663 DrawFrameAndTestDamage(small_damage
);
5665 // The third frame should have no damage, so no quads should be generated.
5666 gfx::Rect no_damage
;
5667 DrawFrameAndTestDamage(no_damage
);
5670 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5671 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5672 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, PreventRasterizeOnDemand
) {
5673 LayerTreeSettings settings
;
5674 CreateHostImpl(settings
, CreateOutputSurface());
5675 EXPECT_FALSE(host_impl_
->GetRendererCapabilities().allow_rasterize_on_demand
);
5678 class FakeMaskLayerImpl
: public LayerImpl
{
5680 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
5682 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
5685 void GetContentsResourceId(ResourceId
* resource_id
,
5686 gfx::Size
* resource_size
) const override
{
5691 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5692 : LayerImpl(tree_impl
, id
) {}
5695 class GLRendererWithSetupQuadForAntialiasing
: public GLRenderer
{
5697 using GLRenderer::ShouldAntialiasQuad
;
5700 TEST_F(LayerTreeHostImplTest
, FarAwayQuadsDontNeedAA
) {
5701 // Due to precision issues (especially on Android), sometimes far
5702 // away quads can end up thinking they need AA.
5703 float device_scale_factor
= 4.f
/ 3.f
;
5704 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5705 gfx::Size
root_size(2000, 1000);
5706 gfx::Size device_viewport_size
=
5707 gfx::ToCeiledSize(gfx::ScaleSize(root_size
, device_scale_factor
));
5708 host_impl_
->SetViewportSize(device_viewport_size
);
5710 host_impl_
->CreatePendingTree();
5711 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
/ 16.f
,
5714 scoped_ptr
<LayerImpl
> scoped_root
=
5715 LayerImpl::Create(host_impl_
->pending_tree(), 1);
5716 LayerImpl
* root
= scoped_root
.get();
5717 root
->SetHasRenderSurface(true);
5719 host_impl_
->pending_tree()->SetRootLayer(scoped_root
.Pass());
5721 scoped_ptr
<LayerImpl
> scoped_scrolling_layer
=
5722 LayerImpl::Create(host_impl_
->pending_tree(), 2);
5723 LayerImpl
* scrolling_layer
= scoped_scrolling_layer
.get();
5724 root
->AddChild(scoped_scrolling_layer
.Pass());
5726 gfx::Size
content_layer_bounds(100000, 100);
5727 gfx::Size
pile_tile_size(3000, 3000);
5728 scoped_refptr
<FakePicturePileImpl
> pile(FakePicturePileImpl::CreateFilledPile(
5729 pile_tile_size
, content_layer_bounds
));
5731 scoped_ptr
<FakePictureLayerImpl
> scoped_content_layer
=
5732 FakePictureLayerImpl::CreateWithRasterSource(host_impl_
->pending_tree(),
5734 LayerImpl
* content_layer
= scoped_content_layer
.get();
5735 scrolling_layer
->AddChild(scoped_content_layer
.Pass());
5736 content_layer
->SetBounds(content_layer_bounds
);
5737 content_layer
->SetDrawsContent(true);
5739 root
->SetBounds(root_size
);
5741 gfx::ScrollOffset
scroll_offset(100000, 0);
5742 scrolling_layer
->SetScrollClipLayer(root
->id());
5743 scrolling_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
5745 host_impl_
->ActivateSyncTree();
5747 bool update_lcd_text
= false;
5748 host_impl_
->active_tree()->UpdateDrawProperties(update_lcd_text
);
5749 ASSERT_EQ(1u, host_impl_
->active_tree()->RenderSurfaceLayerList().size());
5751 LayerTreeHostImpl::FrameData frame
;
5752 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5754 ASSERT_EQ(1u, frame
.render_passes
.size());
5755 ASSERT_LE(1u, frame
.render_passes
[0]->quad_list
.size());
5756 const DrawQuad
* quad
= frame
.render_passes
[0]->quad_list
.front();
5759 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
5760 quad
->quadTransform(), quad
, false);
5761 EXPECT_FALSE(antialiased
);
5763 host_impl_
->DrawLayers(&frame
);
5764 host_impl_
->DidDrawAllLayers(frame
);
5768 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
5770 CompositorFrameMetadataTest()
5771 : swap_buffers_complete_(0) {}
5773 void DidSwapBuffersCompleteOnImplThread() override
{
5774 swap_buffers_complete_
++;
5777 int swap_buffers_complete_
;
5780 TEST_F(CompositorFrameMetadataTest
, CompositorFrameAckCountsAsSwapComplete
) {
5781 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5783 LayerTreeHostImpl::FrameData frame
;
5784 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5785 host_impl_
->DrawLayers(&frame
);
5786 host_impl_
->DidDrawAllLayers(frame
);
5788 CompositorFrameAck ack
;
5789 host_impl_
->ReclaimResources(&ack
);
5790 host_impl_
->DidSwapBuffersComplete();
5791 EXPECT_EQ(swap_buffers_complete_
, 1);
5794 class CountingSoftwareDevice
: public SoftwareOutputDevice
{
5796 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5798 SkCanvas
* BeginPaint(const gfx::Rect
& damage_rect
) override
{
5800 return SoftwareOutputDevice::BeginPaint(damage_rect
);
5802 void EndPaint(SoftwareFrameData
* frame_data
) override
{
5804 SoftwareOutputDevice::EndPaint(frame_data
);
5807 int frames_began_
, frames_ended_
;
5810 TEST_F(LayerTreeHostImplTest
, ForcedDrawToSoftwareDeviceBasicRender
) {
5811 // No main thread evictions in resourceless software mode.
5812 set_reduce_memory_result(false);
5813 CountingSoftwareDevice
* software_device
= new CountingSoftwareDevice();
5814 EXPECT_TRUE(CreateHostImpl(
5816 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device
))));
5817 host_impl_
->SetViewportSize(gfx::Size(50, 50));
5819 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5821 const gfx::Transform external_transform
;
5822 const gfx::Rect external_viewport
;
5823 const gfx::Rect external_clip
;
5824 const bool resourceless_software_draw
= true;
5825 host_impl_
->SetExternalDrawConstraints(external_transform
,
5830 resourceless_software_draw
);
5832 EXPECT_EQ(0, software_device
->frames_began_
);
5833 EXPECT_EQ(0, software_device
->frames_ended_
);
5837 EXPECT_EQ(1, software_device
->frames_began_
);
5838 EXPECT_EQ(1, software_device
->frames_ended_
);
5840 // Call another API method that is likely to hit nullptr in this mode.
5841 scoped_refptr
<base::trace_event::TracedValue
> state
=
5842 make_scoped_refptr(new base::trace_event::TracedValue());
5843 host_impl_
->ActivationStateAsValueInto(state
.get());
5846 TEST_F(LayerTreeHostImplTest
,
5847 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers
) {
5848 set_reduce_memory_result(false);
5849 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5850 FakeOutputSurface::CreateSoftware(
5851 make_scoped_ptr(new CountingSoftwareDevice
))));
5853 const gfx::Transform external_transform
;
5854 const gfx::Rect external_viewport
;
5855 const gfx::Rect external_clip
;
5856 const bool resourceless_software_draw
= true;
5857 host_impl_
->SetExternalDrawConstraints(external_transform
,
5862 resourceless_software_draw
);
5864 // SolidColorLayerImpl will be drawn.
5865 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
5866 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
5868 // VideoLayerImpl will not be drawn.
5869 FakeVideoFrameProvider provider
;
5870 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
5871 host_impl_
->active_tree(), 2, &provider
, media::VIDEO_ROTATION_0
);
5872 video_layer
->SetBounds(gfx::Size(10, 10));
5873 video_layer
->SetContentBounds(gfx::Size(10, 10));
5874 video_layer
->SetDrawsContent(true);
5875 root_layer
->AddChild(video_layer
.Pass());
5876 SetupRootLayerImpl(root_layer
.Pass());
5878 LayerTreeHostImpl::FrameData frame
;
5879 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5880 host_impl_
->DrawLayers(&frame
);
5881 host_impl_
->DidDrawAllLayers(frame
);
5883 EXPECT_EQ(1u, frame
.will_draw_layers
.size());
5884 EXPECT_EQ(host_impl_
->active_tree()->root_layer(), frame
.will_draw_layers
[0]);
5887 // Checks that we have a non-0 default allocation if we pass a context that
5888 // doesn't support memory management extensions.
5889 TEST_F(LayerTreeHostImplTest
, DefaultMemoryAllocation
) {
5890 LayerTreeSettings settings
;
5891 host_impl_
= LayerTreeHostImpl::Create(
5892 settings
, this, &proxy_
, &stats_instrumentation_
,
5893 shared_bitmap_manager_
.get(), gpu_memory_buffer_manager_
.get(),
5894 task_graph_runner_
.get(), 0);
5896 scoped_ptr
<OutputSurface
> output_surface(
5897 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5898 host_impl_
->InitializeRenderer(output_surface
.Pass());
5899 EXPECT_LT(0ul, host_impl_
->memory_allocation_limit_bytes());
5902 TEST_F(LayerTreeHostImplTest
, MemoryPolicy
) {
5903 ManagedMemoryPolicy
policy1(
5904 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING
, 1000);
5905 int everything_cutoff_value
= ManagedMemoryPolicy::PriorityCutoffToValue(
5906 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING
);
5907 int allow_nice_to_have_cutoff_value
=
5908 ManagedMemoryPolicy::PriorityCutoffToValue(
5909 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE
);
5910 int nothing_cutoff_value
= ManagedMemoryPolicy::PriorityCutoffToValue(
5911 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING
);
5913 // GPU rasterization should be disabled by default on the tree(s)
5914 EXPECT_FALSE(host_impl_
->active_tree()->use_gpu_rasterization());
5915 EXPECT_TRUE(host_impl_
->pending_tree() == NULL
);
5917 host_impl_
->SetVisible(true);
5918 host_impl_
->SetMemoryPolicy(policy1
);
5919 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
5920 EXPECT_EQ(everything_cutoff_value
, current_priority_cutoff_value_
);
5922 host_impl_
->SetVisible(false);
5923 EXPECT_EQ(0u, current_limit_bytes_
);
5924 EXPECT_EQ(nothing_cutoff_value
, current_priority_cutoff_value_
);
5926 host_impl_
->SetVisible(true);
5927 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
5928 EXPECT_EQ(everything_cutoff_value
, current_priority_cutoff_value_
);
5930 // Now enable GPU rasterization and test if we get nice to have cutoff,
5932 LayerTreeSettings settings
;
5933 settings
.gpu_rasterization_enabled
= true;
5934 CreateHostImpl(settings
, CreateOutputSurface());
5935 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
5936 host_impl_
->SetHasGpuRasterizationTrigger(true);
5937 host_impl_
->SetVisible(true);
5938 host_impl_
->SetMemoryPolicy(policy1
);
5939 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
5940 EXPECT_EQ(allow_nice_to_have_cutoff_value
, current_priority_cutoff_value_
);
5942 host_impl_
->SetVisible(false);
5943 EXPECT_EQ(0u, current_limit_bytes_
);
5944 EXPECT_EQ(nothing_cutoff_value
, current_priority_cutoff_value_
);
5947 TEST_F(LayerTreeHostImplTest
, RequireHighResWhenVisible
) {
5948 ASSERT_TRUE(host_impl_
->active_tree());
5950 // RequiresHighResToDraw is set when new output surface is used.
5951 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5953 host_impl_
->ResetRequiresHighResToDraw();
5955 host_impl_
->SetVisible(false);
5956 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
5957 host_impl_
->SetVisible(true);
5958 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5959 host_impl_
->SetVisible(false);
5960 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5962 host_impl_
->ResetRequiresHighResToDraw();
5964 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
5965 host_impl_
->SetVisible(true);
5966 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5969 TEST_F(LayerTreeHostImplTest
, RequireHighResAfterGpuRasterizationToggles
) {
5970 ASSERT_TRUE(host_impl_
->active_tree());
5971 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
5973 // RequiresHighResToDraw is set when new output surface is used.
5974 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5976 host_impl_
->ResetRequiresHighResToDraw();
5978 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
5979 host_impl_
->SetHasGpuRasterizationTrigger(false);
5980 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
5981 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
5982 host_impl_
->SetHasGpuRasterizationTrigger(true);
5983 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
5984 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5985 host_impl_
->SetHasGpuRasterizationTrigger(false);
5986 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
5987 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5989 host_impl_
->ResetRequiresHighResToDraw();
5991 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
5992 host_impl_
->SetHasGpuRasterizationTrigger(true);
5993 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
5994 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
5997 class LayerTreeHostImplTestPrepareTiles
: public LayerTreeHostImplTest
{
5999 void SetUp() override
{
6000 LayerTreeSettings settings
;
6001 settings
.impl_side_painting
= true;
6003 fake_host_impl_
= new FakeLayerTreeHostImpl(settings
, &proxy_
,
6004 shared_bitmap_manager_
.get(),
6005 task_graph_runner_
.get());
6006 host_impl_
.reset(fake_host_impl_
);
6007 host_impl_
->InitializeRenderer(CreateOutputSurface());
6008 host_impl_
->SetViewportSize(gfx::Size(10, 10));
6011 FakeLayerTreeHostImpl
* fake_host_impl_
;
6014 TEST_F(LayerTreeHostImplTestPrepareTiles
, PrepareTilesWhenInvisible
) {
6015 fake_host_impl_
->DidModifyTilePriorities();
6016 EXPECT_TRUE(fake_host_impl_
->prepare_tiles_needed());
6017 fake_host_impl_
->SetVisible(false);
6018 EXPECT_FALSE(fake_host_impl_
->prepare_tiles_needed());
6021 TEST_F(LayerTreeHostImplTest
, UIResourceManagement
) {
6022 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6023 TestWebGraphicsContext3D::Create();
6024 TestWebGraphicsContext3D
* context3d
= context
.get();
6025 scoped_ptr
<FakeOutputSurface
> output_surface
= FakeOutputSurface::Create3d();
6026 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6028 EXPECT_EQ(0u, context3d
->NumTextures());
6030 UIResourceId ui_resource_id
= 1;
6031 bool is_opaque
= false;
6032 UIResourceBitmap
bitmap(gfx::Size(1, 1), is_opaque
);
6033 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6034 EXPECT_EQ(1u, context3d
->NumTextures());
6035 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6038 // Multiple requests with the same id is allowed. The previous texture is
6040 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6041 EXPECT_EQ(1u, context3d
->NumTextures());
6042 ResourceId id2
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6044 EXPECT_NE(id1
, id2
);
6046 // Deleting invalid UIResourceId is allowed and does not change state.
6047 host_impl_
->DeleteUIResource(-1);
6048 EXPECT_EQ(1u, context3d
->NumTextures());
6050 // Should return zero for invalid UIResourceId. Number of textures should
6052 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(-1));
6053 EXPECT_EQ(1u, context3d
->NumTextures());
6055 host_impl_
->DeleteUIResource(ui_resource_id
);
6056 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(ui_resource_id
));
6057 EXPECT_EQ(0u, context3d
->NumTextures());
6059 // Should not change state for multiple deletion on one UIResourceId
6060 host_impl_
->DeleteUIResource(ui_resource_id
);
6061 EXPECT_EQ(0u, context3d
->NumTextures());
6064 TEST_F(LayerTreeHostImplTest
, CreateETC1UIResource
) {
6065 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6066 TestWebGraphicsContext3D::Create();
6067 TestWebGraphicsContext3D
* context3d
= context
.get();
6068 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6070 EXPECT_EQ(0u, context3d
->NumTextures());
6072 gfx::Size
size(4, 4);
6073 // SkImageInfo has no support for ETC1. The |info| below contains the right
6074 // total pixel size for the bitmap but not the right height and width. The
6075 // correct width/height are passed directly to UIResourceBitmap.
6077 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType
, kPremul_SkAlphaType
);
6078 skia::RefPtr
<SkPixelRef
> pixel_ref
=
6079 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info
, 0, 0));
6080 pixel_ref
->setImmutable();
6081 UIResourceBitmap
bitmap(pixel_ref
, size
);
6082 UIResourceId ui_resource_id
= 1;
6083 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6084 EXPECT_EQ(1u, context3d
->NumTextures());
6085 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6089 void ShutdownReleasesContext_Callback(scoped_ptr
<CopyOutputResult
> result
) {
6092 TEST_F(LayerTreeHostImplTest
, ShutdownReleasesContext
) {
6093 scoped_refptr
<TestContextProvider
> context_provider
=
6094 TestContextProvider::Create();
6096 CreateHostImpl(DefaultSettings(),
6097 FakeOutputSurface::Create3d(context_provider
));
6099 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6101 ScopedPtrVector
<CopyOutputRequest
> requests
;
6102 requests
.push_back(CopyOutputRequest::CreateRequest(
6103 base::Bind(&ShutdownReleasesContext_Callback
)));
6105 host_impl_
->active_tree()->root_layer()->PassCopyRequests(&requests
);
6107 LayerTreeHostImpl::FrameData frame
;
6108 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6109 host_impl_
->DrawLayers(&frame
);
6110 host_impl_
->DidDrawAllLayers(frame
);
6112 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6113 // texture in a texture mailbox.
6114 EXPECT_FALSE(context_provider
->HasOneRef());
6115 EXPECT_EQ(1u, context_provider
->TestContext3d()->NumTextures());
6117 host_impl_
= nullptr;
6119 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6120 // released, and the texture deleted.
6121 EXPECT_TRUE(context_provider
->HasOneRef());
6122 EXPECT_EQ(0u, context_provider
->TestContext3d()->NumTextures());
6125 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldNotBubble
) {
6126 // When flinging via touch, only the child should scroll (we should not
6128 gfx::Size
surface_size(10, 10);
6129 gfx::Size
content_size(20, 20);
6130 scoped_ptr
<LayerImpl
> root_clip
=
6131 LayerImpl::Create(host_impl_
->active_tree(), 3);
6132 root_clip
->SetHasRenderSurface(true);
6134 scoped_ptr
<LayerImpl
> root
=
6135 CreateScrollableLayer(1, content_size
, root_clip
.get());
6136 root
->SetIsContainerForFixedPositionLayers(true);
6137 scoped_ptr
<LayerImpl
> child
=
6138 CreateScrollableLayer(2, content_size
, root_clip
.get());
6140 root
->AddChild(child
.Pass());
6141 int root_id
= root
->id();
6142 root_clip
->AddChild(root
.Pass());
6144 host_impl_
->SetViewportSize(surface_size
);
6145 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6146 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
6148 host_impl_
->active_tree()->DidBecomeActive();
6151 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6152 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6154 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6156 gfx::Vector2d
scroll_delta(0, 100);
6157 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6158 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6160 host_impl_
->ScrollEnd();
6162 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6163 host_impl_
->ProcessScrollDeltas();
6165 // Only the child should have scrolled.
6166 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6167 ExpectNone(*scroll_info
.get(), root_id
);
6171 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldLockToFirstScrolledLayer
) {
6172 // Scroll a child layer beyond its maximum scroll range and make sure the
6173 // the scroll doesn't bubble up to the parent layer.
6174 gfx::Size
surface_size(10, 10);
6175 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
6176 root
->SetHasRenderSurface(true);
6177 scoped_ptr
<LayerImpl
> root_scrolling
=
6178 CreateScrollableLayer(2, surface_size
, root
.get());
6180 scoped_ptr
<LayerImpl
> grand_child
=
6181 CreateScrollableLayer(4, surface_size
, root
.get());
6182 grand_child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6184 scoped_ptr
<LayerImpl
> child
=
6185 CreateScrollableLayer(3, surface_size
, root
.get());
6186 child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6187 child
->AddChild(grand_child
.Pass());
6189 root_scrolling
->AddChild(child
.Pass());
6190 root
->AddChild(root_scrolling
.Pass());
6191 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6192 host_impl_
->active_tree()->DidBecomeActive();
6193 host_impl_
->SetViewportSize(surface_size
);
6196 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
6198 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
6199 LayerImpl
* grand_child
= child
->children()[0];
6201 gfx::Vector2d
scroll_delta(0, -2);
6202 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6203 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6204 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6206 // The grand child should have scrolled up to its limit.
6207 scroll_info
= host_impl_
->ProcessScrollDeltas();
6208 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6209 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6210 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6212 // The child should have received the bubbled delta, but the locked
6213 // scrolling layer should remain set as the grand child.
6214 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6215 scroll_info
= host_impl_
->ProcessScrollDeltas();
6216 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6217 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6218 ExpectContains(*scroll_info
, child
->id(), scroll_delta
);
6219 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6221 // The first |ScrollBy| after the fling should re-lock the scrolling
6222 // layer to the first layer that scrolled, which is the child.
6223 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6224 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6225 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6227 // The child should have scrolled up to its limit.
6228 scroll_info
= host_impl_
->ProcessScrollDeltas();
6229 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6230 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6231 ExpectContains(*scroll_info
, child
->id(), scroll_delta
+ scroll_delta
);
6233 // As the locked layer is at it's limit, no further scrolling can occur.
6234 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6235 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6236 host_impl_
->ScrollEnd();
6240 TEST_F(LayerTreeHostImplTest
, WheelFlingShouldBubble
) {
6241 // When flinging via wheel, the root should eventually scroll (we should
6243 gfx::Size
surface_size(10, 10);
6244 gfx::Size
content_size(20, 20);
6245 scoped_ptr
<LayerImpl
> root_clip
=
6246 LayerImpl::Create(host_impl_
->active_tree(), 3);
6247 root_clip
->SetHasRenderSurface(true);
6248 scoped_ptr
<LayerImpl
> root_scroll
=
6249 CreateScrollableLayer(1, content_size
, root_clip
.get());
6250 int root_scroll_id
= root_scroll
->id();
6251 scoped_ptr
<LayerImpl
> child
=
6252 CreateScrollableLayer(2, content_size
, root_clip
.get());
6254 root_scroll
->AddChild(child
.Pass());
6255 root_clip
->AddChild(root_scroll
.Pass());
6257 host_impl_
->SetViewportSize(surface_size
);
6258 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6259 host_impl_
->active_tree()->DidBecomeActive();
6262 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6263 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6265 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6267 gfx::Vector2d
scroll_delta(0, 100);
6268 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6269 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6271 host_impl_
->ScrollEnd();
6273 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6274 host_impl_
->ProcessScrollDeltas();
6276 // The root should have scrolled.
6277 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6278 ExpectContains(*scroll_info
.get(), root_scroll_id
, gfx::Vector2d(0, 10));
6282 TEST_F(LayerTreeHostImplTest
, ScrollUnknownNotOnAncestorChain
) {
6283 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6284 // we should return SCROLL_UNKNOWN.
6285 gfx::Size
content_size(100, 100);
6286 SetupScrollAndContentsLayers(content_size
);
6288 int scroll_layer_id
= 2;
6289 LayerImpl
* scroll_layer
=
6290 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6291 scroll_layer
->SetDrawsContent(true);
6293 int page_scale_layer_id
= 5;
6294 LayerImpl
* page_scale_layer
=
6295 host_impl_
->active_tree()->LayerById(page_scale_layer_id
);
6297 int occluder_layer_id
= 6;
6298 scoped_ptr
<LayerImpl
> occluder_layer
=
6299 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6300 occluder_layer
->SetDrawsContent(true);
6301 occluder_layer
->SetBounds(content_size
);
6302 occluder_layer
->SetContentBounds(content_size
);
6303 occluder_layer
->SetPosition(gfx::PointF());
6305 // The parent of the occluder is *above* the scroller.
6306 page_scale_layer
->AddChild(occluder_layer
.Pass());
6310 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6311 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6314 TEST_F(LayerTreeHostImplTest
, ScrollUnknownScrollAncestorMismatch
) {
6315 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6316 // is not the first scroller we encounter when walking up from the layer, we
6317 // should also return SCROLL_UNKNOWN.
6318 gfx::Size
content_size(100, 100);
6319 SetupScrollAndContentsLayers(content_size
);
6321 int scroll_layer_id
= 2;
6322 LayerImpl
* scroll_layer
=
6323 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6324 scroll_layer
->SetDrawsContent(true);
6326 int occluder_layer_id
= 6;
6327 scoped_ptr
<LayerImpl
> occluder_layer
=
6328 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6329 occluder_layer
->SetDrawsContent(true);
6330 occluder_layer
->SetBounds(content_size
);
6331 occluder_layer
->SetContentBounds(content_size
);
6332 occluder_layer
->SetPosition(gfx::PointF(-10.f
, -10.f
));
6334 int child_scroll_clip_layer_id
= 7;
6335 scoped_ptr
<LayerImpl
> child_scroll_clip
=
6336 LayerImpl::Create(host_impl_
->active_tree(), child_scroll_clip_layer_id
);
6338 int child_scroll_layer_id
= 8;
6339 scoped_ptr
<LayerImpl
> child_scroll
= CreateScrollableLayer(
6340 child_scroll_layer_id
, content_size
, child_scroll_clip
.get());
6342 child_scroll
->SetPosition(gfx::PointF(10.f
, 10.f
));
6344 child_scroll
->AddChild(occluder_layer
.Pass());
6345 scroll_layer
->AddChild(child_scroll
.Pass());
6349 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6350 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6353 TEST_F(LayerTreeHostImplTest
, NotScrollInvisibleScroller
) {
6354 gfx::Size
content_size(100, 100);
6355 SetupScrollAndContentsLayers(content_size
);
6357 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6359 int scroll_layer_id
= 2;
6360 LayerImpl
* scroll_layer
=
6361 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6363 int child_scroll_layer_id
= 7;
6364 scoped_ptr
<LayerImpl
> child_scroll
=
6365 CreateScrollableLayer(child_scroll_layer_id
, content_size
, root
);
6366 child_scroll
->SetDrawsContent(false);
6368 scroll_layer
->AddChild(child_scroll
.Pass());
6372 // We should not have scrolled |child_scroll| even though we technically "hit"
6373 // it. The reason for this is that if the scrolling the scroll would not move
6374 // any layer that is a drawn RSLL member, then we can ignore the hit.
6376 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6377 // started scrolling the inner viewport.
6378 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6379 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6381 EXPECT_EQ(2, host_impl_
->CurrentlyScrollingLayer()->id());
6384 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleDescendent
) {
6385 gfx::Size
content_size(100, 100);
6386 SetupScrollAndContentsLayers(content_size
);
6388 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6389 LayerImpl
* root_scroll_layer
= host_impl_
->active_tree()->LayerById(2);
6391 scoped_ptr
<LayerImpl
> invisible_scroll_layer
=
6392 CreateScrollableLayer(7, content_size
, root
);
6393 invisible_scroll_layer
->SetDrawsContent(false);
6395 scoped_ptr
<LayerImpl
> child_layer
=
6396 LayerImpl::Create(host_impl_
->active_tree(), 8);
6397 child_layer
->SetDrawsContent(false);
6399 scoped_ptr
<LayerImpl
> grand_child_layer
=
6400 LayerImpl::Create(host_impl_
->active_tree(), 9);
6401 grand_child_layer
->SetDrawsContent(true);
6402 grand_child_layer
->SetBounds(content_size
);
6403 grand_child_layer
->SetContentBounds(content_size
);
6404 // Move the grand child so it's not hit by our test point.
6405 grand_child_layer
->SetPosition(gfx::PointF(10.f
, 10.f
));
6407 child_layer
->AddChild(grand_child_layer
.Pass());
6408 invisible_scroll_layer
->AddChild(child_layer
.Pass());
6409 root_scroll_layer
->AddChild(invisible_scroll_layer
.Pass());
6413 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6414 // a descendant which is a drawn RSLL member.
6415 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6416 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6418 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6421 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleScrollChild
) {
6422 // This test case is very similar to the one above with one key difference:
6423 // the invisible scroller has a scroll child that is indeed draw contents.
6424 // If we attempt to initiate a gesture scroll off of the visible scroll child
6425 // we should still start the scroll child.
6426 gfx::Size
content_size(100, 100);
6427 SetupScrollAndContentsLayers(content_size
);
6429 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6431 int scroll_layer_id
= 2;
6432 LayerImpl
* scroll_layer
=
6433 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6435 int scroll_child_id
= 6;
6436 scoped_ptr
<LayerImpl
> scroll_child
=
6437 LayerImpl::Create(host_impl_
->active_tree(), scroll_child_id
);
6438 scroll_child
->SetDrawsContent(true);
6439 scroll_child
->SetBounds(content_size
);
6440 scroll_child
->SetContentBounds(content_size
);
6441 // Move the scroll child so it's not hit by our test point.
6442 scroll_child
->SetPosition(gfx::PointF(10.f
, 10.f
));
6444 int invisible_scroll_layer_id
= 7;
6445 scoped_ptr
<LayerImpl
> invisible_scroll
=
6446 CreateScrollableLayer(invisible_scroll_layer_id
, content_size
, root
);
6447 invisible_scroll
->SetDrawsContent(false);
6449 int container_id
= 8;
6450 scoped_ptr
<LayerImpl
> container
=
6451 LayerImpl::Create(host_impl_
->active_tree(), container_id
);
6453 scoped_ptr
<std::set
<LayerImpl
*>> scroll_children(new std::set
<LayerImpl
*>);
6454 scroll_children
->insert(scroll_child
.get());
6455 invisible_scroll
->SetScrollChildren(scroll_children
.release());
6457 scroll_child
->SetScrollParent(invisible_scroll
.get());
6459 container
->AddChild(invisible_scroll
.Pass());
6460 container
->AddChild(scroll_child
.Pass());
6462 scroll_layer
->AddChild(container
.Pass());
6466 // We should have scrolled |child_scroll| even though it is invisible.
6467 // The reason for this is that if the scrolling the scroll would move a layer
6468 // that is a drawn RSLL member, then we should accept this hit.
6469 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6470 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6472 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6475 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6476 // to CompositorFrameMetadata after SwapBuffers();
6477 TEST_F(LayerTreeHostImplTest
, LatencyInfoPassedToCompositorFrameMetadata
) {
6478 scoped_ptr
<SolidColorLayerImpl
> root
=
6479 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6480 root
->SetPosition(gfx::PointF());
6481 root
->SetBounds(gfx::Size(10, 10));
6482 root
->SetContentBounds(gfx::Size(10, 10));
6483 root
->SetDrawsContent(true);
6484 root
->SetHasRenderSurface(true);
6486 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6488 FakeOutputSurface
* fake_output_surface
=
6489 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6491 const std::vector
<ui::LatencyInfo
>& metadata_latency_before
=
6492 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6493 EXPECT_TRUE(metadata_latency_before
.empty());
6495 ui::LatencyInfo latency_info
;
6496 latency_info
.AddLatencyNumber(
6497 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, 0);
6498 scoped_ptr
<SwapPromise
> swap_promise(
6499 new LatencyInfoSwapPromise(latency_info
));
6500 host_impl_
->active_tree()->QueueSwapPromise(swap_promise
.Pass());
6501 host_impl_
->SetNeedsRedraw();
6503 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6504 LayerTreeHostImpl::FrameData frame
;
6505 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6506 host_impl_
->DrawLayers(&frame
);
6507 host_impl_
->DidDrawAllLayers(frame
);
6508 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6510 const std::vector
<ui::LatencyInfo
>& metadata_latency_after
=
6511 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6512 EXPECT_EQ(1u, metadata_latency_after
.size());
6513 EXPECT_TRUE(metadata_latency_after
[0].FindLatency(
6514 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, NULL
));
6517 TEST_F(LayerTreeHostImplTest
, SelectionBoundsPassedToCompositorFrameMetadata
) {
6518 int root_layer_id
= 1;
6519 scoped_ptr
<SolidColorLayerImpl
> root
=
6520 SolidColorLayerImpl::Create(host_impl_
->active_tree(), root_layer_id
);
6521 root
->SetPosition(gfx::PointF());
6522 root
->SetBounds(gfx::Size(10, 10));
6523 root
->SetContentBounds(gfx::Size(10, 10));
6524 root
->SetDrawsContent(true);
6525 root
->SetHasRenderSurface(true);
6527 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6529 // Ensure the default frame selection bounds are empty.
6530 FakeOutputSurface
* fake_output_surface
=
6531 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6532 const ViewportSelection
& selection_before
=
6533 fake_output_surface
->last_sent_frame().metadata
.selection
;
6534 EXPECT_EQ(ViewportSelectionBound(), selection_before
.start
);
6535 EXPECT_EQ(ViewportSelectionBound(), selection_before
.end
);
6537 // Plumb the layer-local selection bounds.
6538 gfx::PointF
selection_top(5, 0);
6539 gfx::PointF
selection_bottom(5, 5);
6540 LayerSelection selection
;
6541 selection
.start
.type
= SELECTION_BOUND_CENTER
;
6542 selection
.start
.layer_id
= root_layer_id
;
6543 selection
.start
.edge_bottom
= selection_bottom
;
6544 selection
.start
.edge_top
= selection_top
;
6545 selection
.end
= selection
.start
;
6546 host_impl_
->active_tree()->RegisterSelection(selection
);
6548 // Trigger a draw-swap sequence.
6549 host_impl_
->SetNeedsRedraw();
6551 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6552 LayerTreeHostImpl::FrameData frame
;
6553 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6554 host_impl_
->DrawLayers(&frame
);
6555 host_impl_
->DidDrawAllLayers(frame
);
6556 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6558 // Ensure the selection bounds have propagated to the frame metadata.
6559 const ViewportSelection
& selection_after
=
6560 fake_output_surface
->last_sent_frame().metadata
.selection
;
6561 EXPECT_EQ(selection
.start
.type
, selection_after
.start
.type
);
6562 EXPECT_EQ(selection
.end
.type
, selection_after
.end
.type
);
6563 EXPECT_EQ(selection_bottom
, selection_after
.start
.edge_bottom
);
6564 EXPECT_EQ(selection_top
, selection_after
.start
.edge_top
);
6565 EXPECT_TRUE(selection_after
.start
.visible
);
6566 EXPECT_TRUE(selection_after
.start
.visible
);
6569 class SimpleSwapPromiseMonitor
: public SwapPromiseMonitor
{
6571 SimpleSwapPromiseMonitor(LayerTreeHost
* layer_tree_host
,
6572 LayerTreeHostImpl
* layer_tree_host_impl
,
6573 int* set_needs_commit_count
,
6574 int* set_needs_redraw_count
,
6575 int* forward_to_main_count
)
6576 : SwapPromiseMonitor(layer_tree_host
, layer_tree_host_impl
),
6577 set_needs_commit_count_(set_needs_commit_count
),
6578 set_needs_redraw_count_(set_needs_redraw_count
),
6579 forward_to_main_count_(forward_to_main_count
) {}
6581 ~SimpleSwapPromiseMonitor() override
{}
6583 void OnSetNeedsCommitOnMain() override
{ (*set_needs_commit_count_
)++; }
6585 void OnSetNeedsRedrawOnImpl() override
{ (*set_needs_redraw_count_
)++; }
6587 void OnForwardScrollUpdateToMainThreadOnImpl() override
{
6588 (*forward_to_main_count_
)++;
6592 int* set_needs_commit_count_
;
6593 int* set_needs_redraw_count_
;
6594 int* forward_to_main_count_
;
6597 TEST_F(LayerTreeHostImplTest
, SimpleSwapPromiseMonitor
) {
6598 int set_needs_commit_count
= 0;
6599 int set_needs_redraw_count
= 0;
6600 int forward_to_main_count
= 0;
6603 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6604 new SimpleSwapPromiseMonitor(NULL
,
6606 &set_needs_commit_count
,
6607 &set_needs_redraw_count
,
6608 &forward_to_main_count
));
6609 host_impl_
->SetNeedsRedraw();
6610 EXPECT_EQ(0, set_needs_commit_count
);
6611 EXPECT_EQ(1, set_needs_redraw_count
);
6612 EXPECT_EQ(0, forward_to_main_count
);
6615 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6617 host_impl_
->SetNeedsRedraw();
6618 EXPECT_EQ(0, set_needs_commit_count
);
6619 EXPECT_EQ(1, set_needs_redraw_count
);
6620 EXPECT_EQ(0, forward_to_main_count
);
6623 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6624 new SimpleSwapPromiseMonitor(NULL
,
6626 &set_needs_commit_count
,
6627 &set_needs_redraw_count
,
6628 &forward_to_main_count
));
6629 host_impl_
->SetNeedsRedrawRect(gfx::Rect(10, 10));
6630 EXPECT_EQ(0, set_needs_commit_count
);
6631 EXPECT_EQ(2, set_needs_redraw_count
);
6632 EXPECT_EQ(0, forward_to_main_count
);
6636 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6637 new SimpleSwapPromiseMonitor(NULL
,
6639 &set_needs_commit_count
,
6640 &set_needs_redraw_count
,
6641 &forward_to_main_count
));
6642 // Empty damage rect won't signal the monitor.
6643 host_impl_
->SetNeedsRedrawRect(gfx::Rect());
6644 EXPECT_EQ(0, set_needs_commit_count
);
6645 EXPECT_EQ(2, set_needs_redraw_count
);
6646 EXPECT_EQ(0, forward_to_main_count
);
6650 set_needs_commit_count
= 0;
6651 set_needs_redraw_count
= 0;
6652 forward_to_main_count
= 0;
6653 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6654 new SimpleSwapPromiseMonitor(NULL
,
6656 &set_needs_commit_count
,
6657 &set_needs_redraw_count
,
6658 &forward_to_main_count
));
6659 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
6661 // Scrolling normally should not trigger any forwarding.
6662 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6663 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6665 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
6666 host_impl_
->ScrollEnd();
6668 EXPECT_EQ(0, set_needs_commit_count
);
6669 EXPECT_EQ(1, set_needs_redraw_count
);
6670 EXPECT_EQ(0, forward_to_main_count
);
6672 // Scrolling with a scroll handler should defer the swap to the main
6674 scroll_layer
->SetHaveScrollEventHandlers(true);
6675 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6676 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6678 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
6679 host_impl_
->ScrollEnd();
6681 EXPECT_EQ(0, set_needs_commit_count
);
6682 EXPECT_EQ(2, set_needs_redraw_count
);
6683 EXPECT_EQ(1, forward_to_main_count
);
6687 class LayerTreeHostImplWithTopControlsTest
: public LayerTreeHostImplTest
{
6689 void SetUp() override
{
6690 LayerTreeSettings settings
= DefaultSettings();
6691 CreateHostImpl(settings
, CreateOutputSurface());
6692 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
6693 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
6694 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
6698 static const int top_controls_height_
;
6701 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_
= 50;
6703 TEST_F(LayerTreeHostImplWithTopControlsTest
, NoIdleAnimations
) {
6704 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6705 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6706 host_impl_
->Animate(base::TimeTicks());
6707 EXPECT_FALSE(did_request_redraw_
);
6710 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsHeightIsCommitted
) {
6711 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6712 EXPECT_FALSE(did_request_redraw_
);
6713 host_impl_
->CreatePendingTree();
6714 host_impl_
->sync_tree()->set_top_controls_height(100);
6715 host_impl_
->ActivateSyncTree();
6716 EXPECT_EQ(100, host_impl_
->top_controls_manager()->TopControlsHeight());
6719 TEST_F(LayerTreeHostImplWithTopControlsTest
,
6720 TopControlsStayFullyVisibleOnHeightChange
) {
6721 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6722 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6724 host_impl_
->CreatePendingTree();
6725 host_impl_
->sync_tree()->set_top_controls_height(0);
6726 host_impl_
->ActivateSyncTree();
6727 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6729 host_impl_
->CreatePendingTree();
6730 host_impl_
->sync_tree()->set_top_controls_height(50);
6731 host_impl_
->ActivateSyncTree();
6732 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6735 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationScheduling
) {
6736 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6737 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6738 host_impl_
->DidChangeTopControlsPosition();
6739 EXPECT_TRUE(did_request_animate_
);
6740 EXPECT_TRUE(did_request_redraw_
);
6743 TEST_F(LayerTreeHostImplWithTopControlsTest
, ScrollHandledByTopControls
) {
6744 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6745 host_impl_
->SetViewportSize(gfx::Size(100, 100));
6746 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6747 BOTH
, SHOWN
, false);
6750 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6751 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6752 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6753 EXPECT_EQ(gfx::Vector2dF().ToString(),
6754 scroll_layer
->CurrentScrollOffset().ToString());
6756 // Scroll just the top controls and verify that the scroll succeeds.
6757 const float residue
= 10;
6758 float offset
= top_controls_height_
- residue
;
6760 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6761 EXPECT_FLOAT_EQ(-offset
,
6762 host_impl_
->top_controls_manager()->ControlsTopOffset());
6763 EXPECT_EQ(gfx::Vector2dF().ToString(),
6764 scroll_layer
->CurrentScrollOffset().ToString());
6766 // Scroll across the boundary
6767 const float content_scroll
= 20;
6768 offset
= residue
+ content_scroll
;
6770 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6771 EXPECT_EQ(-top_controls_height_
,
6772 host_impl_
->top_controls_manager()->ControlsTopOffset());
6773 EXPECT_EQ(gfx::Vector2dF(0, content_scroll
).ToString(),
6774 scroll_layer
->CurrentScrollOffset().ToString());
6776 // Now scroll back to the top of the content
6777 offset
= -content_scroll
;
6779 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6780 EXPECT_EQ(-top_controls_height_
,
6781 host_impl_
->top_controls_manager()->ControlsTopOffset());
6782 EXPECT_EQ(gfx::Vector2dF().ToString(),
6783 scroll_layer
->CurrentScrollOffset().ToString());
6785 // And scroll the top controls completely into view
6786 offset
= -top_controls_height_
;
6788 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6789 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6790 EXPECT_EQ(gfx::Vector2dF().ToString(),
6791 scroll_layer
->CurrentScrollOffset().ToString());
6793 // And attempt to scroll past the end
6795 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6796 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6797 EXPECT_EQ(gfx::Vector2dF().ToString(),
6798 scroll_layer
->CurrentScrollOffset().ToString());
6800 host_impl_
->ScrollEnd();
6803 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAtOrigin
) {
6804 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6805 host_impl_
->SetViewportSize(gfx::Size(100, 200));
6806 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6807 BOTH
, SHOWN
, false);
6810 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6811 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6812 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6813 EXPECT_EQ(gfx::Vector2dF().ToString(),
6814 scroll_layer
->CurrentScrollOffset().ToString());
6816 // Scroll the top controls partially.
6817 const float residue
= 35;
6818 float offset
= top_controls_height_
- residue
;
6820 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6821 EXPECT_FLOAT_EQ(-offset
,
6822 host_impl_
->top_controls_manager()->ControlsTopOffset());
6823 EXPECT_EQ(gfx::Vector2dF().ToString(),
6824 scroll_layer
->CurrentScrollOffset().ToString());
6826 did_request_redraw_
= false;
6827 did_request_animate_
= false;
6828 did_request_commit_
= false;
6830 // End the scroll while the controls are still offset from their limit.
6831 host_impl_
->ScrollEnd();
6832 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
6833 EXPECT_TRUE(did_request_animate_
);
6834 EXPECT_TRUE(did_request_redraw_
);
6835 EXPECT_FALSE(did_request_commit_
);
6837 // The top controls should properly animate until finished, despite the scroll
6838 // offset being at the origin.
6839 base::TimeTicks animation_time
= gfx::FrameTime::Now();
6840 while (did_request_animate_
) {
6841 did_request_redraw_
= false;
6842 did_request_animate_
= false;
6843 did_request_commit_
= false;
6846 host_impl_
->top_controls_manager()->ControlsTopOffset();
6848 animation_time
+= base::TimeDelta::FromMilliseconds(5);
6849 host_impl_
->Animate(animation_time
);
6850 EXPECT_EQ(gfx::Vector2dF().ToString(),
6851 scroll_layer
->CurrentScrollOffset().ToString());
6854 host_impl_
->top_controls_manager()->ControlsTopOffset();
6856 // No commit is needed as the controls are animating the content offset,
6857 // not the scroll offset.
6858 EXPECT_FALSE(did_request_commit_
);
6860 if (new_offset
!= old_offset
)
6861 EXPECT_TRUE(did_request_redraw_
);
6863 if (new_offset
!= 0) {
6864 EXPECT_TRUE(host_impl_
->top_controls_manager()->animation());
6865 EXPECT_TRUE(did_request_animate_
);
6868 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
6871 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAfterScroll
) {
6872 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6873 host_impl_
->SetViewportSize(gfx::Size(100, 100));
6874 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6875 BOTH
, SHOWN
, false);
6876 float initial_scroll_offset
= 50;
6877 scroll_layer
->PushScrollOffsetFromMainThread(
6878 gfx::ScrollOffset(0, initial_scroll_offset
));
6881 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6882 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6883 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6884 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6885 scroll_layer
->CurrentScrollOffset().ToString());
6887 // Scroll the top controls partially.
6888 const float residue
= 15;
6889 float offset
= top_controls_height_
- residue
;
6891 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6892 EXPECT_FLOAT_EQ(-offset
,
6893 host_impl_
->top_controls_manager()->ControlsTopOffset());
6894 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6895 scroll_layer
->CurrentScrollOffset().ToString());
6897 did_request_redraw_
= false;
6898 did_request_animate_
= false;
6899 did_request_commit_
= false;
6901 // End the scroll while the controls are still offset from the limit.
6902 host_impl_
->ScrollEnd();
6903 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
6904 EXPECT_TRUE(did_request_animate_
);
6905 EXPECT_TRUE(did_request_redraw_
);
6906 EXPECT_FALSE(did_request_commit_
);
6908 // Animate the top controls to the limit.
6909 base::TimeTicks animation_time
= gfx::FrameTime::Now();
6910 while (did_request_animate_
) {
6911 did_request_redraw_
= false;
6912 did_request_animate_
= false;
6913 did_request_commit_
= false;
6916 host_impl_
->top_controls_manager()->ControlsTopOffset();
6918 animation_time
+= base::TimeDelta::FromMilliseconds(5);
6919 host_impl_
->Animate(animation_time
);
6922 host_impl_
->top_controls_manager()->ControlsTopOffset();
6924 if (new_offset
!= old_offset
) {
6925 EXPECT_TRUE(did_request_redraw_
);
6926 EXPECT_TRUE(did_request_commit_
);
6929 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
6930 EXPECT_EQ(-top_controls_height_
,
6931 host_impl_
->top_controls_manager()->ControlsTopOffset());
6934 TEST_F(LayerTreeHostImplWithTopControlsTest
,
6935 TopControlsAnimationAfterMainThreadFlingStopped
) {
6936 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6937 host_impl_
->SetViewportSize(gfx::Size(100, 100));
6938 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
6940 float initial_scroll_offset
= 50;
6941 scroll_layer
->PushScrollOffsetFromMainThread(
6942 gfx::ScrollOffset(0, initial_scroll_offset
));
6945 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6946 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6947 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6948 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6949 scroll_layer
->CurrentScrollOffset().ToString());
6951 // Scroll the top controls partially.
6952 const float residue
= 15;
6953 float offset
= top_controls_height_
- residue
;
6955 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6956 EXPECT_FLOAT_EQ(-offset
,
6957 host_impl_
->top_controls_manager()->ControlsTopOffset());
6958 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6959 scroll_layer
->CurrentScrollOffset().ToString());
6961 did_request_redraw_
= false;
6962 did_request_animate_
= false;
6963 did_request_commit_
= false;
6965 // End the fling while the controls are still offset from the limit.
6966 host_impl_
->MainThreadHasStoppedFlinging();
6967 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
6968 EXPECT_TRUE(did_request_animate_
);
6969 EXPECT_TRUE(did_request_redraw_
);
6970 EXPECT_FALSE(did_request_commit_
);
6972 // Animate the top controls to the limit.
6973 base::TimeTicks animation_time
= gfx::FrameTime::Now();
6974 while (did_request_animate_
) {
6975 did_request_redraw_
= false;
6976 did_request_animate_
= false;
6977 did_request_commit_
= false;
6979 float old_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
6981 animation_time
+= base::TimeDelta::FromMilliseconds(5);
6982 host_impl_
->Animate(animation_time
);
6984 float new_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
6986 if (new_offset
!= old_offset
) {
6987 EXPECT_TRUE(did_request_redraw_
);
6988 EXPECT_TRUE(did_request_commit_
);
6991 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
6992 EXPECT_EQ(-top_controls_height_
,
6993 host_impl_
->top_controls_manager()->ControlsTopOffset());
6996 TEST_F(LayerTreeHostImplWithTopControlsTest
,
6997 TopControlsScrollDeltaInOverScroll
) {
6998 // test varifies that the overscroll delta should not have accumulated in
6999 // the top controls if we do a hide and show without releasing finger.
7001 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7002 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7003 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7007 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7008 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7009 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7013 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7014 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7015 EXPECT_EQ(gfx::Vector2dF().ToString(),
7016 scroll_layer
->CurrentScrollOffset().ToString());
7019 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7020 EXPECT_EQ(gfx::Vector2dF(0, offset
).ToString(),
7021 scroll_layer
->CurrentScrollOffset().ToString());
7024 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7026 // Should have fully scrolled
7027 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer
->MaxScrollOffset().y()).ToString(),
7028 scroll_layer
->CurrentScrollOffset().ToString());
7030 float overscrollamount
= 10;
7032 // Overscroll the content
7034 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount
))
7036 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset
).ToString(),
7037 scroll_layer
->CurrentScrollOffset().ToString());
7038 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount
).ToString(),
7039 host_impl_
->accumulated_root_overscroll().ToString());
7041 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset
))
7043 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7044 scroll_layer
->CurrentScrollOffset().ToString());
7045 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7048 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset
)).did_scroll
);
7049 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7050 scroll_layer
->CurrentScrollOffset().ToString());
7052 // Top controls should be fully visible
7053 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7055 host_impl_
->ScrollEnd();
7058 class LayerTreeHostImplVirtualViewportTest
: public LayerTreeHostImplTest
{
7060 void SetupVirtualViewportLayers(const gfx::Size
& content_size
,
7061 const gfx::Size
& outer_viewport
,
7062 const gfx::Size
& inner_viewport
) {
7063 LayerTreeImpl
* layer_tree_impl
= host_impl_
->active_tree();
7064 const int kOuterViewportClipLayerId
= 6;
7065 const int kOuterViewportScrollLayerId
= 7;
7066 const int kInnerViewportScrollLayerId
= 2;
7067 const int kInnerViewportClipLayerId
= 4;
7068 const int kPageScaleLayerId
= 5;
7070 scoped_ptr
<LayerImpl
> inner_scroll
=
7071 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
7072 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
7073 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7075 scoped_ptr
<LayerImpl
> inner_clip
=
7076 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
7077 inner_clip
->SetBounds(inner_viewport
);
7079 scoped_ptr
<LayerImpl
> page_scale
=
7080 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
7082 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
7083 inner_scroll
->SetBounds(outer_viewport
);
7084 inner_scroll
->SetContentBounds(outer_viewport
);
7085 inner_scroll
->SetPosition(gfx::PointF());
7087 scoped_ptr
<LayerImpl
> outer_clip
=
7088 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
7089 outer_clip
->SetBounds(outer_viewport
);
7090 outer_clip
->SetIsContainerForFixedPositionLayers(true);
7092 scoped_ptr
<LayerImpl
> outer_scroll
=
7093 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
7094 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
7095 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7096 outer_scroll
->SetBounds(content_size
);
7097 outer_scroll
->SetContentBounds(content_size
);
7098 outer_scroll
->SetPosition(gfx::PointF());
7100 scoped_ptr
<LayerImpl
> contents
=
7101 LayerImpl::Create(layer_tree_impl
, 8);
7102 contents
->SetDrawsContent(true);
7103 contents
->SetBounds(content_size
);
7104 contents
->SetContentBounds(content_size
);
7105 contents
->SetPosition(gfx::PointF());
7107 outer_scroll
->AddChild(contents
.Pass());
7108 outer_clip
->AddChild(outer_scroll
.Pass());
7109 inner_scroll
->AddChild(outer_clip
.Pass());
7110 page_scale
->AddChild(inner_scroll
.Pass());
7111 inner_clip
->AddChild(page_scale
.Pass());
7113 inner_clip
->SetHasRenderSurface(true);
7114 layer_tree_impl
->SetRootLayer(inner_clip
.Pass());
7115 layer_tree_impl
->SetViewportLayersFromIds(
7116 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
7117 kOuterViewportScrollLayerId
);
7119 host_impl_
->active_tree()->DidBecomeActive();
7123 TEST_F(LayerTreeHostImplVirtualViewportTest
, ScrollBothInnerAndOuterLayer
) {
7124 gfx::Size content_size
= gfx::Size(100, 160);
7125 gfx::Size outer_viewport
= gfx::Size(50, 80);
7126 gfx::Size inner_viewport
= gfx::Size(25, 40);
7128 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7130 TestScrollOffsetDelegate scroll_delegate
;
7131 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
7133 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7134 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7137 gfx::ScrollOffset inner_expected
;
7138 gfx::ScrollOffset outer_expected
;
7139 EXPECT_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7140 EXPECT_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7142 gfx::ScrollOffset
current_offset(70.f
, 100.f
);
7144 scroll_delegate
.set_getter_return_value(current_offset
);
7145 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
7146 EXPECT_EQ(gfx::ScrollOffset(25.f
, 40.f
), inner_scroll
->MaxScrollOffset());
7147 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
), outer_scroll
->MaxScrollOffset());
7149 // Outer viewport scrolls first. Then the rest is applied to the inner
7151 EXPECT_EQ(gfx::ScrollOffset(20.f
, 20.f
),
7152 inner_scroll
->CurrentScrollOffset());
7153 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
),
7154 outer_scroll
->CurrentScrollOffset());
7158 TEST_F(LayerTreeHostImplVirtualViewportTest
, FlingScrollBubblesToInner
) {
7159 gfx::Size content_size
= gfx::Size(100, 160);
7160 gfx::Size outer_viewport
= gfx::Size(50, 80);
7161 gfx::Size inner_viewport
= gfx::Size(25, 40);
7163 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7165 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7166 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7169 gfx::Vector2dF inner_expected
;
7170 gfx::Vector2dF outer_expected
;
7171 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7172 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7174 // Make sure the fling goes to the outer viewport first
7175 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7176 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7177 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7179 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7180 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7181 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7183 host_impl_
->ScrollEnd();
7185 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7186 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7188 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7189 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7190 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7191 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7193 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7194 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7196 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7197 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7199 host_impl_
->ScrollEnd();
7201 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7202 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7206 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7207 DiagonalScrollBubblesPerfectlyToInner
) {
7208 gfx::Size content_size
= gfx::Size(100, 160);
7209 gfx::Size outer_viewport
= gfx::Size(50, 80);
7210 gfx::Size inner_viewport
= gfx::Size(25, 40);
7212 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7214 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7215 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7218 gfx::Vector2dF inner_expected
;
7219 gfx::Vector2dF outer_expected
;
7220 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7221 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7223 // Make sure the scroll goes to the outer viewport first.
7224 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7225 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7226 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7227 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7228 InputHandler::GESTURE
));
7230 // Scroll near the edge of the outer viewport.
7231 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7232 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7233 outer_expected
+= scroll_delta
;
7234 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7235 InputHandler::GESTURE
));
7237 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7238 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7240 // Now diagonal scroll across the outer viewport boundary in a single event.
7241 // The entirety of the scroll should be consumed, as bubbling between inner
7242 // and outer viewport layers is perfect.
7243 host_impl_
->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta
, 2));
7244 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7245 InputHandler::GESTURE
));
7246 outer_expected
+= scroll_delta
;
7247 inner_expected
+= scroll_delta
;
7248 host_impl_
->ScrollEnd();
7249 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7250 gfx::Point(), InputHandler::GESTURE
));
7252 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7253 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7257 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7258 TouchFlingCanLockToViewportLayerAfterBubbling
) {
7259 gfx::Size content_size
= gfx::Size(100, 160);
7260 gfx::Size outer_viewport
= gfx::Size(50, 80);
7261 gfx::Size inner_viewport
= gfx::Size(25, 40);
7263 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7265 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7266 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7268 scoped_ptr
<LayerImpl
> child
=
7269 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7270 LayerImpl
* child_scroll
= child
.get();
7271 outer_scroll
->children()[0]->AddChild(child
.Pass());
7275 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
7277 gfx::Vector2d
scroll_delta(0, inner_viewport
.height());
7278 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7279 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7280 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7281 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7282 InputHandler::GESTURE
));
7284 // The child should have scrolled up to its limit.
7285 scroll_info
= host_impl_
->ProcessScrollDeltas();
7286 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
7287 ExpectContains(*scroll_info
, child_scroll
->id(), scroll_delta
);
7288 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7290 // The first |ScrollBy| after the fling should re-lock the scrolling
7291 // layer to the first layer that scrolled, the inner viewport scroll layer.
7292 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7293 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7294 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7295 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7296 InputHandler::GESTURE
));
7298 // The inner viewport should have scrolled up to its limit.
7299 scroll_info
= host_impl_
->ProcessScrollDeltas();
7300 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
7301 ExpectContains(*scroll_info
, child_scroll
->id(), scroll_delta
);
7302 ExpectContains(*scroll_info
, inner_scroll
->id(), scroll_delta
);
7304 // As the locked layer is at its limit, no further scrolling can occur.
7305 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7306 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7307 host_impl_
->ScrollEnd();
7308 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7309 gfx::Point(), InputHandler::GESTURE
));
7313 class LayerTreeHostImplWithImplicitLimitsTest
: public LayerTreeHostImplTest
{
7315 void SetUp() override
{
7316 LayerTreeSettings settings
= DefaultSettings();
7317 settings
.max_memory_for_prepaint_percentage
= 50;
7318 CreateHostImpl(settings
, CreateOutputSurface());
7322 TEST_F(LayerTreeHostImplWithImplicitLimitsTest
, ImplicitMemoryLimits
) {
7323 // Set up a memory policy and percentages which could cause
7324 // 32-bit integer overflows.
7325 ManagedMemoryPolicy
mem_policy(300 * 1024 * 1024); // 300MB
7327 // Verify implicit limits are calculated correctly with no overflows
7328 host_impl_
->SetMemoryPolicy(mem_policy
);
7329 EXPECT_EQ(host_impl_
->global_tile_state().hard_memory_limit_in_bytes
,
7330 300u * 1024u * 1024u);
7331 EXPECT_EQ(host_impl_
->global_tile_state().soft_memory_limit_in_bytes
,
7332 150u * 1024u * 1024u);
7335 TEST_F(LayerTreeHostImplTest
, ExternalTransformReflectedInNextDraw
) {
7336 const gfx::Size
layer_size(100, 100);
7337 gfx::Transform external_transform
;
7338 const gfx::Rect
external_viewport(layer_size
);
7339 const gfx::Rect
external_clip(layer_size
);
7340 const bool resourceless_software_draw
= false;
7341 LayerImpl
* layer
= SetupScrollAndContentsLayers(layer_size
);
7343 host_impl_
->SetExternalDrawConstraints(external_transform
,
7348 resourceless_software_draw
);
7350 EXPECT_TRANSFORMATION_MATRIX_EQ(
7351 external_transform
, layer
->draw_properties().target_space_transform
);
7353 external_transform
.Translate(20, 20);
7354 host_impl_
->SetExternalDrawConstraints(external_transform
,
7359 resourceless_software_draw
);
7361 EXPECT_TRANSFORMATION_MATRIX_EQ(
7362 external_transform
, layer
->draw_properties().target_space_transform
);
7365 TEST_F(LayerTreeHostImplTest
, ScrollAnimated
) {
7366 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7369 base::TimeTicks start_time
=
7370 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7372 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7373 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7375 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7377 host_impl_
->Animate(start_time
);
7378 host_impl_
->UpdateAnimationState(true);
7380 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
7382 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(50));
7383 host_impl_
->UpdateAnimationState(true);
7385 float y
= scrolling_layer
->CurrentScrollOffset().y();
7386 EXPECT_TRUE(y
> 1 && y
< 49);
7389 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7390 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7392 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(200));
7393 host_impl_
->UpdateAnimationState(true);
7395 y
= scrolling_layer
->CurrentScrollOffset().y();
7396 EXPECT_TRUE(y
> 50 && y
< 100);
7397 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
7399 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(250));
7400 host_impl_
->UpdateAnimationState(true);
7402 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7403 scrolling_layer
->CurrentScrollOffset());
7404 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
7407 TEST_F(LayerTreeHostImplTest
, InvalidLayerNotAddedToRasterQueue
) {
7408 host_impl_
->CreatePendingTree();
7410 Region empty_invalidation
;
7411 scoped_refptr
<RasterSource
> pile_with_tiles(
7412 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
7413 gfx::Size(10, 10)));
7415 scoped_ptr
<FakePictureLayerImpl
> layer
=
7416 FakePictureLayerImpl::Create(host_impl_
->pending_tree(), 11);
7417 layer
->SetBounds(gfx::Size(10, 10));
7418 layer
->set_gpu_raster_max_texture_size(host_impl_
->device_viewport_size());
7419 layer
->SetDrawsContent(true);
7420 layer
->tilings()->AddTiling(1.0f
, pile_with_tiles
);
7421 layer
->UpdateRasterSource(pile_with_tiles
, &empty_invalidation
, nullptr);
7422 layer
->tilings()->tiling_at(0)->set_resolution(
7423 TileResolution::HIGH_RESOLUTION
);
7424 layer
->tilings()->tiling_at(0)->CreateAllTilesForTesting();
7425 layer
->tilings()->tiling_at(0)->ComputeTilePriorityRects(
7426 gfx::Rect(gfx::Size(10, 10)), 1.f
, 1.0, Occlusion());
7427 host_impl_
->pending_tree()->SetRootLayer(layer
.Pass());
7429 FakePictureLayerImpl
* root_layer
= static_cast<FakePictureLayerImpl
*>(
7430 host_impl_
->pending_tree()->root_layer());
7432 root_layer
->set_has_valid_tile_priorities(true);
7433 scoped_ptr
<RasterTilePriorityQueue
> non_empty_raster_priority_queue_all
=
7434 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
7435 RasterTilePriorityQueue::Type::ALL
);
7436 EXPECT_FALSE(non_empty_raster_priority_queue_all
->IsEmpty());
7438 root_layer
->set_has_valid_tile_priorities(false);
7439 scoped_ptr
<RasterTilePriorityQueue
> empty_raster_priority_queue_all
=
7440 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
7441 RasterTilePriorityQueue::Type::ALL
);
7442 EXPECT_TRUE(empty_raster_priority_queue_all
->IsEmpty());
7445 TEST_F(LayerTreeHostImplTest
, DidBecomeActive
) {
7446 host_impl_
->CreatePendingTree();
7447 host_impl_
->ActivateSyncTree();
7448 host_impl_
->CreatePendingTree();
7450 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
7452 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
7453 FakePictureLayerImpl::Create(pending_tree
, 10);
7454 FakePictureLayerImpl
* raw_pending_layer
= pending_layer
.get();
7455 pending_tree
->SetRootLayer(pending_layer
.Pass());
7456 ASSERT_EQ(raw_pending_layer
, pending_tree
->root_layer());
7458 EXPECT_EQ(0u, raw_pending_layer
->did_become_active_call_count());
7459 pending_tree
->DidBecomeActive();
7460 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7462 scoped_ptr
<FakePictureLayerImpl
> mask_layer
=
7463 FakePictureLayerImpl::Create(pending_tree
, 11);
7464 FakePictureLayerImpl
* raw_mask_layer
= mask_layer
.get();
7465 raw_pending_layer
->SetMaskLayer(mask_layer
.Pass());
7466 ASSERT_EQ(raw_mask_layer
, raw_pending_layer
->mask_layer());
7468 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7469 EXPECT_EQ(0u, raw_mask_layer
->did_become_active_call_count());
7470 pending_tree
->DidBecomeActive();
7471 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7472 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7474 scoped_ptr
<FakePictureLayerImpl
> replica_layer
=
7475 FakePictureLayerImpl::Create(pending_tree
, 12);
7476 scoped_ptr
<FakePictureLayerImpl
> replica_mask_layer
=
7477 FakePictureLayerImpl::Create(pending_tree
, 13);
7478 FakePictureLayerImpl
* raw_replica_mask_layer
= replica_mask_layer
.get();
7479 replica_layer
->SetMaskLayer(replica_mask_layer
.Pass());
7480 raw_pending_layer
->SetReplicaLayer(replica_layer
.Pass());
7481 ASSERT_EQ(raw_replica_mask_layer
,
7482 raw_pending_layer
->replica_layer()->mask_layer());
7484 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7485 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7486 EXPECT_EQ(0u, raw_replica_mask_layer
->did_become_active_call_count());
7487 pending_tree
->DidBecomeActive();
7488 EXPECT_EQ(3u, raw_pending_layer
->did_become_active_call_count());
7489 EXPECT_EQ(2u, raw_mask_layer
->did_become_active_call_count());
7490 EXPECT_EQ(1u, raw_replica_mask_layer
->did_become_active_call_count());
7493 TEST_F(LayerTreeHostImplTest
, WheelScrollWithPageScaleFactorOnInnerLayer
) {
7494 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
7495 host_impl_
->SetViewportSize(gfx::Size(50, 50));
7498 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
7500 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
7501 float page_scale_factor
= 1.f
;
7503 // The scroll deltas should have the page scale factor applied.
7505 host_impl_
->active_tree()->PushPageScaleFromMainThread(
7506 page_scale_factor
, min_page_scale
, max_page_scale
);
7507 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
7508 scroll_layer
->SetScrollDelta(gfx::Vector2d());
7510 float page_scale_delta
= 2.f
;
7511 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
7512 host_impl_
->PinchGestureBegin();
7513 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
7514 host_impl_
->PinchGestureEnd();
7515 host_impl_
->ScrollEnd();
7517 gfx::Vector2dF
scroll_delta(0, 5);
7518 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7519 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
7520 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
7522 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7523 host_impl_
->ScrollEnd();
7524 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
7525 scroll_layer
->CurrentScrollOffset());
7529 class LayerTreeHostImplCountingLostSurfaces
: public LayerTreeHostImplTest
{
7531 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7532 void DidLoseOutputSurfaceOnImplThread() override
{ num_lost_surfaces_
++; }
7535 int num_lost_surfaces_
;
7538 TEST_F(LayerTreeHostImplCountingLostSurfaces
, TwiceLostSurface
) {
7539 // Really we just need at least one client notification each time
7540 // we go from having a valid output surface to not having a valid output
7542 EXPECT_EQ(0, num_lost_surfaces_
);
7543 host_impl_
->DidLoseOutputSurface();
7544 EXPECT_EQ(1, num_lost_surfaces_
);
7545 host_impl_
->DidLoseOutputSurface();
7546 EXPECT_LE(1, num_lost_surfaces_
);
7549 TEST_F(LayerTreeHostImplTest
, RemoveUnreferencedRenderPass
) {
7550 LayerTreeHostImpl::FrameData frame
;
7551 frame
.render_passes
.push_back(RenderPass::Create());
7552 RenderPass
* pass3
= frame
.render_passes
.back();
7553 frame
.render_passes
.push_back(RenderPass::Create());
7554 RenderPass
* pass2
= frame
.render_passes
.back();
7555 frame
.render_passes
.push_back(RenderPass::Create());
7556 RenderPass
* pass1
= frame
.render_passes
.back();
7558 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7559 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7560 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7562 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7563 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7564 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7566 // Add a quad to each pass so they aren't empty.
7567 SolidColorDrawQuad
* color_quad
;
7568 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7569 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7570 color_quad
= pass2
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7571 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7572 color_quad
= pass3
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7573 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7575 // pass3 is referenced by pass2.
7576 RenderPassDrawQuad
* rpdq
=
7577 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7578 rpdq
->material
= DrawQuad::RENDER_PASS
;
7579 rpdq
->render_pass_id
= pass3
->id
;
7581 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
7582 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7583 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7584 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7585 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7586 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7587 EXPECT_EQ(1u, frame
.render_passes
.size());
7588 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7591 TEST_F(LayerTreeHostImplTest
, RemoveEmptyRenderPass
) {
7592 LayerTreeHostImpl::FrameData frame
;
7593 frame
.render_passes
.push_back(RenderPass::Create());
7594 RenderPass
* pass3
= frame
.render_passes
.back();
7595 frame
.render_passes
.push_back(RenderPass::Create());
7596 RenderPass
* pass2
= frame
.render_passes
.back();
7597 frame
.render_passes
.push_back(RenderPass::Create());
7598 RenderPass
* pass1
= frame
.render_passes
.back();
7600 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7601 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7602 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7604 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7605 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7606 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7608 // pass1 is not empty, but pass2 and pass3 are.
7609 SolidColorDrawQuad
* color_quad
;
7610 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7611 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7613 // pass3 is referenced by pass2.
7614 RenderPassDrawQuad
* rpdq
=
7615 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7616 rpdq
->material
= DrawQuad::RENDER_PASS
;
7617 rpdq
->render_pass_id
= pass3
->id
;
7619 // pass2 is referenced by pass1.
7620 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7621 rpdq
->material
= DrawQuad::RENDER_PASS
;
7622 rpdq
->render_pass_id
= pass2
->id
;
7624 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7625 // should be removed.
7626 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7627 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7628 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7629 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7630 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7631 EXPECT_EQ(1u, frame
.render_passes
.size());
7632 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7633 // The RenderPassDrawQuad should be removed from pass1.
7634 EXPECT_EQ(1u, pass1
->quad_list
.size());
7635 EXPECT_EQ(DrawQuad::SOLID_COLOR
, pass1
->quad_list
.ElementAt(0)->material
);
7638 TEST_F(LayerTreeHostImplTest
, DoNotRemoveEmptyRootRenderPass
) {
7639 LayerTreeHostImpl::FrameData frame
;
7640 frame
.render_passes
.push_back(RenderPass::Create());
7641 RenderPass
* pass3
= frame
.render_passes
.back();
7642 frame
.render_passes
.push_back(RenderPass::Create());
7643 RenderPass
* pass2
= frame
.render_passes
.back();
7644 frame
.render_passes
.push_back(RenderPass::Create());
7645 RenderPass
* pass1
= frame
.render_passes
.back();
7647 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7648 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7649 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7651 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7652 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7653 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7655 // pass3 is referenced by pass2.
7656 RenderPassDrawQuad
* rpdq
=
7657 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7658 rpdq
->material
= DrawQuad::RENDER_PASS
;
7659 rpdq
->render_pass_id
= pass3
->id
;
7661 // pass2 is referenced by pass1.
7662 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7663 rpdq
->material
= DrawQuad::RENDER_PASS
;
7664 rpdq
->render_pass_id
= pass2
->id
;
7666 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7667 // should be removed. Then pass1 is empty too, but it's the root so it should
7669 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7670 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7671 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7672 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7673 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7674 EXPECT_EQ(1u, frame
.render_passes
.size());
7675 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7676 // The RenderPassDrawQuad should be removed from pass1.
7677 EXPECT_EQ(0u, pass1
->quad_list
.size());
7680 class FakeVideoFrameController
: public VideoFrameController
{
7682 void OnBeginFrame(const BeginFrameArgs
& args
) override
{
7683 begin_frame_args_
= args
;
7686 const BeginFrameArgs
& begin_frame_args() { return begin_frame_args_
; }
7689 BeginFrameArgs begin_frame_args_
;
7692 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerInsideFrame
) {
7693 BeginFrameArgs begin_frame_args
=
7694 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7695 FakeVideoFrameController controller
;
7697 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7698 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7699 host_impl_
->AddVideoFrameController(&controller
);
7700 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
7701 host_impl_
->DidFinishImplFrame();
7704 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerOutsideFrame
) {
7705 BeginFrameArgs begin_frame_args
=
7706 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7707 FakeVideoFrameController controller
;
7709 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7710 host_impl_
->DidFinishImplFrame();
7712 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7713 host_impl_
->AddVideoFrameController(&controller
);
7714 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7716 begin_frame_args
= CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7717 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7718 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7719 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
7722 TEST_F(LayerTreeHostImplTest
, GpuRasterizationStatusModes
) {
7723 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7725 host_impl_
->SetHasGpuRasterizationTrigger(true);
7726 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
7727 EXPECT_EQ(GpuRasterizationStatus::ON
, host_impl_
->gpu_rasterization_status());
7728 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
7730 host_impl_
->SetHasGpuRasterizationTrigger(false);
7731 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
7732 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT
,
7733 host_impl_
->gpu_rasterization_status());
7734 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7736 host_impl_
->SetHasGpuRasterizationTrigger(true);
7737 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
7738 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT
,
7739 host_impl_
->gpu_rasterization_status());
7740 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7741 EXPECT_FALSE(host_impl_
->use_msaa());
7743 scoped_ptr
<TestWebGraphicsContext3D
> context_with_msaa
=
7744 TestWebGraphicsContext3D::Create();
7745 context_with_msaa
->SetMaxSamples(8);
7747 LayerTreeSettings msaaSettings
= GpuRasterizationEnabledSettings();
7748 msaaSettings
.gpu_rasterization_msaa_sample_count
= 4;
7749 EXPECT_TRUE(CreateHostImpl(
7750 msaaSettings
, FakeOutputSurface::Create3d(context_with_msaa
.Pass())));
7751 host_impl_
->SetHasGpuRasterizationTrigger(true);
7752 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
7753 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT
,
7754 host_impl_
->gpu_rasterization_status());
7755 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
7756 EXPECT_TRUE(host_impl_
->use_msaa());
7758 LayerTreeSettings settings
= DefaultSettings();
7759 settings
.gpu_rasterization_enabled
= false;
7760 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
7761 host_impl_
->SetHasGpuRasterizationTrigger(true);
7762 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
7763 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE
,
7764 host_impl_
->gpu_rasterization_status());
7765 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7767 settings
.gpu_rasterization_forced
= true;
7768 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
7770 host_impl_
->SetHasGpuRasterizationTrigger(false);
7771 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
7772 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED
,
7773 host_impl_
->gpu_rasterization_status());
7774 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
7777 // A mock output surface which lets us detect calls to ForceReclaimResources.
7778 class MockReclaimResourcesOutputSurface
: public FakeOutputSurface
{
7780 static scoped_ptr
<MockReclaimResourcesOutputSurface
> Create3d() {
7781 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
7782 TestContextProvider::Create(), TestContextProvider::Create(), false));
7785 MOCK_METHOD0(ForceReclaimResources
, void());
7788 MockReclaimResourcesOutputSurface(
7789 scoped_refptr
<ContextProvider
> context_provider
,
7790 scoped_refptr
<ContextProvider
> worker_context_provider
,
7791 bool delegated_rendering
)
7792 : FakeOutputSurface(context_provider
,
7793 worker_context_provider
,
7794 delegated_rendering
) {}
7797 // Display::Draw (and the planned Display Scheduler) currently rely on resources
7798 // being reclaimed to block drawing between BeginCommit / Swap. This test
7799 // ensures that BeginCommit triggers ForceReclaimResources. See
7800 // crbug.com/489515.
7801 TEST_F(LayerTreeHostImplTest
, BeginCommitReclaimsResources
) {
7802 scoped_ptr
<MockReclaimResourcesOutputSurface
> output_surface(
7803 MockReclaimResourcesOutputSurface::Create3d());
7804 // Hold an unowned pointer to the output surface to use for mock expectations.
7805 MockReclaimResourcesOutputSurface
* mock_output_surface
= output_surface
.get();
7807 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
7808 EXPECT_CALL(*mock_output_surface
, ForceReclaimResources()).Times(1);
7809 host_impl_
->BeginCommit();