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/command_line.h"
11 #include "base/containers/hash_tables.h"
12 #include "base/containers/scoped_ptr_hash_map.h"
13 #include "cc/animation/scrollbar_animation_controller_thinning.h"
14 #include "cc/base/latency_info_swap_promise.h"
15 #include "cc/base/math_util.h"
16 #include "cc/input/page_scale_animation.h"
17 #include "cc/input/top_controls_manager.h"
18 #include "cc/layers/append_quads_data.h"
19 #include "cc/layers/delegated_renderer_layer_impl.h"
20 #include "cc/layers/heads_up_display_layer_impl.h"
21 #include "cc/layers/io_surface_layer_impl.h"
22 #include "cc/layers/layer_impl.h"
23 #include "cc/layers/painted_scrollbar_layer_impl.h"
24 #include "cc/layers/render_surface_impl.h"
25 #include "cc/layers/solid_color_layer_impl.h"
26 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
27 #include "cc/layers/texture_layer_impl.h"
28 #include "cc/layers/tiled_layer_impl.h"
29 #include "cc/layers/video_layer_impl.h"
30 #include "cc/output/begin_frame_args.h"
31 #include "cc/output/compositor_frame_ack.h"
32 #include "cc/output/compositor_frame_metadata.h"
33 #include "cc/output/copy_output_request.h"
34 #include "cc/output/copy_output_result.h"
35 #include "cc/output/gl_renderer.h"
36 #include "cc/quads/render_pass_draw_quad.h"
37 #include "cc/quads/solid_color_draw_quad.h"
38 #include "cc/quads/texture_draw_quad.h"
39 #include "cc/quads/tile_draw_quad.h"
40 #include "cc/resources/layer_tiling_data.h"
41 #include "cc/test/animation_test_common.h"
42 #include "cc/test/begin_frame_args_test.h"
43 #include "cc/test/fake_layer_tree_host_impl.h"
44 #include "cc/test/fake_output_surface.h"
45 #include "cc/test/fake_output_surface_client.h"
46 #include "cc/test/fake_picture_layer_impl.h"
47 #include "cc/test/fake_picture_pile_impl.h"
48 #include "cc/test/fake_proxy.h"
49 #include "cc/test/fake_rendering_stats_instrumentation.h"
50 #include "cc/test/fake_video_frame_provider.h"
51 #include "cc/test/geometry_test_utils.h"
52 #include "cc/test/layer_test_common.h"
53 #include "cc/test/render_pass_test_common.h"
54 #include "cc/test/test_shared_bitmap_manager.h"
55 #include "cc/test/test_web_graphics_context_3d.h"
56 #include "cc/trees/layer_tree_impl.h"
57 #include "cc/trees/single_thread_proxy.h"
58 #include "media/base/media.h"
59 #include "testing/gmock/include/gmock/gmock.h"
60 #include "testing/gtest/include/gtest/gtest.h"
61 #include "third_party/skia/include/core/SkMallocPixelRef.h"
62 #include "ui/gfx/frame_time.h"
63 #include "ui/gfx/rect_conversions.h"
64 #include "ui/gfx/size_conversions.h"
65 #include "ui/gfx/vector2d_conversions.h"
67 using ::testing::Mock
;
68 using ::testing::Return
;
69 using ::testing::AnyNumber
;
70 using ::testing::AtLeast
;
72 using media::VideoFrame
;
77 class LayerTreeHostImplTest
: public testing::Test
,
78 public LayerTreeHostImplClient
{
80 LayerTreeHostImplTest()
81 : proxy_(base::MessageLoopProxy::current(),
82 base::MessageLoopProxy::current()),
83 always_impl_thread_(&proxy_
),
84 always_main_thread_blocked_(&proxy_
),
85 shared_bitmap_manager_(new TestSharedBitmapManager()),
86 on_can_draw_state_changed_called_(false),
87 did_notify_ready_to_activate_(false),
88 did_request_commit_(false),
89 did_request_redraw_(false),
90 did_request_animate_(false),
91 did_request_manage_tiles_(false),
92 did_upload_visible_tile_(false),
93 reduce_memory_result_(true),
94 current_limit_bytes_(0),
95 current_priority_cutoff_value_(0) {
96 media::InitializeMediaLibraryForTesting();
99 LayerTreeSettings
DefaultSettings() {
100 LayerTreeSettings settings
;
101 settings
.minimum_occlusion_tracking_size
= gfx::Size();
102 settings
.impl_side_painting
= true;
103 settings
.texture_id_allocation_chunk_size
= 1;
104 settings
.report_overscroll_only_for_scrollable_axes
= true;
108 virtual void SetUp() override
{
109 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
112 virtual void TearDown() override
{}
114 virtual void UpdateRendererCapabilitiesOnImplThread() override
{}
115 virtual void DidLoseOutputSurfaceOnImplThread() override
{}
116 virtual void CommitVSyncParameters(base::TimeTicks timebase
,
117 base::TimeDelta interval
) override
{}
118 virtual void SetEstimatedParentDrawTime(base::TimeDelta draw_time
) override
{}
119 virtual void SetMaxSwapsPendingOnImplThread(int max
) override
{}
120 virtual void DidSwapBuffersOnImplThread() override
{}
121 virtual void DidSwapBuffersCompleteOnImplThread() override
{}
122 virtual void OnCanDrawStateChanged(bool can_draw
) override
{
123 on_can_draw_state_changed_called_
= true;
125 virtual void NotifyReadyToActivate() override
{
126 did_notify_ready_to_activate_
= true;
127 host_impl_
->ActivateSyncTree();
129 virtual void SetNeedsRedrawOnImplThread() override
{
130 did_request_redraw_
= true;
132 virtual void SetNeedsRedrawRectOnImplThread(
133 const gfx::Rect
& damage_rect
) override
{
134 did_request_redraw_
= true;
136 virtual void SetNeedsAnimateOnImplThread() override
{
137 did_request_animate_
= true;
139 virtual void SetNeedsManageTilesOnImplThread() override
{
140 did_request_manage_tiles_
= true;
142 virtual void DidInitializeVisibleTileOnImplThread() override
{
143 did_upload_visible_tile_
= true;
145 virtual void SetNeedsCommitOnImplThread() override
{
146 did_request_commit_
= true;
148 virtual void PostAnimationEventsToMainThreadOnImplThread(
149 scoped_ptr
<AnimationEventsVector
> events
) override
{}
150 virtual bool ReduceContentsTextureMemoryOnImplThread(
151 size_t limit_bytes
, int priority_cutoff
) override
{
152 current_limit_bytes_
= limit_bytes
;
153 current_priority_cutoff_value_
= priority_cutoff
;
154 return reduce_memory_result_
;
156 virtual bool IsInsideDraw() override
{ return false; }
157 virtual void RenewTreePriority() override
{}
158 virtual void PostDelayedScrollbarFadeOnImplThread(
159 const base::Closure
& start_fade
,
160 base::TimeDelta delay
) override
{
161 scrollbar_fade_start_
= start_fade
;
162 requested_scrollbar_animation_delay_
= delay
;
164 virtual void DidActivateSyncTree() override
{}
165 virtual void DidManageTiles() override
{}
167 void set_reduce_memory_result(bool reduce_memory_result
) {
168 reduce_memory_result_
= reduce_memory_result
;
171 bool CreateHostImpl(const LayerTreeSettings
& settings
,
172 scoped_ptr
<OutputSurface
> output_surface
) {
173 host_impl_
= LayerTreeHostImpl::Create(settings
,
176 &stats_instrumentation_
,
177 shared_bitmap_manager_
.get(),
179 bool init
= host_impl_
->InitializeRenderer(output_surface
.Pass());
180 host_impl_
->SetViewportSize(gfx::Size(10, 10));
184 void SetupRootLayerImpl(scoped_ptr
<LayerImpl
> root
) {
185 root
->SetPosition(gfx::PointF());
186 root
->SetBounds(gfx::Size(10, 10));
187 root
->SetContentBounds(gfx::Size(10, 10));
188 root
->SetDrawsContent(true);
189 root
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 10, 10);
190 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
193 static void ExpectClearedScrollDeltasRecursive(LayerImpl
* layer
) {
194 ASSERT_EQ(layer
->ScrollDelta(), gfx::Vector2d());
195 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
196 ExpectClearedScrollDeltasRecursive(layer
->children()[i
]);
199 static void ExpectContains(const ScrollAndScaleSet
& scroll_info
,
201 const gfx::Vector2d
& scroll_delta
) {
202 int times_encountered
= 0;
204 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
205 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
207 EXPECT_VECTOR_EQ(scroll_delta
, scroll_info
.scrolls
[i
].scroll_delta
);
211 ASSERT_EQ(1, times_encountered
);
214 static void ExpectNone(const ScrollAndScaleSet
& scroll_info
, int id
) {
215 int times_encountered
= 0;
217 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
218 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
223 ASSERT_EQ(0, times_encountered
);
226 LayerImpl
* CreateScrollAndContentsLayers(LayerTreeImpl
* layer_tree_impl
,
227 const gfx::Size
& content_size
) {
228 const int kInnerViewportScrollLayerId
= 2;
229 const int kInnerViewportClipLayerId
= 4;
230 const int kPageScaleLayerId
= 5;
231 scoped_ptr
<LayerImpl
> root
=
232 LayerImpl::Create(layer_tree_impl
, 1);
233 root
->SetBounds(content_size
);
234 root
->SetContentBounds(content_size
);
235 root
->SetPosition(gfx::PointF());
237 scoped_ptr
<LayerImpl
> scroll
=
238 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
239 LayerImpl
* scroll_layer
= scroll
.get();
240 scroll
->SetIsContainerForFixedPositionLayers(true);
241 scroll
->SetScrollOffset(gfx::ScrollOffset());
243 scoped_ptr
<LayerImpl
> clip
=
244 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
246 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
248 scoped_ptr
<LayerImpl
> page_scale
=
249 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
251 scroll
->SetScrollClipLayer(clip
->id());
252 scroll
->SetBounds(content_size
);
253 scroll
->SetContentBounds(content_size
);
254 scroll
->SetPosition(gfx::PointF());
255 scroll
->SetIsContainerForFixedPositionLayers(true);
257 scoped_ptr
<LayerImpl
> contents
=
258 LayerImpl::Create(layer_tree_impl
, 3);
259 contents
->SetDrawsContent(true);
260 contents
->SetBounds(content_size
);
261 contents
->SetContentBounds(content_size
);
262 contents
->SetPosition(gfx::PointF());
264 scroll
->AddChild(contents
.Pass());
265 page_scale
->AddChild(scroll
.Pass());
266 clip
->AddChild(page_scale
.Pass());
267 root
->AddChild(clip
.Pass());
269 layer_tree_impl
->SetRootLayer(root
.Pass());
270 layer_tree_impl
->SetViewportLayersFromIds(
271 kPageScaleLayerId
, kInnerViewportScrollLayerId
, Layer::INVALID_ID
);
276 LayerImpl
* SetupScrollAndContentsLayers(const gfx::Size
& content_size
) {
277 LayerImpl
* scroll_layer
= CreateScrollAndContentsLayers(
278 host_impl_
->active_tree(), content_size
);
279 host_impl_
->active_tree()->DidBecomeActive();
283 // TODO(wjmaclean) Add clip-layer pointer to parameters.
284 scoped_ptr
<LayerImpl
> CreateScrollableLayer(int id
,
285 const gfx::Size
& size
,
286 LayerImpl
* clip_layer
) {
288 DCHECK(id
!= clip_layer
->id());
289 scoped_ptr
<LayerImpl
> layer
=
290 LayerImpl::Create(host_impl_
->active_tree(), id
);
291 layer
->SetScrollClipLayer(clip_layer
->id());
292 layer
->SetDrawsContent(true);
293 layer
->SetBounds(size
);
294 layer
->SetContentBounds(size
);
295 clip_layer
->SetBounds(gfx::Size(size
.width() / 2, size
.height() / 2));
300 LayerTreeHostImpl::FrameData frame
;
301 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
302 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
303 host_impl_
->DidDrawAllLayers(frame
);
306 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor
);
307 void pinch_zoom_pan_viewport_test(float device_scale_factor
);
308 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor
);
309 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
310 float device_scale_factor
);
312 void CheckNotifyCalledIfCanDrawChanged(bool always_draw
) {
313 // Note: It is not possible to disable the renderer once it has been set,
314 // so we do not need to test that disabling the renderer notifies us
315 // that can_draw changed.
316 EXPECT_FALSE(host_impl_
->CanDraw());
317 on_can_draw_state_changed_called_
= false;
319 // Set up the root layer, which allows us to draw.
320 SetupScrollAndContentsLayers(gfx::Size(100, 100));
321 EXPECT_TRUE(host_impl_
->CanDraw());
322 EXPECT_TRUE(on_can_draw_state_changed_called_
);
323 on_can_draw_state_changed_called_
= false;
325 // Toggle the root layer to make sure it toggles can_draw
326 host_impl_
->active_tree()->SetRootLayer(scoped_ptr
<LayerImpl
>());
327 EXPECT_FALSE(host_impl_
->CanDraw());
328 EXPECT_TRUE(on_can_draw_state_changed_called_
);
329 on_can_draw_state_changed_called_
= false;
331 SetupScrollAndContentsLayers(gfx::Size(100, 100));
332 EXPECT_TRUE(host_impl_
->CanDraw());
333 EXPECT_TRUE(on_can_draw_state_changed_called_
);
334 on_can_draw_state_changed_called_
= false;
336 // Toggle the device viewport size to make sure it toggles can_draw.
337 host_impl_
->SetViewportSize(gfx::Size());
339 EXPECT_TRUE(host_impl_
->CanDraw());
341 EXPECT_FALSE(host_impl_
->CanDraw());
343 EXPECT_TRUE(on_can_draw_state_changed_called_
);
344 on_can_draw_state_changed_called_
= false;
346 host_impl_
->SetViewportSize(gfx::Size(100, 100));
347 EXPECT_TRUE(host_impl_
->CanDraw());
348 EXPECT_TRUE(on_can_draw_state_changed_called_
);
349 on_can_draw_state_changed_called_
= false;
351 // Toggle contents textures purged without causing any evictions,
352 // and make sure that it does not change can_draw.
353 set_reduce_memory_result(false);
354 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
355 host_impl_
->memory_allocation_limit_bytes() - 1));
356 EXPECT_TRUE(host_impl_
->CanDraw());
357 EXPECT_FALSE(on_can_draw_state_changed_called_
);
358 on_can_draw_state_changed_called_
= false;
360 // Toggle contents textures purged to make sure it toggles can_draw.
361 set_reduce_memory_result(true);
362 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
363 host_impl_
->memory_allocation_limit_bytes() - 1));
365 EXPECT_TRUE(host_impl_
->CanDraw());
367 EXPECT_FALSE(host_impl_
->CanDraw());
369 EXPECT_TRUE(on_can_draw_state_changed_called_
);
370 on_can_draw_state_changed_called_
= false;
372 host_impl_
->active_tree()->ResetContentsTexturesPurged();
373 EXPECT_TRUE(host_impl_
->CanDraw());
374 EXPECT_TRUE(on_can_draw_state_changed_called_
);
375 on_can_draw_state_changed_called_
= false;
378 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor
);
381 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() {
382 return FakeOutputSurface::Create3d();
385 void DrawOneFrame() {
386 LayerTreeHostImpl::FrameData frame_data
;
387 host_impl_
->PrepareToDraw(&frame_data
);
388 host_impl_
->DidDrawAllLayers(frame_data
);
392 DebugScopedSetImplThread always_impl_thread_
;
393 DebugScopedSetMainThreadBlocked always_main_thread_blocked_
;
395 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
396 scoped_ptr
<LayerTreeHostImpl
> host_impl_
;
397 FakeRenderingStatsInstrumentation stats_instrumentation_
;
398 bool on_can_draw_state_changed_called_
;
399 bool did_notify_ready_to_activate_
;
400 bool did_request_commit_
;
401 bool did_request_redraw_
;
402 bool did_request_animate_
;
403 bool did_request_manage_tiles_
;
404 bool did_upload_visible_tile_
;
405 bool reduce_memory_result_
;
406 base::Closure scrollbar_fade_start_
;
407 base::TimeDelta requested_scrollbar_animation_delay_
;
408 size_t current_limit_bytes_
;
409 int current_priority_cutoff_value_
;
412 TEST_F(LayerTreeHostImplTest
, NotifyIfCanDrawChanged
) {
413 bool always_draw
= false;
414 CheckNotifyCalledIfCanDrawChanged(always_draw
);
417 TEST_F(LayerTreeHostImplTest
, CanDrawIncompleteFrames
) {
418 CreateHostImpl(DefaultSettings(),
419 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
421 bool always_draw
= true;
422 CheckNotifyCalledIfCanDrawChanged(always_draw
);
425 TEST_F(LayerTreeHostImplTest
, ScrollDeltaNoLayers
) {
426 ASSERT_FALSE(host_impl_
->active_tree()->root_layer());
428 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
429 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
432 TEST_F(LayerTreeHostImplTest
, ScrollDeltaTreeButNoChanges
) {
434 scoped_ptr
<LayerImpl
> root
=
435 LayerImpl::Create(host_impl_
->active_tree(), 1);
436 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
437 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 3));
438 root
->children()[1]->AddChild(
439 LayerImpl::Create(host_impl_
->active_tree(), 4));
440 root
->children()[1]->AddChild(
441 LayerImpl::Create(host_impl_
->active_tree(), 5));
442 root
->children()[1]->children()[0]->AddChild(
443 LayerImpl::Create(host_impl_
->active_tree(), 6));
444 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
446 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
448 ExpectClearedScrollDeltasRecursive(root
);
450 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
452 scroll_info
= host_impl_
->ProcessScrollDeltas();
453 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
454 ExpectClearedScrollDeltasRecursive(root
);
456 scroll_info
= host_impl_
->ProcessScrollDeltas();
457 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
458 ExpectClearedScrollDeltasRecursive(root
);
461 TEST_F(LayerTreeHostImplTest
, ScrollDeltaRepeatedScrolls
) {
462 gfx::ScrollOffset
scroll_offset(20, 30);
463 gfx::Vector2d
scroll_delta(11, -15);
465 scoped_ptr
<LayerImpl
> root_clip
=
466 LayerImpl::Create(host_impl_
->active_tree(), 2);
467 scoped_ptr
<LayerImpl
> root
=
468 LayerImpl::Create(host_impl_
->active_tree(), 1);
469 root_clip
->SetBounds(gfx::Size(10, 10));
470 LayerImpl
* root_layer
= root
.get();
471 root_clip
->AddChild(root
.Pass());
472 root_layer
->SetBounds(gfx::Size(110, 110));
473 root_layer
->SetScrollClipLayer(root_clip
->id());
474 root_layer
->SetScrollOffset(scroll_offset
);
475 root_layer
->ScrollBy(scroll_delta
);
476 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
478 LayerImpl
* root
= host_impl_
->active_tree()->root_layer()->children()[0];
480 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
482 scroll_info
= host_impl_
->ProcessScrollDeltas();
483 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
484 EXPECT_VECTOR_EQ(root
->sent_scroll_delta(), scroll_delta
);
485 ExpectContains(*scroll_info
, root
->id(), scroll_delta
);
487 gfx::Vector2d
scroll_delta2(-5, 27);
488 root
->ScrollBy(scroll_delta2
);
489 scroll_info
= host_impl_
->ProcessScrollDeltas();
490 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
491 EXPECT_VECTOR_EQ(root
->sent_scroll_delta(), scroll_delta
+ scroll_delta2
);
492 ExpectContains(*scroll_info
, root
->id(), scroll_delta
+ scroll_delta2
);
494 root
->ScrollBy(gfx::Vector2d());
495 scroll_info
= host_impl_
->ProcessScrollDeltas();
496 EXPECT_EQ(root
->sent_scroll_delta(), scroll_delta
+ scroll_delta2
);
499 TEST_F(LayerTreeHostImplTest
, ScrollRootCallsCommitAndRedraw
) {
500 SetupScrollAndContentsLayers(gfx::Size(100, 100));
501 host_impl_
->SetViewportSize(gfx::Size(50, 50));
504 EXPECT_EQ(InputHandler::ScrollStarted
,
505 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
506 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
507 InputHandler::Wheel
));
508 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
509 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
510 InputHandler::Wheel
));
511 host_impl_
->ScrollEnd();
512 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
513 InputHandler::Wheel
));
514 EXPECT_TRUE(did_request_redraw_
);
515 EXPECT_TRUE(did_request_commit_
);
518 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRootLayer
) {
519 // We should not crash when trying to scroll an empty layer tree.
520 EXPECT_EQ(InputHandler::ScrollIgnored
,
521 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
524 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRenderer
) {
525 scoped_ptr
<TestWebGraphicsContext3D
> context_owned
=
526 TestWebGraphicsContext3D::Create();
527 context_owned
->set_context_lost(true);
529 // Initialization will fail.
530 EXPECT_FALSE(CreateHostImpl(
531 DefaultSettings(), FakeOutputSurface::Create3d(context_owned
.Pass())));
533 SetupScrollAndContentsLayers(gfx::Size(100, 100));
535 // We should not crash when trying to scroll after the renderer initialization
537 EXPECT_EQ(InputHandler::ScrollStarted
,
538 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
541 TEST_F(LayerTreeHostImplTest
, ReplaceTreeWhileScrolling
) {
542 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
543 host_impl_
->SetViewportSize(gfx::Size(50, 50));
546 // We should not crash if the tree is replaced while we are scrolling.
547 EXPECT_EQ(InputHandler::ScrollStarted
,
548 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
549 host_impl_
->active_tree()->DetachLayerTree();
551 scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
553 // We should still be scrolling, because the scrolled layer also exists in the
555 gfx::Vector2d
scroll_delta(0, 10);
556 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
557 host_impl_
->ScrollEnd();
558 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
559 ExpectContains(*scroll_info
, scroll_layer
->id(), scroll_delta
);
562 TEST_F(LayerTreeHostImplTest
, ClearRootRenderSurfaceAndScroll
) {
563 SetupScrollAndContentsLayers(gfx::Size(100, 100));
564 host_impl_
->SetViewportSize(gfx::Size(50, 50));
567 // We should be able to scroll even if the root layer loses its render surface
568 // after the most recent render.
569 host_impl_
->active_tree()->root_layer()->ClearRenderSurface();
570 host_impl_
->active_tree()->set_needs_update_draw_properties();
572 EXPECT_EQ(InputHandler::ScrollStarted
,
573 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
576 TEST_F(LayerTreeHostImplTest
, WheelEventHandlers
) {
577 SetupScrollAndContentsLayers(gfx::Size(100, 100));
578 host_impl_
->SetViewportSize(gfx::Size(50, 50));
580 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
582 root
->SetHaveWheelEventHandlers(true);
584 // With registered event handlers, wheel scrolls have to go to the main
586 EXPECT_EQ(InputHandler::ScrollOnMainThread
,
587 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
589 // But gesture scrolls can still be handled.
590 EXPECT_EQ(InputHandler::ScrollStarted
,
591 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
594 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchscreen
) {
595 SetupScrollAndContentsLayers(gfx::Size(100, 100));
596 host_impl_
->SetViewportSize(gfx::Size(50, 50));
599 // Ignore the fling since no layer is being scrolled
600 EXPECT_EQ(InputHandler::ScrollIgnored
,
601 host_impl_
->FlingScrollBegin());
603 // Start scrolling a layer
604 EXPECT_EQ(InputHandler::ScrollStarted
,
605 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
607 // Now the fling should go ahead since we've started scrolling a layer
608 EXPECT_EQ(InputHandler::ScrollStarted
,
609 host_impl_
->FlingScrollBegin());
612 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchpad
) {
613 SetupScrollAndContentsLayers(gfx::Size(100, 100));
614 host_impl_
->SetViewportSize(gfx::Size(50, 50));
617 // Ignore the fling since no layer is being scrolled
618 EXPECT_EQ(InputHandler::ScrollIgnored
,
619 host_impl_
->FlingScrollBegin());
621 // Start scrolling a layer
622 EXPECT_EQ(InputHandler::ScrollStarted
,
623 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
625 // Now the fling should go ahead since we've started scrolling a layer
626 EXPECT_EQ(InputHandler::ScrollStarted
,
627 host_impl_
->FlingScrollBegin());
630 TEST_F(LayerTreeHostImplTest
, NoFlingWhenScrollingOnMain
) {
631 SetupScrollAndContentsLayers(gfx::Size(100, 100));
632 host_impl_
->SetViewportSize(gfx::Size(50, 50));
634 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
636 root
->SetShouldScrollOnMainThread(true);
638 // Start scrolling a layer
639 EXPECT_EQ(InputHandler::ScrollOnMainThread
,
640 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
642 // The fling should be ignored since there's no layer being scrolled impl-side
643 EXPECT_EQ(InputHandler::ScrollIgnored
,
644 host_impl_
->FlingScrollBegin());
647 TEST_F(LayerTreeHostImplTest
, ShouldScrollOnMainThread
) {
648 SetupScrollAndContentsLayers(gfx::Size(100, 100));
649 host_impl_
->SetViewportSize(gfx::Size(50, 50));
651 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
653 root
->SetShouldScrollOnMainThread(true);
655 EXPECT_EQ(InputHandler::ScrollOnMainThread
,
656 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
657 EXPECT_EQ(InputHandler::ScrollOnMainThread
,
658 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
661 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionBasic
) {
662 SetupScrollAndContentsLayers(gfx::Size(200, 200));
663 host_impl_
->SetViewportSize(gfx::Size(100, 100));
665 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
666 root
->SetContentsScale(2.f
, 2.f
);
667 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
671 // All scroll types inside the non-fast scrollable region should fail.
672 EXPECT_EQ(InputHandler::ScrollOnMainThread
,
673 host_impl_
->ScrollBegin(gfx::Point(25, 25),
674 InputHandler::Wheel
));
675 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
676 InputHandler::Wheel
));
677 EXPECT_EQ(InputHandler::ScrollOnMainThread
,
678 host_impl_
->ScrollBegin(gfx::Point(25, 25),
679 InputHandler::Gesture
));
680 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
681 InputHandler::Gesture
));
683 // All scroll types outside this region should succeed.
684 EXPECT_EQ(InputHandler::ScrollStarted
,
685 host_impl_
->ScrollBegin(gfx::Point(75, 75),
686 InputHandler::Wheel
));
687 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
688 InputHandler::Gesture
));
689 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
690 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
691 InputHandler::Gesture
));
692 host_impl_
->ScrollEnd();
693 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
694 InputHandler::Gesture
));
695 EXPECT_EQ(InputHandler::ScrollStarted
,
696 host_impl_
->ScrollBegin(gfx::Point(75, 75),
697 InputHandler::Gesture
));
698 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
699 InputHandler::Gesture
));
700 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
701 host_impl_
->ScrollEnd();
702 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
703 InputHandler::Gesture
));
706 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionWithOffset
) {
707 SetupScrollAndContentsLayers(gfx::Size(200, 200));
708 host_impl_
->SetViewportSize(gfx::Size(100, 100));
710 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
711 root
->SetContentsScale(2.f
, 2.f
);
712 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
713 root
->SetPosition(gfx::PointF(-25.f
, 0.f
));
717 // This point would fall into the non-fast scrollable region except that we've
718 // moved the layer down by 25 pixels.
719 EXPECT_EQ(InputHandler::ScrollStarted
,
720 host_impl_
->ScrollBegin(gfx::Point(40, 10),
721 InputHandler::Wheel
));
722 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
723 InputHandler::Wheel
));
724 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
725 host_impl_
->ScrollEnd();
727 // This point is still inside the non-fast region.
728 EXPECT_EQ(InputHandler::ScrollOnMainThread
,
729 host_impl_
->ScrollBegin(gfx::Point(10, 10),
730 InputHandler::Wheel
));
733 TEST_F(LayerTreeHostImplTest
, ScrollHandlerNotPresent
) {
734 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
735 EXPECT_FALSE(scroll_layer
->have_scroll_event_handlers());
736 host_impl_
->SetViewportSize(gfx::Size(50, 50));
739 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
740 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
);
741 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
742 host_impl_
->ScrollEnd();
743 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
746 TEST_F(LayerTreeHostImplTest
, ScrollHandlerPresent
) {
747 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
748 scroll_layer
->SetHaveScrollEventHandlers(true);
749 host_impl_
->SetViewportSize(gfx::Size(50, 50));
752 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
753 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
);
754 EXPECT_TRUE(host_impl_
->scroll_affects_scroll_handler());
755 host_impl_
->ScrollEnd();
756 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
759 TEST_F(LayerTreeHostImplTest
, ScrollByReturnsCorrectValue
) {
760 SetupScrollAndContentsLayers(gfx::Size(200, 200));
761 host_impl_
->SetViewportSize(gfx::Size(100, 100));
765 EXPECT_EQ(InputHandler::ScrollStarted
,
766 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
768 // Trying to scroll to the left/top will not succeed.
769 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
770 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
771 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
773 // Scrolling to the right/bottom will succeed.
774 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
775 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
776 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
778 // Scrolling to left/top will now succeed.
779 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
780 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
781 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
783 // Scrolling diagonally against an edge will succeed.
784 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
785 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
786 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
788 // Trying to scroll more than the available space will also succeed.
789 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
792 TEST_F(LayerTreeHostImplTest
, ScrollVerticallyByPageReturnsCorrectValue
) {
793 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
794 host_impl_
->SetViewportSize(gfx::Size(100, 1000));
798 EXPECT_EQ(InputHandler::ScrollStarted
,
799 host_impl_
->ScrollBegin(gfx::Point(),
800 InputHandler::Wheel
));
802 // Trying to scroll without a vertical scrollbar will fail.
803 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
804 gfx::Point(), SCROLL_FORWARD
));
805 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
806 gfx::Point(), SCROLL_BACKWARD
));
808 scoped_ptr
<PaintedScrollbarLayerImpl
> vertical_scrollbar(
809 PaintedScrollbarLayerImpl::Create(
810 host_impl_
->active_tree(),
813 vertical_scrollbar
->SetBounds(gfx::Size(15, 1000));
814 host_impl_
->InnerViewportScrollLayer()->AddScrollbar(
815 vertical_scrollbar
.get());
817 // Trying to scroll with a vertical scrollbar will succeed.
818 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
819 gfx::Point(), SCROLL_FORWARD
));
820 EXPECT_FLOAT_EQ(875.f
,
821 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
822 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
823 gfx::Point(), SCROLL_BACKWARD
));
826 // The user-scrollability breaks for zoomed-in pages. So disable this.
827 // http://crbug.com/322223
828 TEST_F(LayerTreeHostImplTest
, DISABLED_ScrollWithUserUnscrollableLayers
) {
829 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
830 host_impl_
->SetViewportSize(gfx::Size(100, 100));
832 gfx::Size
overflow_size(400, 400);
833 ASSERT_EQ(1u, scroll_layer
->children().size());
834 LayerImpl
* overflow
= scroll_layer
->children()[0];
835 overflow
->SetBounds(overflow_size
);
836 overflow
->SetContentBounds(overflow_size
);
837 overflow
->SetScrollClipLayer(scroll_layer
->parent()->id());
838 overflow
->SetScrollOffset(gfx::ScrollOffset());
839 overflow
->SetPosition(gfx::PointF());
842 gfx::Point
scroll_position(10, 10);
844 EXPECT_EQ(InputHandler::ScrollStarted
,
845 host_impl_
->ScrollBegin(scroll_position
, InputHandler::Wheel
));
846 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->TotalScrollOffset());
847 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow
->TotalScrollOffset());
849 gfx::Vector2dF
scroll_delta(10, 10);
850 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
851 host_impl_
->ScrollEnd();
852 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->TotalScrollOffset());
853 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->TotalScrollOffset());
855 overflow
->set_user_scrollable_horizontal(false);
857 EXPECT_EQ(InputHandler::ScrollStarted
,
858 host_impl_
->ScrollBegin(scroll_position
, InputHandler::Wheel
));
859 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->TotalScrollOffset());
860 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->TotalScrollOffset());
862 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
863 host_impl_
->ScrollEnd();
864 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->TotalScrollOffset());
865 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->TotalScrollOffset());
867 overflow
->set_user_scrollable_vertical(false);
869 EXPECT_EQ(InputHandler::ScrollStarted
,
870 host_impl_
->ScrollBegin(scroll_position
, InputHandler::Wheel
));
871 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->TotalScrollOffset());
872 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->TotalScrollOffset());
874 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
875 host_impl_
->ScrollEnd();
876 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer
->TotalScrollOffset());
877 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->TotalScrollOffset());
880 TEST_F(LayerTreeHostImplTest
,
881 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion
) {
882 SetupScrollAndContentsLayers(gfx::Size(100, 100));
883 host_impl_
->SetViewportSize(gfx::Size(50, 50));
886 // We should be able to hit test for touch event handlers even if the root
887 // layer loses its render surface after the most recent render.
888 host_impl_
->active_tree()->root_layer()->ClearRenderSurface();
889 host_impl_
->active_tree()->set_needs_update_draw_properties();
891 EXPECT_EQ(host_impl_
->HaveTouchEventHandlersAt(gfx::Point()), false);
894 TEST_F(LayerTreeHostImplTest
, ImplPinchZoom
) {
895 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
896 host_impl_
->SetViewportSize(gfx::Size(50, 50));
899 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
900 LayerImpl
* container_layer
= scroll_layer
->scroll_clip_layer();
901 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
903 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
904 float page_scale_factor
= 1.f
;
906 // The impl-based pinch zoom should adjust the max scroll position.
908 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(
909 page_scale_factor
, min_page_scale
, max_page_scale
);
910 host_impl_
->active_tree()->SetPageScaleDelta(1.f
);
911 scroll_layer
->SetScrollDelta(gfx::Vector2d());
913 float page_scale_delta
= 2.f
;
914 gfx::Vector2dF
expected_container_size_delta(
915 container_layer
->bounds().width(), container_layer
->bounds().height());
916 expected_container_size_delta
.Scale((1.f
- page_scale_delta
) /
917 (page_scale_factor
* page_scale_delta
));
919 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture
);
920 host_impl_
->PinchGestureBegin();
921 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
922 // While the gesture is still active, the scroll layer should have a
923 // container size delta = container->bounds() * ((1.f -
924 // page_scale_delta)/())
925 EXPECT_EQ(expected_container_size_delta
,
926 scroll_layer
->FixedContainerSizeDelta());
927 host_impl_
->PinchGestureEnd();
928 host_impl_
->ScrollEnd();
929 EXPECT_FALSE(did_request_animate_
);
930 EXPECT_TRUE(did_request_redraw_
);
931 EXPECT_TRUE(did_request_commit_
);
932 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
934 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
935 host_impl_
->ProcessScrollDeltas();
936 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
938 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
939 scroll_layer
->MaxScrollOffset().ToString());
942 // Scrolling after a pinch gesture should always be in local space. The
943 // scroll deltas do not have the page scale factor applied.
945 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(
946 page_scale_factor
, min_page_scale
, max_page_scale
);
947 host_impl_
->active_tree()->SetPageScaleDelta(1.f
);
948 scroll_layer
->SetScrollDelta(gfx::Vector2d());
950 float page_scale_delta
= 2.f
;
951 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
);
952 host_impl_
->PinchGestureBegin();
953 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
954 host_impl_
->PinchGestureEnd();
955 host_impl_
->ScrollEnd();
957 gfx::Vector2d
scroll_delta(0, 10);
958 EXPECT_EQ(InputHandler::ScrollStarted
,
959 host_impl_
->ScrollBegin(gfx::Point(5, 5),
960 InputHandler::Wheel
));
961 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
962 host_impl_
->ScrollEnd();
964 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
965 host_impl_
->ProcessScrollDeltas();
966 ExpectContains(*scroll_info
.get(),
972 TEST_F(LayerTreeHostImplTest
, ScrollWithSwapPromises
) {
973 ui::LatencyInfo latency_info
;
974 latency_info
.trace_id
= 1234;
975 scoped_ptr
<SwapPromise
> swap_promise(
976 new LatencyInfoSwapPromise(latency_info
));
978 SetupScrollAndContentsLayers(gfx::Size(100, 100));
979 EXPECT_EQ(InputHandler::ScrollStarted
,
980 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
981 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
982 host_impl_
->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise
.Pass());
983 host_impl_
->ScrollEnd();
985 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
986 EXPECT_EQ(1u, scroll_info
->swap_promises
.size());
987 EXPECT_EQ(latency_info
.trace_id
, scroll_info
->swap_promises
[0]->TraceId());
990 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
991 SetupScrollAndContentsLayers(gfx::Size(100, 100));
992 host_impl_
->SetViewportSize(gfx::Size(50, 50));
995 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
996 DCHECK(scroll_layer
);
998 float min_page_scale
= 1.f
;
999 float max_page_scale
= 4.f
;
1001 // Basic pinch zoom in gesture
1003 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
1006 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1008 float page_scale_delta
= 2.f
;
1009 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture
);
1010 host_impl_
->PinchGestureBegin();
1011 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1012 host_impl_
->PinchGestureEnd();
1013 host_impl_
->ScrollEnd();
1014 EXPECT_FALSE(did_request_animate_
);
1015 EXPECT_TRUE(did_request_redraw_
);
1016 EXPECT_TRUE(did_request_commit_
);
1018 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1019 host_impl_
->ProcessScrollDeltas();
1020 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1025 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
1028 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1029 float page_scale_delta
= 10.f
;
1031 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture
);
1032 host_impl_
->PinchGestureBegin();
1033 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1034 host_impl_
->PinchGestureEnd();
1035 host_impl_
->ScrollEnd();
1037 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1038 host_impl_
->ProcessScrollDeltas();
1039 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
1042 // Zoom-out clamping
1044 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
1047 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1048 scroll_layer
->SetScrollOffset(gfx::ScrollOffset(50, 50));
1050 float page_scale_delta
= 0.1f
;
1051 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
);
1052 host_impl_
->PinchGestureBegin();
1053 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1054 host_impl_
->PinchGestureEnd();
1055 host_impl_
->ScrollEnd();
1057 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1058 host_impl_
->ProcessScrollDeltas();
1059 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1061 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1064 // Two-finger panning should not happen based on pinch events only
1066 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
1069 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1070 scroll_layer
->SetScrollOffset(gfx::ScrollOffset(20, 20));
1072 float page_scale_delta
= 1.f
;
1073 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture
);
1074 host_impl_
->PinchGestureBegin();
1075 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1076 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1077 host_impl_
->PinchGestureEnd();
1078 host_impl_
->ScrollEnd();
1080 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1081 host_impl_
->ProcessScrollDeltas();
1082 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1083 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1086 // Two-finger panning should work with interleaved scroll events
1088 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
1091 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1092 scroll_layer
->SetScrollOffset(gfx::ScrollOffset(20, 20));
1094 float page_scale_delta
= 1.f
;
1095 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture
);
1096 host_impl_
->PinchGestureBegin();
1097 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1098 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1099 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1100 host_impl_
->PinchGestureEnd();
1101 host_impl_
->ScrollEnd();
1103 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1104 host_impl_
->ProcessScrollDeltas();
1105 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1106 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-10, -10));
1109 // Two-finger panning should work when starting fully zoomed out.
1111 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(0.5f
,
1114 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1115 scroll_layer
->SetScrollOffset(gfx::ScrollOffset(0, 0));
1117 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture
);
1118 host_impl_
->PinchGestureBegin();
1119 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1120 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(0, 0));
1121 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1122 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(10, 10));
1123 host_impl_
->PinchGestureEnd();
1124 host_impl_
->ScrollEnd();
1126 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1127 host_impl_
->ProcessScrollDeltas();
1128 EXPECT_EQ(scroll_info
->page_scale_delta
, 2.f
);
1129 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(20, 20));
1133 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
1134 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1135 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1138 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1139 DCHECK(scroll_layer
);
1141 float min_page_scale
= 0.5f
;
1142 float max_page_scale
= 4.f
;
1143 base::TimeTicks start_time
= base::TimeTicks() +
1144 base::TimeDelta::FromSeconds(1);
1145 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1146 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1147 base::TimeTicks end_time
= start_time
+ duration
;
1149 // Non-anchor zoom-in
1151 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
1154 scroll_layer
->SetScrollOffset(gfx::ScrollOffset(50, 50));
1156 did_request_redraw_
= false;
1157 did_request_animate_
= false;
1158 host_impl_
->active_tree()->SetPageScaleAnimation(
1163 host_impl_
->ActivateSyncTree();
1164 EXPECT_FALSE(did_request_redraw_
);
1165 EXPECT_TRUE(did_request_animate_
);
1167 did_request_redraw_
= false;
1168 did_request_animate_
= false;
1169 host_impl_
->Animate(start_time
);
1170 EXPECT_TRUE(did_request_redraw_
);
1171 EXPECT_TRUE(did_request_animate_
);
1173 did_request_redraw_
= false;
1174 did_request_animate_
= false;
1175 host_impl_
->Animate(halfway_through_animation
);
1176 EXPECT_TRUE(did_request_redraw_
);
1177 EXPECT_TRUE(did_request_animate_
);
1179 did_request_redraw_
= false;
1180 did_request_animate_
= false;
1181 did_request_commit_
= false;
1182 host_impl_
->Animate(end_time
);
1183 EXPECT_TRUE(did_request_commit_
);
1184 EXPECT_FALSE(did_request_animate_
);
1186 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1187 host_impl_
->ProcessScrollDeltas();
1188 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
1189 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1194 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
1197 scroll_layer
->SetScrollOffset(gfx::ScrollOffset(50, 50));
1199 did_request_redraw_
= false;
1200 did_request_animate_
= false;
1201 host_impl_
->active_tree()->SetPageScaleAnimation(
1202 gfx::Vector2d(25, 25), true, min_page_scale
, duration
);
1203 host_impl_
->ActivateSyncTree();
1204 EXPECT_FALSE(did_request_redraw_
);
1205 EXPECT_TRUE(did_request_animate_
);
1207 did_request_redraw_
= false;
1208 did_request_animate_
= false;
1209 host_impl_
->Animate(start_time
);
1210 EXPECT_TRUE(did_request_redraw_
);
1211 EXPECT_TRUE(did_request_animate_
);
1213 did_request_redraw_
= false;
1214 did_request_commit_
= false;
1215 did_request_animate_
= false;
1216 host_impl_
->Animate(end_time
);
1217 EXPECT_TRUE(did_request_redraw_
);
1218 EXPECT_FALSE(did_request_animate_
);
1219 EXPECT_TRUE(did_request_commit_
);
1221 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1222 host_impl_
->ProcessScrollDeltas();
1223 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1224 // Pushed to (0,0) via clamping against contents layer size.
1225 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1229 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
1230 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1231 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1234 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1235 DCHECK(scroll_layer
);
1237 float min_page_scale
= 0.5f
;
1238 float max_page_scale
= 4.f
;
1239 base::TimeTicks start_time
= base::TimeTicks() +
1240 base::TimeDelta::FromSeconds(1);
1241 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1242 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1243 base::TimeTicks end_time
= start_time
+ duration
;
1245 // Anchor zoom with unchanged page scale should not change scroll or scale.
1247 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
1250 scroll_layer
->SetScrollOffset(gfx::ScrollOffset(50, 50));
1252 host_impl_
->active_tree()->SetPageScaleAnimation(
1257 host_impl_
->ActivateSyncTree();
1258 host_impl_
->Animate(start_time
);
1259 host_impl_
->Animate(halfway_through_animation
);
1260 EXPECT_TRUE(did_request_redraw_
);
1261 host_impl_
->Animate(end_time
);
1262 EXPECT_TRUE(did_request_commit_
);
1264 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1265 host_impl_
->ProcessScrollDeltas();
1266 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
1267 ExpectNone(*scroll_info
, scroll_layer
->id());
1271 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationTransferedOnSyncTreeActivate
) {
1272 host_impl_
->CreatePendingTree();
1273 CreateScrollAndContentsLayers(
1274 host_impl_
->pending_tree(),
1275 gfx::Size(100, 100));
1276 host_impl_
->ActivateSyncTree();
1279 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1280 DCHECK(scroll_layer
);
1282 float min_page_scale
= 0.5f
;
1283 float max_page_scale
= 4.f
;
1284 host_impl_
->sync_tree()->SetPageScaleFactorAndLimits(1.f
,
1287 host_impl_
->ActivateSyncTree();
1289 base::TimeTicks start_time
= base::TimeTicks() +
1290 base::TimeDelta::FromSeconds(1);
1291 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1292 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1293 base::TimeTicks end_time
= start_time
+ duration
;
1294 float target_scale
= 2.f
;
1296 scroll_layer
->SetScrollOffset(gfx::ScrollOffset(50, 50));
1298 // Make sure TakePageScaleAnimation works properly.
1299 host_impl_
->sync_tree()->SetPageScaleAnimation(
1304 scoped_ptr
<PageScaleAnimation
> psa
=
1305 host_impl_
->sync_tree()->TakePageScaleAnimation();
1306 EXPECT_EQ(target_scale
, psa
->target_page_scale_factor());
1307 EXPECT_EQ(duration
, psa
->duration());
1308 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePageScaleAnimation());
1310 // Recreate the PSA. Nothing should happen here since the tree containing the
1311 // PSA hasn't been activated yet.
1312 did_request_redraw_
= false;
1313 did_request_animate_
= false;
1314 host_impl_
->sync_tree()->SetPageScaleAnimation(
1319 host_impl_
->Animate(halfway_through_animation
);
1320 EXPECT_FALSE(did_request_animate_
);
1321 EXPECT_FALSE(did_request_redraw_
);
1323 // Activate the sync tree. This should cause the animation to become enabled.
1324 // It should also clear the pointer on the sync tree.
1325 host_impl_
->ActivateSyncTree();
1326 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePageScaleAnimation().get());
1327 EXPECT_FALSE(did_request_redraw_
);
1328 EXPECT_TRUE(did_request_animate_
);
1330 // From here on, make sure the animation runs as normal.
1331 did_request_redraw_
= false;
1332 did_request_animate_
= false;
1333 host_impl_
->Animate(start_time
);
1334 EXPECT_TRUE(did_request_redraw_
);
1335 EXPECT_TRUE(did_request_animate_
);
1337 did_request_redraw_
= false;
1338 did_request_animate_
= false;
1339 host_impl_
->Animate(halfway_through_animation
);
1340 EXPECT_TRUE(did_request_redraw_
);
1341 EXPECT_TRUE(did_request_animate_
);
1343 did_request_redraw_
= false;
1344 did_request_animate_
= false;
1345 did_request_commit_
= false;
1346 host_impl_
->Animate(end_time
);
1347 EXPECT_TRUE(did_request_commit_
);
1348 EXPECT_FALSE(did_request_animate_
);
1350 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1351 host_impl_
->ProcessScrollDeltas();
1352 EXPECT_EQ(scroll_info
->page_scale_delta
, target_scale
);
1353 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1356 class LayerTreeHostImplOverridePhysicalTime
: public LayerTreeHostImpl
{
1358 LayerTreeHostImplOverridePhysicalTime(
1359 const LayerTreeSettings
& settings
,
1360 LayerTreeHostImplClient
* client
,
1362 SharedBitmapManager
* manager
,
1363 RenderingStatsInstrumentation
* rendering_stats_instrumentation
)
1364 : LayerTreeHostImpl(settings
,
1367 rendering_stats_instrumentation
,
1371 virtual BeginFrameArgs
CurrentBeginFrameArgs() const override
{
1372 return CreateBeginFrameArgsForTesting(fake_current_physical_time_
);
1375 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now
) {
1376 fake_current_physical_time_
= fake_now
;
1380 base::TimeTicks fake_current_physical_time_
;
1383 #define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST() \
1384 gfx::Size viewport_size(10, 10); \
1385 gfx::Size content_size(100, 100); \
1387 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = \
1388 new LayerTreeHostImplOverridePhysicalTime(settings, \
1391 shared_bitmap_manager_.get(), \
1392 &stats_instrumentation_); \
1393 host_impl_ = make_scoped_ptr(host_impl_override_time); \
1394 host_impl_->InitializeRenderer(CreateOutputSurface()); \
1395 host_impl_->SetViewportSize(viewport_size); \
1397 scoped_ptr<LayerImpl> root = \
1398 LayerImpl::Create(host_impl_->active_tree(), 1); \
1399 root->SetBounds(viewport_size); \
1401 scoped_ptr<LayerImpl> scroll = \
1402 LayerImpl::Create(host_impl_->active_tree(), 2); \
1403 scroll->SetScrollClipLayer(root->id()); \
1404 scroll->SetScrollOffset(gfx::ScrollOffset()); \
1405 root->SetBounds(viewport_size); \
1406 scroll->SetBounds(content_size); \
1407 scroll->SetContentBounds(content_size); \
1408 scroll->SetIsContainerForFixedPositionLayers(true); \
1410 scoped_ptr<LayerImpl> contents = \
1411 LayerImpl::Create(host_impl_->active_tree(), 3); \
1412 contents->SetDrawsContent(true); \
1413 contents->SetBounds(content_size); \
1414 contents->SetContentBounds(content_size); \
1416 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = \
1417 SolidColorScrollbarLayerImpl::Create( \
1418 host_impl_->active_tree(), 4, VERTICAL, 10, 0, false, true); \
1419 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); \
1421 scroll->AddChild(contents.Pass()); \
1422 root->AddChild(scroll.Pass()); \
1423 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1); \
1424 root->AddChild(scrollbar.Pass()); \
1426 host_impl_->active_tree()->SetRootLayer(root.Pass()); \
1427 host_impl_->active_tree()->SetViewportLayersFromIds( \
1428 1, 2, Layer::INVALID_ID); \
1429 host_impl_->active_tree()->DidBecomeActive(); \
1432 TEST_F(LayerTreeHostImplTest
, ScrollbarLinearFadeScheduling
) {
1433 LayerTreeSettings settings
;
1434 settings
.scrollbar_animator
= LayerTreeSettings::LinearFade
;
1435 settings
.scrollbar_fade_delay_ms
= 20;
1436 settings
.scrollbar_fade_duration_ms
= 20;
1438 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1440 base::TimeTicks fake_now
= gfx::FrameTime::Now();
1442 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_
);
1443 EXPECT_FALSE(did_request_redraw_
);
1445 // If no scroll happened during a scroll gesture, it should have no effect.
1446 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
);
1447 host_impl_
->ScrollEnd();
1448 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_
);
1449 EXPECT_FALSE(did_request_redraw_
);
1450 EXPECT_TRUE(scrollbar_fade_start_
.Equals(base::Closure()));
1452 // After a scroll, a fade animation should be scheduled about 20ms from now.
1453 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
);
1454 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1455 host_impl_
->ScrollEnd();
1456 did_request_redraw_
= false;
1457 did_request_animate_
= false;
1458 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1459 requested_scrollbar_animation_delay_
);
1460 EXPECT_FALSE(did_request_redraw_
);
1461 EXPECT_FALSE(did_request_animate_
);
1462 requested_scrollbar_animation_delay_
= base::TimeDelta();
1463 scrollbar_fade_start_
.Run();
1464 host_impl_
->Animate(fake_now
);
1466 // After the fade begins, we should start getting redraws instead of a
1467 // scheduled animation.
1468 fake_now
+= base::TimeDelta::FromMilliseconds(25);
1469 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_
);
1470 EXPECT_TRUE(did_request_animate_
);
1471 did_request_animate_
= false;
1473 // Setting the scroll offset outside a scroll should also cause the scrollbar
1474 // to appear and to schedule a fade.
1475 host_impl_
->InnerViewportScrollLayer()->SetScrollOffset(
1476 gfx::ScrollOffset(5, 5));
1477 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1478 requested_scrollbar_animation_delay_
);
1479 EXPECT_FALSE(did_request_redraw_
);
1480 EXPECT_FALSE(did_request_animate_
);
1481 requested_scrollbar_animation_delay_
= base::TimeDelta();
1483 // Unnecessarily Fade animation of solid color scrollbar is not triggered.
1484 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
);
1485 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1486 host_impl_
->ScrollEnd();
1487 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_
);
1490 TEST_F(LayerTreeHostImplTest
, ScrollbarFadePinchZoomScrollbars
) {
1491 LayerTreeSettings settings
;
1492 settings
.scrollbar_animator
= LayerTreeSettings::LinearFade
;
1493 settings
.scrollbar_fade_delay_ms
= 20;
1494 settings
.scrollbar_fade_duration_ms
= 20;
1495 settings
.use_pinch_zoom_scrollbars
= true;
1497 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1499 base::TimeTicks fake_now
= gfx::FrameTime::Now();
1501 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
, 1.f
, 4.f
);
1503 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_
);
1504 EXPECT_FALSE(did_request_animate_
);
1506 // If no scroll happened during a scroll gesture, it should have no effect.
1507 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
);
1508 host_impl_
->ScrollEnd();
1509 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_
);
1510 EXPECT_FALSE(did_request_animate_
);
1511 EXPECT_TRUE(scrollbar_fade_start_
.Equals(base::Closure()));
1513 // After a scroll, no fade animation should be scheduled.
1514 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
);
1515 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1516 host_impl_
->ScrollEnd();
1517 did_request_redraw_
= false;
1518 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_
);
1519 EXPECT_FALSE(did_request_animate_
);
1520 requested_scrollbar_animation_delay_
= base::TimeDelta();
1522 // We should not see any draw requests.
1523 fake_now
+= base::TimeDelta::FromMilliseconds(25);
1524 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_
);
1525 EXPECT_FALSE(did_request_animate_
);
1527 // Make page scale > min so that subsequent scrolls will trigger fades.
1528 host_impl_
->active_tree()->SetPageScaleDelta(1.1f
);
1530 // After a scroll, a fade animation should be scheduled about 20ms from now.
1531 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
);
1532 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1533 host_impl_
->ScrollEnd();
1534 did_request_redraw_
= false;
1535 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1536 requested_scrollbar_animation_delay_
);
1537 EXPECT_FALSE(did_request_animate_
);
1538 requested_scrollbar_animation_delay_
= base::TimeDelta();
1539 scrollbar_fade_start_
.Run();
1541 // After the fade begins, we should start getting redraws instead of a
1542 // scheduled animation.
1543 fake_now
+= base::TimeDelta::FromMilliseconds(25);
1544 host_impl_
->Animate(fake_now
);
1545 EXPECT_TRUE(did_request_animate_
);
1548 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1549 float device_scale_factor
) {
1550 LayerTreeSettings settings
;
1551 settings
.scrollbar_fade_delay_ms
= 500;
1552 settings
.scrollbar_fade_duration_ms
= 300;
1553 settings
.scrollbar_animator
= LayerTreeSettings::Thinning
;
1555 gfx::Size
viewport_size(300, 200);
1556 gfx::Size device_viewport_size
= gfx::ToFlooredSize(
1557 gfx::ScaleSize(viewport_size
, device_scale_factor
));
1558 gfx::Size
content_size(1000, 1000);
1560 CreateHostImpl(settings
, CreateOutputSurface());
1561 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
1562 host_impl_
->SetViewportSize(device_viewport_size
);
1564 scoped_ptr
<LayerImpl
> root
=
1565 LayerImpl::Create(host_impl_
->active_tree(), 1);
1566 root
->SetBounds(viewport_size
);
1568 scoped_ptr
<LayerImpl
> scroll
=
1569 LayerImpl::Create(host_impl_
->active_tree(), 2);
1570 scroll
->SetScrollClipLayer(root
->id());
1571 scroll
->SetScrollOffset(gfx::ScrollOffset());
1572 scroll
->SetBounds(content_size
);
1573 scroll
->SetContentBounds(content_size
);
1574 scroll
->SetIsContainerForFixedPositionLayers(true);
1576 scoped_ptr
<LayerImpl
> contents
=
1577 LayerImpl::Create(host_impl_
->active_tree(), 3);
1578 contents
->SetDrawsContent(true);
1579 contents
->SetBounds(content_size
);
1580 contents
->SetContentBounds(content_size
);
1582 // The scrollbar is on the right side.
1583 scoped_ptr
<PaintedScrollbarLayerImpl
> scrollbar
=
1584 PaintedScrollbarLayerImpl::Create(host_impl_
->active_tree(), 5, VERTICAL
);
1585 scrollbar
->SetDrawsContent(true);
1586 scrollbar
->SetBounds(gfx::Size(15, viewport_size
.height()));
1587 scrollbar
->SetContentBounds(gfx::Size(15, viewport_size
.height()));
1588 scrollbar
->SetPosition(gfx::Point(285, 0));
1590 scroll
->AddChild(contents
.Pass());
1591 root
->AddChild(scroll
.Pass());
1592 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
1593 root
->AddChild(scrollbar
.Pass());
1595 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1596 host_impl_
->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID
);
1597 host_impl_
->active_tree()->DidBecomeActive();
1600 LayerImpl
* root_scroll
=
1601 host_impl_
->active_tree()->InnerViewportScrollLayer();
1602 ASSERT_TRUE(root_scroll
->scrollbar_animation_controller());
1603 ScrollbarAnimationControllerThinning
* scrollbar_animation_controller
=
1604 static_cast<ScrollbarAnimationControllerThinning
*>(
1605 root_scroll
->scrollbar_animation_controller());
1606 scrollbar_animation_controller
->set_mouse_move_distance_for_test(100.f
);
1608 host_impl_
->MouseMoveAt(gfx::Point(1, 1));
1609 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1611 host_impl_
->MouseMoveAt(gfx::Point(200, 50));
1612 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1614 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
1615 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1617 scrollbar_animation_controller
->set_mouse_move_distance_for_test(102.f
);
1618 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
1619 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1621 did_request_redraw_
= false;
1622 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1623 host_impl_
->MouseMoveAt(gfx::Point(290, 100));
1624 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1625 host_impl_
->MouseMoveAt(gfx::Point(290, 120));
1626 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1627 host_impl_
->MouseMoveAt(gfx::Point(150, 120));
1628 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1631 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf1
) {
1632 SetupMouseMoveAtWithDeviceScale(1.f
);
1635 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf2
) {
1636 SetupMouseMoveAtWithDeviceScale(2.f
);
1639 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
1640 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1641 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1642 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
, 0.5f
, 4.f
);
1645 CompositorFrameMetadata metadata
=
1646 host_impl_
->MakeCompositorFrameMetadata();
1647 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
1648 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
1649 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.scrollable_viewport_size
);
1650 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1651 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1652 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1655 // Scrolling should update metadata immediately.
1656 EXPECT_EQ(InputHandler::ScrollStarted
,
1657 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
1658 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1660 CompositorFrameMetadata metadata
=
1661 host_impl_
->MakeCompositorFrameMetadata();
1662 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1664 host_impl_
->ScrollEnd();
1666 CompositorFrameMetadata metadata
=
1667 host_impl_
->MakeCompositorFrameMetadata();
1668 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1671 // Page scale should update metadata correctly (shrinking only the viewport).
1672 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
);
1673 host_impl_
->PinchGestureBegin();
1674 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
1675 host_impl_
->PinchGestureEnd();
1676 host_impl_
->ScrollEnd();
1678 CompositorFrameMetadata metadata
=
1679 host_impl_
->MakeCompositorFrameMetadata();
1680 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1681 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
1682 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.scrollable_viewport_size
);
1683 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1684 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1685 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1688 // Likewise if set from the main thread.
1689 host_impl_
->ProcessScrollDeltas();
1690 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(4.f
, 0.5f
, 4.f
);
1691 host_impl_
->active_tree()->SetPageScaleDelta(1.f
);
1693 CompositorFrameMetadata metadata
=
1694 host_impl_
->MakeCompositorFrameMetadata();
1695 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1696 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
1697 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.scrollable_viewport_size
);
1698 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1699 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1700 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1704 class DidDrawCheckLayer
: public LayerImpl
{
1706 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
1707 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl
, id
));
1710 virtual bool WillDraw(DrawMode draw_mode
, ResourceProvider
* provider
)
1712 will_draw_called_
= true;
1713 if (will_draw_returns_false_
)
1715 return LayerImpl::WillDraw(draw_mode
, provider
);
1718 virtual void AppendQuads(RenderPass
* render_pass
,
1719 const OcclusionTracker
<LayerImpl
>& occlusion_tracker
,
1720 AppendQuadsData
* append_quads_data
) override
{
1721 append_quads_called_
= true;
1722 LayerImpl::AppendQuads(render_pass
, occlusion_tracker
, append_quads_data
);
1725 virtual void DidDraw(ResourceProvider
* provider
) override
{
1726 did_draw_called_
= true;
1727 LayerImpl::DidDraw(provider
);
1730 bool will_draw_called() const { return will_draw_called_
; }
1731 bool append_quads_called() const { return append_quads_called_
; }
1732 bool did_draw_called() const { return did_draw_called_
; }
1734 void set_will_draw_returns_false() { will_draw_returns_false_
= true; }
1736 void ClearDidDrawCheck() {
1737 will_draw_called_
= false;
1738 append_quads_called_
= false;
1739 did_draw_called_
= false;
1743 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
1744 : LayerImpl(tree_impl
, id
),
1745 will_draw_returns_false_(false),
1746 will_draw_called_(false),
1747 append_quads_called_(false),
1748 did_draw_called_(false) {
1749 SetBounds(gfx::Size(10, 10));
1750 SetContentBounds(gfx::Size(10, 10));
1751 SetDrawsContent(true);
1752 draw_properties().visible_content_rect
= gfx::Rect(0, 0, 10, 10);
1756 bool will_draw_returns_false_
;
1757 bool will_draw_called_
;
1758 bool append_quads_called_
;
1759 bool did_draw_called_
;
1762 TEST_F(LayerTreeHostImplTest
, WillDrawReturningFalseDoesNotCall
) {
1763 // The root layer is always drawn, so run this test on a child layer that
1764 // will be masked out by the root layer's bounds.
1765 host_impl_
->active_tree()->SetRootLayer(
1766 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
1767 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
1768 host_impl_
->active_tree()->root_layer());
1770 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
1771 DidDrawCheckLayer
* layer
=
1772 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
1775 LayerTreeHostImpl::FrameData frame
;
1776 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
1777 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
1778 host_impl_
->DidDrawAllLayers(frame
);
1780 EXPECT_TRUE(layer
->will_draw_called());
1781 EXPECT_TRUE(layer
->append_quads_called());
1782 EXPECT_TRUE(layer
->did_draw_called());
1785 host_impl_
->SetViewportDamage(gfx::Rect(10, 10));
1788 LayerTreeHostImpl::FrameData frame
;
1790 layer
->set_will_draw_returns_false();
1791 layer
->ClearDidDrawCheck();
1793 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
1794 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
1795 host_impl_
->DidDrawAllLayers(frame
);
1797 EXPECT_TRUE(layer
->will_draw_called());
1798 EXPECT_FALSE(layer
->append_quads_called());
1799 EXPECT_FALSE(layer
->did_draw_called());
1803 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
1804 // The root layer is always drawn, so run this test on a child layer that
1805 // will be masked out by the root layer's bounds.
1806 host_impl_
->active_tree()->SetRootLayer(
1807 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
1808 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
1809 host_impl_
->active_tree()->root_layer());
1810 root
->SetMasksToBounds(true);
1812 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
1813 DidDrawCheckLayer
* layer
=
1814 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
1815 // Ensure visible_content_rect for layer is empty.
1816 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
1817 layer
->SetBounds(gfx::Size(10, 10));
1818 layer
->SetContentBounds(gfx::Size(10, 10));
1820 LayerTreeHostImpl::FrameData frame
;
1822 EXPECT_FALSE(layer
->will_draw_called());
1823 EXPECT_FALSE(layer
->did_draw_called());
1825 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
1826 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
1827 host_impl_
->DidDrawAllLayers(frame
);
1829 EXPECT_FALSE(layer
->will_draw_called());
1830 EXPECT_FALSE(layer
->did_draw_called());
1832 EXPECT_TRUE(layer
->visible_content_rect().IsEmpty());
1834 // Ensure visible_content_rect for layer is not empty
1835 layer
->SetPosition(gfx::PointF());
1837 EXPECT_FALSE(layer
->will_draw_called());
1838 EXPECT_FALSE(layer
->did_draw_called());
1840 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
1841 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
1842 host_impl_
->DidDrawAllLayers(frame
);
1844 EXPECT_TRUE(layer
->will_draw_called());
1845 EXPECT_TRUE(layer
->did_draw_called());
1847 EXPECT_FALSE(layer
->visible_content_rect().IsEmpty());
1850 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
1851 gfx::Size
big_size(1000, 1000);
1852 host_impl_
->SetViewportSize(big_size
);
1854 host_impl_
->active_tree()->SetRootLayer(
1855 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
1856 DidDrawCheckLayer
* root
=
1857 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1859 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
1860 DidDrawCheckLayer
* occluded_layer
=
1861 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
1863 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
1864 DidDrawCheckLayer
* top_layer
=
1865 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
1866 // This layer covers the occluded_layer above. Make this layer large so it can
1868 top_layer
->SetBounds(big_size
);
1869 top_layer
->SetContentBounds(big_size
);
1870 top_layer
->SetContentsOpaque(true);
1872 LayerTreeHostImpl::FrameData frame
;
1874 EXPECT_FALSE(occluded_layer
->will_draw_called());
1875 EXPECT_FALSE(occluded_layer
->did_draw_called());
1876 EXPECT_FALSE(top_layer
->will_draw_called());
1877 EXPECT_FALSE(top_layer
->did_draw_called());
1879 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
1880 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
1881 host_impl_
->DidDrawAllLayers(frame
);
1883 EXPECT_FALSE(occluded_layer
->will_draw_called());
1884 EXPECT_FALSE(occluded_layer
->did_draw_called());
1885 EXPECT_TRUE(top_layer
->will_draw_called());
1886 EXPECT_TRUE(top_layer
->did_draw_called());
1889 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
1890 host_impl_
->active_tree()->SetRootLayer(
1891 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
1892 DidDrawCheckLayer
* root
=
1893 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1895 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
1896 DidDrawCheckLayer
* layer1
=
1897 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
1899 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
1900 DidDrawCheckLayer
* layer2
=
1901 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
1903 layer1
->SetOpacity(0.3f
);
1904 layer1
->SetShouldFlattenTransform(true);
1906 EXPECT_FALSE(root
->did_draw_called());
1907 EXPECT_FALSE(layer1
->did_draw_called());
1908 EXPECT_FALSE(layer2
->did_draw_called());
1910 LayerTreeHostImpl::FrameData frame
;
1911 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
1912 host_impl_
->active_tree()->root_layer());
1913 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
1914 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
1915 host_impl_
->DidDrawAllLayers(frame
);
1917 EXPECT_TRUE(root
->did_draw_called());
1918 EXPECT_TRUE(layer1
->did_draw_called());
1919 EXPECT_TRUE(layer2
->did_draw_called());
1921 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
1922 EXPECT_TRUE(!!layer1
->render_surface());
1925 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
1927 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
1930 bool had_incomplete_tile
,
1932 ResourceProvider
* resource_provider
) {
1933 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl
,
1936 had_incomplete_tile
,
1938 resource_provider
));
1941 virtual void AppendQuads(RenderPass
* render_pass
,
1942 const OcclusionTracker
<LayerImpl
>& occlusion_tracker
,
1943 AppendQuadsData
* append_quads_data
) override
{
1944 LayerImpl::AppendQuads(render_pass
, occlusion_tracker
, append_quads_data
);
1945 if (had_incomplete_tile_
)
1946 append_quads_data
->num_incomplete_tiles
++;
1948 append_quads_data
->num_missing_tiles
++;
1952 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
1955 bool had_incomplete_tile
,
1957 ResourceProvider
* resource_provider
)
1958 : DidDrawCheckLayer(tree_impl
, id
),
1959 tile_missing_(tile_missing
),
1960 had_incomplete_tile_(had_incomplete_tile
) {
1962 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1966 bool had_incomplete_tile_
;
1969 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsOnDefault
) {
1970 host_impl_
->active_tree()->SetRootLayer(
1971 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
1972 DidDrawCheckLayer
* root
=
1973 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1975 bool tile_missing
= false;
1976 bool had_incomplete_tile
= false;
1977 bool is_animating
= false;
1979 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
1982 had_incomplete_tile
,
1984 host_impl_
->resource_provider()));
1986 LayerTreeHostImpl::FrameData frame
;
1988 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
1989 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
1990 host_impl_
->DidDrawAllLayers(frame
);
1993 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsWithAnimatedLayer
) {
1994 host_impl_
->active_tree()->SetRootLayer(
1995 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
1996 DidDrawCheckLayer
* root
=
1997 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1998 bool tile_missing
= false;
1999 bool had_incomplete_tile
= false;
2000 bool is_animating
= true;
2002 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
2005 had_incomplete_tile
,
2007 host_impl_
->resource_provider()));
2009 LayerTreeHostImpl::FrameData frame
;
2011 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2012 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
2013 host_impl_
->DidDrawAllLayers(frame
);
2016 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsWithMissingTiles
) {
2017 host_impl_
->active_tree()->SetRootLayer(
2018 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2019 DidDrawCheckLayer
* root
=
2020 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2022 LayerTreeHostImpl::FrameData frame
;
2023 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2024 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
2025 host_impl_
->DidDrawAllLayers(frame
);
2026 host_impl_
->SwapBuffers(frame
);
2028 bool tile_missing
= true;
2029 bool had_incomplete_tile
= false;
2030 bool is_animating
= false;
2032 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
2035 had_incomplete_tile
,
2037 host_impl_
->resource_provider()));
2038 LayerTreeHostImpl::FrameData frame2
;
2039 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame2
));
2040 host_impl_
->DrawLayers(&frame2
, gfx::FrameTime::Now());
2041 host_impl_
->DidDrawAllLayers(frame2
);
2044 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsWithIncompleteTile
) {
2045 host_impl_
->active_tree()->SetRootLayer(
2046 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2047 DidDrawCheckLayer
* root
=
2048 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2050 LayerTreeHostImpl::FrameData frame
;
2051 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2052 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
2053 host_impl_
->DidDrawAllLayers(frame
);
2054 host_impl_
->SwapBuffers(frame
);
2056 bool tile_missing
= false;
2057 bool had_incomplete_tile
= true;
2058 bool is_animating
= false;
2060 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
2063 had_incomplete_tile
,
2065 host_impl_
->resource_provider()));
2066 LayerTreeHostImpl::FrameData frame2
;
2067 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame2
));
2068 host_impl_
->DrawLayers(&frame2
, gfx::FrameTime::Now());
2069 host_impl_
->DidDrawAllLayers(frame2
);
2072 TEST_F(LayerTreeHostImplTest
,
2073 PrepareToDrawFailsWithAnimationAndMissingTilesUsesCheckerboard
) {
2074 host_impl_
->active_tree()->SetRootLayer(
2075 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 5));
2076 DidDrawCheckLayer
* root
=
2077 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2079 LayerTreeHostImpl::FrameData frame
;
2080 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2081 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
2082 host_impl_
->DidDrawAllLayers(frame
);
2083 host_impl_
->SwapBuffers(frame
);
2085 bool tile_missing
= true;
2086 bool had_incomplete_tile
= false;
2087 bool is_animating
= true;
2089 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
2092 had_incomplete_tile
,
2094 host_impl_
->resource_provider()));
2095 LayerTreeHostImpl::FrameData frame2
;
2096 EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
,
2097 host_impl_
->PrepareToDraw(&frame2
));
2098 host_impl_
->DrawLayers(&frame2
, gfx::FrameTime::Now());
2099 host_impl_
->DidDrawAllLayers(frame2
);
2102 TEST_F(LayerTreeHostImplTest
,
2103 PrepareToDrawSucceedsWithAnimationAndIncompleteTiles
) {
2104 host_impl_
->active_tree()->SetRootLayer(
2105 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 5));
2106 DidDrawCheckLayer
* root
=
2107 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2109 LayerTreeHostImpl::FrameData frame
;
2110 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2111 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
2112 host_impl_
->DidDrawAllLayers(frame
);
2113 host_impl_
->SwapBuffers(frame
);
2115 bool tile_missing
= false;
2116 bool had_incomplete_tile
= true;
2117 bool is_animating
= true;
2119 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
2122 had_incomplete_tile
,
2124 host_impl_
->resource_provider()));
2125 LayerTreeHostImpl::FrameData frame2
;
2126 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame2
));
2127 host_impl_
->DrawLayers(&frame2
, gfx::FrameTime::Now());
2128 host_impl_
->DidDrawAllLayers(frame2
);
2131 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsWhenHighResRequired
) {
2132 host_impl_
->active_tree()->SetRootLayer(
2133 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 7));
2134 DidDrawCheckLayer
* root
=
2135 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2137 LayerTreeHostImpl::FrameData frame
;
2138 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2139 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
2140 host_impl_
->DidDrawAllLayers(frame
);
2141 host_impl_
->SwapBuffers(frame
);
2143 bool tile_missing
= false;
2144 bool had_incomplete_tile
= false;
2145 bool is_animating
= false;
2147 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
2150 had_incomplete_tile
,
2152 host_impl_
->resource_provider()));
2153 host_impl_
->active_tree()->SetRequiresHighResToDraw();
2154 LayerTreeHostImpl::FrameData frame2
;
2155 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame2
));
2156 host_impl_
->DrawLayers(&frame2
, gfx::FrameTime::Now());
2157 host_impl_
->DidDrawAllLayers(frame2
);
2160 TEST_F(LayerTreeHostImplTest
,
2161 PrepareToDrawFailsWhenHighResRequiredAndIncompleteTiles
) {
2162 host_impl_
->active_tree()->SetRootLayer(
2163 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 7));
2164 DidDrawCheckLayer
* root
=
2165 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2167 LayerTreeHostImpl::FrameData frame
;
2168 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2169 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
2170 host_impl_
->DidDrawAllLayers(frame
);
2171 host_impl_
->SwapBuffers(frame
);
2173 bool tile_missing
= false;
2174 bool had_incomplete_tile
= true;
2175 bool is_animating
= false;
2177 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
2180 had_incomplete_tile
,
2182 host_impl_
->resource_provider()));
2183 host_impl_
->active_tree()->SetRequiresHighResToDraw();
2184 LayerTreeHostImpl::FrameData frame2
;
2185 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
,
2186 host_impl_
->PrepareToDraw(&frame2
));
2187 host_impl_
->DrawLayers(&frame2
, gfx::FrameTime::Now());
2188 host_impl_
->DidDrawAllLayers(frame2
);
2191 TEST_F(LayerTreeHostImplTest
,
2192 PrepareToDrawFailsWhenHighResRequiredAndMissingTile
) {
2193 host_impl_
->active_tree()->SetRootLayer(
2194 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 7));
2195 DidDrawCheckLayer
* root
=
2196 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2198 LayerTreeHostImpl::FrameData frame
;
2199 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2200 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
2201 host_impl_
->DidDrawAllLayers(frame
);
2202 host_impl_
->SwapBuffers(frame
);
2204 bool tile_missing
= true;
2205 bool had_incomplete_tile
= false;
2206 bool is_animating
= false;
2208 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
2211 had_incomplete_tile
,
2213 host_impl_
->resource_provider()));
2214 host_impl_
->active_tree()->SetRequiresHighResToDraw();
2215 LayerTreeHostImpl::FrameData frame2
;
2216 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
,
2217 host_impl_
->PrepareToDraw(&frame2
));
2218 host_impl_
->DrawLayers(&frame2
, gfx::FrameTime::Now());
2219 host_impl_
->DidDrawAllLayers(frame2
);
2222 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
2223 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2224 root
->SetScrollClipLayer(Layer::INVALID_ID
);
2225 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2228 // Scroll event is ignored because layer is not scrollable.
2229 EXPECT_EQ(InputHandler::ScrollIgnored
,
2230 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
2231 EXPECT_FALSE(did_request_redraw_
);
2232 EXPECT_FALSE(did_request_commit_
);
2235 class LayerTreeHostImplTopControlsTest
: public LayerTreeHostImplTest
{
2237 LayerTreeHostImplTopControlsTest()
2238 // Make the clip size the same as the layer (content) size so the layer is
2240 : layer_size_(10, 10),
2241 clip_size_(layer_size_
) {
2242 settings_
.calculate_top_controls_position
= true;
2243 settings_
.top_controls_height
= 50;
2246 gfx::Size(clip_size_
.width(),
2247 clip_size_
.height() + settings_
.top_controls_height
);
2250 void SetupTopControlsAndScrollLayer() {
2251 CreateHostImpl(settings_
, CreateOutputSurface());
2253 scoped_ptr
<LayerImpl
> root
=
2254 LayerImpl::Create(host_impl_
->active_tree(), 1);
2255 scoped_ptr
<LayerImpl
> root_clip
=
2256 LayerImpl::Create(host_impl_
->active_tree(), 2);
2257 root_clip
->SetBounds(clip_size_
);
2258 root
->SetScrollClipLayer(root_clip
->id());
2259 root
->SetBounds(layer_size_
);
2260 root
->SetContentBounds(layer_size_
);
2261 root
->SetPosition(gfx::PointF());
2262 root
->SetDrawsContent(false);
2263 root
->SetIsContainerForFixedPositionLayers(true);
2264 int inner_viewport_scroll_layer_id
= root
->id();
2265 int page_scale_layer_id
= root_clip
->id();
2266 root_clip
->AddChild(root
.Pass());
2267 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
2268 host_impl_
->active_tree()->SetViewportLayersFromIds(
2269 page_scale_layer_id
, inner_viewport_scroll_layer_id
, Layer::INVALID_ID
);
2270 // Set a viewport size that is large enough to contain both the top controls
2271 // and some content.
2272 host_impl_
->SetViewportSize(viewport_size_
);
2273 host_impl_
->SetTopControlsLayoutHeight(
2274 settings_
.top_controls_height
);
2275 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2276 EXPECT_EQ(clip_size_
, root_clip_ptr
->bounds());
2278 host_impl_
->CreatePendingTree();
2280 LayerImpl::Create(host_impl_
->sync_tree(), 1);
2282 LayerImpl::Create(host_impl_
->sync_tree(), 2);
2283 root_clip
->SetBounds(clip_size_
);
2284 root
->SetScrollClipLayer(root_clip
->id());
2285 root
->SetBounds(layer_size_
);
2286 root
->SetContentBounds(layer_size_
);
2287 root
->SetPosition(gfx::PointF());
2288 root
->SetDrawsContent(false);
2289 root
->SetIsContainerForFixedPositionLayers(true);
2290 inner_viewport_scroll_layer_id
= root
->id();
2291 page_scale_layer_id
= root_clip
->id();
2292 root_clip
->AddChild(root
.Pass());
2293 host_impl_
->sync_tree()->SetRootLayer(root_clip
.Pass());
2294 host_impl_
->sync_tree()->SetViewportLayersFromIds(
2295 page_scale_layer_id
, inner_viewport_scroll_layer_id
, Layer::INVALID_ID
);
2296 // Set a viewport size that is large enough to contain both the top controls
2297 // and some content.
2298 host_impl_
->SetViewportSize(viewport_size_
);
2299 host_impl_
->sync_tree()->set_top_controls_layout_height(
2300 settings_
.top_controls_height
);
2301 root_clip_ptr
= host_impl_
->sync_tree()->root_layer();
2302 EXPECT_EQ(clip_size_
, root_clip_ptr
->bounds());
2306 gfx::Size layer_size_
;
2307 gfx::Size clip_size_
;
2308 gfx::Size viewport_size_
;
2310 LayerTreeSettings settings_
;
2311 }; // class LayerTreeHostImplTopControlsTest
2313 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsByFractionalAmount
) {
2314 SetupTopControlsAndScrollLayer();
2317 EXPECT_EQ(InputHandler::ScrollStarted
,
2318 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
2320 // Make the test scroll delta a fractional amount, to verify that the
2321 // fixed container size delta is (1) non-zero, and (2) fractional, and
2322 // (3) matches the movement of the top controls.
2323 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.25f
);
2324 host_impl_
->top_controls_manager()->ScrollBegin();
2325 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2326 host_impl_
->top_controls_manager()->ScrollEnd();
2328 LayerImpl
* inner_viewport_scroll_layer
=
2329 host_impl_
->active_tree()->InnerViewportScrollLayer();
2330 DCHECK(inner_viewport_scroll_layer
);
2331 host_impl_
->ScrollEnd();
2332 EXPECT_EQ(top_controls_scroll_delta
,
2333 inner_viewport_scroll_layer
->FixedContainerSizeDelta());
2336 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsWithPageScale
) {
2337 SetupTopControlsAndScrollLayer();
2340 EXPECT_EQ(InputHandler::ScrollStarted
,
2341 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
2343 float page_scale
= 1.5f
;
2344 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(page_scale
, 1.f
, 2.f
);
2346 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.f
);
2347 gfx::Vector2dF expected_container_size_delta
=
2348 ScaleVector2d(top_controls_scroll_delta
, 1.f
/ page_scale
);
2349 host_impl_
->top_controls_manager()->ScrollBegin();
2350 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2351 host_impl_
->top_controls_manager()->ScrollEnd();
2353 LayerImpl
* inner_viewport_scroll_layer
=
2354 host_impl_
->active_tree()->InnerViewportScrollLayer();
2355 DCHECK(inner_viewport_scroll_layer
);
2356 host_impl_
->ScrollEnd();
2358 // Use a tolerance that requires the container size delta to be within 0.01
2360 double tolerance
= 0.0001;
2362 (expected_container_size_delta
-
2363 inner_viewport_scroll_layer
->FixedContainerSizeDelta()).LengthSquared(),
2367 // Ensure setting the top controls position explicitly using the setters on the
2368 // TreeImpl correctly affects the top controls manager and viewport bounds.
2369 TEST_F(LayerTreeHostImplTopControlsTest
, PositionTopControlsExplicitly
) {
2370 SetupTopControlsAndScrollLayer();
2373 host_impl_
->active_tree()->set_top_controls_delta(0.f
);
2374 host_impl_
->active_tree()->set_top_controls_content_offset(30.f
);
2375 EXPECT_EQ(30.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2376 EXPECT_EQ(-20.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
2378 host_impl_
->active_tree()->set_top_controls_delta(-30.f
);
2379 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2380 EXPECT_EQ(-50.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
2382 host_impl_
->DidChangeTopControlsPosition();
2384 // Now that top controls have moved, expect the clip to resize.
2385 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2386 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2389 // Test that the top_controls delta and sent delta are appropriately
2390 // applied on sync tree activation. The total top controls offset shouldn't
2391 // change after the activation.
2392 TEST_F(LayerTreeHostImplTopControlsTest
, ApplyDeltaOnTreeActivation
) {
2393 SetupTopControlsAndScrollLayer();
2396 host_impl_
->sync_tree()->set_top_controls_content_offset(15.f
);
2398 host_impl_
->active_tree()->set_top_controls_content_offset(20.f
);
2399 host_impl_
->active_tree()->set_top_controls_delta(-20.f
);
2400 host_impl_
->active_tree()->set_sent_top_controls_delta(-5.f
);
2402 host_impl_
->DidChangeTopControlsPosition();
2403 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2404 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2405 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2407 host_impl_
->active_tree()->total_top_controls_content_offset());
2409 host_impl_
->ActivateSyncTree();
2411 root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2412 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2413 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2415 EXPECT_EQ(0.f
, host_impl_
->active_tree()->sent_top_controls_delta());
2416 EXPECT_EQ(-15.f
, host_impl_
->active_tree()->top_controls_delta());
2417 EXPECT_EQ(15.f
, host_impl_
->active_tree()->top_controls_content_offset());
2419 host_impl_
->active_tree()->total_top_controls_content_offset());
2422 // Test that changing the top controls layout height is correctly applied to
2423 // the inner viewport container bounds. That is, the top controls layout
2424 // height is the amount that the inner viewport container was shrunk outside
2425 // the compositor to accommodate the top controls.
2426 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsLayoutHeightChanged
) {
2427 SetupTopControlsAndScrollLayer();
2430 host_impl_
->sync_tree()->set_top_controls_content_offset(15.f
);
2431 host_impl_
->sync_tree()->set_top_controls_layout_height(15.f
);
2433 host_impl_
->active_tree()->set_top_controls_content_offset(20.f
);
2434 host_impl_
->active_tree()->set_top_controls_delta(-20.f
);
2435 host_impl_
->active_tree()->set_sent_top_controls_delta(-5.f
);
2437 host_impl_
->DidChangeTopControlsPosition();
2438 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2439 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2440 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2442 host_impl_
->sync_tree()->root_layer()->SetBounds(
2443 gfx::Size(root_clip_ptr
->bounds().width(),
2444 root_clip_ptr
->bounds().height() - 15.f
));
2446 host_impl_
->ActivateSyncTree();
2448 root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2449 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2451 // The total bounds should remain unchanged since the bounds delta should
2452 // account for the difference between the layout height and the current
2453 // top controls offset.
2454 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2455 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 15.f
), root_clip_ptr
->bounds_delta());
2457 host_impl_
->active_tree()->set_top_controls_delta(0.f
);
2458 host_impl_
->DidChangeTopControlsPosition();
2460 EXPECT_EQ(15.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2461 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 0.f
), root_clip_ptr
->bounds_delta());
2462 EXPECT_EQ(gfx::Size(viewport_size_
.width(), viewport_size_
.height()-15.f
),
2463 root_clip_ptr
->bounds());
2466 TEST_F(LayerTreeHostImplTopControlsTest
,
2467 ScrollNonScrollableRootWithTopControls
) {
2468 SetupTopControlsAndScrollLayer();
2471 EXPECT_EQ(InputHandler::ScrollStarted
,
2472 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
2474 host_impl_
->top_controls_manager()->ScrollBegin();
2475 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
2476 host_impl_
->top_controls_manager()->ScrollEnd();
2477 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2478 // Now that top controls have moved, expect the clip to resize.
2479 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2480 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2482 host_impl_
->ScrollEnd();
2484 EXPECT_EQ(InputHandler::ScrollStarted
,
2485 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
2487 float scroll_increment_y
= -25.f
;
2488 host_impl_
->top_controls_manager()->ScrollBegin();
2489 host_impl_
->top_controls_manager()->ScrollBy(
2490 gfx::Vector2dF(0.f
, scroll_increment_y
));
2491 EXPECT_EQ(-scroll_increment_y
,
2492 host_impl_
->top_controls_manager()->ContentTopOffset());
2493 // Now that top controls have moved, expect the clip to resize.
2494 EXPECT_EQ(gfx::Size(viewport_size_
.width(),
2495 viewport_size_
.height() + scroll_increment_y
),
2496 root_clip_ptr
->bounds());
2498 host_impl_
->top_controls_manager()->ScrollBy(
2499 gfx::Vector2dF(0.f
, scroll_increment_y
));
2500 host_impl_
->top_controls_manager()->ScrollEnd();
2501 EXPECT_EQ(-2 * scroll_increment_y
,
2502 host_impl_
->top_controls_manager()->ContentTopOffset());
2503 // Now that top controls have moved, expect the clip to resize.
2504 EXPECT_EQ(clip_size_
, root_clip_ptr
->bounds());
2506 host_impl_
->ScrollEnd();
2508 // Verify the layer is once-again non-scrollable.
2510 gfx::ScrollOffset(),
2511 host_impl_
->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
2513 EXPECT_EQ(InputHandler::ScrollStarted
,
2514 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
2517 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
2518 // Test the configuration where a non-composited root layer is embedded in a
2519 // scrollable outer layer.
2520 gfx::Size
surface_size(10, 10);
2521 gfx::Size
contents_size(20, 20);
2523 scoped_ptr
<LayerImpl
> content_layer
=
2524 LayerImpl::Create(host_impl_
->active_tree(), 1);
2525 content_layer
->SetDrawsContent(true);
2526 content_layer
->SetPosition(gfx::PointF());
2527 content_layer
->SetBounds(contents_size
);
2528 content_layer
->SetContentBounds(contents_size
);
2529 content_layer
->SetContentsScale(2.f
, 2.f
);
2531 scoped_ptr
<LayerImpl
> scroll_clip_layer
=
2532 LayerImpl::Create(host_impl_
->active_tree(), 3);
2533 scroll_clip_layer
->SetBounds(surface_size
);
2535 scoped_ptr
<LayerImpl
> scroll_layer
=
2536 LayerImpl::Create(host_impl_
->active_tree(), 2);
2537 scroll_layer
->SetScrollClipLayer(3);
2538 scroll_layer
->SetBounds(contents_size
);
2539 scroll_layer
->SetContentBounds(contents_size
);
2540 scroll_layer
->SetPosition(gfx::PointF());
2541 scroll_layer
->AddChild(content_layer
.Pass());
2542 scroll_clip_layer
->AddChild(scroll_layer
.Pass());
2544 host_impl_
->active_tree()->SetRootLayer(scroll_clip_layer
.Pass());
2545 host_impl_
->SetViewportSize(surface_size
);
2548 EXPECT_EQ(InputHandler::ScrollStarted
,
2549 host_impl_
->ScrollBegin(gfx::Point(5, 5),
2550 InputHandler::Wheel
));
2551 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2552 host_impl_
->ScrollEnd();
2553 EXPECT_TRUE(did_request_redraw_
);
2554 EXPECT_TRUE(did_request_commit_
);
2557 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
2558 gfx::Size
surface_size(10, 10);
2559 gfx::Size
contents_size(20, 20);
2560 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2561 root
->SetBounds(surface_size
);
2562 root
->SetContentBounds(contents_size
);
2563 root
->AddChild(CreateScrollableLayer(2, contents_size
, root
.get()));
2564 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2565 host_impl_
->SetViewportSize(surface_size
);
2568 EXPECT_EQ(InputHandler::ScrollStarted
,
2569 host_impl_
->ScrollBegin(gfx::Point(5, 5),
2570 InputHandler::Wheel
));
2571 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2572 host_impl_
->ScrollEnd();
2573 EXPECT_TRUE(did_request_redraw_
);
2574 EXPECT_TRUE(did_request_commit_
);
2577 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
2578 gfx::Size
surface_size(10, 10);
2579 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2580 root
->AddChild(CreateScrollableLayer(2, surface_size
, root
.get()));
2581 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2582 host_impl_
->SetViewportSize(surface_size
);
2585 // Scroll event is ignored because the input coordinate is outside the layer
2587 EXPECT_EQ(InputHandler::ScrollIgnored
,
2588 host_impl_
->ScrollBegin(gfx::Point(15, 5),
2589 InputHandler::Wheel
));
2590 EXPECT_FALSE(did_request_redraw_
);
2591 EXPECT_FALSE(did_request_commit_
);
2594 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
2595 gfx::Size
surface_size(10, 10);
2596 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2597 scoped_ptr
<LayerImpl
> child
=
2598 CreateScrollableLayer(2, surface_size
, root
.get());
2599 host_impl_
->SetViewportSize(surface_size
);
2601 gfx::Transform matrix
;
2602 matrix
.RotateAboutXAxis(180.0);
2603 child
->SetTransform(matrix
);
2604 child
->SetDoubleSided(false);
2606 root
->AddChild(child
.Pass());
2607 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2610 // Scroll event is ignored because the scrollable layer is not facing the
2611 // viewer and there is nothing scrollable behind it.
2612 EXPECT_EQ(InputHandler::ScrollIgnored
,
2613 host_impl_
->ScrollBegin(gfx::Point(5, 5),
2614 InputHandler::Wheel
));
2615 EXPECT_FALSE(did_request_redraw_
);
2616 EXPECT_FALSE(did_request_commit_
);
2619 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
2620 gfx::Size
surface_size(10, 10);
2621 scoped_ptr
<LayerImpl
> clip_layer
=
2622 LayerImpl::Create(host_impl_
->active_tree(), 3);
2623 scoped_ptr
<LayerImpl
> content_layer
=
2624 CreateScrollableLayer(1, surface_size
, clip_layer
.get());
2625 content_layer
->SetShouldScrollOnMainThread(true);
2626 content_layer
->SetScrollClipLayer(Layer::INVALID_ID
);
2628 // Note: we can use the same clip layer for both since both calls to
2629 // CreateScrollableLayer() use the same surface size.
2630 scoped_ptr
<LayerImpl
> scroll_layer
=
2631 CreateScrollableLayer(2, surface_size
, clip_layer
.get());
2632 scroll_layer
->AddChild(content_layer
.Pass());
2633 clip_layer
->AddChild(scroll_layer
.Pass());
2635 host_impl_
->active_tree()->SetRootLayer(clip_layer
.Pass());
2636 host_impl_
->SetViewportSize(surface_size
);
2639 // Scrolling fails because the content layer is asking to be scrolled on the
2641 EXPECT_EQ(InputHandler::ScrollOnMainThread
,
2642 host_impl_
->ScrollBegin(gfx::Point(5, 5),
2643 InputHandler::Wheel
));
2646 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
2647 gfx::Size
surface_size(20, 20);
2648 gfx::Size
viewport_size(10, 10);
2649 float page_scale
= 2.f
;
2650 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2651 scoped_ptr
<LayerImpl
> root_clip
=
2652 LayerImpl::Create(host_impl_
->active_tree(), 2);
2653 scoped_ptr
<LayerImpl
> root_scrolling
=
2654 CreateScrollableLayer(3, surface_size
, root_clip
.get());
2655 EXPECT_EQ(viewport_size
, root_clip
->bounds());
2656 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
2657 root_clip
->AddChild(root_scrolling
.Pass());
2658 root
->AddChild(root_clip
.Pass());
2659 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2660 // The behaviour in this test assumes the page scale is applied at a layer
2661 // above the clip layer.
2662 host_impl_
->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID
);
2663 host_impl_
->active_tree()->DidBecomeActive();
2664 host_impl_
->SetViewportSize(viewport_size
);
2667 LayerImpl
* root_scroll
=
2668 host_impl_
->active_tree()->InnerViewportScrollLayer();
2669 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
2671 gfx::Vector2d
scroll_delta(0, 10);
2672 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
2673 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
2674 EXPECT_EQ(InputHandler::ScrollStarted
,
2675 host_impl_
->ScrollBegin(gfx::Point(5, 5),
2676 InputHandler::Wheel
));
2677 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2678 host_impl_
->ScrollEnd();
2680 // Set new page scale from main thread.
2681 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(page_scale
,
2685 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
2686 ExpectContains(*scroll_info
.get(), root_scroll
->id(), expected_scroll_delta
);
2688 // The scroll range should also have been updated.
2689 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
2691 // The page scale delta remains constant because the impl thread did not
2693 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
2696 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
2697 gfx::Size
surface_size(20, 20);
2698 gfx::Size
viewport_size(10, 10);
2699 float page_scale
= 2.f
;
2700 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2701 scoped_ptr
<LayerImpl
> root_clip
=
2702 LayerImpl::Create(host_impl_
->active_tree(), 2);
2703 scoped_ptr
<LayerImpl
> root_scrolling
=
2704 CreateScrollableLayer(3, surface_size
, root_clip
.get());
2705 EXPECT_EQ(viewport_size
, root_clip
->bounds());
2706 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
2707 root_clip
->AddChild(root_scrolling
.Pass());
2708 root
->AddChild(root_clip
.Pass());
2709 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2710 // The behaviour in this test assumes the page scale is applied at a layer
2711 // above the clip layer.
2712 host_impl_
->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID
);
2713 host_impl_
->active_tree()->DidBecomeActive();
2714 host_impl_
->SetViewportSize(viewport_size
);
2715 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
, 1.f
, page_scale
);
2718 LayerImpl
* root_scroll
=
2719 host_impl_
->active_tree()->InnerViewportScrollLayer();
2720 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
2722 gfx::Vector2d
scroll_delta(0, 10);
2723 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
2724 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
2725 EXPECT_EQ(InputHandler::ScrollStarted
,
2726 host_impl_
->ScrollBegin(gfx::Point(5, 5),
2727 InputHandler::Wheel
));
2728 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2729 host_impl_
->ScrollEnd();
2731 // Set new page scale on impl thread by pinching.
2732 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
);
2733 host_impl_
->PinchGestureBegin();
2734 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
2735 host_impl_
->PinchGestureEnd();
2736 host_impl_
->ScrollEnd();
2739 // The scroll delta is not scaled because the main thread did not scale.
2740 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
2741 ExpectContains(*scroll_info
.get(), root_scroll
->id(), expected_scroll_delta
);
2743 // The scroll range should also have been updated.
2744 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
2746 // The page scale delta should match the new scale on the impl side.
2747 EXPECT_EQ(page_scale
, host_impl_
->active_tree()->total_page_scale_factor());
2750 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
2751 gfx::Size
surface_size(10, 10);
2752 float default_page_scale
= 1.f
;
2753 gfx::Transform default_page_scale_matrix
;
2754 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
2756 float new_page_scale
= 2.f
;
2757 gfx::Transform new_page_scale_matrix
;
2758 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
2760 // Create a normal scrollable root layer and another scrollable child layer.
2761 LayerImpl
* scroll
= SetupScrollAndContentsLayers(surface_size
);
2762 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
2763 LayerImpl
* child
= scroll
->children()[0];
2765 scoped_ptr
<LayerImpl
> scrollable_child_clip
=
2766 LayerImpl::Create(host_impl_
->active_tree(), 6);
2767 scoped_ptr
<LayerImpl
> scrollable_child
=
2768 CreateScrollableLayer(7, surface_size
, scrollable_child_clip
.get());
2769 scrollable_child_clip
->AddChild(scrollable_child
.Pass());
2770 child
->AddChild(scrollable_child_clip
.Pass());
2771 LayerImpl
* grand_child
= child
->children()[0];
2773 // Set new page scale on impl thread by pinching.
2774 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
);
2775 host_impl_
->PinchGestureBegin();
2776 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
2777 host_impl_
->PinchGestureEnd();
2778 host_impl_
->ScrollEnd();
2781 EXPECT_EQ(1.f
, root
->contents_scale_x());
2782 EXPECT_EQ(1.f
, root
->contents_scale_y());
2783 EXPECT_EQ(1.f
, scroll
->contents_scale_x());
2784 EXPECT_EQ(1.f
, scroll
->contents_scale_y());
2785 EXPECT_EQ(1.f
, child
->contents_scale_x());
2786 EXPECT_EQ(1.f
, child
->contents_scale_y());
2787 EXPECT_EQ(1.f
, grand_child
->contents_scale_x());
2788 EXPECT_EQ(1.f
, grand_child
->contents_scale_y());
2790 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
2791 // the page scale delta on the root layer is applied hierarchically.
2792 LayerTreeHostImpl::FrameData frame
;
2793 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2794 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
2795 host_impl_
->DidDrawAllLayers(frame
);
2797 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(0, 0));
2798 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(1, 1));
2799 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(0, 0));
2800 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(1, 1));
2801 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
2802 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
2803 EXPECT_EQ(new_page_scale
,
2804 grand_child
->draw_transform().matrix().getDouble(0, 0));
2805 EXPECT_EQ(new_page_scale
,
2806 grand_child
->draw_transform().matrix().getDouble(1, 1));
2809 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
2810 gfx::Size
surface_size(30, 30);
2811 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2812 root
->SetBounds(gfx::Size(5, 5));
2813 scoped_ptr
<LayerImpl
> root_scrolling
=
2814 LayerImpl::Create(host_impl_
->active_tree(), 2);
2815 root_scrolling
->SetBounds(surface_size
);
2816 root_scrolling
->SetContentBounds(surface_size
);
2817 root_scrolling
->SetScrollClipLayer(root
->id());
2818 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
2819 LayerImpl
* root_scrolling_ptr
= root_scrolling
.get();
2820 root
->AddChild(root_scrolling
.Pass());
2821 int child_scroll_layer_id
= 3;
2822 scoped_ptr
<LayerImpl
> child_scrolling
= CreateScrollableLayer(
2823 child_scroll_layer_id
, surface_size
, root_scrolling_ptr
);
2824 LayerImpl
* child
= child_scrolling
.get();
2825 root_scrolling_ptr
->AddChild(child_scrolling
.Pass());
2826 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2827 host_impl_
->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID
);
2828 host_impl_
->active_tree()->DidBecomeActive();
2829 host_impl_
->SetViewportSize(surface_size
);
2832 gfx::Vector2d
scroll_delta(0, 10);
2833 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
2834 gfx::ScrollOffset
expected_max_scroll(child
->MaxScrollOffset());
2835 EXPECT_EQ(InputHandler::ScrollStarted
,
2836 host_impl_
->ScrollBegin(gfx::Point(5, 5),
2837 InputHandler::Wheel
));
2838 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2839 host_impl_
->ScrollEnd();
2841 float page_scale
= 2.f
;
2842 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(page_scale
,
2848 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
2850 *scroll_info
.get(), child_scroll_layer_id
, expected_scroll_delta
);
2852 // The scroll range should not have changed.
2853 EXPECT_EQ(child
->MaxScrollOffset(), expected_max_scroll
);
2855 // The page scale delta remains constant because the impl thread did not
2857 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
2860 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
2861 // Scroll a child layer beyond its maximum scroll range and make sure the
2862 // parent layer is scrolled on the axis on which the child was unable to
2864 gfx::Size
surface_size(10, 10);
2865 gfx::Size
content_size(20, 20);
2866 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2867 root
->SetBounds(surface_size
);
2869 scoped_ptr
<LayerImpl
> grand_child
=
2870 CreateScrollableLayer(3, content_size
, root
.get());
2872 scoped_ptr
<LayerImpl
> child
=
2873 CreateScrollableLayer(2, content_size
, root
.get());
2874 LayerImpl
* grand_child_layer
= grand_child
.get();
2875 child
->AddChild(grand_child
.Pass());
2877 LayerImpl
* child_layer
= child
.get();
2878 root
->AddChild(child
.Pass());
2879 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2880 host_impl_
->active_tree()->DidBecomeActive();
2881 host_impl_
->SetViewportSize(surface_size
);
2882 grand_child_layer
->SetScrollOffset(gfx::ScrollOffset(0, 5));
2883 child_layer
->SetScrollOffset(gfx::ScrollOffset(3, 0));
2887 gfx::Vector2d
scroll_delta(-8, -7);
2888 EXPECT_EQ(InputHandler::ScrollStarted
,
2889 host_impl_
->ScrollBegin(gfx::Point(),
2890 InputHandler::Wheel
));
2891 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2892 host_impl_
->ScrollEnd();
2894 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
2895 host_impl_
->ProcessScrollDeltas();
2897 // The grand child should have scrolled up to its limit.
2898 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
2899 LayerImpl
* grand_child
= child
->children()[0];
2900 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -5));
2902 // The child should have only scrolled on the other axis.
2903 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(-3, 0));
2907 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
2908 // Scroll a child layer beyond its maximum scroll range and make sure the
2909 // the scroll doesn't bubble up to the parent layer.
2910 gfx::Size
surface_size(20, 20);
2911 gfx::Size
viewport_size(10, 10);
2912 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2913 scoped_ptr
<LayerImpl
> root_scrolling
=
2914 CreateScrollableLayer(2, surface_size
, root
.get());
2915 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
2917 scoped_ptr
<LayerImpl
> grand_child
=
2918 CreateScrollableLayer(4, surface_size
, root
.get());
2920 scoped_ptr
<LayerImpl
> child
=
2921 CreateScrollableLayer(3, surface_size
, root
.get());
2922 LayerImpl
* grand_child_layer
= grand_child
.get();
2923 child
->AddChild(grand_child
.Pass());
2925 LayerImpl
* child_layer
= child
.get();
2926 root_scrolling
->AddChild(child
.Pass());
2927 root
->AddChild(root_scrolling
.Pass());
2928 EXPECT_EQ(viewport_size
, root
->bounds());
2929 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2930 host_impl_
->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID
);
2931 host_impl_
->active_tree()->DidBecomeActive();
2932 host_impl_
->SetViewportSize(viewport_size
);
2934 grand_child_layer
->SetScrollOffset(gfx::ScrollOffset(0, 2));
2935 child_layer
->SetScrollOffset(gfx::ScrollOffset(0, 3));
2939 gfx::Vector2d
scroll_delta(0, -10);
2940 EXPECT_EQ(InputHandler::ScrollStarted
,
2941 host_impl_
->ScrollBegin(gfx::Point(),
2942 InputHandler::NonBubblingGesture
));
2943 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2944 host_impl_
->ScrollEnd();
2946 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
2947 host_impl_
->ProcessScrollDeltas();
2949 // The grand child should have scrolled up to its limit.
2951 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
2952 LayerImpl
* grand_child
= child
->children()[0];
2953 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -2));
2955 // The child should not have scrolled.
2956 ExpectNone(*scroll_info
.get(), child
->id());
2958 // The next time we scroll we should only scroll the parent.
2959 scroll_delta
= gfx::Vector2d(0, -3);
2960 EXPECT_EQ(InputHandler::ScrollStarted
,
2961 host_impl_
->ScrollBegin(gfx::Point(5, 5),
2962 InputHandler::NonBubblingGesture
));
2963 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
2964 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2965 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
2966 host_impl_
->ScrollEnd();
2968 scroll_info
= host_impl_
->ProcessScrollDeltas();
2970 // The child should have scrolled up to its limit.
2971 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(0, -3));
2973 // The grand child should not have scrolled.
2974 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -2));
2976 // After scrolling the parent, another scroll on the opposite direction
2977 // should still scroll the child.
2978 scroll_delta
= gfx::Vector2d(0, 7);
2979 EXPECT_EQ(InputHandler::ScrollStarted
,
2980 host_impl_
->ScrollBegin(gfx::Point(5, 5),
2981 InputHandler::NonBubblingGesture
));
2982 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
2983 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2984 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
2985 host_impl_
->ScrollEnd();
2987 scroll_info
= host_impl_
->ProcessScrollDeltas();
2989 // The grand child should have scrolled.
2990 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, 5));
2992 // The child should not have scrolled.
2993 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(0, -3));
2996 // Scrolling should be adjusted from viewport space.
2997 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(2.f
, 2.f
, 2.f
);
2998 host_impl_
->active_tree()->SetPageScaleDelta(1.f
);
3000 scroll_delta
= gfx::Vector2d(0, -2);
3001 EXPECT_EQ(InputHandler::ScrollStarted
,
3002 host_impl_
->ScrollBegin(gfx::Point(1, 1),
3003 InputHandler::NonBubblingGesture
));
3004 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
3005 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3006 host_impl_
->ScrollEnd();
3008 scroll_info
= host_impl_
->ProcessScrollDeltas();
3010 // Should have scrolled by half the amount in layer space (5 - 2/2)
3011 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, 4));
3014 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
3015 // When we try to scroll a non-scrollable child layer, the scroll delta
3016 // should be applied to one of its ancestors if possible.
3017 gfx::Size
surface_size(10, 10);
3018 gfx::Size
content_size(20, 20);
3019 scoped_ptr
<LayerImpl
> root_clip
=
3020 LayerImpl::Create(host_impl_
->active_tree(), 3);
3021 scoped_ptr
<LayerImpl
> root
=
3022 CreateScrollableLayer(1, content_size
, root_clip
.get());
3023 // Make 'root' the clip layer for child: since they have the same sizes the
3024 // child will have zero max_scroll_offset and scrolls will bubble.
3025 scoped_ptr
<LayerImpl
> child
=
3026 CreateScrollableLayer(2, content_size
, root
.get());
3027 child
->SetIsContainerForFixedPositionLayers(true);
3028 root
->SetBounds(content_size
);
3030 int root_scroll_id
= root
->id();
3031 root
->AddChild(child
.Pass());
3032 root_clip
->AddChild(root
.Pass());
3034 host_impl_
->SetViewportSize(surface_size
);
3035 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3036 host_impl_
->active_tree()->SetViewportLayersFromIds(3, 2, Layer::INVALID_ID
);
3037 host_impl_
->active_tree()->DidBecomeActive();
3040 gfx::Vector2d
scroll_delta(0, 4);
3041 EXPECT_EQ(InputHandler::ScrollStarted
,
3042 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3043 InputHandler::Wheel
));
3044 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3045 host_impl_
->ScrollEnd();
3047 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3048 host_impl_
->ProcessScrollDeltas();
3050 // Only the root scroll should have scrolled.
3051 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
3052 ExpectContains(*scroll_info
.get(), root_scroll_id
, scroll_delta
);
3056 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
3057 gfx::Size
surface_size(10, 10);
3058 scoped_ptr
<LayerImpl
> root_clip
=
3059 LayerImpl::Create(host_impl_
->active_tree(), 1);
3060 scoped_ptr
<LayerImpl
> root_scroll
=
3061 CreateScrollableLayer(2, surface_size
, root_clip
.get());
3062 root_scroll
->SetIsContainerForFixedPositionLayers(true);
3063 root_clip
->AddChild(root_scroll
.Pass());
3064 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3065 host_impl_
->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID
);
3066 host_impl_
->active_tree()->DidBecomeActive();
3067 host_impl_
->SetViewportSize(surface_size
);
3069 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3072 host_impl_
->active_tree()->DetachLayerTree();
3073 scoped_ptr
<LayerImpl
> root_clip2
=
3074 LayerImpl::Create(host_impl_
->active_tree(), 3);
3075 scoped_ptr
<LayerImpl
> root_scroll2
=
3076 CreateScrollableLayer(4, surface_size
, root_clip2
.get());
3077 root_scroll2
->SetIsContainerForFixedPositionLayers(true);
3078 root_clip2
->AddChild(root_scroll2
.Pass());
3079 host_impl_
->active_tree()->SetRootLayer(root_clip2
.Pass());
3080 host_impl_
->active_tree()->SetViewportLayersFromIds(3, 4, Layer::INVALID_ID
);
3081 host_impl_
->active_tree()->DidBecomeActive();
3083 // Scrolling should still work even though we did not draw yet.
3084 EXPECT_EQ(InputHandler::ScrollStarted
,
3085 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3086 InputHandler::Wheel
));
3089 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
3090 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3092 // Rotate the root layer 90 degrees counter-clockwise about its center.
3093 gfx::Transform rotate_transform
;
3094 rotate_transform
.Rotate(-90.0);
3095 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
3097 gfx::Size
surface_size(50, 50);
3098 host_impl_
->SetViewportSize(surface_size
);
3101 // Scroll to the right in screen coordinates with a gesture.
3102 gfx::Vector2d
gesture_scroll_delta(10, 0);
3103 EXPECT_EQ(InputHandler::ScrollStarted
,
3104 host_impl_
->ScrollBegin(gfx::Point(),
3105 InputHandler::Gesture
));
3106 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3107 host_impl_
->ScrollEnd();
3109 // The layer should have scrolled down in its local coordinates.
3110 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3111 ExpectContains(*scroll_info
.get(),
3113 gfx::Vector2d(0, gesture_scroll_delta
.x()));
3115 // Reset and scroll down with the wheel.
3116 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
3117 gfx::Vector2d
wheel_scroll_delta(0, 10);
3118 EXPECT_EQ(InputHandler::ScrollStarted
,
3119 host_impl_
->ScrollBegin(gfx::Point(),
3120 InputHandler::Wheel
));
3121 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
3122 host_impl_
->ScrollEnd();
3124 // The layer should have scrolled down in its local coordinates.
3125 scroll_info
= host_impl_
->ProcessScrollDeltas();
3126 ExpectContains(*scroll_info
.get(),
3128 wheel_scroll_delta
);
3131 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
3132 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3133 int child_clip_layer_id
= 6;
3134 int child_layer_id
= 7;
3135 float child_layer_angle
= -20.f
;
3137 // Create a child layer that is rotated to a non-axis-aligned angle.
3138 scoped_ptr
<LayerImpl
> clip_layer
=
3139 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
3140 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
3141 child_layer_id
, scroll_layer
->content_bounds(), clip_layer
.get());
3142 gfx::Transform rotate_transform
;
3143 rotate_transform
.Translate(-50.0, -50.0);
3144 rotate_transform
.Rotate(child_layer_angle
);
3145 rotate_transform
.Translate(50.0, 50.0);
3146 clip_layer
->SetTransform(rotate_transform
);
3148 // Only allow vertical scrolling.
3149 clip_layer
->SetBounds(
3150 gfx::Size(child
->bounds().width(), child
->bounds().height() / 2));
3151 // The rotation depends on the layer's transform origin, and the child layer
3152 // is a different size than the clip, so make sure the clip layer's origin
3153 // lines up over the child.
3154 clip_layer
->SetTransformOrigin(gfx::Point3F(
3155 clip_layer
->bounds().width() * 0.5f
, clip_layer
->bounds().height(), 0.f
));
3156 LayerImpl
* child_ptr
= child
.get();
3157 clip_layer
->AddChild(child
.Pass());
3158 scroll_layer
->AddChild(clip_layer
.Pass());
3160 gfx::Size
surface_size(50, 50);
3161 host_impl_
->SetViewportSize(surface_size
);
3164 // Scroll down in screen coordinates with a gesture.
3165 gfx::Vector2d
gesture_scroll_delta(0, 10);
3166 EXPECT_EQ(InputHandler::ScrollStarted
,
3167 host_impl_
->ScrollBegin(gfx::Point(1, 1),
3168 InputHandler::Gesture
));
3169 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3170 host_impl_
->ScrollEnd();
3172 // The child layer should have scrolled down in its local coordinates an
3173 // amount proportional to the angle between it and the input scroll delta.
3174 gfx::Vector2d
expected_scroll_delta(
3176 gesture_scroll_delta
.y() *
3177 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
3178 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3179 host_impl_
->ProcessScrollDeltas();
3180 ExpectContains(*scroll_info
.get(), child_layer_id
, expected_scroll_delta
);
3182 // The root scroll layer should not have scrolled, because the input delta
3183 // was close to the layer's axis of movement.
3184 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
3187 // Now reset and scroll the same amount horizontally.
3188 child_ptr
->SetScrollDelta(gfx::Vector2dF());
3189 gfx::Vector2d
gesture_scroll_delta(10, 0);
3190 EXPECT_EQ(InputHandler::ScrollStarted
,
3191 host_impl_
->ScrollBegin(gfx::Point(1, 1),
3192 InputHandler::Gesture
));
3193 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3194 host_impl_
->ScrollEnd();
3196 // The child layer should have scrolled down in its local coordinates an
3197 // amount proportional to the angle between it and the input scroll delta.
3198 gfx::Vector2d
expected_scroll_delta(
3200 -gesture_scroll_delta
.x() *
3201 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
3202 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3203 host_impl_
->ProcessScrollDeltas();
3204 ExpectContains(*scroll_info
.get(), child_layer_id
, expected_scroll_delta
);
3206 // The root scroll layer should have scrolled more, since the input scroll
3207 // delta was mostly orthogonal to the child layer's vertical scroll axis.
3208 gfx::Vector2d
expected_root_scroll_delta(
3209 gesture_scroll_delta
.x() *
3210 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
3212 ExpectContains(*scroll_info
.get(),
3214 expected_root_scroll_delta
);
3218 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
3219 LayerImpl
* scroll_layer
=
3220 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3222 // Scale the layer to twice its normal size.
3224 gfx::Transform scale_transform
;
3225 scale_transform
.Scale(scale
, scale
);
3226 scroll_layer
->SetTransform(scale_transform
);
3228 gfx::Size
surface_size(50, 50);
3229 host_impl_
->SetViewportSize(surface_size
);
3232 // Scroll down in screen coordinates with a gesture.
3233 gfx::Vector2d
scroll_delta(0, 10);
3234 EXPECT_EQ(InputHandler::ScrollStarted
,
3235 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
3236 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3237 host_impl_
->ScrollEnd();
3239 // The layer should have scrolled down in its local coordinates, but half the
3241 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3242 ExpectContains(*scroll_info
.get(),
3244 gfx::Vector2d(0, scroll_delta
.y() / scale
));
3246 // Reset and scroll down with the wheel.
3247 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
3248 gfx::Vector2d
wheel_scroll_delta(0, 10);
3249 EXPECT_EQ(InputHandler::ScrollStarted
,
3250 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
3251 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
3252 host_impl_
->ScrollEnd();
3254 // The scale should not have been applied to the scroll delta.
3255 scroll_info
= host_impl_
->ProcessScrollDeltas();
3256 ExpectContains(*scroll_info
.get(),
3258 wheel_scroll_delta
);
3261 TEST_F(LayerTreeHostImplTest
, ScrollViewportRounding
) {
3265 SetupScrollAndContentsLayers(gfx::Size(width
, height
));
3266 host_impl_
->active_tree()->InnerViewportContainerLayer()->SetBounds(
3267 gfx::Size(width
* scale
- 1, height
* scale
));
3268 host_impl_
->SetDeviceScaleFactor(scale
);
3269 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
, 0.5f
, 4.f
);
3271 LayerImpl
* inner_viewport_scroll_layer
=
3272 host_impl_
->active_tree()->InnerViewportScrollLayer();
3273 EXPECT_EQ(gfx::ScrollOffset(0, 0),
3274 inner_viewport_scroll_layer
->MaxScrollOffset());
3277 class TestScrollOffsetDelegate
: public LayerScrollOffsetDelegate
{
3279 TestScrollOffsetDelegate()
3280 : page_scale_factor_(0.f
),
3281 min_page_scale_factor_(-1.f
),
3282 max_page_scale_factor_(-1.f
) {}
3284 virtual ~TestScrollOffsetDelegate() {}
3286 virtual gfx::ScrollOffset
GetTotalScrollOffset() override
{
3287 return getter_return_value_
;
3290 virtual bool IsExternalFlingActive() const override
{ return false; }
3292 virtual void UpdateRootLayerState(
3293 const gfx::ScrollOffset
& total_scroll_offset
,
3294 const gfx::ScrollOffset
& max_scroll_offset
,
3295 const gfx::SizeF
& scrollable_size
,
3296 float page_scale_factor
,
3297 float min_page_scale_factor
,
3298 float max_page_scale_factor
) override
{
3299 DCHECK(total_scroll_offset
.x() <= max_scroll_offset
.x());
3300 DCHECK(total_scroll_offset
.y() <= max_scroll_offset
.y());
3301 last_set_scroll_offset_
= total_scroll_offset
;
3302 max_scroll_offset_
= max_scroll_offset
;
3303 scrollable_size_
= scrollable_size
;
3304 page_scale_factor_
= page_scale_factor
;
3305 min_page_scale_factor_
= min_page_scale_factor
;
3306 max_page_scale_factor_
= max_page_scale_factor
;
3309 gfx::ScrollOffset
last_set_scroll_offset() {
3310 return last_set_scroll_offset_
;
3313 void set_getter_return_value(const gfx::ScrollOffset
& value
) {
3314 getter_return_value_
= value
;
3317 gfx::ScrollOffset
max_scroll_offset() const {
3318 return max_scroll_offset_
;
3321 gfx::SizeF
scrollable_size() const {
3322 return scrollable_size_
;
3325 float page_scale_factor() const {
3326 return page_scale_factor_
;
3329 float min_page_scale_factor() const {
3330 return min_page_scale_factor_
;
3333 float max_page_scale_factor() const {
3334 return max_page_scale_factor_
;
3338 gfx::ScrollOffset last_set_scroll_offset_
;
3339 gfx::ScrollOffset getter_return_value_
;
3340 gfx::ScrollOffset max_scroll_offset_
;
3341 gfx::SizeF scrollable_size_
;
3342 float page_scale_factor_
;
3343 float min_page_scale_factor_
;
3344 float max_page_scale_factor_
;
3347 TEST_F(LayerTreeHostImplTest
, RootLayerScrollOffsetDelegation
) {
3348 TestScrollOffsetDelegate scroll_delegate
;
3349 host_impl_
->SetViewportSize(gfx::Size(10, 20));
3350 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3351 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
3352 clip_layer
->SetBounds(gfx::Size(10, 20));
3354 // Setting the delegate results in the current scroll offset being set.
3355 gfx::Vector2dF
initial_scroll_delta(10.f
, 10.f
);
3356 scroll_layer
->SetScrollOffset(gfx::ScrollOffset());
3357 scroll_layer
->SetScrollDelta(initial_scroll_delta
);
3358 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
3359 EXPECT_EQ(initial_scroll_delta
.ToString(),
3360 scroll_delegate
.last_set_scroll_offset().ToString());
3362 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3363 // page_scale_factor and {min|max}_page_scale_factor being set.
3364 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate
.scrollable_size());
3365 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate
.max_scroll_offset());
3366 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
3367 EXPECT_EQ(0.f
, scroll_delegate
.min_page_scale_factor());
3368 EXPECT_EQ(0.f
, scroll_delegate
.max_page_scale_factor());
3370 // Updating page scale immediately updates the delegate.
3371 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(2.f
, 0.5f
, 4.f
);
3372 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
3373 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
3374 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
3375 host_impl_
->active_tree()->SetPageScaleDelta(1.5f
);
3376 EXPECT_EQ(3.f
, scroll_delegate
.page_scale_factor());
3377 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
3378 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
3379 host_impl_
->active_tree()->SetPageScaleDelta(1.f
);
3380 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
, 0.5f
, 4.f
);
3381 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
3382 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
3383 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
3385 // The pinch gesture doesn't put the delegate into a state where the scroll
3386 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3388 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
);
3389 host_impl_
->PinchGestureBegin();
3390 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
3391 host_impl_
->PinchGestureUpdate(.5f
, gfx::Point());
3392 host_impl_
->PinchGestureEnd();
3393 host_impl_
->ScrollEnd();
3395 // Scrolling should be relative to the offset as returned by the delegate.
3396 gfx::Vector2dF
scroll_delta(0.f
, 10.f
);
3397 gfx::ScrollOffset
current_offset(7.f
, 8.f
);
3399 scroll_delegate
.set_getter_return_value(current_offset
);
3400 EXPECT_EQ(InputHandler::ScrollStarted
,
3401 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
3403 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3404 EXPECT_EQ(ScrollOffsetWithDelta(current_offset
, scroll_delta
),
3405 scroll_delegate
.last_set_scroll_offset());
3407 current_offset
= gfx::ScrollOffset(42.f
, 41.f
);
3408 scroll_delegate
.set_getter_return_value(current_offset
);
3409 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3410 EXPECT_EQ(current_offset
+ gfx::ScrollOffset(scroll_delta
),
3411 scroll_delegate
.last_set_scroll_offset());
3412 host_impl_
->ScrollEnd();
3413 scroll_delegate
.set_getter_return_value(gfx::ScrollOffset());
3415 // Forces a full tree synchronization and ensures that the scroll delegate
3416 // sees the correct size of the new tree.
3417 gfx::Size
new_size(42, 24);
3418 host_impl_
->CreatePendingTree();
3419 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), new_size
);
3420 host_impl_
->ActivateSyncTree();
3421 EXPECT_EQ(new_size
, scroll_delegate
.scrollable_size());
3423 // Un-setting the delegate should propagate the delegate's current offset to
3424 // the root scrollable layer.
3425 current_offset
= gfx::ScrollOffset(13.f
, 12.f
);
3426 scroll_delegate
.set_getter_return_value(current_offset
);
3427 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
3429 EXPECT_EQ(current_offset
.ToString(),
3430 scroll_layer
->TotalScrollOffset().ToString());
3433 void CheckLayerScrollDelta(LayerImpl
* layer
, gfx::Vector2dF scroll_delta
) {
3434 const gfx::Transform target_space_transform
=
3435 layer
->draw_properties().target_space_transform
;
3436 EXPECT_TRUE(target_space_transform
.IsScaleOrTranslation());
3437 gfx::Point translated_point
;
3438 target_space_transform
.TransformPoint(&translated_point
);
3439 gfx::Point expected_point
= gfx::Point() - ToRoundedVector2d(scroll_delta
);
3440 EXPECT_EQ(expected_point
.ToString(), translated_point
.ToString());
3443 TEST_F(LayerTreeHostImplTest
,
3444 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw
) {
3445 TestScrollOffsetDelegate scroll_delegate
;
3446 host_impl_
->SetViewportSize(gfx::Size(10, 20));
3447 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3448 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
3449 clip_layer
->SetBounds(gfx::Size(10, 20));
3450 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
3452 // Draw first frame to clear any pending draws and check scroll.
3454 CheckLayerScrollDelta(scroll_layer
, gfx::Vector2dF(0.f
, 0.f
));
3455 EXPECT_FALSE(host_impl_
->active_tree()->needs_update_draw_properties());
3457 // Set external scroll delta on delegate and notify LayerTreeHost.
3458 gfx::ScrollOffset
scroll_offset(10.f
, 10.f
);
3459 scroll_delegate
.set_getter_return_value(scroll_offset
);
3460 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
3462 // Check scroll delta reflected in layer.
3464 CheckLayerScrollDelta(scroll_layer
, ScrollOffsetToVector2dF(scroll_offset
));
3466 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
3469 TEST_F(LayerTreeHostImplTest
, OverscrollRoot
) {
3470 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3471 host_impl_
->SetViewportSize(gfx::Size(50, 50));
3472 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
, 0.5f
, 4.f
);
3474 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
3476 // In-bounds scrolling does not affect overscroll.
3477 EXPECT_EQ(InputHandler::ScrollStarted
,
3478 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
3479 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3480 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
3482 // Overscroll events are reflected immediately.
3483 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
3484 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
3486 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
3487 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
3488 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
3489 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
3490 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
3491 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
3492 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
3493 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
3494 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_
->accumulated_root_overscroll());
3495 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
3496 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_
->accumulated_root_overscroll());
3497 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
3498 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
3500 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
3501 // as no scroll occurs.
3502 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3503 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_
->accumulated_root_overscroll());
3504 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3505 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_
->accumulated_root_overscroll());
3506 // Overscroll resets on valid scroll.
3507 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3508 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
3509 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3510 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
3511 host_impl_
->ScrollEnd();
3515 TEST_F(LayerTreeHostImplTest
, OverscrollChildWithoutBubbling
) {
3516 // Scroll child layers beyond their maximum scroll range and make sure root
3517 // overscroll does not accumulate.
3518 gfx::Size
surface_size(10, 10);
3519 scoped_ptr
<LayerImpl
> root_clip
=
3520 LayerImpl::Create(host_impl_
->active_tree(), 4);
3521 scoped_ptr
<LayerImpl
> root
=
3522 CreateScrollableLayer(1, surface_size
, root_clip
.get());
3524 scoped_ptr
<LayerImpl
> grand_child
=
3525 CreateScrollableLayer(3, surface_size
, root_clip
.get());
3527 scoped_ptr
<LayerImpl
> child
=
3528 CreateScrollableLayer(2, surface_size
, root_clip
.get());
3529 LayerImpl
* grand_child_layer
= grand_child
.get();
3530 child
->AddChild(grand_child
.Pass());
3532 LayerImpl
* child_layer
= child
.get();
3533 root
->AddChild(child
.Pass());
3534 root_clip
->AddChild(root
.Pass());
3535 child_layer
->SetScrollOffset(gfx::ScrollOffset(0, 3));
3536 grand_child_layer
->SetScrollOffset(gfx::ScrollOffset(0, 2));
3537 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3538 host_impl_
->active_tree()->DidBecomeActive();
3539 host_impl_
->SetViewportSize(surface_size
);
3542 gfx::Vector2d
scroll_delta(0, -10);
3543 EXPECT_EQ(InputHandler::ScrollStarted
,
3544 host_impl_
->ScrollBegin(gfx::Point(),
3545 InputHandler::NonBubblingGesture
));
3546 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3547 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
3548 host_impl_
->ScrollEnd();
3550 // The next time we scroll we should only scroll the parent, but overscroll
3551 // should still not reach the root layer.
3552 scroll_delta
= gfx::Vector2d(0, -30);
3553 EXPECT_EQ(InputHandler::ScrollStarted
,
3554 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3555 InputHandler::NonBubblingGesture
));
3556 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
3557 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
3558 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3559 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_layer
);
3560 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
3561 host_impl_
->ScrollEnd();
3563 // After scrolling the parent, another scroll on the opposite direction
3564 // should scroll the child.
3565 scroll_delta
= gfx::Vector2d(0, 70);
3566 EXPECT_EQ(InputHandler::ScrollStarted
,
3567 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3568 InputHandler::NonBubblingGesture
));
3569 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
3570 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3571 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
3572 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
3573 host_impl_
->ScrollEnd();
3577 TEST_F(LayerTreeHostImplTest
, OverscrollChildEventBubbling
) {
3578 // When we try to scroll a non-scrollable child layer, the scroll delta
3579 // should be applied to one of its ancestors if possible. Overscroll should
3580 // be reflected only when it has bubbled up to the root scrolling layer.
3581 gfx::Size
surface_size(10, 10);
3582 gfx::Size
content_size(20, 20);
3583 scoped_ptr
<LayerImpl
> root_clip
=
3584 LayerImpl::Create(host_impl_
->active_tree(), 3);
3585 scoped_ptr
<LayerImpl
> root
=
3586 CreateScrollableLayer(1, content_size
, root_clip
.get());
3587 root
->SetIsContainerForFixedPositionLayers(true);
3588 scoped_ptr
<LayerImpl
> child
=
3589 CreateScrollableLayer(2, content_size
, root_clip
.get());
3591 child
->SetScrollClipLayer(Layer::INVALID_ID
);
3592 root
->AddChild(child
.Pass());
3593 root_clip
->AddChild(root
.Pass());
3595 host_impl_
->SetViewportSize(surface_size
);
3596 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3597 host_impl_
->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID
);
3598 host_impl_
->active_tree()->DidBecomeActive();
3601 gfx::Vector2d
scroll_delta(0, 8);
3602 EXPECT_EQ(InputHandler::ScrollStarted
,
3603 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3604 InputHandler::Wheel
));
3605 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3606 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
3607 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3608 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_
->accumulated_root_overscroll());
3609 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3610 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_
->accumulated_root_overscroll());
3611 host_impl_
->ScrollEnd();
3615 TEST_F(LayerTreeHostImplTest
, OverscrollAlways
) {
3616 LayerTreeSettings settings
;
3617 CreateHostImpl(settings
, CreateOutputSurface());
3619 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(50, 50));
3620 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
3621 clip_layer
->SetBounds(gfx::Size(50, 50));
3622 host_impl_
->SetViewportSize(gfx::Size(50, 50));
3623 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
, 0.5f
, 4.f
);
3625 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
3627 // Even though the layer can't scroll the overscroll still happens.
3628 EXPECT_EQ(InputHandler::ScrollStarted
,
3629 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
3630 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3631 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
3634 TEST_F(LayerTreeHostImplTest
, NoOverscrollOnFractionalDeviceScale
) {
3635 gfx::Size
surface_size(980, 1439);
3636 gfx::Size
content_size(980, 1438);
3637 float device_scale_factor
= 1.5f
;
3638 scoped_ptr
<LayerImpl
> root_clip
=
3639 LayerImpl::Create(host_impl_
->active_tree(), 3);
3640 scoped_ptr
<LayerImpl
> root
=
3641 CreateScrollableLayer(1, content_size
, root_clip
.get());
3642 root
->SetIsContainerForFixedPositionLayers(true);
3643 scoped_ptr
<LayerImpl
> child
=
3644 CreateScrollableLayer(2, content_size
, root_clip
.get());
3645 root
->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
3646 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(
3647 0.326531f
, 0.326531f
, 5.f
);
3648 host_impl_
->active_tree()->SetPageScaleDelta(1.f
);
3649 child
->SetScrollClipLayer(Layer::INVALID_ID
);
3650 root
->AddChild(child
.Pass());
3651 root_clip
->AddChild(root
.Pass());
3653 host_impl_
->SetViewportSize(surface_size
);
3654 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
3655 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3656 host_impl_
->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID
);
3657 host_impl_
->active_tree()->DidBecomeActive();
3660 // Horizontal & Vertical GlowEffect should not be applied when
3661 // content size is less then view port size. For Example Horizontal &
3662 // vertical GlowEffect should not be applied in about:blank page.
3663 EXPECT_EQ(InputHandler::ScrollStarted
,
3664 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel
));
3665 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
3666 EXPECT_EQ(gfx::Vector2dF().ToString(),
3667 host_impl_
->accumulated_root_overscroll().ToString());
3669 host_impl_
->ScrollEnd();
3673 TEST_F(LayerTreeHostImplTest
, NoOverscrollWhenNotAtEdge
) {
3674 gfx::Size
surface_size(100, 100);
3675 gfx::Size
content_size(200, 200);
3676 scoped_ptr
<LayerImpl
> root_clip
=
3677 LayerImpl::Create(host_impl_
->active_tree(), 3);
3678 scoped_ptr
<LayerImpl
> root
=
3679 CreateScrollableLayer(1, content_size
, root_clip
.get());
3680 root
->SetIsContainerForFixedPositionLayers(true);
3681 scoped_ptr
<LayerImpl
> child
=
3682 CreateScrollableLayer(2, content_size
, root_clip
.get());
3684 child
->SetScrollClipLayer(Layer::INVALID_ID
);
3685 root
->AddChild(child
.Pass());
3686 root_clip
->AddChild(root
.Pass());
3688 host_impl_
->SetViewportSize(surface_size
);
3689 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3690 host_impl_
->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID
);
3691 host_impl_
->active_tree()->DidBecomeActive();
3694 // Edge glow effect should be applicable only upon reaching Edges
3695 // of the content. unnecessary glow effect calls shouldn't be
3696 // called while scrolling up without reaching the edge of the content.
3697 EXPECT_EQ(InputHandler::ScrollStarted
,
3698 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel
));
3699 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
3700 EXPECT_EQ(gfx::Vector2dF().ToString(),
3701 host_impl_
->accumulated_root_overscroll().ToString());
3702 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f
));
3703 EXPECT_EQ(gfx::Vector2dF().ToString(),
3704 host_impl_
->accumulated_root_overscroll().ToString());
3705 host_impl_
->ScrollEnd();
3706 // unusedrootDelta should be subtracted from applied delta so that
3707 // unwanted glow effect calls are not called.
3708 EXPECT_EQ(InputHandler::ScrollStarted
,
3709 host_impl_
->ScrollBegin(gfx::Point(0, 0),
3710 InputHandler::NonBubblingGesture
));
3711 EXPECT_EQ(InputHandler::ScrollStarted
, host_impl_
->FlingScrollBegin());
3712 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
3713 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
3714 host_impl_
->accumulated_root_overscroll().ToString());
3716 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f
, -0.01f
));
3717 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
3718 host_impl_
->accumulated_root_overscroll().ToString());
3719 host_impl_
->ScrollEnd();
3720 // TestCase to check kEpsilon, which prevents minute values to trigger
3721 // gloweffect without reaching edge.
3722 EXPECT_EQ(InputHandler::ScrollStarted
,
3723 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel
));
3724 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f
, 0.1f
));
3725 EXPECT_EQ(gfx::Vector2dF().ToString(),
3726 host_impl_
->accumulated_root_overscroll().ToString());
3727 host_impl_
->ScrollEnd();
3731 class BlendStateCheckLayer
: public LayerImpl
{
3733 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
3735 ResourceProvider
* resource_provider
) {
3736 return make_scoped_ptr(
3737 new BlendStateCheckLayer(tree_impl
, id
, resource_provider
));
3740 virtual void AppendQuads(RenderPass
* render_pass
,
3741 const OcclusionTracker
<LayerImpl
>& occlusion_tracker
,
3742 AppendQuadsData
* append_quads_data
) override
{
3743 quads_appended_
= true;
3745 gfx::Rect opaque_rect
;
3746 if (contents_opaque())
3747 opaque_rect
= quad_rect_
;
3749 opaque_rect
= opaque_content_rect_
;
3750 gfx::Rect visible_quad_rect
= quad_rect_
;
3752 SharedQuadState
* shared_quad_state
=
3753 render_pass
->CreateAndAppendSharedQuadState();
3754 PopulateSharedQuadState(shared_quad_state
);
3756 TileDrawQuad
* test_blending_draw_quad
=
3757 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
3758 test_blending_draw_quad
->SetNew(shared_quad_state
,
3763 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
3766 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
3767 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
3768 EXPECT_EQ(has_render_surface_
, !!render_surface());
3771 void SetExpectation(bool blend
, bool has_render_surface
) {
3773 has_render_surface_
= has_render_surface
;
3774 quads_appended_
= false;
3777 bool quads_appended() const { return quads_appended_
; }
3779 void SetQuadRect(const gfx::Rect
& rect
) { quad_rect_
= rect
; }
3780 void SetQuadVisibleRect(const gfx::Rect
& rect
) { quad_visible_rect_
= rect
; }
3781 void SetOpaqueContentRect(const gfx::Rect
& rect
) {
3782 opaque_content_rect_
= rect
;
3786 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
3788 ResourceProvider
* resource_provider
)
3789 : LayerImpl(tree_impl
, id
),
3791 has_render_surface_(false),
3792 quads_appended_(false),
3793 quad_rect_(5, 5, 5, 5),
3794 quad_visible_rect_(5, 5, 5, 5),
3795 resource_id_(resource_provider
->CreateResource(
3798 ResourceProvider::TextureHintImmutable
,
3800 resource_provider
->AllocateForTesting(resource_id_
);
3801 SetBounds(gfx::Size(10, 10));
3802 SetContentBounds(gfx::Size(10, 10));
3803 SetDrawsContent(true);
3807 bool has_render_surface_
;
3808 bool quads_appended_
;
3809 gfx::Rect quad_rect_
;
3810 gfx::Rect opaque_content_rect_
;
3811 gfx::Rect quad_visible_rect_
;
3812 ResourceProvider::ResourceId resource_id_
;
3815 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
3817 scoped_ptr
<LayerImpl
> root
=
3818 LayerImpl::Create(host_impl_
->active_tree(), 1);
3819 root
->SetBounds(gfx::Size(10, 10));
3820 root
->SetContentBounds(root
->bounds());
3821 root
->SetDrawsContent(false);
3822 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3824 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
3827 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
3829 host_impl_
->resource_provider()));
3830 BlendStateCheckLayer
* layer1
=
3831 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
3832 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
3834 LayerTreeHostImpl::FrameData frame
;
3836 // Opaque layer, drawn without blending.
3837 layer1
->SetContentsOpaque(true);
3838 layer1
->SetExpectation(false, false);
3839 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3840 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3841 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3842 EXPECT_TRUE(layer1
->quads_appended());
3843 host_impl_
->DidDrawAllLayers(frame
);
3845 // Layer with translucent content and painting, so drawn with blending.
3846 layer1
->SetContentsOpaque(false);
3847 layer1
->SetExpectation(true, false);
3848 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3849 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3850 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3851 EXPECT_TRUE(layer1
->quads_appended());
3852 host_impl_
->DidDrawAllLayers(frame
);
3854 // Layer with translucent opacity, drawn with blending.
3855 layer1
->SetContentsOpaque(true);
3856 layer1
->SetOpacity(0.5f
);
3857 layer1
->SetExpectation(true, false);
3858 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3859 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3860 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3861 EXPECT_TRUE(layer1
->quads_appended());
3862 host_impl_
->DidDrawAllLayers(frame
);
3864 // Layer with translucent opacity and painting, drawn with blending.
3865 layer1
->SetContentsOpaque(true);
3866 layer1
->SetOpacity(0.5f
);
3867 layer1
->SetExpectation(true, false);
3868 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3869 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3870 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3871 EXPECT_TRUE(layer1
->quads_appended());
3872 host_impl_
->DidDrawAllLayers(frame
);
3875 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
3877 host_impl_
->resource_provider()));
3878 BlendStateCheckLayer
* layer2
=
3879 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
3880 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
3882 // 2 opaque layers, drawn without blending.
3883 layer1
->SetContentsOpaque(true);
3884 layer1
->SetOpacity(1.f
);
3885 layer1
->SetExpectation(false, false);
3886 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3887 layer2
->SetContentsOpaque(true);
3888 layer2
->SetOpacity(1.f
);
3889 layer2
->SetExpectation(false, false);
3890 layer2
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3891 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3892 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3893 EXPECT_TRUE(layer1
->quads_appended());
3894 EXPECT_TRUE(layer2
->quads_appended());
3895 host_impl_
->DidDrawAllLayers(frame
);
3897 // Parent layer with translucent content, drawn with blending.
3898 // Child layer with opaque content, drawn without blending.
3899 layer1
->SetContentsOpaque(false);
3900 layer1
->SetExpectation(true, false);
3901 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3902 layer2
->SetExpectation(false, false);
3903 layer2
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3904 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3905 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3906 EXPECT_TRUE(layer1
->quads_appended());
3907 EXPECT_TRUE(layer2
->quads_appended());
3908 host_impl_
->DidDrawAllLayers(frame
);
3910 // Parent layer with translucent content but opaque painting, drawn without
3912 // Child layer with opaque content, drawn without blending.
3913 layer1
->SetContentsOpaque(true);
3914 layer1
->SetExpectation(false, false);
3915 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3916 layer2
->SetExpectation(false, false);
3917 layer2
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3918 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3919 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3920 EXPECT_TRUE(layer1
->quads_appended());
3921 EXPECT_TRUE(layer2
->quads_appended());
3922 host_impl_
->DidDrawAllLayers(frame
);
3924 // Parent layer with translucent opacity and opaque content. Since it has a
3925 // drawing child, it's drawn to a render surface which carries the opacity,
3926 // so it's itself drawn without blending.
3927 // Child layer with opaque content, drawn without blending (parent surface
3928 // carries the inherited opacity).
3929 layer1
->SetContentsOpaque(true);
3930 layer1
->SetOpacity(0.5f
);
3931 layer1
->SetExpectation(false, true);
3932 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3933 layer2
->SetExpectation(false, false);
3934 layer2
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3935 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
3936 host_impl_
->active_tree()->root_layer());
3937 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3938 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3939 EXPECT_TRUE(layer1
->quads_appended());
3940 EXPECT_TRUE(layer2
->quads_appended());
3941 host_impl_
->DidDrawAllLayers(frame
);
3943 // Draw again, but with child non-opaque, to make sure
3944 // layer1 not culled.
3945 layer1
->SetContentsOpaque(true);
3946 layer1
->SetOpacity(1.f
);
3947 layer1
->SetExpectation(false, false);
3948 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3949 layer2
->SetContentsOpaque(true);
3950 layer2
->SetOpacity(0.5f
);
3951 layer2
->SetExpectation(true, false);
3952 layer2
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3953 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3954 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3955 EXPECT_TRUE(layer1
->quads_appended());
3956 EXPECT_TRUE(layer2
->quads_appended());
3957 host_impl_
->DidDrawAllLayers(frame
);
3959 // A second way of making the child non-opaque.
3960 layer1
->SetContentsOpaque(true);
3961 layer1
->SetOpacity(1.f
);
3962 layer1
->SetExpectation(false, false);
3963 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3964 layer2
->SetContentsOpaque(false);
3965 layer2
->SetOpacity(1.f
);
3966 layer2
->SetExpectation(true, false);
3967 layer2
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3968 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3969 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3970 EXPECT_TRUE(layer1
->quads_appended());
3971 EXPECT_TRUE(layer2
->quads_appended());
3972 host_impl_
->DidDrawAllLayers(frame
);
3974 // And when the layer says its not opaque but is painted opaque, it is not
3976 layer1
->SetContentsOpaque(true);
3977 layer1
->SetOpacity(1.f
);
3978 layer1
->SetExpectation(false, false);
3979 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3980 layer2
->SetContentsOpaque(true);
3981 layer2
->SetOpacity(1.f
);
3982 layer2
->SetExpectation(false, false);
3983 layer2
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3984 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3985 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3986 EXPECT_TRUE(layer1
->quads_appended());
3987 EXPECT_TRUE(layer2
->quads_appended());
3988 host_impl_
->DidDrawAllLayers(frame
);
3990 // Layer with partially opaque contents, drawn with blending.
3991 layer1
->SetContentsOpaque(false);
3992 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3993 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
3994 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3995 layer1
->SetExpectation(true, false);
3996 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
3997 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3998 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
3999 EXPECT_TRUE(layer1
->quads_appended());
4000 host_impl_
->DidDrawAllLayers(frame
);
4002 // Layer with partially opaque contents partially culled, drawn with blending.
4003 layer1
->SetContentsOpaque(false);
4004 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4005 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
4006 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4007 layer1
->SetExpectation(true, false);
4008 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
4009 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4010 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4011 EXPECT_TRUE(layer1
->quads_appended());
4012 host_impl_
->DidDrawAllLayers(frame
);
4014 // Layer with partially opaque contents culled, drawn with blending.
4015 layer1
->SetContentsOpaque(false);
4016 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4017 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
4018 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4019 layer1
->SetExpectation(true, false);
4020 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
4021 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4022 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4023 EXPECT_TRUE(layer1
->quads_appended());
4024 host_impl_
->DidDrawAllLayers(frame
);
4026 // Layer with partially opaque contents and translucent contents culled, drawn
4027 // without blending.
4028 layer1
->SetContentsOpaque(false);
4029 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4030 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
4031 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4032 layer1
->SetExpectation(false, false);
4033 layer1
->SetUpdateRect(gfx::RectF(layer1
->content_bounds()));
4034 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4035 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4036 EXPECT_TRUE(layer1
->quads_appended());
4037 host_impl_
->DidDrawAllLayers(frame
);
4040 class LayerTreeHostImplViewportCoveredTest
: public LayerTreeHostImplTest
{
4042 LayerTreeHostImplViewportCoveredTest() :
4043 gutter_quad_material_(DrawQuad::SOLID_COLOR
),
4045 did_activate_pending_tree_(false) {}
4047 scoped_ptr
<OutputSurface
> CreateFakeOutputSurface(bool always_draw
) {
4049 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
4051 return FakeOutputSurface::Create3d();
4054 void SetupActiveTreeLayers() {
4055 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
4056 host_impl_
->active_tree()->SetRootLayer(
4057 LayerImpl::Create(host_impl_
->active_tree(), 1));
4058 host_impl_
->active_tree()->root_layer()->AddChild(
4059 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4061 host_impl_
->resource_provider()));
4062 child_
= static_cast<BlendStateCheckLayer
*>(
4063 host_impl_
->active_tree()->root_layer()->children()[0]);
4064 child_
->SetExpectation(false, false);
4065 child_
->SetContentsOpaque(true);
4068 // Expect no gutter rects.
4069 void TestLayerCoversFullViewport() {
4070 gfx::Rect
layer_rect(viewport_size_
);
4071 child_
->SetPosition(layer_rect
.origin());
4072 child_
->SetBounds(layer_rect
.size());
4073 child_
->SetContentBounds(layer_rect
.size());
4074 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4075 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4077 LayerTreeHostImpl::FrameData frame
;
4078 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4079 ASSERT_EQ(1u, frame
.render_passes
.size());
4081 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4082 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4083 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4085 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4086 host_impl_
->DidDrawAllLayers(frame
);
4089 // Expect fullscreen gutter rect.
4090 void TestEmptyLayer() {
4091 gfx::Rect
layer_rect(0, 0, 0, 0);
4092 child_
->SetPosition(layer_rect
.origin());
4093 child_
->SetBounds(layer_rect
.size());
4094 child_
->SetContentBounds(layer_rect
.size());
4095 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4096 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4098 LayerTreeHostImpl::FrameData frame
;
4099 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4100 ASSERT_EQ(1u, frame
.render_passes
.size());
4102 EXPECT_EQ(1u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4103 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4104 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4106 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4107 host_impl_
->DidDrawAllLayers(frame
);
4110 // Expect four surrounding gutter rects.
4111 void TestLayerInMiddleOfViewport() {
4112 gfx::Rect
layer_rect(500, 500, 200, 200);
4113 child_
->SetPosition(layer_rect
.origin());
4114 child_
->SetBounds(layer_rect
.size());
4115 child_
->SetContentBounds(layer_rect
.size());
4116 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4117 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4119 LayerTreeHostImpl::FrameData frame
;
4120 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4121 ASSERT_EQ(1u, frame
.render_passes
.size());
4123 EXPECT_EQ(4u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4124 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
4125 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4127 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4128 host_impl_
->DidDrawAllLayers(frame
);
4131 // Expect no gutter rects.
4132 void TestLayerIsLargerThanViewport() {
4133 gfx::Rect
layer_rect(viewport_size_
.width() + 10,
4134 viewport_size_
.height() + 10);
4135 child_
->SetPosition(layer_rect
.origin());
4136 child_
->SetBounds(layer_rect
.size());
4137 child_
->SetContentBounds(layer_rect
.size());
4138 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4139 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4141 LayerTreeHostImpl::FrameData frame
;
4142 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4143 ASSERT_EQ(1u, frame
.render_passes
.size());
4145 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4146 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4147 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4149 host_impl_
->DidDrawAllLayers(frame
);
4152 virtual void DidActivateSyncTree() override
{
4153 did_activate_pending_tree_
= true;
4156 void set_gutter_quad_material(DrawQuad::Material material
) {
4157 gutter_quad_material_
= material
;
4159 void set_gutter_texture_size(const gfx::Size
& gutter_texture_size
) {
4160 gutter_texture_size_
= gutter_texture_size
;
4164 size_t CountGutterQuads(const QuadList
& quad_list
) {
4165 size_t num_gutter_quads
= 0;
4166 for (const auto& quad
: quad_list
) {
4167 num_gutter_quads
+= (quad
.material
== gutter_quad_material_
) ? 1 : 0;
4169 return num_gutter_quads
;
4172 void VerifyQuadsExactlyCoverViewport(const QuadList
& quad_list
) {
4173 LayerTestCommon::VerifyQuadsExactlyCoverRect(
4174 quad_list
, gfx::Rect(DipSizeToPixelSize(viewport_size_
)));
4177 // Make sure that the texture coordinates match their expectations.
4178 void ValidateTextureDrawQuads(const QuadList
& quad_list
) {
4179 for (const auto& quad
: quad_list
) {
4180 if (quad
.material
!= DrawQuad::TEXTURE_CONTENT
)
4182 const TextureDrawQuad
* texture_quad
=
4183 TextureDrawQuad::MaterialCast(&quad
);
4184 gfx::SizeF gutter_texture_size_pixels
= gfx::ScaleSize(
4185 gutter_texture_size_
, host_impl_
->device_scale_factor());
4186 EXPECT_EQ(texture_quad
->uv_top_left
.x(),
4187 texture_quad
->rect
.x() / gutter_texture_size_pixels
.width());
4188 EXPECT_EQ(texture_quad
->uv_top_left
.y(),
4189 texture_quad
->rect
.y() / gutter_texture_size_pixels
.height());
4191 texture_quad
->uv_bottom_right
.x(),
4192 texture_quad
->rect
.right() / gutter_texture_size_pixels
.width());
4194 texture_quad
->uv_bottom_right
.y(),
4195 texture_quad
->rect
.bottom() / gutter_texture_size_pixels
.height());
4199 gfx::Size
DipSizeToPixelSize(const gfx::Size
& size
) {
4200 return gfx::ToRoundedSize(
4201 gfx::ScaleSize(size
, host_impl_
->device_scale_factor()));
4204 DrawQuad::Material gutter_quad_material_
;
4205 gfx::Size gutter_texture_size_
;
4206 gfx::Size viewport_size_
;
4207 BlendStateCheckLayer
* child_
;
4208 bool did_activate_pending_tree_
;
4211 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCovered
) {
4212 viewport_size_
= gfx::Size(1000, 1000);
4214 bool always_draw
= false;
4215 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4217 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4218 SetupActiveTreeLayers();
4219 TestLayerCoversFullViewport();
4221 TestLayerInMiddleOfViewport();
4222 TestLayerIsLargerThanViewport();
4225 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredScaled
) {
4226 viewport_size_
= gfx::Size(1000, 1000);
4228 bool always_draw
= false;
4229 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4231 host_impl_
->SetDeviceScaleFactor(2.f
);
4232 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4233 SetupActiveTreeLayers();
4234 TestLayerCoversFullViewport();
4236 TestLayerInMiddleOfViewport();
4237 TestLayerIsLargerThanViewport();
4240 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredOverhangBitmap
) {
4241 viewport_size_
= gfx::Size(1000, 1000);
4243 bool always_draw
= false;
4244 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4246 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4247 SetupActiveTreeLayers();
4249 // Specify an overhang bitmap to use.
4250 bool is_opaque
= false;
4251 UIResourceBitmap
ui_resource_bitmap(gfx::Size(2, 2), is_opaque
);
4252 ui_resource_bitmap
.SetWrapMode(UIResourceBitmap::REPEAT
);
4253 UIResourceId ui_resource_id
= 12345;
4254 host_impl_
->CreateUIResource(ui_resource_id
, ui_resource_bitmap
);
4255 host_impl_
->SetOverhangUIResource(ui_resource_id
, gfx::Size(32, 32));
4256 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT
);
4257 set_gutter_texture_size(gfx::Size(32, 32));
4259 TestLayerCoversFullViewport();
4261 TestLayerInMiddleOfViewport();
4262 TestLayerIsLargerThanViewport();
4264 // Change the resource size.
4265 host_impl_
->SetOverhangUIResource(ui_resource_id
, gfx::Size(128, 16));
4266 set_gutter_texture_size(gfx::Size(128, 16));
4268 TestLayerCoversFullViewport();
4270 TestLayerInMiddleOfViewport();
4271 TestLayerIsLargerThanViewport();
4273 // Change the device scale factor
4274 host_impl_
->SetDeviceScaleFactor(2.f
);
4275 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4277 TestLayerCoversFullViewport();
4279 TestLayerInMiddleOfViewport();
4280 TestLayerIsLargerThanViewport();
4283 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeGrowViewportInvalid
) {
4284 viewport_size_
= gfx::Size(1000, 1000);
4286 bool always_draw
= true;
4287 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4289 // Pending tree to force active_tree size invalid. Not used otherwise.
4290 host_impl_
->CreatePendingTree();
4291 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4292 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
4294 SetupActiveTreeLayers();
4296 TestLayerInMiddleOfViewport();
4297 TestLayerIsLargerThanViewport();
4300 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeShrinkViewportInvalid
) {
4301 viewport_size_
= gfx::Size(1000, 1000);
4303 bool always_draw
= true;
4304 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4306 // Set larger viewport and activate it to active tree.
4307 host_impl_
->CreatePendingTree();
4308 gfx::Size
larger_viewport(viewport_size_
.width() + 100,
4309 viewport_size_
.height() + 100);
4310 host_impl_
->SetViewportSize(DipSizeToPixelSize(larger_viewport
));
4311 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
4312 host_impl_
->ActivateSyncTree();
4313 EXPECT_TRUE(did_activate_pending_tree_
);
4314 EXPECT_FALSE(host_impl_
->active_tree()->ViewportSizeInvalid());
4316 // Shrink pending tree viewport without activating.
4317 host_impl_
->CreatePendingTree();
4318 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4319 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
4321 SetupActiveTreeLayers();
4323 TestLayerInMiddleOfViewport();
4324 TestLayerIsLargerThanViewport();
4327 class FakeDrawableLayerImpl
: public LayerImpl
{
4329 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
4330 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl
, id
));
4333 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
4334 : LayerImpl(tree_impl
, id
) {}
4337 // Only reshape when we know we are going to draw. Otherwise, the reshape
4338 // can leave the window at the wrong size if we never draw and the proper
4339 // viewport size is never set.
4340 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
4341 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
4342 scoped_ptr
<OutputSurface
> output_surface(
4343 FakeOutputSurface::Create3d(provider
));
4344 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
4346 scoped_ptr
<LayerImpl
> root
=
4347 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
4348 root
->SetBounds(gfx::Size(10, 10));
4349 root
->SetContentBounds(gfx::Size(10, 10));
4350 root
->SetDrawsContent(true);
4351 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4352 EXPECT_FALSE(provider
->TestContext3d()->reshape_called());
4353 provider
->TestContext3d()->clear_reshape_called();
4355 LayerTreeHostImpl::FrameData frame
;
4356 host_impl_
->SetViewportSize(gfx::Size(10, 10));
4357 host_impl_
->SetDeviceScaleFactor(1.f
);
4358 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4359 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4360 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
4361 EXPECT_EQ(provider
->TestContext3d()->width(), 10);
4362 EXPECT_EQ(provider
->TestContext3d()->height(), 10);
4363 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
4364 host_impl_
->DidDrawAllLayers(frame
);
4365 provider
->TestContext3d()->clear_reshape_called();
4367 host_impl_
->SetViewportSize(gfx::Size(20, 30));
4368 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4369 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4370 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
4371 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
4372 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
4373 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
4374 host_impl_
->DidDrawAllLayers(frame
);
4375 provider
->TestContext3d()->clear_reshape_called();
4377 host_impl_
->SetDeviceScaleFactor(2.f
);
4378 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4379 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4380 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
4381 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
4382 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
4383 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 2.f
);
4384 host_impl_
->DidDrawAllLayers(frame
);
4385 provider
->TestContext3d()->clear_reshape_called();
4388 // Make sure damage tracking propagates all the way to the graphics context,
4389 // where it should request to swap only the sub-buffer that is damaged.
4390 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
4391 scoped_refptr
<TestContextProvider
> context_provider(
4392 TestContextProvider::Create());
4393 context_provider
->BindToCurrentThread();
4394 context_provider
->TestContext3d()->set_have_post_sub_buffer(true);
4396 scoped_ptr
<OutputSurface
> output_surface(
4397 FakeOutputSurface::Create3d(context_provider
));
4399 // This test creates its own LayerTreeHostImpl, so
4400 // that we can force partial swap enabled.
4401 LayerTreeSettings settings
;
4402 settings
.partial_swap_enabled
= true;
4403 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
4404 new TestSharedBitmapManager());
4405 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
4406 LayerTreeHostImpl::Create(settings
,
4409 &stats_instrumentation_
,
4410 shared_bitmap_manager
.get(),
4412 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
4413 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
4415 scoped_ptr
<LayerImpl
> root
=
4416 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
4417 scoped_ptr
<LayerImpl
> child
=
4418 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
4419 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
4420 child
->SetBounds(gfx::Size(14, 15));
4421 child
->SetContentBounds(gfx::Size(14, 15));
4422 child
->SetDrawsContent(true);
4423 root
->SetBounds(gfx::Size(500, 500));
4424 root
->SetContentBounds(gfx::Size(500, 500));
4425 root
->SetDrawsContent(true);
4426 root
->AddChild(child
.Pass());
4427 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
4429 LayerTreeHostImpl::FrameData frame
;
4431 // First frame, the entire screen should get swapped.
4432 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
4433 layer_tree_host_impl
->DrawLayers(&frame
, gfx::FrameTime::Now());
4434 layer_tree_host_impl
->DidDrawAllLayers(frame
);
4435 layer_tree_host_impl
->SwapBuffers(frame
);
4436 EXPECT_EQ(TestContextSupport::SWAP
,
4437 context_provider
->support()->last_swap_type());
4439 // Second frame, only the damaged area should get swapped. Damage should be
4440 // the union of old and new child rects.
4441 // expected damage rect: gfx::Rect(26, 28);
4442 // expected swap rect: vertically flipped, with origin at bottom left corner.
4443 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
4445 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
4446 layer_tree_host_impl
->DrawLayers(&frame
, gfx::FrameTime::Now());
4447 host_impl_
->DidDrawAllLayers(frame
);
4448 layer_tree_host_impl
->SwapBuffers(frame
);
4450 // Make sure that partial swap is constrained to the viewport dimensions
4451 // expected damage rect: gfx::Rect(500, 500);
4452 // expected swap rect: flipped damage rect, but also clamped to viewport
4453 EXPECT_EQ(TestContextSupport::PARTIAL_SWAP
,
4454 context_provider
->support()->last_swap_type());
4455 gfx::Rect
expected_swap_rect(0, 500-28, 26, 28);
4456 EXPECT_EQ(expected_swap_rect
.ToString(),
4457 context_provider
->support()->
4458 last_partial_swap_rect().ToString());
4460 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
4461 // This will damage everything.
4462 layer_tree_host_impl
->active_tree()->root_layer()->SetBackgroundColor(
4464 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
4465 layer_tree_host_impl
->DrawLayers(&frame
, gfx::FrameTime::Now());
4466 host_impl_
->DidDrawAllLayers(frame
);
4467 layer_tree_host_impl
->SwapBuffers(frame
);
4469 EXPECT_EQ(TestContextSupport::SWAP
,
4470 context_provider
->support()->last_swap_type());
4473 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
4474 scoped_ptr
<LayerImpl
> root
=
4475 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
4476 scoped_ptr
<LayerImpl
> child
=
4477 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
4478 child
->SetBounds(gfx::Size(10, 10));
4479 child
->SetContentBounds(gfx::Size(10, 10));
4480 child
->SetDrawsContent(true);
4481 root
->SetBounds(gfx::Size(10, 10));
4482 root
->SetContentBounds(gfx::Size(10, 10));
4483 root
->SetDrawsContent(true);
4484 root
->SetForceRenderSurface(true);
4485 root
->AddChild(child
.Pass());
4487 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4489 LayerTreeHostImpl::FrameData frame
;
4491 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4492 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
4493 EXPECT_EQ(1u, frame
.render_passes
.size());
4494 host_impl_
->DidDrawAllLayers(frame
);
4497 class FakeLayerWithQuads
: public LayerImpl
{
4499 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
4500 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl
, id
));
4503 virtual void AppendQuads(RenderPass
* render_pass
,
4504 const OcclusionTracker
<LayerImpl
>& occlusion_tracker
,
4505 AppendQuadsData
* append_quads_data
) override
{
4506 SharedQuadState
* shared_quad_state
=
4507 render_pass
->CreateAndAppendSharedQuadState();
4508 PopulateSharedQuadState(shared_quad_state
);
4510 SkColor gray
= SkColorSetRGB(100, 100, 100);
4511 gfx::Rect
quad_rect(content_bounds());
4512 gfx::Rect
visible_quad_rect(quad_rect
);
4513 SolidColorDrawQuad
* my_quad
=
4514 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
4516 shared_quad_state
, quad_rect
, visible_quad_rect
, gray
, false);
4520 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
4521 : LayerImpl(tree_impl
, id
) {}
4524 class MockContext
: public TestWebGraphicsContext3D
{
4526 MOCK_METHOD1(useProgram
, void(GLuint program
));
4527 MOCK_METHOD5(uniform4f
, void(GLint location
,
4532 MOCK_METHOD4(uniformMatrix4fv
, void(GLint location
,
4534 GLboolean transpose
,
4535 const GLfloat
* value
));
4536 MOCK_METHOD4(drawElements
, void(GLenum mode
,
4540 MOCK_METHOD1(enable
, void(GLenum cap
));
4541 MOCK_METHOD1(disable
, void(GLenum cap
));
4542 MOCK_METHOD4(scissor
, void(GLint x
,
4548 class MockContextHarness
{
4550 MockContext
* context_
;
4553 explicit MockContextHarness(MockContext
* context
)
4554 : context_(context
) {
4555 context_
->set_have_post_sub_buffer(true);
4557 // Catch "uninteresting" calls
4558 EXPECT_CALL(*context_
, useProgram(_
))
4561 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
4564 // These are not asserted
4565 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
4566 .WillRepeatedly(Return());
4568 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
4569 .WillRepeatedly(Return());
4571 // Any un-sanctioned calls to enable() are OK
4572 EXPECT_CALL(*context_
, enable(_
))
4573 .WillRepeatedly(Return());
4575 // Any un-sanctioned calls to disable() are OK
4576 EXPECT_CALL(*context_
, disable(_
))
4577 .WillRepeatedly(Return());
4580 void MustDrawSolidQuad() {
4581 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
4583 .RetiresOnSaturation();
4585 EXPECT_CALL(*context_
, useProgram(_
))
4587 .RetiresOnSaturation();
4590 void MustSetScissor(int x
, int y
, int width
, int height
) {
4591 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
4592 .WillRepeatedly(Return());
4594 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
4596 .WillRepeatedly(Return());
4599 void MustSetNoScissor() {
4600 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
4601 .WillRepeatedly(Return());
4603 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
4606 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
4611 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
4612 scoped_ptr
<MockContext
> mock_context_owned(new MockContext
);
4613 MockContext
* mock_context
= mock_context_owned
.get();
4614 MockContextHarness
harness(mock_context
);
4617 LayerTreeSettings settings
= DefaultSettings();
4618 settings
.partial_swap_enabled
= false;
4619 CreateHostImpl(settings
,
4620 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
4621 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
4623 // Without partial swap, and no clipping, no scissor is set.
4624 harness
.MustDrawSolidQuad();
4625 harness
.MustSetNoScissor();
4627 LayerTreeHostImpl::FrameData frame
;
4628 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4629 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4630 host_impl_
->DidDrawAllLayers(frame
);
4632 Mock::VerifyAndClearExpectations(&mock_context
);
4634 // Without partial swap, but a layer does clip its subtree, one scissor is
4636 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
4637 harness
.MustDrawSolidQuad();
4638 harness
.MustSetScissor(0, 0, 10, 10);
4640 LayerTreeHostImpl::FrameData frame
;
4641 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4642 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4643 host_impl_
->DidDrawAllLayers(frame
);
4645 Mock::VerifyAndClearExpectations(&mock_context
);
4648 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
4649 scoped_ptr
<MockContext
> context_owned(new MockContext
);
4650 MockContext
* mock_context
= context_owned
.get();
4651 MockContextHarness
harness(mock_context
);
4653 LayerTreeSettings settings
= DefaultSettings();
4654 settings
.partial_swap_enabled
= true;
4655 CreateHostImpl(settings
, FakeOutputSurface::Create3d(context_owned
.Pass()));
4656 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
4658 // The first frame is not a partially-swapped one.
4659 harness
.MustSetScissor(0, 0, 10, 10);
4660 harness
.MustDrawSolidQuad();
4662 LayerTreeHostImpl::FrameData frame
;
4663 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4664 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4665 host_impl_
->DidDrawAllLayers(frame
);
4667 Mock::VerifyAndClearExpectations(&mock_context
);
4669 // Damage a portion of the frame.
4670 host_impl_
->active_tree()->root_layer()->SetUpdateRect(
4671 gfx::Rect(0, 0, 2, 3));
4673 // The second frame will be partially-swapped (the y coordinates are flipped).
4674 harness
.MustSetScissor(0, 7, 2, 3);
4675 harness
.MustDrawSolidQuad();
4677 LayerTreeHostImpl::FrameData frame
;
4678 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4679 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4680 host_impl_
->DidDrawAllLayers(frame
);
4682 Mock::VerifyAndClearExpectations(&mock_context
);
4685 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
4687 LayerTreeHostImplClient
* client
,
4689 SharedBitmapManager
* manager
,
4690 RenderingStatsInstrumentation
* stats_instrumentation
) {
4691 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
4692 scoped_ptr
<OutputSurface
> output_surface(
4693 FakeOutputSurface::Create3d(provider
));
4694 provider
->BindToCurrentThread();
4695 provider
->TestContext3d()->set_have_post_sub_buffer(true);
4697 LayerTreeSettings settings
;
4698 settings
.partial_swap_enabled
= partial_swap
;
4699 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
= LayerTreeHostImpl::Create(
4700 settings
, client
, proxy
, stats_instrumentation
, manager
, 0);
4701 my_host_impl
->InitializeRenderer(output_surface
.Pass());
4702 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
4705 Layers are created as follows:
4707 +--------------------+
4711 | | +-------------------+
4713 | | +-------------------+
4718 +--------------------+
4720 Layers 1, 2 have render surfaces
4722 scoped_ptr
<LayerImpl
> root
=
4723 LayerImpl::Create(my_host_impl
->active_tree(), 1);
4724 scoped_ptr
<LayerImpl
> child
=
4725 LayerImpl::Create(my_host_impl
->active_tree(), 2);
4726 scoped_ptr
<LayerImpl
> grand_child
=
4727 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
4729 gfx::Rect
root_rect(0, 0, 100, 100);
4730 gfx::Rect
child_rect(10, 10, 50, 50);
4731 gfx::Rect
grand_child_rect(5, 5, 150, 150);
4733 root
->CreateRenderSurface();
4734 root
->SetPosition(root_rect
.origin());
4735 root
->SetBounds(root_rect
.size());
4736 root
->SetContentBounds(root
->bounds());
4737 root
->draw_properties().visible_content_rect
= root_rect
;
4738 root
->SetDrawsContent(false);
4739 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
4741 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
4742 child
->SetOpacity(0.5f
);
4743 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
4744 child
->SetContentBounds(child
->bounds());
4745 child
->draw_properties().visible_content_rect
= child_rect
;
4746 child
->SetDrawsContent(false);
4747 child
->SetForceRenderSurface(true);
4749 grand_child
->SetPosition(grand_child_rect
.origin());
4750 grand_child
->SetBounds(grand_child_rect
.size());
4751 grand_child
->SetContentBounds(grand_child
->bounds());
4752 grand_child
->draw_properties().visible_content_rect
= grand_child_rect
;
4753 grand_child
->SetDrawsContent(true);
4755 child
->AddChild(grand_child
.Pass());
4756 root
->AddChild(child
.Pass());
4758 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
4759 return my_host_impl
.Pass();
4762 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
4763 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
4764 new TestSharedBitmapManager());
4765 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
4766 SetupLayersForOpacity(true,
4769 shared_bitmap_manager
.get(),
4770 &stats_instrumentation_
);
4772 LayerTreeHostImpl::FrameData frame
;
4773 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
4775 // Verify all quads have been computed
4776 ASSERT_EQ(2U, frame
.render_passes
.size());
4777 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4778 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
4779 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
4780 frame
.render_passes
[0]->quad_list
.front()->material
);
4781 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4782 frame
.render_passes
[1]->quad_list
.front()->material
);
4784 my_host_impl
->DrawLayers(&frame
, gfx::FrameTime::Now());
4785 my_host_impl
->DidDrawAllLayers(frame
);
4789 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
4790 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
4791 new TestSharedBitmapManager());
4792 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
4793 SetupLayersForOpacity(false,
4796 shared_bitmap_manager
.get(),
4797 &stats_instrumentation_
);
4799 LayerTreeHostImpl::FrameData frame
;
4800 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
4802 // Verify all quads have been computed
4803 ASSERT_EQ(2U, frame
.render_passes
.size());
4804 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4805 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
4806 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
4807 frame
.render_passes
[0]->quad_list
.front()->material
);
4808 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4809 frame
.render_passes
[1]->quad_list
.front()->material
);
4811 my_host_impl
->DrawLayers(&frame
, gfx::FrameTime::Now());
4812 my_host_impl
->DidDrawAllLayers(frame
);
4816 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
4817 scoped_ptr
<TestWebGraphicsContext3D
> context
=
4818 TestWebGraphicsContext3D::Create();
4819 TestWebGraphicsContext3D
* context3d
= context
.get();
4820 scoped_ptr
<OutputSurface
> output_surface(
4821 FakeOutputSurface::Create3d(context
.Pass()));
4822 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
4824 scoped_ptr
<LayerImpl
> root_layer
=
4825 LayerImpl::Create(host_impl_
->active_tree(), 1);
4826 root_layer
->SetBounds(gfx::Size(10, 10));
4828 scoped_refptr
<VideoFrame
> softwareFrame
=
4829 media::VideoFrame::CreateColorFrame(
4830 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
4831 FakeVideoFrameProvider provider
;
4832 provider
.set_frame(softwareFrame
);
4833 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
4834 host_impl_
->active_tree(), 4, &provider
, media::VIDEO_ROTATION_0
);
4835 video_layer
->SetBounds(gfx::Size(10, 10));
4836 video_layer
->SetContentBounds(gfx::Size(10, 10));
4837 video_layer
->SetDrawsContent(true);
4838 root_layer
->AddChild(video_layer
.Pass());
4840 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
4841 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
4842 io_surface_layer
->SetBounds(gfx::Size(10, 10));
4843 io_surface_layer
->SetContentBounds(gfx::Size(10, 10));
4844 io_surface_layer
->SetDrawsContent(true);
4845 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
4846 root_layer
->AddChild(io_surface_layer
.Pass());
4848 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
4850 EXPECT_EQ(0u, context3d
->NumTextures());
4852 LayerTreeHostImpl::FrameData frame
;
4853 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4854 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4855 host_impl_
->DidDrawAllLayers(frame
);
4856 host_impl_
->SwapBuffers(frame
);
4858 EXPECT_GT(context3d
->NumTextures(), 0u);
4860 // Kill the layer tree.
4861 host_impl_
->active_tree()->SetRootLayer(
4862 LayerImpl::Create(host_impl_
->active_tree(), 100));
4863 // There should be no textures left in use after.
4864 EXPECT_EQ(0u, context3d
->NumTextures());
4867 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
4869 MOCK_METHOD1(useProgram
, void(GLuint program
));
4870 MOCK_METHOD4(drawElements
, void(GLenum mode
,
4876 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
4877 scoped_ptr
<MockDrawQuadsToFillScreenContext
> mock_context_owned(
4878 new MockDrawQuadsToFillScreenContext
);
4879 MockDrawQuadsToFillScreenContext
* mock_context
= mock_context_owned
.get();
4882 LayerTreeSettings settings
= DefaultSettings();
4883 settings
.partial_swap_enabled
= false;
4884 CreateHostImpl(settings
,
4885 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
4886 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
4887 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
4889 // Verify one quad is drawn when transparent background set is not set.
4890 host_impl_
->active_tree()->set_has_transparent_background(false);
4891 EXPECT_CALL(*mock_context
, useProgram(_
))
4893 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
4895 LayerTreeHostImpl::FrameData frame
;
4896 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4897 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4898 host_impl_
->DidDrawAllLayers(frame
);
4899 Mock::VerifyAndClearExpectations(&mock_context
);
4901 // Verify no quads are drawn when transparent background is set.
4902 host_impl_
->active_tree()->set_has_transparent_background(true);
4903 host_impl_
->SetFullRootLayerDamage();
4904 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4905 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4906 host_impl_
->DidDrawAllLayers(frame
);
4907 Mock::VerifyAndClearExpectations(&mock_context
);
4910 TEST_F(LayerTreeHostImplTest
, ReleaseContentsTextureShouldTriggerCommit
) {
4911 set_reduce_memory_result(false);
4913 // If changing the memory limit wouldn't result in changing what was
4914 // committed, then no commit should be requested.
4915 set_reduce_memory_result(false);
4916 host_impl_
->set_max_memory_needed_bytes(
4917 host_impl_
->memory_allocation_limit_bytes() - 1);
4918 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
4919 host_impl_
->memory_allocation_limit_bytes() - 1));
4920 EXPECT_FALSE(did_request_commit_
);
4921 did_request_commit_
= false;
4923 // If changing the memory limit would result in changing what was
4924 // committed, then a commit should be requested, even though nothing was
4926 set_reduce_memory_result(false);
4927 host_impl_
->set_max_memory_needed_bytes(
4928 host_impl_
->memory_allocation_limit_bytes());
4929 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
4930 host_impl_
->memory_allocation_limit_bytes() - 1));
4931 EXPECT_TRUE(did_request_commit_
);
4932 did_request_commit_
= false;
4934 // Especially if changing the memory limit caused evictions, we need
4936 set_reduce_memory_result(true);
4937 host_impl_
->set_max_memory_needed_bytes(1);
4938 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
4939 host_impl_
->memory_allocation_limit_bytes() - 1));
4940 EXPECT_TRUE(did_request_commit_
);
4941 did_request_commit_
= false;
4943 // But if we set it to the same value that it was before, we shouldn't
4945 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
4946 host_impl_
->memory_allocation_limit_bytes()));
4947 EXPECT_FALSE(did_request_commit_
);
4950 class LayerTreeHostImplTestWithDelegatingRenderer
4951 : public LayerTreeHostImplTest
{
4953 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
4954 return FakeOutputSurface::CreateDelegating3d();
4957 void DrawFrameAndTestDamage(const gfx::RectF
& expected_damage
) {
4958 bool expect_to_draw
= !expected_damage
.IsEmpty();
4960 LayerTreeHostImpl::FrameData frame
;
4961 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4963 if (!expect_to_draw
) {
4964 // With no damage, we don't draw, and no quads are created.
4965 ASSERT_EQ(0u, frame
.render_passes
.size());
4967 ASSERT_EQ(1u, frame
.render_passes
.size());
4969 // Verify the damage rect for the root render pass.
4970 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
4971 EXPECT_RECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
4973 // Verify the root and child layers' quads are generated and not being
4975 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
4977 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
4978 gfx::RectF
expected_child_visible_rect(child
->content_bounds());
4979 EXPECT_RECT_EQ(expected_child_visible_rect
,
4980 root_render_pass
->quad_list
.front()->visible_rect
);
4982 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
4983 gfx::RectF
expected_root_visible_rect(root
->content_bounds());
4984 EXPECT_RECT_EQ(expected_root_visible_rect
,
4985 root_render_pass
->quad_list
.ElementAt(1)->visible_rect
);
4988 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
4989 host_impl_
->DidDrawAllLayers(frame
);
4990 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
4994 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
4995 scoped_ptr
<SolidColorLayerImpl
> root
=
4996 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
4997 root
->SetPosition(gfx::PointF());
4998 root
->SetBounds(gfx::Size(10, 10));
4999 root
->SetContentBounds(gfx::Size(10, 10));
5000 root
->SetDrawsContent(true);
5002 // Child layer is in the bottom right corner.
5003 scoped_ptr
<SolidColorLayerImpl
> child
=
5004 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
5005 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
5006 child
->SetBounds(gfx::Size(1, 1));
5007 child
->SetContentBounds(gfx::Size(1, 1));
5008 child
->SetDrawsContent(true);
5009 root
->AddChild(child
.Pass());
5011 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5013 // Draw a frame. In the first frame, the entire viewport should be damaged.
5014 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
5015 DrawFrameAndTestDamage(full_frame_damage
);
5017 // The second frame has damage that doesn't touch the child layer. Its quads
5018 // should still be generated.
5019 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
5020 host_impl_
->active_tree()->root_layer()->SetUpdateRect(small_damage
);
5021 DrawFrameAndTestDamage(small_damage
);
5023 // The third frame should have no damage, so no quads should be generated.
5024 gfx::Rect no_damage
;
5025 DrawFrameAndTestDamage(no_damage
);
5028 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5029 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5030 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, PreventRasterizeOnDemand
) {
5031 LayerTreeSettings settings
;
5032 CreateHostImpl(settings
, CreateOutputSurface());
5033 EXPECT_FALSE(host_impl_
->GetRendererCapabilities().allow_rasterize_on_demand
);
5036 class FakeMaskLayerImpl
: public LayerImpl
{
5038 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
5040 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
5043 virtual ResourceProvider::ResourceId
ContentsResourceId() const override
{
5048 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5049 : LayerImpl(tree_impl
, id
) {}
5052 TEST_F(LayerTreeHostImplTest
, MaskLayerWithScaling
) {
5053 LayerTreeSettings settings
;
5054 settings
.layer_transforms_should_scale_layer_contents
= true;
5055 CreateHostImpl(settings
, CreateOutputSurface());
5059 // +-- Scaling Layer (adds a 2x scale)
5061 // +-- Content Layer
5063 scoped_ptr
<LayerImpl
> scoped_root
=
5064 LayerImpl::Create(host_impl_
->active_tree(), 1);
5065 LayerImpl
* root
= scoped_root
.get();
5066 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
5068 scoped_ptr
<LayerImpl
> scoped_scaling_layer
=
5069 LayerImpl::Create(host_impl_
->active_tree(), 2);
5070 LayerImpl
* scaling_layer
= scoped_scaling_layer
.get();
5071 root
->AddChild(scoped_scaling_layer
.Pass());
5073 scoped_ptr
<LayerImpl
> scoped_content_layer
=
5074 LayerImpl::Create(host_impl_
->active_tree(), 3);
5075 LayerImpl
* content_layer
= scoped_content_layer
.get();
5076 scaling_layer
->AddChild(scoped_content_layer
.Pass());
5078 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
5079 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 4);
5080 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
5081 content_layer
->SetMaskLayer(scoped_mask_layer
.Pass());
5083 gfx::Size
root_size(100, 100);
5084 root
->SetBounds(root_size
);
5085 root
->SetContentBounds(root_size
);
5086 root
->SetPosition(gfx::PointF());
5088 gfx::Size
scaling_layer_size(50, 50);
5089 scaling_layer
->SetBounds(scaling_layer_size
);
5090 scaling_layer
->SetContentBounds(scaling_layer_size
);
5091 scaling_layer
->SetPosition(gfx::PointF());
5092 gfx::Transform scale
;
5093 scale
.Scale(2.f
, 2.f
);
5094 scaling_layer
->SetTransform(scale
);
5096 content_layer
->SetBounds(scaling_layer_size
);
5097 content_layer
->SetContentBounds(scaling_layer_size
);
5098 content_layer
->SetPosition(gfx::PointF());
5099 content_layer
->SetDrawsContent(true);
5101 mask_layer
->SetBounds(scaling_layer_size
);
5102 mask_layer
->SetContentBounds(scaling_layer_size
);
5103 mask_layer
->SetPosition(gfx::PointF());
5104 mask_layer
->SetDrawsContent(true);
5107 // Check that the tree scaling is correctly taken into account for the mask,
5108 // that should fully map onto the quad.
5109 float device_scale_factor
= 1.f
;
5110 host_impl_
->SetViewportSize(root_size
);
5111 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5113 LayerTreeHostImpl::FrameData frame
;
5114 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5116 ASSERT_EQ(1u, frame
.render_passes
.size());
5117 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5118 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5119 frame
.render_passes
[0]->quad_list
.front()->material
);
5120 const RenderPassDrawQuad
* render_pass_quad
=
5121 RenderPassDrawQuad::MaterialCast(
5122 frame
.render_passes
[0]->quad_list
.front());
5123 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5124 render_pass_quad
->rect
.ToString());
5125 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5126 render_pass_quad
->mask_uv_rect
.ToString());
5128 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5129 host_impl_
->DidDrawAllLayers(frame
);
5133 // Applying a DSF should change the render surface size, but won't affect
5134 // which part of the mask is used.
5135 device_scale_factor
= 2.f
;
5136 gfx::Size device_viewport
=
5137 gfx::ToFlooredSize(gfx::ScaleSize(root_size
, device_scale_factor
));
5138 host_impl_
->SetViewportSize(device_viewport
);
5139 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5140 host_impl_
->active_tree()->set_needs_update_draw_properties();
5142 LayerTreeHostImpl::FrameData frame
;
5143 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5145 ASSERT_EQ(1u, frame
.render_passes
.size());
5146 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5147 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5148 frame
.render_passes
[0]->quad_list
.front()->material
);
5149 const RenderPassDrawQuad
* render_pass_quad
=
5150 RenderPassDrawQuad::MaterialCast(
5151 frame
.render_passes
[0]->quad_list
.front());
5152 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
5153 render_pass_quad
->rect
.ToString());
5154 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5155 render_pass_quad
->mask_uv_rect
.ToString());
5157 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5158 host_impl_
->DidDrawAllLayers(frame
);
5162 // Applying an equivalent content scale on the content layer and the mask
5163 // should still result in the same part of the mask being used.
5164 gfx::Size content_bounds
=
5165 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size
,
5166 device_scale_factor
));
5167 content_layer
->SetContentBounds(content_bounds
);
5168 content_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
5169 mask_layer
->SetContentBounds(content_bounds
);
5170 mask_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
5171 host_impl_
->active_tree()->set_needs_update_draw_properties();
5173 LayerTreeHostImpl::FrameData frame
;
5174 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5176 ASSERT_EQ(1u, frame
.render_passes
.size());
5177 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5178 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5179 frame
.render_passes
[0]->quad_list
.front()->material
);
5180 const RenderPassDrawQuad
* render_pass_quad
=
5181 RenderPassDrawQuad::MaterialCast(
5182 frame
.render_passes
[0]->quad_list
.front());
5183 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
5184 render_pass_quad
->rect
.ToString());
5185 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5186 render_pass_quad
->mask_uv_rect
.ToString());
5188 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5189 host_impl_
->DidDrawAllLayers(frame
);
5193 TEST_F(LayerTreeHostImplTest
, MaskLayerWithDifferentBounds
) {
5194 // The mask layer has bounds 100x100 but is attached to a layer with bounds
5197 scoped_ptr
<LayerImpl
> scoped_root
=
5198 LayerImpl::Create(host_impl_
->active_tree(), 1);
5199 LayerImpl
* root
= scoped_root
.get();
5200 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
5202 scoped_ptr
<LayerImpl
> scoped_content_layer
=
5203 LayerImpl::Create(host_impl_
->active_tree(), 3);
5204 LayerImpl
* content_layer
= scoped_content_layer
.get();
5205 root
->AddChild(scoped_content_layer
.Pass());
5207 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
5208 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 4);
5209 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
5210 content_layer
->SetMaskLayer(scoped_mask_layer
.Pass());
5212 gfx::Size
root_size(100, 100);
5213 root
->SetBounds(root_size
);
5214 root
->SetContentBounds(root_size
);
5215 root
->SetPosition(gfx::PointF());
5217 gfx::Size
layer_size(50, 50);
5218 content_layer
->SetBounds(layer_size
);
5219 content_layer
->SetContentBounds(layer_size
);
5220 content_layer
->SetPosition(gfx::PointF());
5221 content_layer
->SetDrawsContent(true);
5223 gfx::Size
mask_size(100, 100);
5224 mask_layer
->SetBounds(mask_size
);
5225 mask_layer
->SetContentBounds(mask_size
);
5226 mask_layer
->SetPosition(gfx::PointF());
5227 mask_layer
->SetDrawsContent(true);
5229 // Check that the mask fills the surface.
5230 float device_scale_factor
= 1.f
;
5231 host_impl_
->SetViewportSize(root_size
);
5232 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5234 LayerTreeHostImpl::FrameData frame
;
5235 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5237 ASSERT_EQ(1u, frame
.render_passes
.size());
5238 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5239 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5240 frame
.render_passes
[0]->quad_list
.front()->material
);
5241 const RenderPassDrawQuad
* render_pass_quad
=
5242 RenderPassDrawQuad::MaterialCast(
5243 frame
.render_passes
[0]->quad_list
.front());
5244 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5245 render_pass_quad
->rect
.ToString());
5246 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5247 render_pass_quad
->mask_uv_rect
.ToString());
5249 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5250 host_impl_
->DidDrawAllLayers(frame
);
5253 // Applying a DSF should change the render surface size, but won't affect
5254 // which part of the mask is used.
5255 device_scale_factor
= 2.f
;
5256 gfx::Size device_viewport
=
5257 gfx::ToFlooredSize(gfx::ScaleSize(root_size
, device_scale_factor
));
5258 host_impl_
->SetViewportSize(device_viewport
);
5259 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5260 host_impl_
->active_tree()->set_needs_update_draw_properties();
5262 LayerTreeHostImpl::FrameData frame
;
5263 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5265 ASSERT_EQ(1u, frame
.render_passes
.size());
5266 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5267 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5268 frame
.render_passes
[0]->quad_list
.front()->material
);
5269 const RenderPassDrawQuad
* render_pass_quad
=
5270 RenderPassDrawQuad::MaterialCast(
5271 frame
.render_passes
[0]->quad_list
.front());
5272 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5273 render_pass_quad
->rect
.ToString());
5274 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5275 render_pass_quad
->mask_uv_rect
.ToString());
5277 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5278 host_impl_
->DidDrawAllLayers(frame
);
5281 // Applying an equivalent content scale on the content layer and the mask
5282 // should still result in the same part of the mask being used.
5283 gfx::Size layer_size_large
=
5284 gfx::ToRoundedSize(gfx::ScaleSize(layer_size
, device_scale_factor
));
5285 content_layer
->SetContentBounds(layer_size_large
);
5286 content_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
5287 gfx::Size mask_size_large
=
5288 gfx::ToRoundedSize(gfx::ScaleSize(mask_size
, device_scale_factor
));
5289 mask_layer
->SetContentBounds(mask_size_large
);
5290 mask_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
5291 host_impl_
->active_tree()->set_needs_update_draw_properties();
5293 LayerTreeHostImpl::FrameData frame
;
5294 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5296 ASSERT_EQ(1u, frame
.render_passes
.size());
5297 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5298 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5299 frame
.render_passes
[0]->quad_list
.front()->material
);
5300 const RenderPassDrawQuad
* render_pass_quad
=
5301 RenderPassDrawQuad::MaterialCast(
5302 frame
.render_passes
[0]->quad_list
.front());
5303 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5304 render_pass_quad
->rect
.ToString());
5305 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5306 render_pass_quad
->mask_uv_rect
.ToString());
5308 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5309 host_impl_
->DidDrawAllLayers(frame
);
5312 // Applying a different contents scale to the mask layer means it will have
5313 // a larger texture, but it should use the same tex coords to cover the
5315 mask_layer
->SetContentBounds(mask_size
);
5316 mask_layer
->SetContentsScale(1.f
, 1.f
);
5317 host_impl_
->active_tree()->set_needs_update_draw_properties();
5319 LayerTreeHostImpl::FrameData frame
;
5320 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5322 ASSERT_EQ(1u, frame
.render_passes
.size());
5323 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5324 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5325 frame
.render_passes
[0]->quad_list
.front()->material
);
5326 const RenderPassDrawQuad
* render_pass_quad
=
5327 RenderPassDrawQuad::MaterialCast(
5328 frame
.render_passes
[0]->quad_list
.front());
5329 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5330 render_pass_quad
->rect
.ToString());
5331 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5332 render_pass_quad
->mask_uv_rect
.ToString());
5334 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5335 host_impl_
->DidDrawAllLayers(frame
);
5339 TEST_F(LayerTreeHostImplTest
, ReflectionMaskLayerWithDifferentBounds
) {
5340 // The replica's mask layer has bounds 100x100 but the replica is of a
5341 // layer with bounds 50x50.
5343 scoped_ptr
<LayerImpl
> scoped_root
=
5344 LayerImpl::Create(host_impl_
->active_tree(), 1);
5345 LayerImpl
* root
= scoped_root
.get();
5346 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
5348 scoped_ptr
<LayerImpl
> scoped_content_layer
=
5349 LayerImpl::Create(host_impl_
->active_tree(), 3);
5350 LayerImpl
* content_layer
= scoped_content_layer
.get();
5351 root
->AddChild(scoped_content_layer
.Pass());
5353 scoped_ptr
<LayerImpl
> scoped_replica_layer
=
5354 LayerImpl::Create(host_impl_
->active_tree(), 2);
5355 LayerImpl
* replica_layer
= scoped_replica_layer
.get();
5356 content_layer
->SetReplicaLayer(scoped_replica_layer
.Pass());
5358 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
5359 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 4);
5360 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
5361 replica_layer
->SetMaskLayer(scoped_mask_layer
.Pass());
5363 gfx::Size
root_size(100, 100);
5364 root
->SetBounds(root_size
);
5365 root
->SetContentBounds(root_size
);
5366 root
->SetPosition(gfx::PointF());
5368 gfx::Size
layer_size(50, 50);
5369 content_layer
->SetBounds(layer_size
);
5370 content_layer
->SetContentBounds(layer_size
);
5371 content_layer
->SetPosition(gfx::PointF());
5372 content_layer
->SetDrawsContent(true);
5374 gfx::Size
mask_size(100, 100);
5375 mask_layer
->SetBounds(mask_size
);
5376 mask_layer
->SetContentBounds(mask_size
);
5377 mask_layer
->SetPosition(gfx::PointF());
5378 mask_layer
->SetDrawsContent(true);
5380 // Check that the mask fills the surface.
5381 float device_scale_factor
= 1.f
;
5382 host_impl_
->SetViewportSize(root_size
);
5383 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5385 LayerTreeHostImpl::FrameData frame
;
5386 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5388 ASSERT_EQ(1u, frame
.render_passes
.size());
5389 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5390 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5391 frame
.render_passes
[0]->quad_list
.ElementAt(1)->material
);
5392 const RenderPassDrawQuad
* replica_quad
= RenderPassDrawQuad::MaterialCast(
5393 frame
.render_passes
[0]->quad_list
.ElementAt(1));
5394 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5395 replica_quad
->rect
.ToString());
5396 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5397 replica_quad
->mask_uv_rect
.ToString());
5399 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5400 host_impl_
->DidDrawAllLayers(frame
);
5403 // Applying a DSF should change the render surface size, but won't affect
5404 // which part of the mask is used.
5405 device_scale_factor
= 2.f
;
5406 gfx::Size device_viewport
=
5407 gfx::ToFlooredSize(gfx::ScaleSize(root_size
, device_scale_factor
));
5408 host_impl_
->SetViewportSize(device_viewport
);
5409 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5410 host_impl_
->active_tree()->set_needs_update_draw_properties();
5412 LayerTreeHostImpl::FrameData frame
;
5413 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5415 ASSERT_EQ(1u, frame
.render_passes
.size());
5416 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5417 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5418 frame
.render_passes
[0]->quad_list
.ElementAt(1)->material
);
5419 const RenderPassDrawQuad
* replica_quad
= RenderPassDrawQuad::MaterialCast(
5420 frame
.render_passes
[0]->quad_list
.ElementAt(1));
5421 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5422 replica_quad
->rect
.ToString());
5423 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5424 replica_quad
->mask_uv_rect
.ToString());
5426 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5427 host_impl_
->DidDrawAllLayers(frame
);
5430 // Applying an equivalent content scale on the content layer and the mask
5431 // should still result in the same part of the mask being used.
5432 gfx::Size layer_size_large
=
5433 gfx::ToRoundedSize(gfx::ScaleSize(layer_size
, device_scale_factor
));
5434 content_layer
->SetContentBounds(layer_size_large
);
5435 content_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
5436 gfx::Size mask_size_large
=
5437 gfx::ToRoundedSize(gfx::ScaleSize(mask_size
, device_scale_factor
));
5438 mask_layer
->SetContentBounds(mask_size_large
);
5439 mask_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
5440 host_impl_
->active_tree()->set_needs_update_draw_properties();
5442 LayerTreeHostImpl::FrameData frame
;
5443 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5445 ASSERT_EQ(1u, frame
.render_passes
.size());
5446 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5447 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5448 frame
.render_passes
[0]->quad_list
.ElementAt(1)->material
);
5449 const RenderPassDrawQuad
* replica_quad
= RenderPassDrawQuad::MaterialCast(
5450 frame
.render_passes
[0]->quad_list
.ElementAt(1));
5451 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5452 replica_quad
->rect
.ToString());
5453 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5454 replica_quad
->mask_uv_rect
.ToString());
5456 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5457 host_impl_
->DidDrawAllLayers(frame
);
5460 // Applying a different contents scale to the mask layer means it will have
5461 // a larger texture, but it should use the same tex coords to cover the
5463 mask_layer
->SetContentBounds(mask_size
);
5464 mask_layer
->SetContentsScale(1.f
, 1.f
);
5465 host_impl_
->active_tree()->set_needs_update_draw_properties();
5467 LayerTreeHostImpl::FrameData frame
;
5468 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5470 ASSERT_EQ(1u, frame
.render_passes
.size());
5471 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5472 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5473 frame
.render_passes
[0]->quad_list
.ElementAt(1)->material
);
5474 const RenderPassDrawQuad
* replica_quad
= RenderPassDrawQuad::MaterialCast(
5475 frame
.render_passes
[0]->quad_list
.ElementAt(1));
5476 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5477 replica_quad
->rect
.ToString());
5478 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5479 replica_quad
->mask_uv_rect
.ToString());
5481 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5482 host_impl_
->DidDrawAllLayers(frame
);
5486 TEST_F(LayerTreeHostImplTest
, ReflectionMaskLayerForSurfaceWithUnclippedChild
) {
5487 // The replica is of a layer with bounds 50x50, but it has a child that causes
5488 // the surface bounds to be larger.
5490 scoped_ptr
<LayerImpl
> scoped_root
=
5491 LayerImpl::Create(host_impl_
->active_tree(), 1);
5492 LayerImpl
* root
= scoped_root
.get();
5493 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
5495 scoped_ptr
<LayerImpl
> scoped_content_layer
=
5496 LayerImpl::Create(host_impl_
->active_tree(), 2);
5497 LayerImpl
* content_layer
= scoped_content_layer
.get();
5498 root
->AddChild(scoped_content_layer
.Pass());
5500 scoped_ptr
<LayerImpl
> scoped_content_child_layer
=
5501 LayerImpl::Create(host_impl_
->active_tree(), 3);
5502 LayerImpl
* content_child_layer
= scoped_content_child_layer
.get();
5503 content_layer
->AddChild(scoped_content_child_layer
.Pass());
5505 scoped_ptr
<LayerImpl
> scoped_replica_layer
=
5506 LayerImpl::Create(host_impl_
->active_tree(), 4);
5507 LayerImpl
* replica_layer
= scoped_replica_layer
.get();
5508 content_layer
->SetReplicaLayer(scoped_replica_layer
.Pass());
5510 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
5511 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 5);
5512 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
5513 replica_layer
->SetMaskLayer(scoped_mask_layer
.Pass());
5515 gfx::Size
root_size(100, 100);
5516 root
->SetBounds(root_size
);
5517 root
->SetContentBounds(root_size
);
5518 root
->SetPosition(gfx::PointF());
5520 gfx::Size
layer_size(50, 50);
5521 content_layer
->SetBounds(layer_size
);
5522 content_layer
->SetContentBounds(layer_size
);
5523 content_layer
->SetPosition(gfx::PointF());
5524 content_layer
->SetDrawsContent(true);
5526 gfx::Size
child_size(50, 50);
5527 content_child_layer
->SetBounds(child_size
);
5528 content_child_layer
->SetContentBounds(child_size
);
5529 content_child_layer
->SetPosition(gfx::Point(50, 0));
5530 content_child_layer
->SetDrawsContent(true);
5532 gfx::Size
mask_size(50, 50);
5533 mask_layer
->SetBounds(mask_size
);
5534 mask_layer
->SetContentBounds(mask_size
);
5535 mask_layer
->SetPosition(gfx::PointF());
5536 mask_layer
->SetDrawsContent(true);
5538 float device_scale_factor
= 1.f
;
5539 host_impl_
->SetViewportSize(root_size
);
5540 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5542 LayerTreeHostImpl::FrameData frame
;
5543 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5545 ASSERT_EQ(1u, frame
.render_passes
.size());
5546 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5548 // The surface is 100x50.
5549 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5550 frame
.render_passes
[0]->quad_list
.front()->material
);
5551 const RenderPassDrawQuad
* render_pass_quad
=
5552 RenderPassDrawQuad::MaterialCast(
5553 frame
.render_passes
[0]->quad_list
.front());
5554 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5555 render_pass_quad
->rect
.ToString());
5557 // The mask covers the owning layer only.
5558 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5559 frame
.render_passes
[0]->quad_list
.ElementAt(1)->material
);
5560 const RenderPassDrawQuad
* replica_quad
= RenderPassDrawQuad::MaterialCast(
5561 frame
.render_passes
[0]->quad_list
.ElementAt(1));
5562 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5563 replica_quad
->rect
.ToString());
5564 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 2.f
, 1.f
).ToString(),
5565 replica_quad
->mask_uv_rect
.ToString());
5567 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5568 host_impl_
->DidDrawAllLayers(frame
);
5571 // Move the child to (-50, 0) instead. Now the mask should be moved to still
5572 // cover the layer being replicated.
5573 content_child_layer
->SetPosition(gfx::Point(-50, 0));
5575 LayerTreeHostImpl::FrameData frame
;
5576 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5578 ASSERT_EQ(1u, frame
.render_passes
.size());
5579 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5581 // The surface is 100x50 with its origin at (-50, 0).
5582 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5583 frame
.render_passes
[0]->quad_list
.front()->material
);
5584 const RenderPassDrawQuad
* render_pass_quad
=
5585 RenderPassDrawQuad::MaterialCast(
5586 frame
.render_passes
[0]->quad_list
.front());
5587 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5588 render_pass_quad
->rect
.ToString());
5590 // The mask covers the owning layer only.
5591 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5592 frame
.render_passes
[0]->quad_list
.ElementAt(1)->material
);
5593 const RenderPassDrawQuad
* replica_quad
= RenderPassDrawQuad::MaterialCast(
5594 frame
.render_passes
[0]->quad_list
.ElementAt(1));
5595 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5596 replica_quad
->rect
.ToString());
5597 EXPECT_EQ(gfx::RectF(-1.f
, 0.f
, 2.f
, 1.f
).ToString(),
5598 replica_quad
->mask_uv_rect
.ToString());
5600 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5601 host_impl_
->DidDrawAllLayers(frame
);
5605 TEST_F(LayerTreeHostImplTest
, MaskLayerForSurfaceWithClippedLayer
) {
5606 // The masked layer has bounds 50x50, but it has a child that causes
5607 // the surface bounds to be larger. It also has a parent that clips the
5608 // masked layer and its surface.
5610 scoped_ptr
<LayerImpl
> scoped_root
=
5611 LayerImpl::Create(host_impl_
->active_tree(), 1);
5612 LayerImpl
* root
= scoped_root
.get();
5613 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
5615 scoped_ptr
<LayerImpl
> scoped_clipping_layer
=
5616 LayerImpl::Create(host_impl_
->active_tree(), 2);
5617 LayerImpl
* clipping_layer
= scoped_clipping_layer
.get();
5618 root
->AddChild(scoped_clipping_layer
.Pass());
5620 scoped_ptr
<LayerImpl
> scoped_content_layer
=
5621 LayerImpl::Create(host_impl_
->active_tree(), 3);
5622 LayerImpl
* content_layer
= scoped_content_layer
.get();
5623 clipping_layer
->AddChild(scoped_content_layer
.Pass());
5625 scoped_ptr
<LayerImpl
> scoped_content_child_layer
=
5626 LayerImpl::Create(host_impl_
->active_tree(), 4);
5627 LayerImpl
* content_child_layer
= scoped_content_child_layer
.get();
5628 content_layer
->AddChild(scoped_content_child_layer
.Pass());
5630 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
5631 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 6);
5632 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
5633 content_layer
->SetMaskLayer(scoped_mask_layer
.Pass());
5635 gfx::Size
root_size(100, 100);
5636 root
->SetBounds(root_size
);
5637 root
->SetContentBounds(root_size
);
5638 root
->SetPosition(gfx::PointF());
5640 gfx::Rect
clipping_rect(20, 10, 10, 20);
5641 clipping_layer
->SetBounds(clipping_rect
.size());
5642 clipping_layer
->SetContentBounds(clipping_rect
.size());
5643 clipping_layer
->SetPosition(clipping_rect
.origin());
5644 clipping_layer
->SetMasksToBounds(true);
5646 gfx::Size
layer_size(50, 50);
5647 content_layer
->SetBounds(layer_size
);
5648 content_layer
->SetContentBounds(layer_size
);
5649 content_layer
->SetPosition(gfx::Point() - clipping_rect
.OffsetFromOrigin());
5650 content_layer
->SetDrawsContent(true);
5652 gfx::Size
child_size(50, 50);
5653 content_child_layer
->SetBounds(child_size
);
5654 content_child_layer
->SetContentBounds(child_size
);
5655 content_child_layer
->SetPosition(gfx::Point(50, 0));
5656 content_child_layer
->SetDrawsContent(true);
5658 gfx::Size
mask_size(100, 100);
5659 mask_layer
->SetBounds(mask_size
);
5660 mask_layer
->SetContentBounds(mask_size
);
5661 mask_layer
->SetPosition(gfx::PointF());
5662 mask_layer
->SetDrawsContent(true);
5664 float device_scale_factor
= 1.f
;
5665 host_impl_
->SetViewportSize(root_size
);
5666 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5668 LayerTreeHostImpl::FrameData frame
;
5669 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5671 ASSERT_EQ(1u, frame
.render_passes
.size());
5672 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5674 // The surface is clipped to 10x20.
5675 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5676 frame
.render_passes
[0]->quad_list
.front()->material
);
5677 const RenderPassDrawQuad
* render_pass_quad
=
5678 RenderPassDrawQuad::MaterialCast(
5679 frame
.render_passes
[0]->quad_list
.front());
5680 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
5681 render_pass_quad
->rect
.ToString());
5683 // The masked layer is 50x50, but the surface size is 10x20. So the texture
5684 // coords in the mask are scaled by 10/50 and 20/50.
5685 // The surface is clipped to (20,10) so the mask texture coords are offset
5686 // by 20/50 and 10/50
5687 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f
, 10.f
, 10.f
, 20.f
),
5688 1.f
/ 50.f
).ToString(),
5689 render_pass_quad
->mask_uv_rect
.ToString());
5691 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5692 host_impl_
->DidDrawAllLayers(frame
);
5696 class GLRendererWithSetupQuadForAntialiasing
: public GLRenderer
{
5698 using GLRenderer::SetupQuadForAntialiasing
;
5701 TEST_F(LayerTreeHostImplTest
, FarAwayQuadsDontNeedAA
) {
5702 // Due to precision issues (especially on Android), sometimes far
5703 // away quads can end up thinking they need AA.
5704 float device_scale_factor
= 4.f
/ 3.f
;
5705 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5706 gfx::Size
root_size(2000, 1000);
5707 gfx::Size device_viewport_size
=
5708 gfx::ToCeiledSize(gfx::ScaleSize(root_size
, device_scale_factor
));
5709 host_impl_
->SetViewportSize(device_viewport_size
);
5711 host_impl_
->CreatePendingTree();
5712 host_impl_
->pending_tree()
5713 ->SetPageScaleFactorAndLimits(1.f
, 1.f
/ 16.f
, 16.f
);
5715 scoped_ptr
<LayerImpl
> scoped_root
=
5716 LayerImpl::Create(host_impl_
->pending_tree(), 1);
5717 LayerImpl
* root
= scoped_root
.get();
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::CreateWithPile(host_impl_
->pending_tree(), 3, pile
);
5733 LayerImpl
* content_layer
= scoped_content_layer
.get();
5734 scrolling_layer
->AddChild(scoped_content_layer
.Pass());
5735 content_layer
->SetBounds(content_layer_bounds
);
5736 content_layer
->SetDrawsContent(true);
5738 root
->SetBounds(root_size
);
5740 gfx::ScrollOffset
scroll_offset(100000, 0);
5741 scrolling_layer
->SetScrollClipLayer(root
->id());
5742 scrolling_layer
->SetScrollOffset(scroll_offset
);
5744 host_impl_
->ActivateSyncTree();
5746 host_impl_
->active_tree()->UpdateDrawProperties();
5747 ASSERT_EQ(1u, host_impl_
->active_tree()->RenderSurfaceLayerList().size());
5749 LayerTreeHostImpl::FrameData frame
;
5750 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5752 ASSERT_EQ(1u, frame
.render_passes
.size());
5753 ASSERT_LE(1u, frame
.render_passes
[0]->quad_list
.size());
5754 const DrawQuad
* quad
= frame
.render_passes
[0]->quad_list
.front();
5757 gfx::QuadF device_layer_quad
;
5759 GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
5760 quad
->quadTransform(), quad
, &device_layer_quad
, edge
);
5761 EXPECT_FALSE(antialiased
);
5763 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5764 host_impl_
->DidDrawAllLayers(frame
);
5768 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
5770 CompositorFrameMetadataTest()
5771 : swap_buffers_complete_(0) {}
5773 virtual 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
, base::TimeTicks());
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 virtual SkCanvas
* BeginPaint(const gfx::Rect
& damage_rect
) override
{
5800 return SoftwareOutputDevice::BeginPaint(damage_rect
);
5802 virtual 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 bool delegated_rendering
= false;
5815 FakeOutputSurface
* output_surface
=
5816 FakeOutputSurface::CreateDeferredGL(
5817 scoped_ptr
<SoftwareOutputDevice
>(software_device
),
5818 delegated_rendering
).release();
5819 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5820 scoped_ptr
<OutputSurface
>(output_surface
)));
5821 host_impl_
->SetViewportSize(gfx::Size(50, 50));
5823 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5825 const gfx::Transform external_transform
;
5826 const gfx::Rect external_viewport
;
5827 const gfx::Rect external_clip
;
5828 const bool resourceless_software_draw
= true;
5829 host_impl_
->SetExternalDrawConstraints(external_transform
,
5834 resourceless_software_draw
);
5836 EXPECT_EQ(0, software_device
->frames_began_
);
5837 EXPECT_EQ(0, software_device
->frames_ended_
);
5841 EXPECT_EQ(1, software_device
->frames_began_
);
5842 EXPECT_EQ(1, software_device
->frames_ended_
);
5844 // Call other API methods that are likely to hit NULL pointer in this mode.
5845 EXPECT_TRUE(host_impl_
->AsValue().get());
5846 EXPECT_TRUE(host_impl_
->ActivationStateAsValue().get());
5849 TEST_F(LayerTreeHostImplTest
,
5850 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers
) {
5851 set_reduce_memory_result(false);
5852 bool delegated_rendering
= false;
5853 FakeOutputSurface
* output_surface
=
5854 FakeOutputSurface::CreateDeferredGL(
5855 scoped_ptr
<SoftwareOutputDevice
>(new CountingSoftwareDevice()),
5856 delegated_rendering
).release();
5857 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5858 scoped_ptr
<OutputSurface
>(output_surface
)));
5860 const gfx::Transform external_transform
;
5861 const gfx::Rect external_viewport
;
5862 const gfx::Rect external_clip
;
5863 const bool resourceless_software_draw
= true;
5864 host_impl_
->SetExternalDrawConstraints(external_transform
,
5869 resourceless_software_draw
);
5871 // SolidColorLayerImpl will be drawn.
5872 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
5873 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
5875 // VideoLayerImpl will not be drawn.
5876 FakeVideoFrameProvider provider
;
5877 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
5878 host_impl_
->active_tree(), 2, &provider
, media::VIDEO_ROTATION_0
);
5879 video_layer
->SetBounds(gfx::Size(10, 10));
5880 video_layer
->SetContentBounds(gfx::Size(10, 10));
5881 video_layer
->SetDrawsContent(true);
5882 root_layer
->AddChild(video_layer
.Pass());
5883 SetupRootLayerImpl(root_layer
.Pass());
5885 LayerTreeHostImpl::FrameData frame
;
5886 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5887 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
5888 host_impl_
->DidDrawAllLayers(frame
);
5890 EXPECT_EQ(1u, frame
.will_draw_layers
.size());
5891 EXPECT_EQ(host_impl_
->active_tree()->root_layer(), frame
.will_draw_layers
[0]);
5894 class LayerTreeHostImplTestDeferredInitialize
: public LayerTreeHostImplTest
{
5896 virtual void SetUp() override
{
5897 LayerTreeHostImplTest::SetUp();
5899 set_reduce_memory_result(false);
5901 bool delegated_rendering
= false;
5902 scoped_ptr
<FakeOutputSurface
> output_surface(
5903 FakeOutputSurface::CreateDeferredGL(
5904 scoped_ptr
<SoftwareOutputDevice
>(new CountingSoftwareDevice()),
5905 delegated_rendering
));
5906 output_surface_
= output_surface
.get();
5908 EXPECT_TRUE(CreateHostImpl(DefaultSettings(), output_surface
.Pass()));
5910 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
5911 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
5912 SetupRootLayerImpl(root_layer
.Pass());
5914 onscreen_context_provider_
= TestContextProvider::Create();
5917 virtual void UpdateRendererCapabilitiesOnImplThread() override
{
5918 did_update_renderer_capabilities_
= true;
5921 FakeOutputSurface
* output_surface_
;
5922 scoped_refptr
<TestContextProvider
> onscreen_context_provider_
;
5923 bool did_update_renderer_capabilities_
;
5927 TEST_F(LayerTreeHostImplTestDeferredInitialize
, Success
) {
5931 EXPECT_FALSE(host_impl_
->output_surface()->context_provider());
5933 // DeferredInitialize and hardware draw.
5934 did_update_renderer_capabilities_
= false;
5936 output_surface_
->InitializeAndSetContext3d(onscreen_context_provider_
));
5937 EXPECT_EQ(onscreen_context_provider_
.get(),
5938 host_impl_
->output_surface()->context_provider());
5939 EXPECT_TRUE(did_update_renderer_capabilities_
);
5941 // Defer intialized GL draw.
5944 // Revert back to software.
5945 did_update_renderer_capabilities_
= false;
5946 output_surface_
->ReleaseGL();
5947 EXPECT_FALSE(host_impl_
->output_surface()->context_provider());
5948 EXPECT_TRUE(did_update_renderer_capabilities_
);
5950 // Software draw again.
5954 TEST_F(LayerTreeHostImplTestDeferredInitialize
, Fails
) {
5958 // Fail initialization of the onscreen context before the OutputSurface binds
5959 // it to the thread.
5960 onscreen_context_provider_
->UnboundTestContext3d()->set_context_lost(true);
5962 EXPECT_FALSE(host_impl_
->output_surface()->context_provider());
5964 // DeferredInitialize fails.
5965 did_update_renderer_capabilities_
= false;
5967 output_surface_
->InitializeAndSetContext3d(onscreen_context_provider_
));
5968 EXPECT_FALSE(host_impl_
->output_surface()->context_provider());
5969 EXPECT_FALSE(did_update_renderer_capabilities_
);
5971 // Software draw again.
5975 // Checks that we have a non-0 default allocation if we pass a context that
5976 // doesn't support memory management extensions.
5977 TEST_F(LayerTreeHostImplTest
, DefaultMemoryAllocation
) {
5978 LayerTreeSettings settings
;
5979 host_impl_
= LayerTreeHostImpl::Create(settings
,
5982 &stats_instrumentation_
,
5983 shared_bitmap_manager_
.get(),
5986 scoped_ptr
<OutputSurface
> output_surface(
5987 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5988 host_impl_
->InitializeRenderer(output_surface
.Pass());
5989 EXPECT_LT(0ul, host_impl_
->memory_allocation_limit_bytes());
5992 TEST_F(LayerTreeHostImplTest
, MemoryPolicy
) {
5993 ManagedMemoryPolicy
policy1(
5994 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING
, 1000);
5995 int everything_cutoff_value
= ManagedMemoryPolicy::PriorityCutoffToValue(
5996 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING
);
5997 int allow_nice_to_have_cutoff_value
=
5998 ManagedMemoryPolicy::PriorityCutoffToValue(
5999 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE
);
6000 int nothing_cutoff_value
= ManagedMemoryPolicy::PriorityCutoffToValue(
6001 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING
);
6003 // GPU rasterization should be disabled by default on the tree(s)
6004 EXPECT_FALSE(host_impl_
->active_tree()->use_gpu_rasterization());
6005 EXPECT_TRUE(host_impl_
->pending_tree() == NULL
);
6007 host_impl_
->SetVisible(true);
6008 host_impl_
->SetMemoryPolicy(policy1
);
6009 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
6010 EXPECT_EQ(everything_cutoff_value
, current_priority_cutoff_value_
);
6012 host_impl_
->SetVisible(false);
6013 EXPECT_EQ(0u, current_limit_bytes_
);
6014 EXPECT_EQ(nothing_cutoff_value
, current_priority_cutoff_value_
);
6016 host_impl_
->SetVisible(true);
6017 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
6018 EXPECT_EQ(everything_cutoff_value
, current_priority_cutoff_value_
);
6020 // Now enable GPU rasterization and test if we get nice to have cutoff,
6022 LayerTreeSettings settings
;
6023 settings
.gpu_rasterization_enabled
= true;
6024 host_impl_
= LayerTreeHostImpl::Create(
6025 settings
, this, &proxy_
, &stats_instrumentation_
, NULL
, 0);
6026 host_impl_
->SetUseGpuRasterization(true);
6027 host_impl_
->SetVisible(true);
6028 host_impl_
->SetMemoryPolicy(policy1
);
6029 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
6030 EXPECT_EQ(allow_nice_to_have_cutoff_value
, current_priority_cutoff_value_
);
6032 host_impl_
->SetVisible(false);
6033 EXPECT_EQ(0u, current_limit_bytes_
);
6034 EXPECT_EQ(nothing_cutoff_value
, current_priority_cutoff_value_
);
6037 TEST_F(LayerTreeHostImplTest
, RequireHighResWhenVisible
) {
6038 ASSERT_TRUE(host_impl_
->active_tree());
6040 // RequiresHighResToDraw is set when new output surface is used.
6041 EXPECT_TRUE(host_impl_
->active_tree()->RequiresHighResToDraw());
6043 host_impl_
->active_tree()->ResetRequiresHighResToDraw();
6045 host_impl_
->SetVisible(false);
6046 EXPECT_FALSE(host_impl_
->active_tree()->RequiresHighResToDraw());
6047 host_impl_
->SetVisible(true);
6048 EXPECT_TRUE(host_impl_
->active_tree()->RequiresHighResToDraw());
6049 host_impl_
->SetVisible(false);
6050 EXPECT_TRUE(host_impl_
->active_tree()->RequiresHighResToDraw());
6052 host_impl_
->active_tree()->ResetRequiresHighResToDraw();
6054 EXPECT_FALSE(host_impl_
->active_tree()->RequiresHighResToDraw());
6055 host_impl_
->SetVisible(true);
6056 EXPECT_TRUE(host_impl_
->active_tree()->RequiresHighResToDraw());
6059 TEST_F(LayerTreeHostImplTest
, RequireHighResAfterGpuRasterizationToggles
) {
6060 ASSERT_TRUE(host_impl_
->active_tree());
6061 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
6063 // RequiresHighResToDraw is set when new output surface is used.
6064 EXPECT_TRUE(host_impl_
->active_tree()->RequiresHighResToDraw());
6066 host_impl_
->active_tree()->ResetRequiresHighResToDraw();
6068 host_impl_
->SetUseGpuRasterization(false);
6069 EXPECT_FALSE(host_impl_
->active_tree()->RequiresHighResToDraw());
6070 host_impl_
->SetUseGpuRasterization(true);
6071 EXPECT_TRUE(host_impl_
->active_tree()->RequiresHighResToDraw());
6072 host_impl_
->SetUseGpuRasterization(false);
6073 EXPECT_TRUE(host_impl_
->active_tree()->RequiresHighResToDraw());
6075 host_impl_
->active_tree()->ResetRequiresHighResToDraw();
6077 EXPECT_FALSE(host_impl_
->active_tree()->RequiresHighResToDraw());
6078 host_impl_
->SetUseGpuRasterization(true);
6079 EXPECT_TRUE(host_impl_
->active_tree()->RequiresHighResToDraw());
6082 class LayerTreeHostImplTestManageTiles
: public LayerTreeHostImplTest
{
6084 virtual void SetUp() override
{
6085 LayerTreeSettings settings
;
6086 settings
.impl_side_painting
= true;
6088 fake_host_impl_
= new FakeLayerTreeHostImpl(
6089 settings
, &proxy_
, shared_bitmap_manager_
.get());
6090 host_impl_
.reset(fake_host_impl_
);
6091 host_impl_
->InitializeRenderer(CreateOutputSurface());
6092 host_impl_
->SetViewportSize(gfx::Size(10, 10));
6095 FakeLayerTreeHostImpl
* fake_host_impl_
;
6098 TEST_F(LayerTreeHostImplTestManageTiles
, ManageTilesWhenInvisible
) {
6099 fake_host_impl_
->DidModifyTilePriorities();
6100 EXPECT_TRUE(fake_host_impl_
->manage_tiles_needed());
6101 fake_host_impl_
->SetVisible(false);
6102 EXPECT_FALSE(fake_host_impl_
->manage_tiles_needed());
6105 TEST_F(LayerTreeHostImplTest
, UIResourceManagement
) {
6106 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6107 TestWebGraphicsContext3D::Create();
6108 TestWebGraphicsContext3D
* context3d
= context
.get();
6109 scoped_ptr
<FakeOutputSurface
> output_surface
= FakeOutputSurface::Create3d();
6110 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6112 EXPECT_EQ(0u, context3d
->NumTextures());
6114 UIResourceId ui_resource_id
= 1;
6115 bool is_opaque
= false;
6116 UIResourceBitmap
bitmap(gfx::Size(1, 1), is_opaque
);
6117 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6118 EXPECT_EQ(1u, context3d
->NumTextures());
6119 ResourceProvider::ResourceId id1
=
6120 host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6123 // Multiple requests with the same id is allowed. The previous texture is
6125 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6126 EXPECT_EQ(1u, context3d
->NumTextures());
6127 ResourceProvider::ResourceId id2
=
6128 host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6130 EXPECT_NE(id1
, id2
);
6132 // Deleting invalid UIResourceId is allowed and does not change state.
6133 host_impl_
->DeleteUIResource(-1);
6134 EXPECT_EQ(1u, context3d
->NumTextures());
6136 // Should return zero for invalid UIResourceId. Number of textures should
6138 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(-1));
6139 EXPECT_EQ(1u, context3d
->NumTextures());
6141 host_impl_
->DeleteUIResource(ui_resource_id
);
6142 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(ui_resource_id
));
6143 EXPECT_EQ(0u, context3d
->NumTextures());
6145 // Should not change state for multiple deletion on one UIResourceId
6146 host_impl_
->DeleteUIResource(ui_resource_id
);
6147 EXPECT_EQ(0u, context3d
->NumTextures());
6150 TEST_F(LayerTreeHostImplTest
, CreateETC1UIResource
) {
6151 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6152 TestWebGraphicsContext3D::Create();
6153 TestWebGraphicsContext3D
* context3d
= context
.get();
6154 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6156 EXPECT_EQ(0u, context3d
->NumTextures());
6158 gfx::Size
size(4, 4);
6159 // SkImageInfo has no support for ETC1. The |info| below contains the right
6160 // total pixel size for the bitmap but not the right height and width. The
6161 // correct width/height are passed directly to UIResourceBitmap.
6163 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType
, kPremul_SkAlphaType
);
6164 skia::RefPtr
<SkPixelRef
> pixel_ref
=
6165 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info
, 0, 0));
6166 pixel_ref
->setImmutable();
6167 UIResourceBitmap
bitmap(pixel_ref
, size
);
6168 UIResourceId ui_resource_id
= 1;
6169 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6170 EXPECT_EQ(1u, context3d
->NumTextures());
6171 ResourceProvider::ResourceId id1
=
6172 host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6176 void ShutdownReleasesContext_Callback(scoped_ptr
<CopyOutputResult
> result
) {
6179 TEST_F(LayerTreeHostImplTest
, ShutdownReleasesContext
) {
6180 scoped_refptr
<TestContextProvider
> context_provider
=
6181 TestContextProvider::Create();
6183 CreateHostImpl(DefaultSettings(),
6184 FakeOutputSurface::Create3d(context_provider
));
6186 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6188 ScopedPtrVector
<CopyOutputRequest
> requests
;
6189 requests
.push_back(CopyOutputRequest::CreateRequest(
6190 base::Bind(&ShutdownReleasesContext_Callback
)));
6192 host_impl_
->active_tree()->root_layer()->PassCopyRequests(&requests
);
6194 LayerTreeHostImpl::FrameData frame
;
6195 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6196 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
6197 host_impl_
->DidDrawAllLayers(frame
);
6199 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6200 // texture in a texture mailbox.
6201 EXPECT_FALSE(context_provider
->HasOneRef());
6202 EXPECT_EQ(1u, context_provider
->TestContext3d()->NumTextures());
6204 host_impl_
= nullptr;
6206 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6207 // released, and the texture deleted.
6208 EXPECT_TRUE(context_provider
->HasOneRef());
6209 EXPECT_EQ(0u, context_provider
->TestContext3d()->NumTextures());
6212 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldNotBubble
) {
6213 // When flinging via touch, only the child should scroll (we should not
6215 gfx::Size
surface_size(10, 10);
6216 gfx::Size
content_size(20, 20);
6217 scoped_ptr
<LayerImpl
> root_clip
=
6218 LayerImpl::Create(host_impl_
->active_tree(), 3);
6219 scoped_ptr
<LayerImpl
> root
=
6220 CreateScrollableLayer(1, content_size
, root_clip
.get());
6221 root
->SetIsContainerForFixedPositionLayers(true);
6222 scoped_ptr
<LayerImpl
> child
=
6223 CreateScrollableLayer(2, content_size
, root_clip
.get());
6225 root
->AddChild(child
.Pass());
6226 int root_id
= root
->id();
6227 root_clip
->AddChild(root
.Pass());
6229 host_impl_
->SetViewportSize(surface_size
);
6230 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6231 host_impl_
->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID
);
6232 host_impl_
->active_tree()->DidBecomeActive();
6235 EXPECT_EQ(InputHandler::ScrollStarted
,
6236 host_impl_
->ScrollBegin(gfx::Point(),
6237 InputHandler::Gesture
));
6239 EXPECT_EQ(InputHandler::ScrollStarted
,
6240 host_impl_
->FlingScrollBegin());
6242 gfx::Vector2d
scroll_delta(0, 100);
6243 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6244 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6246 host_impl_
->ScrollEnd();
6248 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6249 host_impl_
->ProcessScrollDeltas();
6251 // Only the child should have scrolled.
6252 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6253 ExpectNone(*scroll_info
.get(), root_id
);
6257 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldLockToFirstScrolledLayer
) {
6258 // Scroll a child layer beyond its maximum scroll range and make sure the
6259 // the scroll doesn't bubble up to the parent layer.
6260 gfx::Size
surface_size(10, 10);
6261 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
6262 scoped_ptr
<LayerImpl
> root_scrolling
=
6263 CreateScrollableLayer(2, surface_size
, root
.get());
6265 scoped_ptr
<LayerImpl
> grand_child
=
6266 CreateScrollableLayer(4, surface_size
, root
.get());
6267 grand_child
->SetScrollOffset(gfx::ScrollOffset(0, 2));
6269 scoped_ptr
<LayerImpl
> child
=
6270 CreateScrollableLayer(3, surface_size
, root
.get());
6271 child
->SetScrollOffset(gfx::ScrollOffset(0, 4));
6272 child
->AddChild(grand_child
.Pass());
6274 root_scrolling
->AddChild(child
.Pass());
6275 root
->AddChild(root_scrolling
.Pass());
6276 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6277 host_impl_
->active_tree()->DidBecomeActive();
6278 host_impl_
->SetViewportSize(surface_size
);
6281 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
6283 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
6284 LayerImpl
* grand_child
= child
->children()[0];
6286 gfx::Vector2d
scroll_delta(0, -2);
6287 EXPECT_EQ(InputHandler::ScrollStarted
,
6288 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
6289 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
));
6291 // The grand child should have scrolled up to its limit.
6292 scroll_info
= host_impl_
->ProcessScrollDeltas();
6293 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6294 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6295 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6297 // The child should have received the bubbled delta, but the locked
6298 // scrolling layer should remain set as the grand child.
6299 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
));
6300 scroll_info
= host_impl_
->ProcessScrollDeltas();
6301 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6302 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6303 ExpectContains(*scroll_info
, child
->id(), scroll_delta
);
6304 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6306 // The first |ScrollBy| after the fling should re-lock the scrolling
6307 // layer to the first layer that scrolled, which is the child.
6308 EXPECT_EQ(InputHandler::ScrollStarted
, host_impl_
->FlingScrollBegin());
6309 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
));
6310 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6312 // The child should have scrolled up to its limit.
6313 scroll_info
= host_impl_
->ProcessScrollDeltas();
6314 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6315 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6316 ExpectContains(*scroll_info
, child
->id(), scroll_delta
+ scroll_delta
);
6318 // As the locked layer is at it's limit, no further scrolling can occur.
6319 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
));
6320 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6321 host_impl_
->ScrollEnd();
6325 TEST_F(LayerTreeHostImplTest
, WheelFlingShouldBubble
) {
6326 // When flinging via wheel, the root should eventually scroll (we should
6328 gfx::Size
surface_size(10, 10);
6329 gfx::Size
content_size(20, 20);
6330 scoped_ptr
<LayerImpl
> root_clip
=
6331 LayerImpl::Create(host_impl_
->active_tree(), 3);
6332 scoped_ptr
<LayerImpl
> root_scroll
=
6333 CreateScrollableLayer(1, content_size
, root_clip
.get());
6334 int root_scroll_id
= root_scroll
->id();
6335 scoped_ptr
<LayerImpl
> child
=
6336 CreateScrollableLayer(2, content_size
, root_clip
.get());
6338 root_scroll
->AddChild(child
.Pass());
6339 root_clip
->AddChild(root_scroll
.Pass());
6341 host_impl_
->SetViewportSize(surface_size
);
6342 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6343 host_impl_
->active_tree()->DidBecomeActive();
6346 EXPECT_EQ(InputHandler::ScrollStarted
,
6347 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
6349 EXPECT_EQ(InputHandler::ScrollStarted
,
6350 host_impl_
->FlingScrollBegin());
6352 gfx::Vector2d
scroll_delta(0, 100);
6353 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6354 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6356 host_impl_
->ScrollEnd();
6358 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6359 host_impl_
->ProcessScrollDeltas();
6361 // The root should have scrolled.
6362 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6363 ExpectContains(*scroll_info
.get(), root_scroll_id
, gfx::Vector2d(0, 10));
6367 TEST_F(LayerTreeHostImplTest
, ScrollUnknownNotOnAncestorChain
) {
6368 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6369 // we should return ScrollUnknown.
6370 gfx::Size
content_size(100, 100);
6371 SetupScrollAndContentsLayers(content_size
);
6373 int scroll_layer_id
= 2;
6374 LayerImpl
* scroll_layer
=
6375 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6376 scroll_layer
->SetDrawsContent(true);
6378 int page_scale_layer_id
= 5;
6379 LayerImpl
* page_scale_layer
=
6380 host_impl_
->active_tree()->LayerById(page_scale_layer_id
);
6382 int occluder_layer_id
= 6;
6383 scoped_ptr
<LayerImpl
> occluder_layer
=
6384 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6385 occluder_layer
->SetDrawsContent(true);
6386 occluder_layer
->SetBounds(content_size
);
6387 occluder_layer
->SetContentBounds(content_size
);
6388 occluder_layer
->SetPosition(gfx::PointF());
6390 // The parent of the occluder is *above* the scroller.
6391 page_scale_layer
->AddChild(occluder_layer
.Pass());
6395 EXPECT_EQ(InputHandler::ScrollUnknown
,
6396 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
6399 TEST_F(LayerTreeHostImplTest
, ScrollUnknownScrollAncestorMismatch
) {
6400 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6401 // is not the first scroller we encounter when walking up from the layer, we
6402 // should also return ScrollUnknown.
6403 gfx::Size
content_size(100, 100);
6404 SetupScrollAndContentsLayers(content_size
);
6406 int scroll_layer_id
= 2;
6407 LayerImpl
* scroll_layer
=
6408 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6409 scroll_layer
->SetDrawsContent(true);
6411 int occluder_layer_id
= 6;
6412 scoped_ptr
<LayerImpl
> occluder_layer
=
6413 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6414 occluder_layer
->SetDrawsContent(true);
6415 occluder_layer
->SetBounds(content_size
);
6416 occluder_layer
->SetContentBounds(content_size
);
6417 occluder_layer
->SetPosition(gfx::PointF(-10.f
, -10.f
));
6419 int child_scroll_clip_layer_id
= 7;
6420 scoped_ptr
<LayerImpl
> child_scroll_clip
=
6421 LayerImpl::Create(host_impl_
->active_tree(), child_scroll_clip_layer_id
);
6423 int child_scroll_layer_id
= 8;
6424 scoped_ptr
<LayerImpl
> child_scroll
= CreateScrollableLayer(
6425 child_scroll_layer_id
, content_size
, child_scroll_clip
.get());
6427 child_scroll
->SetPosition(gfx::PointF(10.f
, 10.f
));
6429 child_scroll
->AddChild(occluder_layer
.Pass());
6430 scroll_layer
->AddChild(child_scroll
.Pass());
6434 EXPECT_EQ(InputHandler::ScrollUnknown
,
6435 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
6438 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScroller
) {
6439 gfx::Size
content_size(100, 100);
6440 SetupScrollAndContentsLayers(content_size
);
6442 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6444 int scroll_layer_id
= 2;
6445 LayerImpl
* scroll_layer
=
6446 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6448 int child_scroll_layer_id
= 7;
6449 scoped_ptr
<LayerImpl
> child_scroll
=
6450 CreateScrollableLayer(child_scroll_layer_id
, content_size
, root
);
6451 child_scroll
->SetDrawsContent(false);
6453 scroll_layer
->AddChild(child_scroll
.Pass());
6457 // We should not have scrolled |child_scroll| even though we technically "hit"
6458 // it. The reason for this is that if the scrolling the scroll would not move
6459 // any layer that is a drawn RSLL member, then we can ignore the hit.
6461 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6462 // overscrolling the inner viewport.
6463 EXPECT_EQ(InputHandler::ScrollStarted
,
6464 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
6466 EXPECT_EQ(2, host_impl_
->CurrentlyScrollingLayer()->id());
6469 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleScrollChild
) {
6470 // This test case is very similar to the one above with one key difference:
6471 // the invisible scroller has a scroll child that is indeed draw contents.
6472 // If we attempt to initiate a gesture scroll off of the visible scroll child
6473 // we should still start the scroll child.
6474 gfx::Size
content_size(100, 100);
6475 SetupScrollAndContentsLayers(content_size
);
6477 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6479 int scroll_layer_id
= 2;
6480 LayerImpl
* scroll_layer
=
6481 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6483 int scroll_child_id
= 6;
6484 scoped_ptr
<LayerImpl
> scroll_child
=
6485 LayerImpl::Create(host_impl_
->active_tree(), scroll_child_id
);
6486 scroll_child
->SetDrawsContent(true);
6487 scroll_child
->SetBounds(content_size
);
6488 scroll_child
->SetContentBounds(content_size
);
6489 // Move the scroll child so it's not hit by our test point.
6490 scroll_child
->SetPosition(gfx::PointF(10.f
, 10.f
));
6492 int invisible_scroll_layer_id
= 7;
6493 scoped_ptr
<LayerImpl
> invisible_scroll
=
6494 CreateScrollableLayer(invisible_scroll_layer_id
, content_size
, root
);
6495 invisible_scroll
->SetDrawsContent(false);
6497 int container_id
= 8;
6498 scoped_ptr
<LayerImpl
> container
=
6499 LayerImpl::Create(host_impl_
->active_tree(), container_id
);
6501 scoped_ptr
<std::set
<LayerImpl
*> > scroll_children(new std::set
<LayerImpl
*>());
6502 scroll_children
->insert(scroll_child
.get());
6503 invisible_scroll
->SetScrollChildren(scroll_children
.release());
6505 scroll_child
->SetScrollParent(invisible_scroll
.get());
6507 container
->AddChild(invisible_scroll
.Pass());
6508 container
->AddChild(scroll_child
.Pass());
6510 scroll_layer
->AddChild(container
.Pass());
6514 // We should not have scrolled |child_scroll| even though we technically "hit"
6515 // it. The reason for this is that if the scrolling the scroll would not move
6516 // any layer that is a drawn RSLL member, then we can ignore the hit.
6518 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6519 // overscrolling the inner viewport.
6520 EXPECT_EQ(InputHandler::ScrollStarted
,
6521 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Wheel
));
6523 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6526 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6527 // to CompositorFrameMetadata after SwapBuffers();
6528 TEST_F(LayerTreeHostImplTest
, LatencyInfoPassedToCompositorFrameMetadata
) {
6529 scoped_ptr
<SolidColorLayerImpl
> root
=
6530 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6531 root
->SetPosition(gfx::PointF());
6532 root
->SetBounds(gfx::Size(10, 10));
6533 root
->SetContentBounds(gfx::Size(10, 10));
6534 root
->SetDrawsContent(true);
6536 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6538 FakeOutputSurface
* fake_output_surface
=
6539 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6541 const std::vector
<ui::LatencyInfo
>& metadata_latency_before
=
6542 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6543 EXPECT_TRUE(metadata_latency_before
.empty());
6545 ui::LatencyInfo latency_info
;
6546 latency_info
.AddLatencyNumber(
6547 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, 0);
6548 scoped_ptr
<SwapPromise
> swap_promise(
6549 new LatencyInfoSwapPromise(latency_info
));
6550 host_impl_
->active_tree()->QueueSwapPromise(swap_promise
.Pass());
6551 host_impl_
->SetNeedsRedraw();
6553 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6554 LayerTreeHostImpl::FrameData frame
;
6555 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6556 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
6557 host_impl_
->DidDrawAllLayers(frame
);
6558 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6560 const std::vector
<ui::LatencyInfo
>& metadata_latency_after
=
6561 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6562 EXPECT_EQ(1u, metadata_latency_after
.size());
6563 EXPECT_TRUE(metadata_latency_after
[0].FindLatency(
6564 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, NULL
));
6567 TEST_F(LayerTreeHostImplTest
, SelectionBoundsPassedToCompositorFrameMetadata
) {
6568 int root_layer_id
= 1;
6569 scoped_ptr
<SolidColorLayerImpl
> root
=
6570 SolidColorLayerImpl::Create(host_impl_
->active_tree(), root_layer_id
);
6571 root
->SetPosition(gfx::PointF());
6572 root
->SetBounds(gfx::Size(10, 10));
6573 root
->SetContentBounds(gfx::Size(10, 10));
6574 root
->SetDrawsContent(true);
6576 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6578 // Ensure the default frame selection bounds are empty.
6579 FakeOutputSurface
* fake_output_surface
=
6580 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6581 const ViewportSelectionBound
& selection_start_before
=
6582 fake_output_surface
->last_sent_frame().metadata
.selection_start
;
6583 const ViewportSelectionBound
& selection_end_before
=
6584 fake_output_surface
->last_sent_frame().metadata
.selection_end
;
6585 EXPECT_EQ(ViewportSelectionBound(), selection_start_before
);
6586 EXPECT_EQ(ViewportSelectionBound(), selection_end_before
);
6588 // Plumb the layer-local selection bounds.
6589 gfx::PointF
selection_top(5, 0);
6590 gfx::PointF
selection_bottom(5, 5);
6591 LayerSelectionBound start
, end
;
6592 start
.type
= SELECTION_BOUND_CENTER
;
6593 start
.layer_id
= root_layer_id
;
6594 start
.edge_bottom
= selection_bottom
;
6595 start
.edge_top
= selection_top
;
6597 host_impl_
->active_tree()->RegisterSelection(start
, end
);
6599 // Trigger a draw-swap sequence.
6600 host_impl_
->SetNeedsRedraw();
6602 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6603 LayerTreeHostImpl::FrameData frame
;
6604 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6605 host_impl_
->DrawLayers(&frame
, gfx::FrameTime::Now());
6606 host_impl_
->DidDrawAllLayers(frame
);
6607 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6609 // Ensure the selection bounds have propagated to the frame metadata.
6610 const ViewportSelectionBound
& selection_start_after
=
6611 fake_output_surface
->last_sent_frame().metadata
.selection_start
;
6612 const ViewportSelectionBound
& selection_end_after
=
6613 fake_output_surface
->last_sent_frame().metadata
.selection_end
;
6614 EXPECT_EQ(start
.type
, selection_start_after
.type
);
6615 EXPECT_EQ(end
.type
, selection_end_after
.type
);
6616 EXPECT_EQ(selection_bottom
, selection_start_after
.edge_bottom
);
6617 EXPECT_EQ(selection_top
, selection_start_after
.edge_top
);
6618 EXPECT_TRUE(selection_start_after
.visible
);
6619 EXPECT_TRUE(selection_start_after
.visible
);
6622 class SimpleSwapPromiseMonitor
: public SwapPromiseMonitor
{
6624 SimpleSwapPromiseMonitor(LayerTreeHost
* layer_tree_host
,
6625 LayerTreeHostImpl
* layer_tree_host_impl
,
6626 int* set_needs_commit_count
,
6627 int* set_needs_redraw_count
,
6628 int* forward_to_main_count
)
6629 : SwapPromiseMonitor(layer_tree_host
, layer_tree_host_impl
),
6630 set_needs_commit_count_(set_needs_commit_count
),
6631 set_needs_redraw_count_(set_needs_redraw_count
),
6632 forward_to_main_count_(forward_to_main_count
) {}
6634 virtual ~SimpleSwapPromiseMonitor() {}
6636 virtual void OnSetNeedsCommitOnMain() override
{
6637 (*set_needs_commit_count_
)++;
6640 virtual void OnSetNeedsRedrawOnImpl() override
{
6641 (*set_needs_redraw_count_
)++;
6644 virtual void OnForwardScrollUpdateToMainThreadOnImpl() override
{
6645 (*forward_to_main_count_
)++;
6649 int* set_needs_commit_count_
;
6650 int* set_needs_redraw_count_
;
6651 int* forward_to_main_count_
;
6654 TEST_F(LayerTreeHostImplTest
, SimpleSwapPromiseMonitor
) {
6655 int set_needs_commit_count
= 0;
6656 int set_needs_redraw_count
= 0;
6657 int forward_to_main_count
= 0;
6660 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6661 new SimpleSwapPromiseMonitor(NULL
,
6663 &set_needs_commit_count
,
6664 &set_needs_redraw_count
,
6665 &forward_to_main_count
));
6666 host_impl_
->SetNeedsRedraw();
6667 EXPECT_EQ(0, set_needs_commit_count
);
6668 EXPECT_EQ(1, set_needs_redraw_count
);
6669 EXPECT_EQ(0, forward_to_main_count
);
6672 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6674 host_impl_
->SetNeedsRedraw();
6675 EXPECT_EQ(0, set_needs_commit_count
);
6676 EXPECT_EQ(1, set_needs_redraw_count
);
6677 EXPECT_EQ(0, forward_to_main_count
);
6680 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6681 new SimpleSwapPromiseMonitor(NULL
,
6683 &set_needs_commit_count
,
6684 &set_needs_redraw_count
,
6685 &forward_to_main_count
));
6686 host_impl_
->SetNeedsRedrawRect(gfx::Rect(10, 10));
6687 EXPECT_EQ(0, set_needs_commit_count
);
6688 EXPECT_EQ(2, set_needs_redraw_count
);
6689 EXPECT_EQ(0, forward_to_main_count
);
6693 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6694 new SimpleSwapPromiseMonitor(NULL
,
6696 &set_needs_commit_count
,
6697 &set_needs_redraw_count
,
6698 &forward_to_main_count
));
6699 // Empty damage rect won't signal the monitor.
6700 host_impl_
->SetNeedsRedrawRect(gfx::Rect());
6701 EXPECT_EQ(0, set_needs_commit_count
);
6702 EXPECT_EQ(2, set_needs_redraw_count
);
6703 EXPECT_EQ(0, forward_to_main_count
);
6707 set_needs_commit_count
= 0;
6708 set_needs_redraw_count
= 0;
6709 forward_to_main_count
= 0;
6710 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6711 new SimpleSwapPromiseMonitor(NULL
,
6713 &set_needs_commit_count
,
6714 &set_needs_redraw_count
,
6715 &forward_to_main_count
));
6716 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
6718 // Scrolling normally should not trigger any forwarding.
6719 EXPECT_EQ(InputHandler::ScrollStarted
,
6720 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
6721 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
6722 host_impl_
->ScrollEnd();
6724 EXPECT_EQ(0, set_needs_commit_count
);
6725 EXPECT_EQ(1, set_needs_redraw_count
);
6726 EXPECT_EQ(0, forward_to_main_count
);
6728 // Scrolling with a scroll handler should defer the swap to the main
6730 scroll_layer
->SetHaveScrollEventHandlers(true);
6731 EXPECT_EQ(InputHandler::ScrollStarted
,
6732 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
6733 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
6734 host_impl_
->ScrollEnd();
6736 EXPECT_EQ(0, set_needs_commit_count
);
6737 EXPECT_EQ(2, set_needs_redraw_count
);
6738 EXPECT_EQ(1, forward_to_main_count
);
6742 class LayerTreeHostImplWithTopControlsTest
: public LayerTreeHostImplTest
{
6744 virtual void SetUp() override
{
6745 LayerTreeSettings settings
= DefaultSettings();
6746 settings
.calculate_top_controls_position
= true;
6747 settings
.top_controls_height
= top_controls_height_
;
6748 CreateHostImpl(settings
, CreateOutputSurface());
6752 static const int top_controls_height_
;
6755 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_
= 50;
6757 TEST_F(LayerTreeHostImplWithTopControlsTest
, NoIdleAnimations
) {
6758 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6759 ->SetScrollOffset(gfx::ScrollOffset(0, 10));
6760 host_impl_
->Animate(base::TimeTicks());
6761 EXPECT_FALSE(did_request_redraw_
);
6764 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationScheduling
) {
6765 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6766 ->SetScrollOffset(gfx::ScrollOffset(0, 10));
6767 host_impl_
->DidChangeTopControlsPosition();
6768 EXPECT_TRUE(did_request_animate_
);
6769 EXPECT_TRUE(did_request_redraw_
);
6772 TEST_F(LayerTreeHostImplWithTopControlsTest
, ScrollHandledByTopControls
) {
6773 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6774 host_impl_
->SetViewportSize(gfx::Size(100, 100));
6775 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6776 BOTH
, SHOWN
, false);
6779 EXPECT_EQ(InputHandler::ScrollStarted
,
6780 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
6781 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6782 EXPECT_EQ(gfx::Vector2dF().ToString(),
6783 scroll_layer
->TotalScrollOffset().ToString());
6785 // Scroll just the top controls and verify that the scroll succeeds.
6786 const float residue
= 10;
6787 float offset
= top_controls_height_
- residue
;
6788 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)));
6789 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6790 EXPECT_EQ(gfx::Vector2dF().ToString(),
6791 scroll_layer
->TotalScrollOffset().ToString());
6793 // Scroll across the boundary
6794 const float content_scroll
= 20;
6795 offset
= residue
+ content_scroll
;
6796 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)));
6797 EXPECT_EQ(-top_controls_height_
,
6798 host_impl_
->top_controls_manager()->ControlsTopOffset());
6799 EXPECT_EQ(gfx::Vector2dF(0, content_scroll
).ToString(),
6800 scroll_layer
->TotalScrollOffset().ToString());
6802 // Now scroll back to the top of the content
6803 offset
= -content_scroll
;
6804 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)));
6805 EXPECT_EQ(-top_controls_height_
,
6806 host_impl_
->top_controls_manager()->ControlsTopOffset());
6807 EXPECT_EQ(gfx::Vector2dF().ToString(),
6808 scroll_layer
->TotalScrollOffset().ToString());
6810 // And scroll the top controls completely into view
6811 offset
= -top_controls_height_
;
6812 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)));
6813 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6814 EXPECT_EQ(gfx::Vector2dF().ToString(),
6815 scroll_layer
->TotalScrollOffset().ToString());
6817 // And attempt to scroll past the end
6818 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)));
6819 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6820 EXPECT_EQ(gfx::Vector2dF().ToString(),
6821 scroll_layer
->TotalScrollOffset().ToString());
6823 host_impl_
->ScrollEnd();
6826 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAtOrigin
) {
6827 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6828 host_impl_
->SetViewportSize(gfx::Size(100, 200));
6829 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6830 BOTH
, SHOWN
, false);
6833 EXPECT_EQ(InputHandler::ScrollStarted
,
6834 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
6835 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6836 EXPECT_EQ(gfx::Vector2dF().ToString(),
6837 scroll_layer
->TotalScrollOffset().ToString());
6839 // Scroll the top controls partially.
6840 const float residue
= 35;
6841 float offset
= top_controls_height_
- residue
;
6842 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)));
6843 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6844 EXPECT_EQ(gfx::Vector2dF().ToString(),
6845 scroll_layer
->TotalScrollOffset().ToString());
6847 did_request_redraw_
= false;
6848 did_request_animate_
= false;
6849 did_request_commit_
= false;
6851 // End the scroll while the controls are still offset from their limit.
6852 host_impl_
->ScrollEnd();
6853 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
6854 EXPECT_TRUE(did_request_animate_
);
6855 EXPECT_TRUE(did_request_redraw_
);
6856 EXPECT_FALSE(did_request_commit_
);
6858 // The top controls should properly animate until finished, despite the scroll
6859 // offset being at the origin.
6860 base::TimeTicks animation_time
= gfx::FrameTime::Now();
6861 while (did_request_animate_
) {
6862 did_request_redraw_
= false;
6863 did_request_animate_
= false;
6864 did_request_commit_
= false;
6867 host_impl_
->top_controls_manager()->ControlsTopOffset();
6869 animation_time
+= base::TimeDelta::FromMilliseconds(5);
6870 host_impl_
->Animate(animation_time
);
6871 EXPECT_EQ(gfx::Vector2dF().ToString(),
6872 scroll_layer
->TotalScrollOffset().ToString());
6875 host_impl_
->top_controls_manager()->ControlsTopOffset();
6877 // No commit is needed as the controls are animating the content offset,
6878 // not the scroll offset.
6879 EXPECT_FALSE(did_request_commit_
);
6881 if (new_offset
!= old_offset
)
6882 EXPECT_TRUE(did_request_redraw_
);
6884 if (new_offset
!= 0) {
6885 EXPECT_TRUE(host_impl_
->top_controls_manager()->animation());
6886 EXPECT_TRUE(did_request_animate_
);
6889 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
6892 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAfterScroll
) {
6893 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6894 host_impl_
->SetViewportSize(gfx::Size(100, 100));
6895 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6896 BOTH
, SHOWN
, false);
6897 float initial_scroll_offset
= 50;
6898 scroll_layer
->SetScrollOffset(gfx::ScrollOffset(0, initial_scroll_offset
));
6901 EXPECT_EQ(InputHandler::ScrollStarted
,
6902 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
6903 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6904 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6905 scroll_layer
->TotalScrollOffset().ToString());
6907 // Scroll the top controls partially.
6908 const float residue
= 15;
6909 float offset
= top_controls_height_
- residue
;
6910 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)));
6911 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6912 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6913 scroll_layer
->TotalScrollOffset().ToString());
6915 did_request_redraw_
= false;
6916 did_request_animate_
= false;
6917 did_request_commit_
= false;
6919 // End the scroll while the controls are still offset from the limit.
6920 host_impl_
->ScrollEnd();
6921 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
6922 EXPECT_TRUE(did_request_animate_
);
6923 EXPECT_TRUE(did_request_redraw_
);
6924 EXPECT_FALSE(did_request_commit_
);
6926 // Animate the top controls to the limit.
6927 base::TimeTicks animation_time
= gfx::FrameTime::Now();
6928 while (did_request_animate_
) {
6929 did_request_redraw_
= false;
6930 did_request_animate_
= false;
6931 did_request_commit_
= false;
6934 host_impl_
->top_controls_manager()->ControlsTopOffset();
6936 animation_time
+= base::TimeDelta::FromMilliseconds(5);
6937 host_impl_
->Animate(animation_time
);
6940 host_impl_
->top_controls_manager()->ControlsTopOffset();
6942 if (new_offset
!= old_offset
) {
6943 EXPECT_TRUE(did_request_redraw_
);
6944 EXPECT_TRUE(did_request_commit_
);
6947 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
6950 class LayerTreeHostImplVirtualViewportTest
: public LayerTreeHostImplTest
{
6952 void SetupVirtualViewportLayers(const gfx::Size
& content_size
,
6953 const gfx::Size
& outer_viewport
,
6954 const gfx::Size
& inner_viewport
) {
6955 LayerTreeImpl
* layer_tree_impl
= host_impl_
->active_tree();
6956 const int kOuterViewportClipLayerId
= 6;
6957 const int kOuterViewportScrollLayerId
= 7;
6958 const int kInnerViewportScrollLayerId
= 2;
6959 const int kInnerViewportClipLayerId
= 4;
6960 const int kPageScaleLayerId
= 5;
6962 scoped_ptr
<LayerImpl
> inner_scroll
=
6963 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
6964 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
6965 inner_scroll
->SetScrollOffset(gfx::ScrollOffset());
6967 scoped_ptr
<LayerImpl
> inner_clip
=
6968 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
6969 inner_clip
->SetBounds(inner_viewport
);
6971 scoped_ptr
<LayerImpl
> page_scale
=
6972 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
6974 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
6975 inner_scroll
->SetBounds(outer_viewport
);
6976 inner_scroll
->SetContentBounds(outer_viewport
);
6977 inner_scroll
->SetPosition(gfx::PointF());
6979 scoped_ptr
<LayerImpl
> outer_clip
=
6980 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
6981 outer_clip
->SetBounds(outer_viewport
);
6982 outer_clip
->SetIsContainerForFixedPositionLayers(true);
6984 scoped_ptr
<LayerImpl
> outer_scroll
=
6985 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
6986 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
6987 outer_scroll
->SetScrollOffset(gfx::ScrollOffset());
6988 outer_scroll
->SetBounds(content_size
);
6989 outer_scroll
->SetContentBounds(content_size
);
6990 outer_scroll
->SetPosition(gfx::PointF());
6992 scoped_ptr
<LayerImpl
> contents
=
6993 LayerImpl::Create(layer_tree_impl
, 8);
6994 contents
->SetDrawsContent(true);
6995 contents
->SetBounds(content_size
);
6996 contents
->SetContentBounds(content_size
);
6997 contents
->SetPosition(gfx::PointF());
6999 outer_scroll
->AddChild(contents
.Pass());
7000 outer_clip
->AddChild(outer_scroll
.Pass());
7001 inner_scroll
->AddChild(outer_clip
.Pass());
7002 page_scale
->AddChild(inner_scroll
.Pass());
7003 inner_clip
->AddChild(page_scale
.Pass());
7005 layer_tree_impl
->SetRootLayer(inner_clip
.Pass());
7006 layer_tree_impl
->SetViewportLayersFromIds(kPageScaleLayerId
,
7007 kInnerViewportScrollLayerId
, kOuterViewportScrollLayerId
);
7009 host_impl_
->active_tree()->DidBecomeActive();
7013 TEST_F(LayerTreeHostImplVirtualViewportTest
, FlingScrollBubblesToInner
) {
7014 gfx::Size content_size
= gfx::Size(100, 160);
7015 gfx::Size outer_viewport
= gfx::Size(50, 80);
7016 gfx::Size inner_viewport
= gfx::Size(25, 40);
7018 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7020 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7021 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7024 gfx::Vector2dF inner_expected
;
7025 gfx::Vector2dF outer_expected
;
7026 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->TotalScrollOffset());
7027 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->TotalScrollOffset());
7029 // Make sure the fling goes to the outer viewport first
7030 EXPECT_EQ(InputHandler::ScrollStarted
,
7031 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
7032 EXPECT_EQ(InputHandler::ScrollStarted
, host_impl_
->FlingScrollBegin());
7034 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7035 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7036 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7038 host_impl_
->ScrollEnd();
7040 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->TotalScrollOffset());
7041 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->TotalScrollOffset());
7043 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7044 EXPECT_EQ(InputHandler::ScrollStarted
,
7045 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::Gesture
));
7046 EXPECT_EQ(InputHandler::ScrollStarted
, host_impl_
->FlingScrollBegin());
7048 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7049 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7051 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7052 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7054 host_impl_
->ScrollEnd();
7056 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->TotalScrollOffset());
7057 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->TotalScrollOffset());
7061 class LayerTreeHostImplWithImplicitLimitsTest
: public LayerTreeHostImplTest
{
7063 virtual void SetUp() override
{
7064 LayerTreeSettings settings
= DefaultSettings();
7065 settings
.max_memory_for_prepaint_percentage
= 50;
7066 CreateHostImpl(settings
, CreateOutputSurface());
7070 TEST_F(LayerTreeHostImplWithImplicitLimitsTest
, ImplicitMemoryLimits
) {
7071 // Set up a memory policy and percentages which could cause
7072 // 32-bit integer overflows.
7073 ManagedMemoryPolicy
mem_policy(300 * 1024 * 1024); // 300MB
7075 // Verify implicit limits are calculated correctly with no overflows
7076 host_impl_
->SetMemoryPolicy(mem_policy
);
7077 EXPECT_EQ(host_impl_
->global_tile_state().hard_memory_limit_in_bytes
,
7078 300u * 1024u * 1024u);
7079 EXPECT_EQ(host_impl_
->global_tile_state().soft_memory_limit_in_bytes
,
7080 150u * 1024u * 1024u);
7083 TEST_F(LayerTreeHostImplTest
, ExternalTransformReflectedInNextDraw
) {
7084 const gfx::Size
layer_size(100, 100);
7085 gfx::Transform external_transform
;
7086 const gfx::Rect
external_viewport(layer_size
);
7087 const gfx::Rect
external_clip(layer_size
);
7088 const bool resourceless_software_draw
= false;
7089 LayerImpl
* layer
= SetupScrollAndContentsLayers(layer_size
);
7091 host_impl_
->SetExternalDrawConstraints(external_transform
,
7096 resourceless_software_draw
);
7098 EXPECT_TRANSFORMATION_MATRIX_EQ(
7099 external_transform
, layer
->draw_properties().target_space_transform
);
7101 external_transform
.Translate(20, 20);
7102 host_impl_
->SetExternalDrawConstraints(external_transform
,
7107 resourceless_software_draw
);
7109 EXPECT_TRANSFORMATION_MATRIX_EQ(
7110 external_transform
, layer
->draw_properties().target_space_transform
);
7113 TEST_F(LayerTreeHostImplTest
, ScrollAnimated
) {
7114 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7117 base::TimeTicks start_time
=
7118 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7120 EXPECT_EQ(InputHandler::ScrollStarted
,
7121 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7123 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7125 host_impl_
->Animate(start_time
);
7126 host_impl_
->UpdateAnimationState(true);
7128 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->TotalScrollOffset());
7130 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(50));
7131 host_impl_
->UpdateAnimationState(true);
7133 float y
= scrolling_layer
->TotalScrollOffset().y();
7134 EXPECT_TRUE(y
> 1 && y
< 49);
7137 EXPECT_EQ(InputHandler::ScrollStarted
,
7138 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7140 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(200));
7141 host_impl_
->UpdateAnimationState(true);
7143 y
= scrolling_layer
->TotalScrollOffset().y();
7144 EXPECT_TRUE(y
> 50 && y
< 100);
7145 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
7147 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(250));
7148 host_impl_
->UpdateAnimationState(true);
7150 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7151 scrolling_layer
->TotalScrollOffset());
7152 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
7155 TEST_F(LayerTreeHostImplTest
, GetPictureLayerImplPairs
) {
7156 host_impl_
->CreatePendingTree();
7157 host_impl_
->ActivateSyncTree();
7158 host_impl_
->CreatePendingTree();
7160 LayerTreeImpl
* active_tree
= host_impl_
->active_tree();
7161 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
7162 EXPECT_NE(active_tree
, pending_tree
);
7164 scoped_ptr
<FakePictureLayerImpl
> active_layer
=
7165 FakePictureLayerImpl::Create(active_tree
, 10);
7166 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
7167 FakePictureLayerImpl::Create(pending_tree
, 10);
7169 std::vector
<PictureLayerImpl::Pair
> layer_pairs
;
7170 host_impl_
->GetPictureLayerImplPairs(&layer_pairs
);
7172 EXPECT_EQ(2u, layer_pairs
.size());
7173 if (layer_pairs
[0].active
) {
7174 EXPECT_EQ(active_layer
.get(), layer_pairs
[0].active
);
7175 EXPECT_EQ(NULL
, layer_pairs
[0].pending
);
7177 EXPECT_EQ(pending_layer
.get(), layer_pairs
[0].pending
);
7178 EXPECT_EQ(NULL
, layer_pairs
[0].active
);
7181 if (layer_pairs
[1].active
) {
7182 EXPECT_EQ(active_layer
.get(), layer_pairs
[1].active
);
7183 EXPECT_EQ(NULL
, layer_pairs
[1].pending
);
7185 EXPECT_EQ(pending_layer
.get(), layer_pairs
[1].pending
);
7186 EXPECT_EQ(NULL
, layer_pairs
[1].active
);
7189 active_layer
->set_twin_layer(pending_layer
.get());
7190 pending_layer
->set_twin_layer(active_layer
.get());
7192 layer_pairs
.clear();
7193 host_impl_
->GetPictureLayerImplPairs(&layer_pairs
);
7194 EXPECT_EQ(1u, layer_pairs
.size());
7196 EXPECT_EQ(active_layer
.get(), layer_pairs
[0].active
);
7197 EXPECT_EQ(pending_layer
.get(), layer_pairs
[0].pending
);
7200 TEST_F(LayerTreeHostImplTest
, DidBecomeActive
) {
7201 host_impl_
->CreatePendingTree();
7202 host_impl_
->ActivateSyncTree();
7203 host_impl_
->CreatePendingTree();
7205 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
7207 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
7208 FakePictureLayerImpl::Create(pending_tree
, 10);
7209 pending_layer
->DoPostCommitInitializationIfNeeded();
7210 FakePictureLayerImpl
* raw_pending_layer
= pending_layer
.get();
7211 pending_tree
->SetRootLayer(pending_layer
.Pass());
7212 ASSERT_EQ(raw_pending_layer
, pending_tree
->root_layer());
7214 EXPECT_EQ(0u, raw_pending_layer
->did_become_active_call_count());
7215 pending_tree
->DidBecomeActive();
7216 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7218 scoped_ptr
<FakePictureLayerImpl
> mask_layer
=
7219 FakePictureLayerImpl::Create(pending_tree
, 11);
7220 mask_layer
->DoPostCommitInitializationIfNeeded();
7221 FakePictureLayerImpl
* raw_mask_layer
= mask_layer
.get();
7222 raw_pending_layer
->SetMaskLayer(mask_layer
.Pass());
7223 ASSERT_EQ(raw_mask_layer
, raw_pending_layer
->mask_layer());
7225 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7226 EXPECT_EQ(0u, raw_mask_layer
->did_become_active_call_count());
7227 pending_tree
->DidBecomeActive();
7228 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7229 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7231 scoped_ptr
<FakePictureLayerImpl
> replica_layer
=
7232 FakePictureLayerImpl::Create(pending_tree
, 12);
7233 scoped_ptr
<FakePictureLayerImpl
> replica_mask_layer
=
7234 FakePictureLayerImpl::Create(pending_tree
, 13);
7235 replica_mask_layer
->DoPostCommitInitializationIfNeeded();
7236 FakePictureLayerImpl
* raw_replica_mask_layer
= replica_mask_layer
.get();
7237 replica_layer
->SetMaskLayer(replica_mask_layer
.Pass());
7238 raw_pending_layer
->SetReplicaLayer(replica_layer
.Pass());
7239 ASSERT_EQ(raw_replica_mask_layer
,
7240 raw_pending_layer
->replica_layer()->mask_layer());
7242 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7243 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7244 EXPECT_EQ(0u, raw_replica_mask_layer
->did_become_active_call_count());
7245 pending_tree
->DidBecomeActive();
7246 EXPECT_EQ(3u, raw_pending_layer
->did_become_active_call_count());
7247 EXPECT_EQ(2u, raw_mask_layer
->did_become_active_call_count());
7248 EXPECT_EQ(1u, raw_replica_mask_layer
->did_become_active_call_count());
7251 class LayerTreeHostImplCountingLostSurfaces
: public LayerTreeHostImplTest
{
7253 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7254 virtual void DidLoseOutputSurfaceOnImplThread() override
{
7255 num_lost_surfaces_
++;
7259 int num_lost_surfaces_
;
7262 TEST_F(LayerTreeHostImplCountingLostSurfaces
, TwiceLostSurface
) {
7263 // Really we just need at least one client notification each time
7264 // we go from having a valid output surface to not having a valid output
7266 EXPECT_EQ(0, num_lost_surfaces_
);
7267 host_impl_
->DidLoseOutputSurface();
7268 EXPECT_EQ(1, num_lost_surfaces_
);
7269 host_impl_
->DidLoseOutputSurface();
7270 EXPECT_LE(1, num_lost_surfaces_
);