1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host_impl.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/containers/scoped_ptr_hash_map.h"
14 #include "cc/animation/scrollbar_animation_controller_thinning.h"
15 #include "cc/base/latency_info_swap_promise.h"
16 #include "cc/base/math_util.h"
17 #include "cc/input/page_scale_animation.h"
18 #include "cc/input/top_controls_manager.h"
19 #include "cc/layers/append_quads_data.h"
20 #include "cc/layers/delegated_renderer_layer_impl.h"
21 #include "cc/layers/heads_up_display_layer_impl.h"
22 #include "cc/layers/io_surface_layer_impl.h"
23 #include "cc/layers/layer_impl.h"
24 #include "cc/layers/painted_scrollbar_layer_impl.h"
25 #include "cc/layers/render_surface_impl.h"
26 #include "cc/layers/solid_color_layer_impl.h"
27 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
28 #include "cc/layers/texture_layer_impl.h"
29 #include "cc/layers/tiled_layer_impl.h"
30 #include "cc/layers/video_layer_impl.h"
31 #include "cc/output/begin_frame_args.h"
32 #include "cc/output/compositor_frame_ack.h"
33 #include "cc/output/compositor_frame_metadata.h"
34 #include "cc/output/copy_output_request.h"
35 #include "cc/output/copy_output_result.h"
36 #include "cc/output/gl_renderer.h"
37 #include "cc/quads/render_pass_draw_quad.h"
38 #include "cc/quads/solid_color_draw_quad.h"
39 #include "cc/quads/texture_draw_quad.h"
40 #include "cc/quads/tile_draw_quad.h"
41 #include "cc/resources/layer_tiling_data.h"
42 #include "cc/test/animation_test_common.h"
43 #include "cc/test/begin_frame_args_test.h"
44 #include "cc/test/fake_layer_tree_host_impl.h"
45 #include "cc/test/fake_output_surface.h"
46 #include "cc/test/fake_output_surface_client.h"
47 #include "cc/test/fake_picture_layer_impl.h"
48 #include "cc/test/fake_picture_pile_impl.h"
49 #include "cc/test/fake_proxy.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_gpu_memory_buffer_manager.h"
55 #include "cc/test/test_shared_bitmap_manager.h"
56 #include "cc/test/test_web_graphics_context_3d.h"
57 #include "cc/trees/layer_tree_impl.h"
58 #include "cc/trees/single_thread_proxy.h"
59 #include "media/base/media.h"
60 #include "testing/gmock/include/gmock/gmock.h"
61 #include "testing/gtest/include/gtest/gtest.h"
62 #include "third_party/skia/include/core/SkMallocPixelRef.h"
63 #include "ui/gfx/frame_time.h"
64 #include "ui/gfx/geometry/rect_conversions.h"
65 #include "ui/gfx/geometry/size_conversions.h"
66 #include "ui/gfx/geometry/vector2d_conversions.h"
68 using ::testing::Mock;
69 using ::testing::Return;
70 using ::testing::AnyNumber;
71 using ::testing::AtLeast;
73 using media::VideoFrame;
78 class LayerTreeHostImplTest : public testing::Test,
79 public LayerTreeHostImplClient {
81 LayerTreeHostImplTest()
82 : proxy_(base::MessageLoopProxy::current(),
83 base::MessageLoopProxy::current()),
84 always_impl_thread_(&proxy_),
85 always_main_thread_blocked_(&proxy_),
86 shared_bitmap_manager_(new TestSharedBitmapManager),
87 gpu_memory_buffer_manager_(new TestGpuMemoryBufferManager),
88 on_can_draw_state_changed_called_(false),
89 did_notify_ready_to_activate_(false),
90 did_request_commit_(false),
91 did_request_redraw_(false),
92 did_request_animate_(false),
93 did_request_manage_tiles_(false),
94 did_upload_visible_tile_(false),
95 reduce_memory_result_(true),
96 current_limit_bytes_(0),
97 current_priority_cutoff_value_(0) {
98 media::InitializeMediaLibraryForTesting();
101 LayerTreeSettings DefaultSettings() {
102 LayerTreeSettings settings;
103 settings.minimum_occlusion_tracking_size = gfx::Size();
104 settings.impl_side_painting = true;
105 settings.texture_id_allocation_chunk_size = 1;
106 settings.report_overscroll_only_for_scrollable_axes = true;
107 settings.use_pinch_virtual_viewport = true;
111 virtual void SetUp() override {
112 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
115 virtual void TearDown() override {}
117 void UpdateRendererCapabilitiesOnImplThread() override {}
118 void DidLoseOutputSurfaceOnImplThread() override {}
119 void CommitVSyncParameters(base::TimeTicks timebase,
120 base::TimeDelta interval) override {}
121 void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {}
122 void SetMaxSwapsPendingOnImplThread(int max) override {}
123 void DidSwapBuffersOnImplThread() override {}
124 void DidSwapBuffersCompleteOnImplThread() override {}
125 void OnCanDrawStateChanged(bool can_draw) override {
126 on_can_draw_state_changed_called_ = true;
128 void NotifyReadyToActivate() override {
129 did_notify_ready_to_activate_ = true;
130 host_impl_->ActivateSyncTree();
132 void SetNeedsRedrawOnImplThread() override { did_request_redraw_ = true; }
133 void SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) override {
134 did_request_redraw_ = true;
136 void SetNeedsAnimateOnImplThread() override { did_request_animate_ = true; }
137 void SetNeedsManageTilesOnImplThread() override {
138 did_request_manage_tiles_ = true;
140 void DidInitializeVisibleTileOnImplThread() override {
141 did_upload_visible_tile_ = true;
143 void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; }
144 void PostAnimationEventsToMainThreadOnImplThread(
145 scoped_ptr<AnimationEventsVector> events) override {}
146 bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
147 int priority_cutoff) override {
148 current_limit_bytes_ = limit_bytes;
149 current_priority_cutoff_value_ = priority_cutoff;
150 return reduce_memory_result_;
152 bool IsInsideDraw() override { return false; }
153 void RenewTreePriority() override {}
154 void PostDelayedScrollbarFadeOnImplThread(const base::Closure& start_fade,
155 base::TimeDelta delay) override {
156 scrollbar_fade_start_ = start_fade;
157 requested_scrollbar_animation_delay_ = delay;
159 void DidActivateSyncTree() override {}
160 void DidManageTiles() override {}
162 void set_reduce_memory_result(bool reduce_memory_result) {
163 reduce_memory_result_ = reduce_memory_result;
166 bool CreateHostImpl(const LayerTreeSettings& settings,
167 scoped_ptr<OutputSurface> output_surface) {
168 host_impl_ = LayerTreeHostImpl::Create(settings,
171 &stats_instrumentation_,
172 shared_bitmap_manager_.get(),
173 gpu_memory_buffer_manager_.get(),
175 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
176 host_impl_->SetViewportSize(gfx::Size(10, 10));
180 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
181 root->SetPosition(gfx::PointF());
182 root->SetBounds(gfx::Size(10, 10));
183 root->SetContentBounds(gfx::Size(10, 10));
184 root->SetDrawsContent(true);
185 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
186 host_impl_->active_tree()->SetRootLayer(root.Pass());
189 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
190 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
191 for (size_t i = 0; i < layer->children().size(); ++i)
192 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
195 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
197 const gfx::Vector2d& scroll_delta) {
198 int times_encountered = 0;
200 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
201 if (scroll_info.scrolls[i].layer_id != id)
203 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
207 ASSERT_EQ(1, times_encountered);
210 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
211 int times_encountered = 0;
213 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
214 if (scroll_info.scrolls[i].layer_id != id)
219 ASSERT_EQ(0, times_encountered);
222 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
223 const gfx::Size& content_size) {
224 const int kInnerViewportScrollLayerId = 2;
225 const int kInnerViewportClipLayerId = 4;
226 const int kPageScaleLayerId = 5;
227 scoped_ptr<LayerImpl> root =
228 LayerImpl::Create(layer_tree_impl, 1);
229 root->SetBounds(content_size);
230 root->SetContentBounds(content_size);
231 root->SetPosition(gfx::PointF());
233 scoped_ptr<LayerImpl> scroll =
234 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
235 LayerImpl* scroll_layer = scroll.get();
236 scroll->SetIsContainerForFixedPositionLayers(true);
237 scroll->SetScrollOffset(gfx::ScrollOffset());
239 scoped_ptr<LayerImpl> clip =
240 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
242 gfx::Size(content_size.width() / 2, content_size.height() / 2));
244 scoped_ptr<LayerImpl> page_scale =
245 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
247 scroll->SetScrollClipLayer(clip->id());
248 scroll->SetBounds(content_size);
249 scroll->SetContentBounds(content_size);
250 scroll->SetPosition(gfx::PointF());
251 scroll->SetIsContainerForFixedPositionLayers(true);
253 scoped_ptr<LayerImpl> contents =
254 LayerImpl::Create(layer_tree_impl, 3);
255 contents->SetDrawsContent(true);
256 contents->SetBounds(content_size);
257 contents->SetContentBounds(content_size);
258 contents->SetPosition(gfx::PointF());
260 scroll->AddChild(contents.Pass());
261 page_scale->AddChild(scroll.Pass());
262 clip->AddChild(page_scale.Pass());
263 root->AddChild(clip.Pass());
265 layer_tree_impl->SetRootLayer(root.Pass());
266 layer_tree_impl->SetViewportLayersFromIds(
267 kPageScaleLayerId, kInnerViewportScrollLayerId, Layer::INVALID_ID);
272 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
273 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
274 host_impl_->active_tree(), content_size);
275 host_impl_->active_tree()->DidBecomeActive();
279 // TODO(wjmaclean) Add clip-layer pointer to parameters.
280 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
281 const gfx::Size& size,
282 LayerImpl* clip_layer) {
284 DCHECK(id != clip_layer->id());
285 scoped_ptr<LayerImpl> layer =
286 LayerImpl::Create(host_impl_->active_tree(), id);
287 layer->SetScrollClipLayer(clip_layer->id());
288 layer->SetDrawsContent(true);
289 layer->SetBounds(size);
290 layer->SetContentBounds(size);
291 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
296 LayerTreeHostImpl::FrameData frame;
297 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
298 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
299 host_impl_->DidDrawAllLayers(frame);
302 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
303 void pinch_zoom_pan_viewport_test(float device_scale_factor);
304 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
305 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
306 float device_scale_factor);
308 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
309 // Note: It is not possible to disable the renderer once it has been set,
310 // so we do not need to test that disabling the renderer notifies us
311 // that can_draw changed.
312 EXPECT_FALSE(host_impl_->CanDraw());
313 on_can_draw_state_changed_called_ = false;
315 // Set up the root layer, which allows us to draw.
316 SetupScrollAndContentsLayers(gfx::Size(100, 100));
317 EXPECT_TRUE(host_impl_->CanDraw());
318 EXPECT_TRUE(on_can_draw_state_changed_called_);
319 on_can_draw_state_changed_called_ = false;
321 // Toggle the root layer to make sure it toggles can_draw
322 host_impl_->active_tree()->SetRootLayer(nullptr);
323 EXPECT_FALSE(host_impl_->CanDraw());
324 EXPECT_TRUE(on_can_draw_state_changed_called_);
325 on_can_draw_state_changed_called_ = false;
327 SetupScrollAndContentsLayers(gfx::Size(100, 100));
328 EXPECT_TRUE(host_impl_->CanDraw());
329 EXPECT_TRUE(on_can_draw_state_changed_called_);
330 on_can_draw_state_changed_called_ = false;
332 // Toggle the device viewport size to make sure it toggles can_draw.
333 host_impl_->SetViewportSize(gfx::Size());
335 EXPECT_TRUE(host_impl_->CanDraw());
337 EXPECT_FALSE(host_impl_->CanDraw());
339 EXPECT_TRUE(on_can_draw_state_changed_called_);
340 on_can_draw_state_changed_called_ = false;
342 host_impl_->SetViewportSize(gfx::Size(100, 100));
343 EXPECT_TRUE(host_impl_->CanDraw());
344 EXPECT_TRUE(on_can_draw_state_changed_called_);
345 on_can_draw_state_changed_called_ = false;
347 // Toggle contents textures purged without causing any evictions,
348 // and make sure that it does not change can_draw.
349 set_reduce_memory_result(false);
350 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
351 host_impl_->memory_allocation_limit_bytes() - 1));
352 EXPECT_TRUE(host_impl_->CanDraw());
353 EXPECT_FALSE(on_can_draw_state_changed_called_);
354 on_can_draw_state_changed_called_ = false;
356 // Toggle contents textures purged to make sure it toggles can_draw.
357 set_reduce_memory_result(true);
358 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
359 host_impl_->memory_allocation_limit_bytes() - 1));
361 EXPECT_TRUE(host_impl_->CanDraw());
363 EXPECT_FALSE(host_impl_->CanDraw());
365 EXPECT_TRUE(on_can_draw_state_changed_called_);
366 on_can_draw_state_changed_called_ = false;
368 host_impl_->active_tree()->ResetContentsTexturesPurged();
369 EXPECT_TRUE(host_impl_->CanDraw());
370 EXPECT_TRUE(on_can_draw_state_changed_called_);
371 on_can_draw_state_changed_called_ = false;
374 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
377 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
378 return FakeOutputSurface::Create3d();
381 void DrawOneFrame() {
382 LayerTreeHostImpl::FrameData frame_data;
383 host_impl_->PrepareToDraw(&frame_data);
384 host_impl_->DidDrawAllLayers(frame_data);
388 DebugScopedSetImplThread always_impl_thread_;
389 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
391 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
392 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
393 scoped_ptr<LayerTreeHostImpl> host_impl_;
394 FakeRenderingStatsInstrumentation stats_instrumentation_;
395 bool on_can_draw_state_changed_called_;
396 bool did_notify_ready_to_activate_;
397 bool did_request_commit_;
398 bool did_request_redraw_;
399 bool did_request_animate_;
400 bool did_request_manage_tiles_;
401 bool did_upload_visible_tile_;
402 bool reduce_memory_result_;
403 base::Closure scrollbar_fade_start_;
404 base::TimeDelta requested_scrollbar_animation_delay_;
405 size_t current_limit_bytes_;
406 int current_priority_cutoff_value_;
409 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
410 bool always_draw = false;
411 CheckNotifyCalledIfCanDrawChanged(always_draw);
414 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
415 CreateHostImpl(DefaultSettings(),
416 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
418 bool always_draw = true;
419 CheckNotifyCalledIfCanDrawChanged(always_draw);
422 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
423 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
425 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
426 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
429 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
431 scoped_ptr<LayerImpl> root =
432 LayerImpl::Create(host_impl_->active_tree(), 1);
433 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
434 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
435 root->children()[1]->AddChild(
436 LayerImpl::Create(host_impl_->active_tree(), 4));
437 root->children()[1]->AddChild(
438 LayerImpl::Create(host_impl_->active_tree(), 5));
439 root->children()[1]->children()[0]->AddChild(
440 LayerImpl::Create(host_impl_->active_tree(), 6));
441 host_impl_->active_tree()->SetRootLayer(root.Pass());
443 LayerImpl* root = host_impl_->active_tree()->root_layer();
445 ExpectClearedScrollDeltasRecursive(root);
447 scoped_ptr<ScrollAndScaleSet> scroll_info;
449 scroll_info = host_impl_->ProcessScrollDeltas();
450 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
451 ExpectClearedScrollDeltasRecursive(root);
453 scroll_info = host_impl_->ProcessScrollDeltas();
454 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
455 ExpectClearedScrollDeltasRecursive(root);
458 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
459 gfx::ScrollOffset scroll_offset(20, 30);
460 gfx::Vector2d scroll_delta(11, -15);
462 scoped_ptr<LayerImpl> root_clip =
463 LayerImpl::Create(host_impl_->active_tree(), 2);
464 scoped_ptr<LayerImpl> root =
465 LayerImpl::Create(host_impl_->active_tree(), 1);
466 root_clip->SetBounds(gfx::Size(10, 10));
467 LayerImpl* root_layer = root.get();
468 root_clip->AddChild(root.Pass());
469 root_layer->SetBounds(gfx::Size(110, 110));
470 root_layer->SetScrollClipLayer(root_clip->id());
471 root_layer->SetScrollOffset(scroll_offset);
472 root_layer->ScrollBy(scroll_delta);
473 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
475 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
477 scoped_ptr<ScrollAndScaleSet> scroll_info;
479 scroll_info = host_impl_->ProcessScrollDeltas();
480 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
481 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta);
482 ExpectContains(*scroll_info, root->id(), scroll_delta);
484 gfx::Vector2d scroll_delta2(-5, 27);
485 root->ScrollBy(scroll_delta2);
486 scroll_info = host_impl_->ProcessScrollDeltas();
487 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
488 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
489 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
491 root->ScrollBy(gfx::Vector2d());
492 scroll_info = host_impl_->ProcessScrollDeltas();
493 EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
496 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
497 SetupScrollAndContentsLayers(gfx::Size(100, 100));
498 host_impl_->SetViewportSize(gfx::Size(50, 50));
501 EXPECT_EQ(InputHandler::ScrollStarted,
502 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
503 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
504 InputHandler::Wheel));
505 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
506 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
507 InputHandler::Wheel));
508 host_impl_->ScrollEnd();
509 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
510 InputHandler::Wheel));
511 EXPECT_TRUE(did_request_redraw_);
512 EXPECT_TRUE(did_request_commit_);
515 TEST_F(LayerTreeHostImplTest, ScrollActiveOnlyAfterScrollMovement) {
516 SetupScrollAndContentsLayers(gfx::Size(100, 100));
517 host_impl_->SetViewportSize(gfx::Size(50, 50));
520 EXPECT_EQ(InputHandler::ScrollStarted,
521 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
522 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
523 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
524 EXPECT_TRUE(host_impl_->IsActivelyScrolling());
525 host_impl_->ScrollEnd();
526 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
529 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
530 // We should not crash when trying to scroll an empty layer tree.
531 EXPECT_EQ(InputHandler::ScrollIgnored,
532 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
535 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
536 scoped_ptr<TestWebGraphicsContext3D> context_owned =
537 TestWebGraphicsContext3D::Create();
538 context_owned->set_context_lost(true);
540 // Initialization will fail.
541 EXPECT_FALSE(CreateHostImpl(
542 DefaultSettings(), FakeOutputSurface::Create3d(context_owned.Pass())));
544 SetupScrollAndContentsLayers(gfx::Size(100, 100));
546 // We should not crash when trying to scroll after the renderer initialization
548 EXPECT_EQ(InputHandler::ScrollStarted,
549 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
552 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
553 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
554 host_impl_->SetViewportSize(gfx::Size(50, 50));
557 // We should not crash if the tree is replaced while we are scrolling.
558 EXPECT_EQ(InputHandler::ScrollStarted,
559 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
560 host_impl_->active_tree()->DetachLayerTree();
562 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
564 // We should still be scrolling, because the scrolled layer also exists in the
566 gfx::Vector2d scroll_delta(0, 10);
567 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
568 host_impl_->ScrollEnd();
569 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
570 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
573 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
574 SetupScrollAndContentsLayers(gfx::Size(100, 100));
575 host_impl_->SetViewportSize(gfx::Size(50, 50));
578 // We should be able to scroll even if the root layer loses its render surface
579 // after the most recent render.
580 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
581 host_impl_->active_tree()->set_needs_update_draw_properties();
583 EXPECT_EQ(InputHandler::ScrollStarted,
584 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
587 TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
588 SetupScrollAndContentsLayers(gfx::Size(100, 100));
589 host_impl_->SetViewportSize(gfx::Size(50, 50));
591 LayerImpl* root = host_impl_->active_tree()->root_layer();
593 root->SetHaveWheelEventHandlers(true);
595 // With registered event handlers, wheel scrolls have to go to the main
597 EXPECT_EQ(InputHandler::ScrollOnMainThread,
598 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
600 // But gesture scrolls can still be handled.
601 EXPECT_EQ(InputHandler::ScrollStarted,
602 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
605 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
606 SetupScrollAndContentsLayers(gfx::Size(100, 100));
607 host_impl_->SetViewportSize(gfx::Size(50, 50));
610 // Ignore the fling since no layer is being scrolled
611 EXPECT_EQ(InputHandler::ScrollIgnored,
612 host_impl_->FlingScrollBegin());
614 // Start scrolling a layer
615 EXPECT_EQ(InputHandler::ScrollStarted,
616 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
618 // Now the fling should go ahead since we've started scrolling a layer
619 EXPECT_EQ(InputHandler::ScrollStarted,
620 host_impl_->FlingScrollBegin());
623 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
624 SetupScrollAndContentsLayers(gfx::Size(100, 100));
625 host_impl_->SetViewportSize(gfx::Size(50, 50));
628 // Ignore the fling since no layer is being scrolled
629 EXPECT_EQ(InputHandler::ScrollIgnored,
630 host_impl_->FlingScrollBegin());
632 // Start scrolling a layer
633 EXPECT_EQ(InputHandler::ScrollStarted,
634 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
636 // Now the fling should go ahead since we've started scrolling a layer
637 EXPECT_EQ(InputHandler::ScrollStarted,
638 host_impl_->FlingScrollBegin());
641 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
642 SetupScrollAndContentsLayers(gfx::Size(100, 100));
643 host_impl_->SetViewportSize(gfx::Size(50, 50));
645 LayerImpl* root = host_impl_->active_tree()->root_layer();
647 root->SetShouldScrollOnMainThread(true);
649 // Start scrolling a layer
650 EXPECT_EQ(InputHandler::ScrollOnMainThread,
651 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
653 // The fling should be ignored since there's no layer being scrolled impl-side
654 EXPECT_EQ(InputHandler::ScrollIgnored,
655 host_impl_->FlingScrollBegin());
658 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
659 SetupScrollAndContentsLayers(gfx::Size(100, 100));
660 host_impl_->SetViewportSize(gfx::Size(50, 50));
662 LayerImpl* root = host_impl_->active_tree()->root_layer();
664 root->SetShouldScrollOnMainThread(true);
666 EXPECT_EQ(InputHandler::ScrollOnMainThread,
667 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
668 EXPECT_EQ(InputHandler::ScrollOnMainThread,
669 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
672 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
673 SetupScrollAndContentsLayers(gfx::Size(200, 200));
674 host_impl_->SetViewportSize(gfx::Size(100, 100));
676 LayerImpl* root = host_impl_->active_tree()->root_layer();
677 root->SetContentsScale(2.f, 2.f);
678 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
682 // All scroll types inside the non-fast scrollable region should fail.
683 EXPECT_EQ(InputHandler::ScrollOnMainThread,
684 host_impl_->ScrollBegin(gfx::Point(25, 25),
685 InputHandler::Wheel));
686 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
687 InputHandler::Wheel));
688 EXPECT_EQ(InputHandler::ScrollOnMainThread,
689 host_impl_->ScrollBegin(gfx::Point(25, 25),
690 InputHandler::Gesture));
691 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
692 InputHandler::Gesture));
694 // All scroll types outside this region should succeed.
695 EXPECT_EQ(InputHandler::ScrollStarted,
696 host_impl_->ScrollBegin(gfx::Point(75, 75),
697 InputHandler::Wheel));
698 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
699 InputHandler::Gesture));
700 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
701 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
702 InputHandler::Gesture));
703 host_impl_->ScrollEnd();
704 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
705 InputHandler::Gesture));
706 EXPECT_EQ(InputHandler::ScrollStarted,
707 host_impl_->ScrollBegin(gfx::Point(75, 75),
708 InputHandler::Gesture));
709 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
710 InputHandler::Gesture));
711 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
712 host_impl_->ScrollEnd();
713 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
714 InputHandler::Gesture));
717 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
718 SetupScrollAndContentsLayers(gfx::Size(200, 200));
719 host_impl_->SetViewportSize(gfx::Size(100, 100));
721 LayerImpl* root = host_impl_->active_tree()->root_layer();
722 root->SetContentsScale(2.f, 2.f);
723 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
724 root->SetPosition(gfx::PointF(-25.f, 0.f));
728 // This point would fall into the non-fast scrollable region except that we've
729 // moved the layer down by 25 pixels.
730 EXPECT_EQ(InputHandler::ScrollStarted,
731 host_impl_->ScrollBegin(gfx::Point(40, 10),
732 InputHandler::Wheel));
733 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
734 InputHandler::Wheel));
735 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
736 host_impl_->ScrollEnd();
738 // This point is still inside the non-fast region.
739 EXPECT_EQ(InputHandler::ScrollOnMainThread,
740 host_impl_->ScrollBegin(gfx::Point(10, 10),
741 InputHandler::Wheel));
744 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
745 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
746 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
747 host_impl_->SetViewportSize(gfx::Size(50, 50));
750 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
751 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
752 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
753 host_impl_->ScrollEnd();
754 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
757 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
758 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
759 scroll_layer->SetHaveScrollEventHandlers(true);
760 host_impl_->SetViewportSize(gfx::Size(50, 50));
763 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
764 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
765 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
766 host_impl_->ScrollEnd();
767 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
770 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
771 SetupScrollAndContentsLayers(gfx::Size(200, 200));
772 host_impl_->SetViewportSize(gfx::Size(100, 100));
776 EXPECT_EQ(InputHandler::ScrollStarted,
777 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
779 // Trying to scroll to the left/top will not succeed.
781 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
783 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
785 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
787 // Scrolling to the right/bottom will succeed.
789 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll);
791 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
793 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll);
795 // Scrolling to left/top will now succeed.
797 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
799 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
801 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
803 // Scrolling diagonally against an edge will succeed.
805 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll);
807 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
809 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll);
811 // Trying to scroll more than the available space will also succeed.
813 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll);
816 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
817 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
818 host_impl_->SetViewportSize(gfx::Size(100, 1000));
822 EXPECT_EQ(InputHandler::ScrollStarted,
823 host_impl_->ScrollBegin(gfx::Point(),
824 InputHandler::Wheel));
826 // Trying to scroll without a vertical scrollbar will fail.
827 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
828 gfx::Point(), SCROLL_FORWARD));
829 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
830 gfx::Point(), SCROLL_BACKWARD));
832 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
833 PaintedScrollbarLayerImpl::Create(
834 host_impl_->active_tree(),
837 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
838 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
839 vertical_scrollbar.get());
841 // Trying to scroll with a vertical scrollbar will succeed.
842 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
843 gfx::Point(), SCROLL_FORWARD));
844 EXPECT_FLOAT_EQ(875.f,
845 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
846 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
847 gfx::Point(), SCROLL_BACKWARD));
850 TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
851 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
852 host_impl_->SetViewportSize(gfx::Size(100, 100));
854 gfx::Size overflow_size(400, 400);
855 ASSERT_EQ(1u, scroll_layer->children().size());
856 LayerImpl* overflow = scroll_layer->children()[0];
857 overflow->SetBounds(overflow_size);
858 overflow->SetContentBounds(overflow_size);
859 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
860 overflow->SetScrollOffset(gfx::ScrollOffset());
861 overflow->SetPosition(gfx::PointF());
864 gfx::Point scroll_position(10, 10);
866 EXPECT_EQ(InputHandler::ScrollStarted,
867 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
868 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
869 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->TotalScrollOffset());
871 gfx::Vector2dF scroll_delta(10, 10);
872 host_impl_->ScrollBy(scroll_position, scroll_delta);
873 host_impl_->ScrollEnd();
874 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
875 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
877 overflow->set_user_scrollable_horizontal(false);
879 EXPECT_EQ(InputHandler::ScrollStarted,
880 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
881 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
882 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
884 host_impl_->ScrollBy(scroll_position, scroll_delta);
885 host_impl_->ScrollEnd();
886 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
887 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
889 overflow->set_user_scrollable_vertical(false);
891 EXPECT_EQ(InputHandler::ScrollStarted,
892 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
893 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
894 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
896 host_impl_->ScrollBy(scroll_position, scroll_delta);
897 host_impl_->ScrollEnd();
898 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->TotalScrollOffset());
899 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
902 TEST_F(LayerTreeHostImplTest,
903 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
904 SetupScrollAndContentsLayers(gfx::Size(100, 100));
905 host_impl_->SetViewportSize(gfx::Size(50, 50));
908 // We should be able to hit test for touch event handlers even if the root
909 // layer loses its render surface after the most recent render.
910 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
911 host_impl_->active_tree()->set_needs_update_draw_properties();
913 EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
916 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
917 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
918 host_impl_->SetViewportSize(gfx::Size(50, 50));
921 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
922 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
923 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
925 float min_page_scale = 1.f, max_page_scale = 4.f;
926 float page_scale_factor = 1.f;
928 // The impl-based pinch zoom should adjust the max scroll position.
930 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
931 page_scale_factor, min_page_scale, max_page_scale);
932 host_impl_->active_tree()->SetPageScaleDelta(1.f);
933 scroll_layer->SetScrollDelta(gfx::Vector2d());
935 float page_scale_delta = 2.f;
937 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
938 host_impl_->PinchGestureBegin();
939 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
940 host_impl_->PinchGestureEnd();
941 host_impl_->ScrollEnd();
942 EXPECT_FALSE(did_request_animate_);
943 EXPECT_TRUE(did_request_redraw_);
944 EXPECT_TRUE(did_request_commit_);
945 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
947 scoped_ptr<ScrollAndScaleSet> scroll_info =
948 host_impl_->ProcessScrollDeltas();
949 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
951 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
952 scroll_layer->MaxScrollOffset().ToString());
955 // Scrolling after a pinch gesture should always be in local space. The
956 // scroll deltas do not have the page scale factor applied.
958 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
959 page_scale_factor, min_page_scale, max_page_scale);
960 host_impl_->active_tree()->SetPageScaleDelta(1.f);
961 scroll_layer->SetScrollDelta(gfx::Vector2d());
963 float page_scale_delta = 2.f;
964 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
965 host_impl_->PinchGestureBegin();
966 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
967 host_impl_->PinchGestureEnd();
968 host_impl_->ScrollEnd();
970 gfx::Vector2d scroll_delta(0, 10);
971 EXPECT_EQ(InputHandler::ScrollStarted,
972 host_impl_->ScrollBegin(gfx::Point(5, 5),
973 InputHandler::Wheel));
974 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
975 host_impl_->ScrollEnd();
977 scoped_ptr<ScrollAndScaleSet> scroll_info =
978 host_impl_->ProcessScrollDeltas();
979 ExpectContains(*scroll_info.get(),
985 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
986 ui::LatencyInfo latency_info;
987 latency_info.trace_id = 1234;
988 scoped_ptr<SwapPromise> swap_promise(
989 new LatencyInfoSwapPromise(latency_info));
991 SetupScrollAndContentsLayers(gfx::Size(100, 100));
992 EXPECT_EQ(InputHandler::ScrollStarted,
993 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
994 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
995 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
996 host_impl_->ScrollEnd();
998 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
999 EXPECT_EQ(1u, scroll_info->swap_promises.size());
1000 EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId());
1003 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1004 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1005 host_impl_->SetViewportSize(gfx::Size(50, 50));
1008 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1009 DCHECK(scroll_layer);
1011 float min_page_scale = 1.f;
1012 float max_page_scale = 4.f;
1014 // Basic pinch zoom in gesture
1016 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1019 scroll_layer->SetScrollDelta(gfx::Vector2d());
1021 float page_scale_delta = 2.f;
1022 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1023 host_impl_->PinchGestureBegin();
1024 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1025 host_impl_->PinchGestureEnd();
1026 host_impl_->ScrollEnd();
1027 EXPECT_FALSE(did_request_animate_);
1028 EXPECT_TRUE(did_request_redraw_);
1029 EXPECT_TRUE(did_request_commit_);
1031 scoped_ptr<ScrollAndScaleSet> scroll_info =
1032 host_impl_->ProcessScrollDeltas();
1033 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1038 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1041 scroll_layer->SetScrollDelta(gfx::Vector2d());
1042 float page_scale_delta = 10.f;
1044 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1045 host_impl_->PinchGestureBegin();
1046 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1047 host_impl_->PinchGestureEnd();
1048 host_impl_->ScrollEnd();
1050 scoped_ptr<ScrollAndScaleSet> scroll_info =
1051 host_impl_->ProcessScrollDeltas();
1052 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1055 // Zoom-out clamping
1057 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1060 scroll_layer->SetScrollDelta(gfx::Vector2d());
1061 scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
1063 float page_scale_delta = 0.1f;
1064 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1065 host_impl_->PinchGestureBegin();
1066 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1067 host_impl_->PinchGestureEnd();
1068 host_impl_->ScrollEnd();
1070 scoped_ptr<ScrollAndScaleSet> scroll_info =
1071 host_impl_->ProcessScrollDeltas();
1072 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1074 EXPECT_TRUE(scroll_info->scrolls.empty());
1077 // Two-finger panning should not happen based on pinch events only
1079 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1082 scroll_layer->SetScrollDelta(gfx::Vector2d());
1083 scroll_layer->SetScrollOffset(gfx::ScrollOffset(20, 20));
1085 float page_scale_delta = 1.f;
1086 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1087 host_impl_->PinchGestureBegin();
1088 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1089 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1090 host_impl_->PinchGestureEnd();
1091 host_impl_->ScrollEnd();
1093 scoped_ptr<ScrollAndScaleSet> scroll_info =
1094 host_impl_->ProcessScrollDeltas();
1095 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1096 EXPECT_TRUE(scroll_info->scrolls.empty());
1099 // Two-finger panning should work with interleaved scroll events
1101 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1104 scroll_layer->SetScrollDelta(gfx::Vector2d());
1105 scroll_layer->SetScrollOffset(gfx::ScrollOffset(20, 20));
1107 float page_scale_delta = 1.f;
1108 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1109 host_impl_->PinchGestureBegin();
1110 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1111 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1112 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1113 host_impl_->PinchGestureEnd();
1114 host_impl_->ScrollEnd();
1116 scoped_ptr<ScrollAndScaleSet> scroll_info =
1117 host_impl_->ProcessScrollDeltas();
1118 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1119 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1122 // Two-finger panning should work when starting fully zoomed out.
1124 host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
1127 scroll_layer->SetScrollDelta(gfx::Vector2d());
1128 scroll_layer->SetScrollOffset(gfx::ScrollOffset(0, 0));
1130 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
1131 host_impl_->PinchGestureBegin();
1132 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1133 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1134 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1135 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1136 host_impl_->PinchGestureEnd();
1137 host_impl_->ScrollEnd();
1139 scoped_ptr<ScrollAndScaleSet> scroll_info =
1140 host_impl_->ProcessScrollDeltas();
1141 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1142 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1146 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1147 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1148 host_impl_->SetViewportSize(gfx::Size(50, 50));
1151 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1152 DCHECK(scroll_layer);
1154 float min_page_scale = 0.5f;
1155 float max_page_scale = 4.f;
1156 base::TimeTicks start_time = base::TimeTicks() +
1157 base::TimeDelta::FromSeconds(1);
1158 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1159 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1160 base::TimeTicks end_time = start_time + duration;
1162 // Non-anchor zoom-in
1164 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1167 scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
1169 did_request_redraw_ = false;
1170 did_request_animate_ = false;
1171 host_impl_->active_tree()->SetPageScaleAnimation(
1176 host_impl_->ActivateSyncTree();
1177 EXPECT_FALSE(did_request_redraw_);
1178 EXPECT_TRUE(did_request_animate_);
1180 did_request_redraw_ = false;
1181 did_request_animate_ = false;
1182 host_impl_->Animate(start_time);
1183 EXPECT_TRUE(did_request_redraw_);
1184 EXPECT_TRUE(did_request_animate_);
1186 did_request_redraw_ = false;
1187 did_request_animate_ = false;
1188 host_impl_->Animate(halfway_through_animation);
1189 EXPECT_TRUE(did_request_redraw_);
1190 EXPECT_TRUE(did_request_animate_);
1192 did_request_redraw_ = false;
1193 did_request_animate_ = false;
1194 did_request_commit_ = false;
1195 host_impl_->Animate(end_time);
1196 EXPECT_TRUE(did_request_commit_);
1197 EXPECT_FALSE(did_request_animate_);
1199 scoped_ptr<ScrollAndScaleSet> scroll_info =
1200 host_impl_->ProcessScrollDeltas();
1201 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1202 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1207 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1210 scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
1212 did_request_redraw_ = false;
1213 did_request_animate_ = false;
1214 host_impl_->active_tree()->SetPageScaleAnimation(
1215 gfx::Vector2d(25, 25), true, min_page_scale, duration);
1216 host_impl_->ActivateSyncTree();
1217 EXPECT_FALSE(did_request_redraw_);
1218 EXPECT_TRUE(did_request_animate_);
1220 did_request_redraw_ = false;
1221 did_request_animate_ = false;
1222 host_impl_->Animate(start_time);
1223 EXPECT_TRUE(did_request_redraw_);
1224 EXPECT_TRUE(did_request_animate_);
1226 did_request_redraw_ = false;
1227 did_request_commit_ = false;
1228 did_request_animate_ = false;
1229 host_impl_->Animate(end_time);
1230 EXPECT_TRUE(did_request_redraw_);
1231 EXPECT_FALSE(did_request_animate_);
1232 EXPECT_TRUE(did_request_commit_);
1234 scoped_ptr<ScrollAndScaleSet> scroll_info =
1235 host_impl_->ProcessScrollDeltas();
1236 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1237 // Pushed to (0,0) via clamping against contents layer size.
1238 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1242 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1243 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1244 host_impl_->SetViewportSize(gfx::Size(50, 50));
1247 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1248 DCHECK(scroll_layer);
1250 float min_page_scale = 0.5f;
1251 float max_page_scale = 4.f;
1252 base::TimeTicks start_time = base::TimeTicks() +
1253 base::TimeDelta::FromSeconds(1);
1254 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1255 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1256 base::TimeTicks end_time = start_time + duration;
1258 // Anchor zoom with unchanged page scale should not change scroll or scale.
1260 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1263 scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
1265 host_impl_->active_tree()->SetPageScaleAnimation(
1270 host_impl_->ActivateSyncTree();
1271 host_impl_->Animate(start_time);
1272 host_impl_->Animate(halfway_through_animation);
1273 EXPECT_TRUE(did_request_redraw_);
1274 host_impl_->Animate(end_time);
1275 EXPECT_TRUE(did_request_commit_);
1277 scoped_ptr<ScrollAndScaleSet> scroll_info =
1278 host_impl_->ProcessScrollDeltas();
1279 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1280 ExpectNone(*scroll_info, scroll_layer->id());
1284 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
1285 host_impl_->CreatePendingTree();
1286 CreateScrollAndContentsLayers(
1287 host_impl_->pending_tree(),
1288 gfx::Size(100, 100));
1289 host_impl_->ActivateSyncTree();
1292 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1293 DCHECK(scroll_layer);
1295 float min_page_scale = 0.5f;
1296 float max_page_scale = 4.f;
1297 host_impl_->sync_tree()->SetPageScaleFactorAndLimits(1.f,
1300 host_impl_->ActivateSyncTree();
1302 base::TimeTicks start_time = base::TimeTicks() +
1303 base::TimeDelta::FromSeconds(1);
1304 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1305 base::TimeTicks third_through_animation = start_time + duration / 3;
1306 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1307 base::TimeTicks end_time = start_time + duration;
1308 float target_scale = 2.f;
1310 scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
1312 // Make sure TakePageScaleAnimation works properly.
1313 host_impl_->sync_tree()->SetPageScaleAnimation(
1318 scoped_ptr<PageScaleAnimation> psa =
1319 host_impl_->sync_tree()->TakePageScaleAnimation();
1320 EXPECT_EQ(target_scale, psa->target_page_scale_factor());
1321 EXPECT_EQ(duration, psa->duration());
1322 EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePageScaleAnimation());
1324 // Recreate the PSA. Nothing should happen here since the tree containing the
1325 // PSA hasn't been activated yet.
1326 did_request_redraw_ = false;
1327 did_request_animate_ = false;
1328 host_impl_->sync_tree()->SetPageScaleAnimation(
1333 host_impl_->Animate(halfway_through_animation);
1334 EXPECT_FALSE(did_request_animate_);
1335 EXPECT_FALSE(did_request_redraw_);
1337 // Activate the sync tree. This should cause the animation to become enabled.
1338 // It should also clear the pointer on the sync tree.
1339 host_impl_->ActivateSyncTree();
1340 EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePageScaleAnimation().get());
1341 EXPECT_FALSE(did_request_redraw_);
1342 EXPECT_TRUE(did_request_animate_);
1344 // From here on, make sure the animation runs as normal.
1345 did_request_redraw_ = false;
1346 did_request_animate_ = false;
1347 host_impl_->Animate(start_time);
1348 EXPECT_TRUE(did_request_redraw_);
1349 EXPECT_TRUE(did_request_animate_);
1351 did_request_redraw_ = false;
1352 did_request_animate_ = false;
1353 host_impl_->Animate(third_through_animation);
1354 EXPECT_TRUE(did_request_redraw_);
1355 EXPECT_TRUE(did_request_animate_);
1357 // Another activation shouldn't have any effect on the animation.
1358 host_impl_->ActivateSyncTree();
1360 did_request_redraw_ = false;
1361 did_request_animate_ = false;
1362 host_impl_->Animate(halfway_through_animation);
1363 EXPECT_TRUE(did_request_redraw_);
1364 EXPECT_TRUE(did_request_animate_);
1366 did_request_redraw_ = false;
1367 did_request_animate_ = false;
1368 did_request_commit_ = false;
1369 host_impl_->Animate(end_time);
1370 EXPECT_TRUE(did_request_commit_);
1371 EXPECT_FALSE(did_request_animate_);
1373 scoped_ptr<ScrollAndScaleSet> scroll_info =
1374 host_impl_->ProcessScrollDeltas();
1375 EXPECT_EQ(scroll_info->page_scale_delta, target_scale);
1376 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1379 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1381 LayerTreeHostImplOverridePhysicalTime(
1382 const LayerTreeSettings& settings,
1383 LayerTreeHostImplClient* client,
1385 SharedBitmapManager* manager,
1386 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1387 : LayerTreeHostImpl(settings,
1390 rendering_stats_instrumentation,
1395 BeginFrameArgs CurrentBeginFrameArgs() const override {
1396 return CreateBeginFrameArgsForTesting(fake_current_physical_time_);
1399 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1400 fake_current_physical_time_ = fake_now;
1404 base::TimeTicks fake_current_physical_time_;
1407 #define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST() \
1408 gfx::Size viewport_size(10, 10); \
1409 gfx::Size content_size(100, 100); \
1411 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = \
1412 new LayerTreeHostImplOverridePhysicalTime(settings, \
1415 shared_bitmap_manager_.get(), \
1416 &stats_instrumentation_); \
1417 host_impl_ = make_scoped_ptr(host_impl_override_time); \
1418 host_impl_->InitializeRenderer(CreateOutputSurface()); \
1419 host_impl_->SetViewportSize(viewport_size); \
1421 scoped_ptr<LayerImpl> root = \
1422 LayerImpl::Create(host_impl_->active_tree(), 1); \
1423 root->SetBounds(viewport_size); \
1425 scoped_ptr<LayerImpl> scroll = \
1426 LayerImpl::Create(host_impl_->active_tree(), 2); \
1427 scroll->SetScrollClipLayer(root->id()); \
1428 scroll->SetScrollOffset(gfx::ScrollOffset()); \
1429 root->SetBounds(viewport_size); \
1430 scroll->SetBounds(content_size); \
1431 scroll->SetContentBounds(content_size); \
1432 scroll->SetIsContainerForFixedPositionLayers(true); \
1434 scoped_ptr<LayerImpl> contents = \
1435 LayerImpl::Create(host_impl_->active_tree(), 3); \
1436 contents->SetDrawsContent(true); \
1437 contents->SetBounds(content_size); \
1438 contents->SetContentBounds(content_size); \
1440 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = \
1441 SolidColorScrollbarLayerImpl::Create( \
1442 host_impl_->active_tree(), 4, VERTICAL, 10, 0, false, true); \
1443 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); \
1445 scroll->AddChild(contents.Pass()); \
1446 root->AddChild(scroll.Pass()); \
1447 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1); \
1448 root->AddChild(scrollbar.Pass()); \
1450 host_impl_->active_tree()->SetRootLayer(root.Pass()); \
1451 host_impl_->active_tree()->SetViewportLayersFromIds( \
1452 1, 2, Layer::INVALID_ID); \
1453 host_impl_->active_tree()->DidBecomeActive(); \
1456 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1457 LayerTreeSettings settings;
1458 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1459 settings.scrollbar_fade_delay_ms = 20;
1460 settings.scrollbar_fade_duration_ms = 20;
1462 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1464 base::TimeTicks fake_now = gfx::FrameTime::Now();
1466 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1467 EXPECT_FALSE(did_request_redraw_);
1469 // If no scroll happened during a scroll gesture, it should have no effect.
1470 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1471 host_impl_->ScrollEnd();
1472 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1473 EXPECT_FALSE(did_request_redraw_);
1474 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1476 // After a scroll, a fade animation should be scheduled about 20ms from now.
1477 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1478 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1479 host_impl_->ScrollEnd();
1480 did_request_redraw_ = false;
1481 did_request_animate_ = false;
1482 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1483 requested_scrollbar_animation_delay_);
1484 EXPECT_FALSE(did_request_redraw_);
1485 EXPECT_FALSE(did_request_animate_);
1486 requested_scrollbar_animation_delay_ = base::TimeDelta();
1487 scrollbar_fade_start_.Run();
1488 host_impl_->Animate(fake_now);
1490 // After the fade begins, we should start getting redraws instead of a
1491 // scheduled animation.
1492 fake_now += base::TimeDelta::FromMilliseconds(25);
1493 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1494 EXPECT_TRUE(did_request_animate_);
1495 did_request_animate_ = false;
1497 // Setting the scroll offset outside a scroll should also cause the scrollbar
1498 // to appear and to schedule a fade.
1499 host_impl_->InnerViewportScrollLayer()->SetScrollOffset(
1500 gfx::ScrollOffset(5, 5));
1501 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1502 requested_scrollbar_animation_delay_);
1503 EXPECT_FALSE(did_request_redraw_);
1504 EXPECT_FALSE(did_request_animate_);
1505 requested_scrollbar_animation_delay_ = base::TimeDelta();
1507 // Unnecessarily Fade animation of solid color scrollbar is not triggered.
1508 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1509 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1510 host_impl_->ScrollEnd();
1511 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1514 TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) {
1515 LayerTreeSettings settings;
1516 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1517 settings.scrollbar_fade_delay_ms = 20;
1518 settings.scrollbar_fade_duration_ms = 20;
1519 settings.use_pinch_zoom_scrollbars = true;
1521 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1523 base::TimeTicks fake_now = gfx::FrameTime::Now();
1525 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
1527 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1528 EXPECT_FALSE(did_request_animate_);
1530 // If no scroll happened during a scroll gesture, it should have no effect.
1531 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1532 host_impl_->ScrollEnd();
1533 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1534 EXPECT_FALSE(did_request_animate_);
1535 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1537 // After a scroll, no fade animation should be scheduled.
1538 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1539 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1540 host_impl_->ScrollEnd();
1541 did_request_redraw_ = false;
1542 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1543 EXPECT_FALSE(did_request_animate_);
1544 requested_scrollbar_animation_delay_ = base::TimeDelta();
1546 // We should not see any draw requests.
1547 fake_now += base::TimeDelta::FromMilliseconds(25);
1548 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1549 EXPECT_FALSE(did_request_animate_);
1551 // Make page scale > min so that subsequent scrolls will trigger fades.
1552 host_impl_->active_tree()->SetPageScaleDelta(1.1f);
1554 // After a scroll, a fade animation should be scheduled about 20ms from now.
1555 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1556 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1557 host_impl_->ScrollEnd();
1558 did_request_redraw_ = false;
1559 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1560 requested_scrollbar_animation_delay_);
1561 EXPECT_FALSE(did_request_animate_);
1562 requested_scrollbar_animation_delay_ = base::TimeDelta();
1563 scrollbar_fade_start_.Run();
1565 // After the fade begins, we should start getting redraws instead of a
1566 // scheduled animation.
1567 fake_now += base::TimeDelta::FromMilliseconds(25);
1568 host_impl_->Animate(fake_now);
1569 EXPECT_TRUE(did_request_animate_);
1572 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1573 float device_scale_factor) {
1574 LayerTreeSettings settings;
1575 settings.scrollbar_fade_delay_ms = 500;
1576 settings.scrollbar_fade_duration_ms = 300;
1577 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1579 gfx::Size viewport_size(300, 200);
1580 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1581 gfx::ScaleSize(viewport_size, device_scale_factor));
1582 gfx::Size content_size(1000, 1000);
1584 CreateHostImpl(settings, CreateOutputSurface());
1585 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1586 host_impl_->SetViewportSize(device_viewport_size);
1588 scoped_ptr<LayerImpl> root =
1589 LayerImpl::Create(host_impl_->active_tree(), 1);
1590 root->SetBounds(viewport_size);
1592 scoped_ptr<LayerImpl> scroll =
1593 LayerImpl::Create(host_impl_->active_tree(), 2);
1594 scroll->SetScrollClipLayer(root->id());
1595 scroll->SetScrollOffset(gfx::ScrollOffset());
1596 scroll->SetBounds(content_size);
1597 scroll->SetContentBounds(content_size);
1598 scroll->SetIsContainerForFixedPositionLayers(true);
1600 scoped_ptr<LayerImpl> contents =
1601 LayerImpl::Create(host_impl_->active_tree(), 3);
1602 contents->SetDrawsContent(true);
1603 contents->SetBounds(content_size);
1604 contents->SetContentBounds(content_size);
1606 // The scrollbar is on the right side.
1607 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1608 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1609 scrollbar->SetDrawsContent(true);
1610 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1611 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1612 scrollbar->SetPosition(gfx::Point(285, 0));
1614 scroll->AddChild(contents.Pass());
1615 root->AddChild(scroll.Pass());
1616 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1617 root->AddChild(scrollbar.Pass());
1619 host_impl_->active_tree()->SetRootLayer(root.Pass());
1620 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
1621 host_impl_->active_tree()->DidBecomeActive();
1624 LayerImpl* root_scroll =
1625 host_impl_->active_tree()->InnerViewportScrollLayer();
1626 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1627 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1628 static_cast<ScrollbarAnimationControllerThinning*>(
1629 root_scroll->scrollbar_animation_controller());
1630 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1632 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1633 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1635 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1636 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1638 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1639 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1641 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1642 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1643 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1645 did_request_redraw_ = false;
1646 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1647 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1648 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1649 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1650 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1651 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1652 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1655 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1656 SetupMouseMoveAtWithDeviceScale(1.f);
1659 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1660 SetupMouseMoveAtWithDeviceScale(2.f);
1663 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1664 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1665 host_impl_->SetViewportSize(gfx::Size(50, 50));
1666 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
1669 CompositorFrameMetadata metadata =
1670 host_impl_->MakeCompositorFrameMetadata();
1671 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1672 EXPECT_EQ(1.f, metadata.page_scale_factor);
1673 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
1674 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1675 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1676 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1679 // Scrolling should update metadata immediately.
1680 EXPECT_EQ(InputHandler::ScrollStarted,
1681 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1682 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1684 CompositorFrameMetadata metadata =
1685 host_impl_->MakeCompositorFrameMetadata();
1686 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1688 host_impl_->ScrollEnd();
1690 CompositorFrameMetadata metadata =
1691 host_impl_->MakeCompositorFrameMetadata();
1692 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1695 // Page scale should update metadata correctly (shrinking only the viewport).
1696 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1697 host_impl_->PinchGestureBegin();
1698 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1699 host_impl_->PinchGestureEnd();
1700 host_impl_->ScrollEnd();
1702 CompositorFrameMetadata metadata =
1703 host_impl_->MakeCompositorFrameMetadata();
1704 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1705 EXPECT_EQ(2.f, metadata.page_scale_factor);
1706 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
1707 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1708 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1709 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1712 // Likewise if set from the main thread.
1713 host_impl_->ProcessScrollDeltas();
1714 host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
1715 host_impl_->active_tree()->SetPageScaleDelta(1.f);
1717 CompositorFrameMetadata metadata =
1718 host_impl_->MakeCompositorFrameMetadata();
1719 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1720 EXPECT_EQ(4.f, metadata.page_scale_factor);
1721 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
1722 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1723 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1724 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1728 class DidDrawCheckLayer : public LayerImpl {
1730 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1731 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl, id));
1734 bool WillDraw(DrawMode draw_mode, ResourceProvider* provider) override {
1735 will_draw_called_ = true;
1736 if (will_draw_returns_false_)
1738 return LayerImpl::WillDraw(draw_mode, provider);
1741 void AppendQuads(RenderPass* render_pass,
1742 const Occlusion& occlusion_in_content_space,
1743 AppendQuadsData* append_quads_data) override {
1744 append_quads_called_ = true;
1745 LayerImpl::AppendQuads(
1746 render_pass, occlusion_in_content_space, append_quads_data);
1749 void DidDraw(ResourceProvider* provider) override {
1750 did_draw_called_ = true;
1751 LayerImpl::DidDraw(provider);
1754 bool will_draw_called() const { return will_draw_called_; }
1755 bool append_quads_called() const { return append_quads_called_; }
1756 bool did_draw_called() const { return did_draw_called_; }
1758 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1760 void ClearDidDrawCheck() {
1761 will_draw_called_ = false;
1762 append_quads_called_ = false;
1763 did_draw_called_ = false;
1767 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1768 : LayerImpl(tree_impl, id),
1769 will_draw_returns_false_(false),
1770 will_draw_called_(false),
1771 append_quads_called_(false),
1772 did_draw_called_(false) {
1773 SetBounds(gfx::Size(10, 10));
1774 SetContentBounds(gfx::Size(10, 10));
1775 SetDrawsContent(true);
1776 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1780 bool will_draw_returns_false_;
1781 bool will_draw_called_;
1782 bool append_quads_called_;
1783 bool did_draw_called_;
1786 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1787 // The root layer is always drawn, so run this test on a child layer that
1788 // will be masked out by the root layer's bounds.
1789 host_impl_->active_tree()->SetRootLayer(
1790 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1791 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1792 host_impl_->active_tree()->root_layer());
1794 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1795 DidDrawCheckLayer* layer =
1796 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1799 LayerTreeHostImpl::FrameData frame;
1800 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1801 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1802 host_impl_->DidDrawAllLayers(frame);
1804 EXPECT_TRUE(layer->will_draw_called());
1805 EXPECT_TRUE(layer->append_quads_called());
1806 EXPECT_TRUE(layer->did_draw_called());
1809 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
1812 LayerTreeHostImpl::FrameData frame;
1814 layer->set_will_draw_returns_false();
1815 layer->ClearDidDrawCheck();
1817 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1818 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1819 host_impl_->DidDrawAllLayers(frame);
1821 EXPECT_TRUE(layer->will_draw_called());
1822 EXPECT_FALSE(layer->append_quads_called());
1823 EXPECT_FALSE(layer->did_draw_called());
1827 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1828 // The root layer is always drawn, so run this test on a child layer that
1829 // will be masked out by the root layer's bounds.
1830 host_impl_->active_tree()->SetRootLayer(
1831 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1832 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1833 host_impl_->active_tree()->root_layer());
1834 root->SetMasksToBounds(true);
1836 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1837 DidDrawCheckLayer* layer =
1838 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1839 // Ensure visible_content_rect for layer is empty.
1840 layer->SetPosition(gfx::PointF(100.f, 100.f));
1841 layer->SetBounds(gfx::Size(10, 10));
1842 layer->SetContentBounds(gfx::Size(10, 10));
1844 LayerTreeHostImpl::FrameData frame;
1846 EXPECT_FALSE(layer->will_draw_called());
1847 EXPECT_FALSE(layer->did_draw_called());
1849 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1850 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1851 host_impl_->DidDrawAllLayers(frame);
1853 EXPECT_FALSE(layer->will_draw_called());
1854 EXPECT_FALSE(layer->did_draw_called());
1856 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1858 // Ensure visible_content_rect for layer is not empty
1859 layer->SetPosition(gfx::PointF());
1861 EXPECT_FALSE(layer->will_draw_called());
1862 EXPECT_FALSE(layer->did_draw_called());
1864 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1865 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1866 host_impl_->DidDrawAllLayers(frame);
1868 EXPECT_TRUE(layer->will_draw_called());
1869 EXPECT_TRUE(layer->did_draw_called());
1871 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1874 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1875 gfx::Size big_size(1000, 1000);
1876 host_impl_->SetViewportSize(big_size);
1878 host_impl_->active_tree()->SetRootLayer(
1879 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1880 DidDrawCheckLayer* root =
1881 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1883 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1884 DidDrawCheckLayer* occluded_layer =
1885 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1887 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1888 DidDrawCheckLayer* top_layer =
1889 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1890 // This layer covers the occluded_layer above. Make this layer large so it can
1892 top_layer->SetBounds(big_size);
1893 top_layer->SetContentBounds(big_size);
1894 top_layer->SetContentsOpaque(true);
1896 LayerTreeHostImpl::FrameData frame;
1898 EXPECT_FALSE(occluded_layer->will_draw_called());
1899 EXPECT_FALSE(occluded_layer->did_draw_called());
1900 EXPECT_FALSE(top_layer->will_draw_called());
1901 EXPECT_FALSE(top_layer->did_draw_called());
1903 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1904 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1905 host_impl_->DidDrawAllLayers(frame);
1907 EXPECT_FALSE(occluded_layer->will_draw_called());
1908 EXPECT_FALSE(occluded_layer->did_draw_called());
1909 EXPECT_TRUE(top_layer->will_draw_called());
1910 EXPECT_TRUE(top_layer->did_draw_called());
1913 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1914 host_impl_->active_tree()->SetRootLayer(
1915 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1916 DidDrawCheckLayer* root =
1917 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1919 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1920 DidDrawCheckLayer* layer1 =
1921 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1923 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1924 DidDrawCheckLayer* layer2 =
1925 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1927 layer1->SetOpacity(0.3f);
1928 layer1->SetShouldFlattenTransform(true);
1930 EXPECT_FALSE(root->did_draw_called());
1931 EXPECT_FALSE(layer1->did_draw_called());
1932 EXPECT_FALSE(layer2->did_draw_called());
1934 LayerTreeHostImpl::FrameData frame;
1935 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
1936 host_impl_->active_tree()->root_layer());
1937 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1938 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1939 host_impl_->DidDrawAllLayers(frame);
1941 EXPECT_TRUE(root->did_draw_called());
1942 EXPECT_TRUE(layer1->did_draw_called());
1943 EXPECT_TRUE(layer2->did_draw_called());
1945 EXPECT_NE(root->render_surface(), layer1->render_surface());
1946 EXPECT_TRUE(!!layer1->render_surface());
1949 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1951 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1954 bool had_incomplete_tile,
1956 ResourceProvider* resource_provider) {
1957 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl,
1960 had_incomplete_tile,
1962 resource_provider));
1965 void AppendQuads(RenderPass* render_pass,
1966 const Occlusion& occlusion_in_content_space,
1967 AppendQuadsData* append_quads_data) override {
1968 LayerImpl::AppendQuads(
1969 render_pass, occlusion_in_content_space, append_quads_data);
1970 if (had_incomplete_tile_)
1971 append_quads_data->num_incomplete_tiles++;
1973 append_quads_data->num_missing_tiles++;
1977 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1980 bool had_incomplete_tile,
1982 ResourceProvider* resource_provider)
1983 : DidDrawCheckLayer(tree_impl, id),
1984 tile_missing_(tile_missing),
1985 had_incomplete_tile_(had_incomplete_tile) {
1987 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1991 bool had_incomplete_tile_;
1994 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsOnDefault) {
1995 host_impl_->active_tree()->SetRootLayer(
1996 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1997 DidDrawCheckLayer* root =
1998 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2000 bool tile_missing = false;
2001 bool had_incomplete_tile = false;
2002 bool is_animating = false;
2004 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2007 had_incomplete_tile,
2009 host_impl_->resource_provider()));
2011 LayerTreeHostImpl::FrameData frame;
2013 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2014 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2015 host_impl_->DidDrawAllLayers(frame);
2018 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) {
2019 host_impl_->active_tree()->SetRootLayer(
2020 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2021 DidDrawCheckLayer* root =
2022 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2023 bool tile_missing = false;
2024 bool had_incomplete_tile = false;
2025 bool is_animating = true;
2027 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2030 had_incomplete_tile,
2032 host_impl_->resource_provider()));
2034 LayerTreeHostImpl::FrameData frame;
2036 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2037 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2038 host_impl_->DidDrawAllLayers(frame);
2041 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithMissingTiles) {
2042 host_impl_->active_tree()->SetRootLayer(
2043 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2044 DidDrawCheckLayer* root =
2045 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2047 LayerTreeHostImpl::FrameData frame;
2048 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2049 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2050 host_impl_->DidDrawAllLayers(frame);
2051 host_impl_->SwapBuffers(frame);
2053 bool tile_missing = true;
2054 bool had_incomplete_tile = false;
2055 bool is_animating = false;
2057 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2060 had_incomplete_tile,
2062 host_impl_->resource_provider()));
2063 LayerTreeHostImpl::FrameData frame2;
2064 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
2065 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2066 host_impl_->DidDrawAllLayers(frame2);
2069 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithIncompleteTile) {
2070 host_impl_->active_tree()->SetRootLayer(
2071 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2072 DidDrawCheckLayer* root =
2073 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2075 LayerTreeHostImpl::FrameData frame;
2076 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2077 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2078 host_impl_->DidDrawAllLayers(frame);
2079 host_impl_->SwapBuffers(frame);
2081 bool tile_missing = false;
2082 bool had_incomplete_tile = true;
2083 bool is_animating = false;
2085 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2088 had_incomplete_tile,
2090 host_impl_->resource_provider()));
2091 LayerTreeHostImpl::FrameData frame2;
2092 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
2093 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2094 host_impl_->DidDrawAllLayers(frame2);
2097 TEST_F(LayerTreeHostImplTest,
2098 PrepareToDrawFailsWithAnimationAndMissingTilesUsesCheckerboard) {
2099 host_impl_->active_tree()->SetRootLayer(
2100 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
2101 DidDrawCheckLayer* root =
2102 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2104 LayerTreeHostImpl::FrameData frame;
2105 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2106 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2107 host_impl_->DidDrawAllLayers(frame);
2108 host_impl_->SwapBuffers(frame);
2110 bool tile_missing = true;
2111 bool had_incomplete_tile = false;
2112 bool is_animating = true;
2114 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2117 had_incomplete_tile,
2119 host_impl_->resource_provider()));
2120 LayerTreeHostImpl::FrameData frame2;
2121 EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS,
2122 host_impl_->PrepareToDraw(&frame2));
2123 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2124 host_impl_->DidDrawAllLayers(frame2);
2127 TEST_F(LayerTreeHostImplTest,
2128 PrepareToDrawSucceedsWithAnimationAndIncompleteTiles) {
2129 host_impl_->active_tree()->SetRootLayer(
2130 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
2131 DidDrawCheckLayer* root =
2132 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2134 LayerTreeHostImpl::FrameData frame;
2135 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2136 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2137 host_impl_->DidDrawAllLayers(frame);
2138 host_impl_->SwapBuffers(frame);
2140 bool tile_missing = false;
2141 bool had_incomplete_tile = true;
2142 bool is_animating = true;
2144 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2147 had_incomplete_tile,
2149 host_impl_->resource_provider()));
2150 LayerTreeHostImpl::FrameData frame2;
2151 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
2152 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2153 host_impl_->DidDrawAllLayers(frame2);
2156 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenHighResRequired) {
2157 host_impl_->active_tree()->SetRootLayer(
2158 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2159 DidDrawCheckLayer* root =
2160 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2162 LayerTreeHostImpl::FrameData frame;
2163 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2164 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2165 host_impl_->DidDrawAllLayers(frame);
2166 host_impl_->SwapBuffers(frame);
2168 bool tile_missing = false;
2169 bool had_incomplete_tile = false;
2170 bool is_animating = false;
2172 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2175 had_incomplete_tile,
2177 host_impl_->resource_provider()));
2178 host_impl_->SetRequiresHighResToDraw();
2179 LayerTreeHostImpl::FrameData frame2;
2180 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
2181 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2182 host_impl_->DidDrawAllLayers(frame2);
2185 TEST_F(LayerTreeHostImplTest,
2186 PrepareToDrawFailsWhenHighResRequiredAndIncompleteTiles) {
2187 host_impl_->active_tree()->SetRootLayer(
2188 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2189 DidDrawCheckLayer* root =
2190 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2192 LayerTreeHostImpl::FrameData frame;
2193 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2194 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2195 host_impl_->DidDrawAllLayers(frame);
2196 host_impl_->SwapBuffers(frame);
2198 bool tile_missing = false;
2199 bool had_incomplete_tile = true;
2200 bool is_animating = false;
2202 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2205 had_incomplete_tile,
2207 host_impl_->resource_provider()));
2208 host_impl_->SetRequiresHighResToDraw();
2209 LayerTreeHostImpl::FrameData frame2;
2210 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2211 host_impl_->PrepareToDraw(&frame2));
2212 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2213 host_impl_->DidDrawAllLayers(frame2);
2216 TEST_F(LayerTreeHostImplTest,
2217 PrepareToDrawFailsWhenHighResRequiredAndMissingTile) {
2218 host_impl_->active_tree()->SetRootLayer(
2219 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2220 DidDrawCheckLayer* root =
2221 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2223 LayerTreeHostImpl::FrameData frame;
2224 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2225 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2226 host_impl_->DidDrawAllLayers(frame);
2227 host_impl_->SwapBuffers(frame);
2229 bool tile_missing = true;
2230 bool had_incomplete_tile = false;
2231 bool is_animating = false;
2233 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2236 had_incomplete_tile,
2238 host_impl_->resource_provider()));
2239 host_impl_->SetRequiresHighResToDraw();
2240 LayerTreeHostImpl::FrameData frame2;
2241 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2242 host_impl_->PrepareToDraw(&frame2));
2243 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2244 host_impl_->DidDrawAllLayers(frame2);
2247 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2248 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2249 root->SetScrollClipLayer(Layer::INVALID_ID);
2250 host_impl_->active_tree()->SetRootLayer(root.Pass());
2253 // Scroll event is ignored because layer is not scrollable.
2254 EXPECT_EQ(InputHandler::ScrollIgnored,
2255 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2256 EXPECT_FALSE(did_request_redraw_);
2257 EXPECT_FALSE(did_request_commit_);
2260 // TODO(bokan): Convert these tests to create inner and outer viewports.
2261 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2263 LayerTreeHostImplTopControlsTest()
2264 // Make the clip size the same as the layer (content) size so the layer is
2266 : layer_size_(10, 10),
2267 clip_size_(layer_size_) {
2268 settings_.calculate_top_controls_position = true;
2269 settings_.top_controls_height = 50;
2270 settings_.use_pinch_virtual_viewport = true;
2273 gfx::Size(clip_size_.width(),
2274 clip_size_.height() + settings_.top_controls_height);
2277 void SetupTopControlsAndScrollLayer() {
2278 scoped_ptr<LayerImpl> root =
2279 LayerImpl::Create(host_impl_->active_tree(), 1);
2280 scoped_ptr<LayerImpl> root_clip =
2281 LayerImpl::Create(host_impl_->active_tree(), 2);
2282 root_clip->SetBounds(clip_size_);
2283 root->SetScrollClipLayer(root_clip->id());
2284 root->SetBounds(layer_size_);
2285 root->SetContentBounds(layer_size_);
2286 root->SetPosition(gfx::PointF());
2287 root->SetDrawsContent(false);
2288 root->SetIsContainerForFixedPositionLayers(true);
2289 int inner_viewport_scroll_layer_id = root->id();
2290 int page_scale_layer_id = root_clip->id();
2291 root_clip->AddChild(root.Pass());
2292 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2293 host_impl_->active_tree()->SetViewportLayersFromIds(
2294 page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
2295 // Set a viewport size that is large enough to contain both the top controls
2296 // and some content.
2297 host_impl_->SetViewportSize(viewport_size_);
2298 host_impl_->SetTopControlsLayoutHeight(
2299 settings_.top_controls_height);
2301 host_impl_->CreatePendingTree();
2303 LayerImpl::Create(host_impl_->sync_tree(), 1);
2305 LayerImpl::Create(host_impl_->sync_tree(), 2);
2306 root_clip->SetBounds(clip_size_);
2307 root->SetScrollClipLayer(root_clip->id());
2308 root->SetBounds(layer_size_);
2309 root->SetContentBounds(layer_size_);
2310 root->SetPosition(gfx::PointF());
2311 root->SetDrawsContent(false);
2312 root->SetIsContainerForFixedPositionLayers(true);
2313 inner_viewport_scroll_layer_id = root->id();
2314 page_scale_layer_id = root_clip->id();
2315 root_clip->AddChild(root.Pass());
2316 host_impl_->sync_tree()->SetRootLayer(root_clip.Pass());
2317 host_impl_->sync_tree()->SetViewportLayersFromIds(
2318 page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
2319 // Set a viewport size that is large enough to contain both the top controls
2320 // and some content.
2321 host_impl_->SetViewportSize(viewport_size_);
2322 host_impl_->sync_tree()->set_top_controls_layout_height(
2323 settings_.top_controls_height);
2326 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2327 const gfx::Size& inner_viewport_size,
2328 const gfx::Size& outer_viewport_size,
2329 const gfx::Size& scroll_layer_size) {
2330 CreateHostImpl(settings_, CreateOutputSurface());
2331 host_impl_->SetTopControlsLayoutHeight(
2332 settings_.top_controls_height);
2334 scoped_ptr<LayerImpl> root =
2335 LayerImpl::Create(host_impl_->active_tree(), 1);
2336 scoped_ptr<LayerImpl> root_clip =
2337 LayerImpl::Create(host_impl_->active_tree(), 2);
2338 scoped_ptr<LayerImpl> page_scale =
2339 LayerImpl::Create(host_impl_->active_tree(), 3);
2341 scoped_ptr<LayerImpl> outer_scroll =
2342 LayerImpl::Create(host_impl_->active_tree(), 4);
2343 scoped_ptr<LayerImpl> outer_clip =
2344 LayerImpl::Create(host_impl_->active_tree(), 5);
2346 root_clip->SetBounds(inner_viewport_size);
2347 root->SetScrollClipLayer(root_clip->id());
2348 root->SetBounds(outer_viewport_size);
2349 root->SetContentBounds(outer_viewport_size);
2350 root->SetPosition(gfx::PointF());
2351 root->SetDrawsContent(false);
2352 root->SetIsContainerForFixedPositionLayers(true);
2354 outer_clip->SetBounds(outer_viewport_size);
2355 outer_scroll->SetScrollClipLayer(outer_clip->id());
2356 outer_scroll->SetBounds(scroll_layer_size);
2357 outer_scroll->SetContentBounds(scroll_layer_size);
2358 outer_scroll->SetPosition(gfx::PointF());
2359 outer_scroll->SetDrawsContent(false);
2360 outer_scroll->SetIsContainerForFixedPositionLayers(true);
2362 int inner_viewport_scroll_layer_id = root->id();
2363 int outer_viewport_scroll_layer_id = outer_scroll->id();
2364 int page_scale_layer_id = page_scale->id();
2366 outer_clip->AddChild(outer_scroll.Pass());
2367 root->AddChild(outer_clip.Pass());
2368 page_scale->AddChild(root.Pass());
2369 root_clip->AddChild(page_scale.Pass());
2371 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2372 host_impl_->active_tree()->SetViewportLayersFromIds(
2373 page_scale_layer_id,
2374 inner_viewport_scroll_layer_id,
2375 outer_viewport_scroll_layer_id);
2377 host_impl_->SetViewportSize(inner_viewport_size);
2378 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2379 EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds());
2383 gfx::Size layer_size_;
2384 gfx::Size clip_size_;
2385 gfx::Size viewport_size_;
2387 LayerTreeSettings settings_;
2388 }; // class LayerTreeHostImplTopControlsTest
2390 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2391 SetupTopControlsAndScrollLayerWithVirtualViewport(
2392 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2395 EXPECT_EQ(InputHandler::ScrollStarted,
2396 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2398 // Make the test scroll delta a fractional amount, to verify that the
2399 // fixed container size delta is (1) non-zero, and (2) fractional, and
2400 // (3) matches the movement of the top controls.
2401 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2402 host_impl_->top_controls_manager()->ScrollBegin();
2403 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2404 host_impl_->top_controls_manager()->ScrollEnd();
2406 LayerImpl* inner_viewport_scroll_layer =
2407 host_impl_->active_tree()->InnerViewportScrollLayer();
2408 DCHECK(inner_viewport_scroll_layer);
2409 host_impl_->ScrollEnd();
2410 EXPECT_EQ(top_controls_scroll_delta,
2411 inner_viewport_scroll_layer->FixedContainerSizeDelta());
2414 // In this test, the outer viewport is initially unscrollable. We test that a
2415 // scroll initiated on the inner viewport, causing the top controls to show and
2416 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2417 TEST_F(LayerTreeHostImplTopControlsTest,
2418 TopControlsOuterViewportBecomesScrollable) {
2419 SetupTopControlsAndScrollLayerWithVirtualViewport(
2420 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2423 LayerImpl *inner_scroll =
2424 host_impl_->active_tree()->InnerViewportScrollLayer();
2425 LayerImpl *inner_container =
2426 host_impl_->active_tree()->InnerViewportContainerLayer();
2427 LayerImpl *outer_scroll =
2428 host_impl_->active_tree()->OuterViewportScrollLayer();
2429 LayerImpl *outer_container =
2430 host_impl_->active_tree()->OuterViewportContainerLayer();
2432 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2433 outer_scroll->SetDrawsContent(true);
2434 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 1.f, 2.f);
2436 EXPECT_EQ(InputHandler::ScrollStarted,
2437 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2438 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 50.f));
2440 // The entire scroll delta should have been used to hide the top controls.
2441 // The viewport layers should be resized back to their full sizes.
2443 host_impl_->active_tree()->total_top_controls_content_offset());
2444 EXPECT_EQ(0.f, inner_scroll->TotalScrollOffset().y());
2445 EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height());
2446 EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height());
2448 // The inner viewport should be scrollable by 50px * page_scale.
2449 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 100.f));
2450 EXPECT_EQ(50.f, inner_scroll->TotalScrollOffset().y());
2451 EXPECT_EQ(0.f, outer_scroll->TotalScrollOffset().y());
2452 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset());
2454 host_impl_->ScrollEnd();
2456 EXPECT_EQ(InputHandler::ScrollStarted,
2457 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2458 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
2460 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2462 // The entire scroll delta should have been used to show the top controls.
2463 // The outer viewport should be resized to accomodate and scrolled to the
2464 // bottom of the document to keep the viewport in place.
2466 host_impl_->active_tree()->total_top_controls_content_offset());
2467 EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height());
2468 EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height());
2469 EXPECT_EQ(25.f, outer_scroll->TotalScrollOffset().y());
2470 EXPECT_EQ(25.f, inner_scroll->TotalScrollOffset().y());
2472 // Now when we continue scrolling, make sure the outer viewport gets scrolled
2473 // since it wasn't scrollable when the scroll began.
2474 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f));
2475 EXPECT_EQ(15.f, outer_scroll->TotalScrollOffset().y());
2476 EXPECT_EQ(25.f, inner_scroll->TotalScrollOffset().y());
2478 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f));
2479 EXPECT_EQ(0.f, outer_scroll->TotalScrollOffset().y());
2480 EXPECT_EQ(25.f, inner_scroll->TotalScrollOffset().y());
2482 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2483 host_impl_->ScrollEnd();
2485 EXPECT_EQ(0.f, outer_scroll->TotalScrollOffset().y());
2486 EXPECT_EQ(0.f, inner_scroll->TotalScrollOffset().y());
2489 // Test that the fixed position container delta is appropriately adjusted
2490 // by the top controls showing/hiding and page scale doesn't affect it.
2491 TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
2492 SetupTopControlsAndScrollLayerWithVirtualViewport(
2493 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
2496 float page_scale = 1.5f;
2497 float top_controls_height = settings_.top_controls_height;
2498 LayerImpl* outer_viewport_scroll_layer =
2499 host_impl_->active_tree()->OuterViewportScrollLayer();
2501 // Zoom in, since the fixed container is the outer viewport, the delta should
2503 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale, 1.f, 2.f);
2505 EXPECT_EQ(InputHandler::ScrollStarted,
2506 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2508 // Scroll down, the top controls hiding should expand the viewport size so
2509 // the delta should be equal to the scroll distance.
2510 gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
2511 host_impl_->top_controls_manager()->ScrollBegin();
2512 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2513 EXPECT_EQ(top_controls_height - top_controls_scroll_delta.y(),
2514 host_impl_->top_controls_manager()->ContentTopOffset());
2515 EXPECT_VECTOR_EQ(top_controls_scroll_delta,
2516 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2517 host_impl_->ScrollEnd();
2519 // Scroll past the maximum extent. The delta shouldn't be greater than the
2520 // top controls height.
2521 host_impl_->top_controls_manager()->ScrollBegin();
2522 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2523 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2524 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2525 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2526 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height),
2527 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2528 host_impl_->ScrollEnd();
2530 // Scroll in the direction to make the top controls show.
2531 host_impl_->top_controls_manager()->ScrollBegin();
2532 host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta);
2533 EXPECT_EQ(top_controls_scroll_delta.y(),
2534 host_impl_->top_controls_manager()->ContentTopOffset());
2536 gfx::Vector2dF(0, top_controls_height - top_controls_scroll_delta.y()),
2537 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2538 host_impl_->top_controls_manager()->ScrollEnd();
2541 // Ensure setting the top controls position explicitly using the setters on the
2542 // TreeImpl correctly affects the top controls manager and viewport bounds.
2543 TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
2544 CreateHostImpl(settings_, CreateOutputSurface());
2545 SetupTopControlsAndScrollLayer();
2548 host_impl_->active_tree()->set_top_controls_delta(0.f);
2549 host_impl_->active_tree()->set_top_controls_content_offset(30.f);
2550 EXPECT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
2551 EXPECT_EQ(-20.f, host_impl_->top_controls_manager()->ControlsTopOffset());
2553 host_impl_->active_tree()->set_top_controls_delta(-30.f);
2554 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2555 EXPECT_EQ(-50.f, host_impl_->top_controls_manager()->ControlsTopOffset());
2557 host_impl_->DidChangeTopControlsPosition();
2559 // Now that top controls have moved, expect the clip to resize.
2560 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2561 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2564 // Test that the top_controls delta and sent delta are appropriately
2565 // applied on sync tree activation. The total top controls offset shouldn't
2566 // change after the activation.
2567 TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
2568 CreateHostImpl(settings_, CreateOutputSurface());
2569 SetupTopControlsAndScrollLayer();
2572 host_impl_->sync_tree()->set_top_controls_content_offset(15.f);
2574 host_impl_->active_tree()->set_top_controls_content_offset(20.f);
2575 host_impl_->active_tree()->set_top_controls_delta(-20.f);
2576 host_impl_->active_tree()->set_sent_top_controls_delta(-5.f);
2578 host_impl_->DidChangeTopControlsPosition();
2579 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2580 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2581 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2583 host_impl_->active_tree()->total_top_controls_content_offset());
2585 host_impl_->ActivateSyncTree();
2587 root_clip_ptr = host_impl_->active_tree()->root_layer();
2588 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2589 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2591 EXPECT_EQ(0.f, host_impl_->active_tree()->sent_top_controls_delta());
2592 EXPECT_EQ(-15.f, host_impl_->active_tree()->top_controls_delta());
2593 EXPECT_EQ(15.f, host_impl_->active_tree()->top_controls_content_offset());
2595 host_impl_->active_tree()->total_top_controls_content_offset());
2598 // Test that changing the top controls layout height is correctly applied to
2599 // the inner viewport container bounds. That is, the top controls layout
2600 // height is the amount that the inner viewport container was shrunk outside
2601 // the compositor to accommodate the top controls.
2602 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
2603 CreateHostImpl(settings_, CreateOutputSurface());
2604 SetupTopControlsAndScrollLayer();
2607 host_impl_->sync_tree()->set_top_controls_content_offset(15.f);
2608 host_impl_->sync_tree()->set_top_controls_layout_height(15.f);
2610 host_impl_->active_tree()->set_top_controls_content_offset(20.f);
2611 host_impl_->active_tree()->set_top_controls_delta(-20.f);
2612 host_impl_->active_tree()->set_sent_top_controls_delta(-5.f);
2614 host_impl_->DidChangeTopControlsPosition();
2615 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2616 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2617 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2619 host_impl_->sync_tree()->root_layer()->SetBounds(
2620 gfx::Size(root_clip_ptr->bounds().width(),
2621 root_clip_ptr->bounds().height() - 15.f));
2623 host_impl_->ActivateSyncTree();
2625 root_clip_ptr = host_impl_->active_tree()->root_layer();
2626 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2628 // The total bounds should remain unchanged since the bounds delta should
2629 // account for the difference between the layout height and the current
2630 // top controls offset.
2631 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2632 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 15.f), root_clip_ptr->bounds_delta());
2634 host_impl_->active_tree()->set_top_controls_delta(0.f);
2635 host_impl_->DidChangeTopControlsPosition();
2637 EXPECT_EQ(15.f, host_impl_->top_controls_manager()->ContentTopOffset());
2638 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), root_clip_ptr->bounds_delta());
2639 EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height()-15.f),
2640 root_clip_ptr->bounds());
2643 // Test that showing/hiding the top controls when the viewport is fully scrolled
2644 // doesn't incorrectly change the viewport offset due to clamping from changing
2646 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) {
2647 SetupTopControlsAndScrollLayerWithVirtualViewport(
2648 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2651 EXPECT_EQ(settings_.top_controls_height,
2652 host_impl_->active_tree()->total_top_controls_content_offset());
2654 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
2655 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
2657 // Scroll the viewports to max scroll offset.
2658 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
2659 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
2661 gfx::ScrollOffset viewport_offset =
2662 host_impl_->active_tree()->TotalScrollOffset();
2663 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset);
2665 // Hide the top controls by 25px.
2666 gfx::Vector2dF scroll_delta(0.f, 25.f);
2667 EXPECT_EQ(InputHandler::ScrollStarted,
2668 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2669 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2670 host_impl_->ScrollEnd();
2672 EXPECT_EQ(scroll_delta.y(),
2673 settings_.top_controls_height -
2674 host_impl_->active_tree()->total_top_controls_content_offset());
2676 inner_scroll->ClampScrollToMaxScrollOffset();
2677 outer_scroll->ClampScrollToMaxScrollOffset();
2679 // We should still be fully scrolled.
2680 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
2681 host_impl_->active_tree()->TotalScrollOffset());
2683 viewport_offset = host_impl_->active_tree()->TotalScrollOffset();
2685 // Bring the top controls down by 25px.
2686 scroll_delta = gfx::Vector2dF(0.f, -25.f);
2687 EXPECT_EQ(InputHandler::ScrollStarted,
2688 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2689 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2690 host_impl_->ScrollEnd();
2692 // The viewport offset shouldn't have changed.
2693 EXPECT_EQ(viewport_offset,
2694 host_impl_->active_tree()->TotalScrollOffset());
2696 // Scroll the viewports to max scroll offset.
2697 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
2698 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
2699 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
2700 host_impl_->active_tree()->TotalScrollOffset());
2703 // Test that the top controls coming in and out maintains the same aspect ratio
2704 // between the inner and outer viewports.
2705 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
2706 SetupTopControlsAndScrollLayerWithVirtualViewport(
2707 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2710 EXPECT_EQ(settings_.top_controls_height,
2711 host_impl_->active_tree()->total_top_controls_content_offset());
2713 gfx::Vector2dF scroll_delta(0.f, 25.f);
2714 EXPECT_EQ(InputHandler::ScrollStarted,
2715 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2716 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2717 host_impl_->ScrollEnd();
2719 EXPECT_EQ(scroll_delta.y(),
2720 settings_.top_controls_height -
2721 host_impl_->active_tree()->total_top_controls_content_offset());
2723 // Top controls were hidden by 25px so the inner viewport should have expanded
2725 LayerImpl* outer_container =
2726 host_impl_->active_tree()->OuterViewportContainerLayer();
2727 LayerImpl* inner_container =
2728 host_impl_->active_tree()->InnerViewportContainerLayer();
2729 EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling());
2731 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
2732 float aspect_ratio = inner_container->BoundsForScrolling().width() /
2733 inner_container->BoundsForScrolling().height();
2734 gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio));
2735 EXPECT_EQ(expected, outer_container->BoundsForScrolling());
2737 host_impl_->InnerViewportScrollLayer()->BoundsForScrolling());
2740 // Test that scrolling the outer viewport affects the top controls.
2741 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
2742 SetupTopControlsAndScrollLayerWithVirtualViewport(
2743 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2746 EXPECT_EQ(settings_.top_controls_height,
2747 host_impl_->active_tree()->total_top_controls_content_offset());
2749 // Send a gesture scroll that will scroll the outer viewport, make sure the
2750 // top controls get scrolled.
2751 gfx::Vector2dF scroll_delta(0.f, 15.f);
2752 EXPECT_EQ(InputHandler::ScrollStarted,
2753 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2754 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2755 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
2756 host_impl_->CurrentlyScrollingLayer());
2757 host_impl_->ScrollEnd();
2759 EXPECT_EQ(scroll_delta.y(),
2760 settings_.top_controls_height -
2761 host_impl_->active_tree()->total_top_controls_content_offset());
2763 scroll_delta = gfx::Vector2dF(0.f, 50.f);
2764 EXPECT_EQ(InputHandler::ScrollStarted,
2765 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2766 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2768 EXPECT_EQ(0, host_impl_->active_tree()->total_top_controls_content_offset());
2769 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
2770 host_impl_->CurrentlyScrollingLayer());
2772 host_impl_->ScrollEnd();
2774 // Position the viewports such that the inner viewport will be scrolled.
2775 gfx::Vector2dF inner_viewport_offset(0.f, 25.f);
2776 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
2777 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset);
2779 scroll_delta = gfx::Vector2dF(0.f, -65.f);
2780 EXPECT_EQ(InputHandler::ScrollStarted,
2781 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2782 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2784 EXPECT_EQ(settings_.top_controls_height,
2785 host_impl_->active_tree()->total_top_controls_content_offset());
2786 EXPECT_EQ(inner_viewport_offset.y() +
2787 (scroll_delta.y() + settings_.top_controls_height),
2788 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
2790 host_impl_->ScrollEnd();
2793 TEST_F(LayerTreeHostImplTopControlsTest,
2794 ScrollNonScrollableRootWithTopControls) {
2795 CreateHostImpl(settings_, CreateOutputSurface());
2796 SetupTopControlsAndScrollLayer();
2799 EXPECT_EQ(InputHandler::ScrollStarted,
2800 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2802 host_impl_->top_controls_manager()->ScrollBegin();
2803 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
2804 host_impl_->top_controls_manager()->ScrollEnd();
2805 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2806 // Now that top controls have moved, expect the clip to resize.
2807 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2808 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2810 host_impl_->ScrollEnd();
2812 EXPECT_EQ(InputHandler::ScrollStarted,
2813 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2815 float scroll_increment_y = -25.f;
2816 host_impl_->top_controls_manager()->ScrollBegin();
2817 host_impl_->top_controls_manager()->ScrollBy(
2818 gfx::Vector2dF(0.f, scroll_increment_y));
2819 EXPECT_EQ(-scroll_increment_y,
2820 host_impl_->top_controls_manager()->ContentTopOffset());
2821 // Now that top controls have moved, expect the clip to resize.
2822 EXPECT_EQ(gfx::Size(viewport_size_.width(),
2823 viewport_size_.height() + scroll_increment_y),
2824 root_clip_ptr->bounds());
2826 host_impl_->top_controls_manager()->ScrollBy(
2827 gfx::Vector2dF(0.f, scroll_increment_y));
2828 host_impl_->top_controls_manager()->ScrollEnd();
2829 EXPECT_EQ(-2 * scroll_increment_y,
2830 host_impl_->top_controls_manager()->ContentTopOffset());
2831 // Now that top controls have moved, expect the clip to resize.
2832 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2834 host_impl_->ScrollEnd();
2836 // Verify the layer is once-again non-scrollable.
2838 gfx::ScrollOffset(),
2839 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
2841 EXPECT_EQ(InputHandler::ScrollStarted,
2842 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2845 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
2846 // Test the configuration where a non-composited root layer is embedded in a
2847 // scrollable outer layer.
2848 gfx::Size surface_size(10, 10);
2849 gfx::Size contents_size(20, 20);
2851 scoped_ptr<LayerImpl> content_layer =
2852 LayerImpl::Create(host_impl_->active_tree(), 1);
2853 content_layer->SetDrawsContent(true);
2854 content_layer->SetPosition(gfx::PointF());
2855 content_layer->SetBounds(contents_size);
2856 content_layer->SetContentBounds(contents_size);
2857 content_layer->SetContentsScale(2.f, 2.f);
2859 scoped_ptr<LayerImpl> scroll_clip_layer =
2860 LayerImpl::Create(host_impl_->active_tree(), 3);
2861 scroll_clip_layer->SetBounds(surface_size);
2863 scoped_ptr<LayerImpl> scroll_layer =
2864 LayerImpl::Create(host_impl_->active_tree(), 2);
2865 scroll_layer->SetScrollClipLayer(3);
2866 scroll_layer->SetBounds(contents_size);
2867 scroll_layer->SetContentBounds(contents_size);
2868 scroll_layer->SetPosition(gfx::PointF());
2869 scroll_layer->AddChild(content_layer.Pass());
2870 scroll_clip_layer->AddChild(scroll_layer.Pass());
2872 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
2873 host_impl_->SetViewportSize(surface_size);
2876 EXPECT_EQ(InputHandler::ScrollStarted,
2877 host_impl_->ScrollBegin(gfx::Point(5, 5),
2878 InputHandler::Wheel));
2879 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2880 host_impl_->ScrollEnd();
2881 EXPECT_TRUE(did_request_redraw_);
2882 EXPECT_TRUE(did_request_commit_);
2885 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
2886 gfx::Size surface_size(10, 10);
2887 gfx::Size contents_size(20, 20);
2888 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2889 root->SetBounds(surface_size);
2890 root->SetContentBounds(contents_size);
2891 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
2892 host_impl_->active_tree()->SetRootLayer(root.Pass());
2893 host_impl_->SetViewportSize(surface_size);
2896 EXPECT_EQ(InputHandler::ScrollStarted,
2897 host_impl_->ScrollBegin(gfx::Point(5, 5),
2898 InputHandler::Wheel));
2899 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2900 host_impl_->ScrollEnd();
2901 EXPECT_TRUE(did_request_redraw_);
2902 EXPECT_TRUE(did_request_commit_);
2905 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
2906 gfx::Size surface_size(10, 10);
2907 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2908 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
2909 host_impl_->active_tree()->SetRootLayer(root.Pass());
2910 host_impl_->SetViewportSize(surface_size);
2913 // Scroll event is ignored because the input coordinate is outside the layer
2915 EXPECT_EQ(InputHandler::ScrollIgnored,
2916 host_impl_->ScrollBegin(gfx::Point(15, 5),
2917 InputHandler::Wheel));
2918 EXPECT_FALSE(did_request_redraw_);
2919 EXPECT_FALSE(did_request_commit_);
2922 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
2923 gfx::Size surface_size(10, 10);
2924 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2925 scoped_ptr<LayerImpl> child =
2926 CreateScrollableLayer(2, surface_size, root.get());
2927 host_impl_->SetViewportSize(surface_size);
2929 gfx::Transform matrix;
2930 matrix.RotateAboutXAxis(180.0);
2931 child->SetTransform(matrix);
2932 child->SetDoubleSided(false);
2934 root->AddChild(child.Pass());
2935 host_impl_->active_tree()->SetRootLayer(root.Pass());
2938 // Scroll event is ignored because the scrollable layer is not facing the
2939 // viewer and there is nothing scrollable behind it.
2940 EXPECT_EQ(InputHandler::ScrollIgnored,
2941 host_impl_->ScrollBegin(gfx::Point(5, 5),
2942 InputHandler::Wheel));
2943 EXPECT_FALSE(did_request_redraw_);
2944 EXPECT_FALSE(did_request_commit_);
2947 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
2948 gfx::Size surface_size(10, 10);
2949 scoped_ptr<LayerImpl> clip_layer =
2950 LayerImpl::Create(host_impl_->active_tree(), 3);
2951 scoped_ptr<LayerImpl> content_layer =
2952 CreateScrollableLayer(1, surface_size, clip_layer.get());
2953 content_layer->SetShouldScrollOnMainThread(true);
2954 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
2956 // Note: we can use the same clip layer for both since both calls to
2957 // CreateScrollableLayer() use the same surface size.
2958 scoped_ptr<LayerImpl> scroll_layer =
2959 CreateScrollableLayer(2, surface_size, clip_layer.get());
2960 scroll_layer->AddChild(content_layer.Pass());
2961 clip_layer->AddChild(scroll_layer.Pass());
2963 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
2964 host_impl_->SetViewportSize(surface_size);
2967 // Scrolling fails because the content layer is asking to be scrolled on the
2969 EXPECT_EQ(InputHandler::ScrollOnMainThread,
2970 host_impl_->ScrollBegin(gfx::Point(5, 5),
2971 InputHandler::Wheel));
2974 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
2975 gfx::Size surface_size(20, 20);
2976 gfx::Size viewport_size(10, 10);
2977 float page_scale = 2.f;
2978 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2979 scoped_ptr<LayerImpl> root_clip =
2980 LayerImpl::Create(host_impl_->active_tree(), 2);
2981 scoped_ptr<LayerImpl> root_scrolling =
2982 CreateScrollableLayer(3, surface_size, root_clip.get());
2983 EXPECT_EQ(viewport_size, root_clip->bounds());
2984 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2985 root_clip->AddChild(root_scrolling.Pass());
2986 root->AddChild(root_clip.Pass());
2987 host_impl_->active_tree()->SetRootLayer(root.Pass());
2988 // The behaviour in this test assumes the page scale is applied at a layer
2989 // above the clip layer.
2990 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2991 host_impl_->active_tree()->DidBecomeActive();
2992 host_impl_->SetViewportSize(viewport_size);
2995 LayerImpl* root_scroll =
2996 host_impl_->active_tree()->InnerViewportScrollLayer();
2997 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2999 gfx::Vector2d scroll_delta(0, 10);
3000 gfx::Vector2d expected_scroll_delta = scroll_delta;
3001 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3002 EXPECT_EQ(InputHandler::ScrollStarted,
3003 host_impl_->ScrollBegin(gfx::Point(5, 5),
3004 InputHandler::Wheel));
3005 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3006 host_impl_->ScrollEnd();
3008 // Set new page scale from main thread.
3009 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
3013 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3014 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
3016 // The scroll range should also have been updated.
3017 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3019 // The page scale delta remains constant because the impl thread did not
3021 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3024 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
3025 gfx::Size surface_size(20, 20);
3026 gfx::Size viewport_size(10, 10);
3027 float page_scale = 2.f;
3028 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3029 scoped_ptr<LayerImpl> root_clip =
3030 LayerImpl::Create(host_impl_->active_tree(), 2);
3031 scoped_ptr<LayerImpl> root_scrolling =
3032 CreateScrollableLayer(3, surface_size, root_clip.get());
3033 EXPECT_EQ(viewport_size, root_clip->bounds());
3034 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3035 root_clip->AddChild(root_scrolling.Pass());
3036 root->AddChild(root_clip.Pass());
3037 host_impl_->active_tree()->SetRootLayer(root.Pass());
3038 // The behaviour in this test assumes the page scale is applied at a layer
3039 // above the clip layer.
3040 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
3041 host_impl_->active_tree()->DidBecomeActive();
3042 host_impl_->SetViewportSize(viewport_size);
3043 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
3046 LayerImpl* root_scroll =
3047 host_impl_->active_tree()->InnerViewportScrollLayer();
3048 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3050 gfx::Vector2d scroll_delta(0, 10);
3051 gfx::Vector2d expected_scroll_delta = scroll_delta;
3052 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3053 EXPECT_EQ(InputHandler::ScrollStarted,
3054 host_impl_->ScrollBegin(gfx::Point(5, 5),
3055 InputHandler::Wheel));
3056 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3057 host_impl_->ScrollEnd();
3059 // Set new page scale on impl thread by pinching.
3060 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3061 host_impl_->PinchGestureBegin();
3062 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
3063 host_impl_->PinchGestureEnd();
3064 host_impl_->ScrollEnd();
3067 // The scroll delta is not scaled because the main thread did not scale.
3068 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3069 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
3071 // The scroll range should also have been updated.
3072 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3074 // The page scale delta should match the new scale on the impl side.
3075 EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
3078 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
3079 gfx::Size surface_size(10, 10);
3080 float default_page_scale = 1.f;
3081 gfx::Transform default_page_scale_matrix;
3082 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
3084 float new_page_scale = 2.f;
3085 gfx::Transform new_page_scale_matrix;
3086 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
3088 // Create a normal scrollable root layer and another scrollable child layer.
3089 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
3090 LayerImpl* root = host_impl_->active_tree()->root_layer();
3091 LayerImpl* child = scroll->children()[0];
3093 scoped_ptr<LayerImpl> scrollable_child_clip =
3094 LayerImpl::Create(host_impl_->active_tree(), 6);
3095 scoped_ptr<LayerImpl> scrollable_child =
3096 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
3097 scrollable_child_clip->AddChild(scrollable_child.Pass());
3098 child->AddChild(scrollable_child_clip.Pass());
3099 LayerImpl* grand_child = child->children()[0];
3101 // Set new page scale on impl thread by pinching.
3102 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3103 host_impl_->PinchGestureBegin();
3104 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
3105 host_impl_->PinchGestureEnd();
3106 host_impl_->ScrollEnd();
3109 EXPECT_EQ(1.f, root->contents_scale_x());
3110 EXPECT_EQ(1.f, root->contents_scale_y());
3111 EXPECT_EQ(1.f, scroll->contents_scale_x());
3112 EXPECT_EQ(1.f, scroll->contents_scale_y());
3113 EXPECT_EQ(1.f, child->contents_scale_x());
3114 EXPECT_EQ(1.f, child->contents_scale_y());
3115 EXPECT_EQ(1.f, grand_child->contents_scale_x());
3116 EXPECT_EQ(1.f, grand_child->contents_scale_y());
3118 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3119 // the page scale delta on the root layer is applied hierarchically.
3120 LayerTreeHostImpl::FrameData frame;
3121 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3122 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3123 host_impl_->DidDrawAllLayers(frame);
3125 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
3126 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
3127 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
3128 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
3129 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
3130 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
3131 EXPECT_EQ(new_page_scale,
3132 grand_child->draw_transform().matrix().getDouble(0, 0));
3133 EXPECT_EQ(new_page_scale,
3134 grand_child->draw_transform().matrix().getDouble(1, 1));
3137 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
3138 gfx::Size surface_size(30, 30);
3139 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3140 root->SetBounds(gfx::Size(5, 5));
3141 scoped_ptr<LayerImpl> root_scrolling =
3142 LayerImpl::Create(host_impl_->active_tree(), 2);
3143 root_scrolling->SetBounds(surface_size);
3144 root_scrolling->SetContentBounds(surface_size);
3145 root_scrolling->SetScrollClipLayer(root->id());
3146 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3147 LayerImpl* root_scrolling_ptr = root_scrolling.get();
3148 root->AddChild(root_scrolling.Pass());
3149 int child_scroll_layer_id = 3;
3150 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
3151 child_scroll_layer_id, surface_size, root_scrolling_ptr);
3152 LayerImpl* child = child_scrolling.get();
3153 root_scrolling_ptr->AddChild(child_scrolling.Pass());
3154 host_impl_->active_tree()->SetRootLayer(root.Pass());
3155 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
3156 host_impl_->active_tree()->DidBecomeActive();
3157 host_impl_->SetViewportSize(surface_size);
3160 gfx::Vector2d scroll_delta(0, 10);
3161 gfx::Vector2d expected_scroll_delta(scroll_delta);
3162 gfx::ScrollOffset expected_max_scroll(child->MaxScrollOffset());
3163 EXPECT_EQ(InputHandler::ScrollStarted,
3164 host_impl_->ScrollBegin(gfx::Point(5, 5),
3165 InputHandler::Wheel));
3166 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3167 host_impl_->ScrollEnd();
3169 float page_scale = 2.f;
3170 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
3176 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3178 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
3180 // The scroll range should not have changed.
3181 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
3183 // The page scale delta remains constant because the impl thread did not
3185 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3188 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
3189 // Scroll a child layer beyond its maximum scroll range and make sure the
3190 // parent layer is scrolled on the axis on which the child was unable to
3192 gfx::Size surface_size(10, 10);
3193 gfx::Size content_size(20, 20);
3194 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3195 root->SetBounds(surface_size);
3197 scoped_ptr<LayerImpl> grand_child =
3198 CreateScrollableLayer(3, content_size, root.get());
3200 scoped_ptr<LayerImpl> child =
3201 CreateScrollableLayer(2, content_size, root.get());
3202 LayerImpl* grand_child_layer = grand_child.get();
3203 child->AddChild(grand_child.Pass());
3205 LayerImpl* child_layer = child.get();
3206 root->AddChild(child.Pass());
3207 host_impl_->active_tree()->SetRootLayer(root.Pass());
3208 host_impl_->active_tree()->DidBecomeActive();
3209 host_impl_->SetViewportSize(surface_size);
3210 grand_child_layer->SetScrollOffset(gfx::ScrollOffset(0, 5));
3211 child_layer->SetScrollOffset(gfx::ScrollOffset(3, 0));
3215 gfx::Vector2d scroll_delta(-8, -7);
3216 EXPECT_EQ(InputHandler::ScrollStarted,
3217 host_impl_->ScrollBegin(gfx::Point(),
3218 InputHandler::Wheel));
3219 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3220 host_impl_->ScrollEnd();
3222 scoped_ptr<ScrollAndScaleSet> scroll_info =
3223 host_impl_->ProcessScrollDeltas();
3225 // The grand child should have scrolled up to its limit.
3226 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
3227 LayerImpl* grand_child = child->children()[0];
3228 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
3230 // The child should have only scrolled on the other axis.
3231 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
3235 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
3236 // Scroll a child layer beyond its maximum scroll range and make sure the
3237 // the scroll doesn't bubble up to the parent layer.
3238 gfx::Size surface_size(20, 20);
3239 gfx::Size viewport_size(10, 10);
3240 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3241 scoped_ptr<LayerImpl> root_scrolling =
3242 CreateScrollableLayer(2, surface_size, root.get());
3243 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3245 scoped_ptr<LayerImpl> grand_child =
3246 CreateScrollableLayer(4, surface_size, root.get());
3248 scoped_ptr<LayerImpl> child =
3249 CreateScrollableLayer(3, surface_size, root.get());
3250 LayerImpl* grand_child_layer = grand_child.get();
3251 child->AddChild(grand_child.Pass());
3253 LayerImpl* child_layer = child.get();
3254 root_scrolling->AddChild(child.Pass());
3255 root->AddChild(root_scrolling.Pass());
3256 EXPECT_EQ(viewport_size, root->bounds());
3257 host_impl_->active_tree()->SetRootLayer(root.Pass());
3258 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
3259 host_impl_->active_tree()->DidBecomeActive();
3260 host_impl_->SetViewportSize(viewport_size);
3262 grand_child_layer->SetScrollOffset(gfx::ScrollOffset(0, 2));
3263 child_layer->SetScrollOffset(gfx::ScrollOffset(0, 3));
3267 gfx::Vector2d scroll_delta(0, -10);
3268 EXPECT_EQ(InputHandler::ScrollStarted,
3269 host_impl_->ScrollBegin(gfx::Point(),
3270 InputHandler::NonBubblingGesture));
3271 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3272 host_impl_->ScrollEnd();
3274 scoped_ptr<ScrollAndScaleSet> scroll_info =
3275 host_impl_->ProcessScrollDeltas();
3277 // The grand child should have scrolled up to its limit.
3279 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
3280 LayerImpl* grand_child = child->children()[0];
3281 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
3283 // The child should not have scrolled.
3284 ExpectNone(*scroll_info.get(), child->id());
3286 // The next time we scroll we should only scroll the parent.
3287 scroll_delta = gfx::Vector2d(0, -3);
3288 EXPECT_EQ(InputHandler::ScrollStarted,
3289 host_impl_->ScrollBegin(gfx::Point(5, 5),
3290 InputHandler::NonBubblingGesture));
3291 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3292 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3293 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
3294 host_impl_->ScrollEnd();
3296 scroll_info = host_impl_->ProcessScrollDeltas();
3298 // The child should have scrolled up to its limit.
3299 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
3301 // The grand child should not have scrolled.
3302 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
3304 // After scrolling the parent, another scroll on the opposite direction
3305 // should still scroll the child.
3306 scroll_delta = gfx::Vector2d(0, 7);
3307 EXPECT_EQ(InputHandler::ScrollStarted,
3308 host_impl_->ScrollBegin(gfx::Point(5, 5),
3309 InputHandler::NonBubblingGesture));
3310 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3311 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3312 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3313 host_impl_->ScrollEnd();
3315 scroll_info = host_impl_->ProcessScrollDeltas();
3317 // The grand child should have scrolled.
3318 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
3320 // The child should not have scrolled.
3321 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
3324 // Scrolling should be adjusted from viewport space.
3325 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
3326 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3328 scroll_delta = gfx::Vector2d(0, -2);
3329 EXPECT_EQ(InputHandler::ScrollStarted,
3330 host_impl_->ScrollBegin(gfx::Point(1, 1),
3331 InputHandler::NonBubblingGesture));
3332 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
3333 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3334 host_impl_->ScrollEnd();
3336 scroll_info = host_impl_->ProcessScrollDeltas();
3338 // Should have scrolled by half the amount in layer space (5 - 2/2)
3339 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
3342 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
3343 // When we try to scroll a non-scrollable child layer, the scroll delta
3344 // should be applied to one of its ancestors if possible.
3345 gfx::Size surface_size(10, 10);
3346 gfx::Size content_size(20, 20);
3347 scoped_ptr<LayerImpl> root_clip =
3348 LayerImpl::Create(host_impl_->active_tree(), 3);
3349 scoped_ptr<LayerImpl> root =
3350 CreateScrollableLayer(1, content_size, root_clip.get());
3351 // Make 'root' the clip layer for child: since they have the same sizes the
3352 // child will have zero max_scroll_offset and scrolls will bubble.
3353 scoped_ptr<LayerImpl> child =
3354 CreateScrollableLayer(2, content_size, root.get());
3355 child->SetIsContainerForFixedPositionLayers(true);
3356 root->SetBounds(content_size);
3358 int root_scroll_id = root->id();
3359 root->AddChild(child.Pass());
3360 root_clip->AddChild(root.Pass());
3362 host_impl_->SetViewportSize(surface_size);
3363 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3364 host_impl_->active_tree()->SetViewportLayersFromIds(3, 2, Layer::INVALID_ID);
3365 host_impl_->active_tree()->DidBecomeActive();
3368 gfx::Vector2d scroll_delta(0, 4);
3369 EXPECT_EQ(InputHandler::ScrollStarted,
3370 host_impl_->ScrollBegin(gfx::Point(5, 5),
3371 InputHandler::Wheel));
3372 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3373 host_impl_->ScrollEnd();
3375 scoped_ptr<ScrollAndScaleSet> scroll_info =
3376 host_impl_->ProcessScrollDeltas();
3378 // Only the root scroll should have scrolled.
3379 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
3380 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
3384 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
3385 gfx::Size surface_size(10, 10);
3386 scoped_ptr<LayerImpl> root_clip =
3387 LayerImpl::Create(host_impl_->active_tree(), 1);
3388 scoped_ptr<LayerImpl> root_scroll =
3389 CreateScrollableLayer(2, surface_size, root_clip.get());
3390 root_scroll->SetIsContainerForFixedPositionLayers(true);
3391 root_clip->AddChild(root_scroll.Pass());
3392 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3393 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
3394 host_impl_->active_tree()->DidBecomeActive();
3395 host_impl_->SetViewportSize(surface_size);
3397 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3400 host_impl_->active_tree()->DetachLayerTree();
3401 scoped_ptr<LayerImpl> root_clip2 =
3402 LayerImpl::Create(host_impl_->active_tree(), 3);
3403 scoped_ptr<LayerImpl> root_scroll2 =
3404 CreateScrollableLayer(4, surface_size, root_clip2.get());
3405 root_scroll2->SetIsContainerForFixedPositionLayers(true);
3406 root_clip2->AddChild(root_scroll2.Pass());
3407 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
3408 host_impl_->active_tree()->SetViewportLayersFromIds(3, 4, Layer::INVALID_ID);
3409 host_impl_->active_tree()->DidBecomeActive();
3411 // Scrolling should still work even though we did not draw yet.
3412 EXPECT_EQ(InputHandler::ScrollStarted,
3413 host_impl_->ScrollBegin(gfx::Point(5, 5),
3414 InputHandler::Wheel));
3417 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
3418 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3420 // Rotate the root layer 90 degrees counter-clockwise about its center.
3421 gfx::Transform rotate_transform;
3422 rotate_transform.Rotate(-90.0);
3423 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
3425 gfx::Size surface_size(50, 50);
3426 host_impl_->SetViewportSize(surface_size);
3429 // Scroll to the right in screen coordinates with a gesture.
3430 gfx::Vector2d gesture_scroll_delta(10, 0);
3431 EXPECT_EQ(InputHandler::ScrollStarted,
3432 host_impl_->ScrollBegin(gfx::Point(),
3433 InputHandler::Gesture));
3434 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3435 host_impl_->ScrollEnd();
3437 // The layer should have scrolled down in its local coordinates.
3438 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3439 ExpectContains(*scroll_info.get(),
3441 gfx::Vector2d(0, gesture_scroll_delta.x()));
3443 // Reset and scroll down with the wheel.
3444 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3445 gfx::Vector2d wheel_scroll_delta(0, 10);
3446 EXPECT_EQ(InputHandler::ScrollStarted,
3447 host_impl_->ScrollBegin(gfx::Point(),
3448 InputHandler::Wheel));
3449 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3450 host_impl_->ScrollEnd();
3452 // The layer should have scrolled down in its local coordinates.
3453 scroll_info = host_impl_->ProcessScrollDeltas();
3454 ExpectContains(*scroll_info.get(),
3456 wheel_scroll_delta);
3459 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
3460 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3461 int child_clip_layer_id = 6;
3462 int child_layer_id = 7;
3463 float child_layer_angle = -20.f;
3465 // Create a child layer that is rotated to a non-axis-aligned angle.
3466 scoped_ptr<LayerImpl> clip_layer =
3467 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
3468 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
3469 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
3470 gfx::Transform rotate_transform;
3471 rotate_transform.Translate(-50.0, -50.0);
3472 rotate_transform.Rotate(child_layer_angle);
3473 rotate_transform.Translate(50.0, 50.0);
3474 clip_layer->SetTransform(rotate_transform);
3476 // Only allow vertical scrolling.
3477 clip_layer->SetBounds(
3478 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
3479 // The rotation depends on the layer's transform origin, and the child layer
3480 // is a different size than the clip, so make sure the clip layer's origin
3481 // lines up over the child.
3482 clip_layer->SetTransformOrigin(gfx::Point3F(
3483 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
3484 LayerImpl* child_ptr = child.get();
3485 clip_layer->AddChild(child.Pass());
3486 scroll_layer->AddChild(clip_layer.Pass());
3488 gfx::Size surface_size(50, 50);
3489 host_impl_->SetViewportSize(surface_size);
3492 // Scroll down in screen coordinates with a gesture.
3493 gfx::Vector2d gesture_scroll_delta(0, 10);
3494 EXPECT_EQ(InputHandler::ScrollStarted,
3495 host_impl_->ScrollBegin(gfx::Point(1, 1),
3496 InputHandler::Gesture));
3497 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3498 host_impl_->ScrollEnd();
3500 // The child layer should have scrolled down in its local coordinates an
3501 // amount proportional to the angle between it and the input scroll delta.
3502 gfx::Vector2d expected_scroll_delta(
3504 gesture_scroll_delta.y() *
3505 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
3506 scoped_ptr<ScrollAndScaleSet> scroll_info =
3507 host_impl_->ProcessScrollDeltas();
3508 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
3510 // The root scroll layer should not have scrolled, because the input delta
3511 // was close to the layer's axis of movement.
3512 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
3515 // Now reset and scroll the same amount horizontally.
3516 child_ptr->SetScrollDelta(gfx::Vector2dF());
3517 gfx::Vector2d gesture_scroll_delta(10, 0);
3518 EXPECT_EQ(InputHandler::ScrollStarted,
3519 host_impl_->ScrollBegin(gfx::Point(1, 1),
3520 InputHandler::Gesture));
3521 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3522 host_impl_->ScrollEnd();
3524 // The child layer should have scrolled down in its local coordinates an
3525 // amount proportional to the angle between it and the input scroll delta.
3526 gfx::Vector2d expected_scroll_delta(
3528 -gesture_scroll_delta.x() *
3529 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
3530 scoped_ptr<ScrollAndScaleSet> scroll_info =
3531 host_impl_->ProcessScrollDeltas();
3532 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
3534 // The root scroll layer should have scrolled more, since the input scroll
3535 // delta was mostly orthogonal to the child layer's vertical scroll axis.
3536 gfx::Vector2d expected_root_scroll_delta(
3537 gesture_scroll_delta.x() *
3538 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
3540 ExpectContains(*scroll_info.get(),
3542 expected_root_scroll_delta);
3546 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
3547 LayerImpl* scroll_layer =
3548 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3550 // Scale the layer to twice its normal size.
3552 gfx::Transform scale_transform;
3553 scale_transform.Scale(scale, scale);
3554 scroll_layer->SetTransform(scale_transform);
3556 gfx::Size surface_size(50, 50);
3557 host_impl_->SetViewportSize(surface_size);
3560 // Scroll down in screen coordinates with a gesture.
3561 gfx::Vector2d scroll_delta(0, 10);
3562 EXPECT_EQ(InputHandler::ScrollStarted,
3563 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3564 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3565 host_impl_->ScrollEnd();
3567 // The layer should have scrolled down in its local coordinates, but half the
3569 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3570 ExpectContains(*scroll_info.get(),
3572 gfx::Vector2d(0, scroll_delta.y() / scale));
3574 // Reset and scroll down with the wheel.
3575 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3576 gfx::Vector2d wheel_scroll_delta(0, 10);
3577 EXPECT_EQ(InputHandler::ScrollStarted,
3578 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3579 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3580 host_impl_->ScrollEnd();
3582 // The scale should not have been applied to the scroll delta.
3583 scroll_info = host_impl_->ProcessScrollDeltas();
3584 ExpectContains(*scroll_info.get(),
3586 wheel_scroll_delta);
3589 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
3593 SetupScrollAndContentsLayers(gfx::Size(width, height));
3594 host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
3595 gfx::Size(width * scale - 1, height * scale));
3596 host_impl_->SetDeviceScaleFactor(scale);
3597 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3599 LayerImpl* inner_viewport_scroll_layer =
3600 host_impl_->active_tree()->InnerViewportScrollLayer();
3601 EXPECT_EQ(gfx::ScrollOffset(0, 0),
3602 inner_viewport_scroll_layer->MaxScrollOffset());
3605 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
3607 TestScrollOffsetDelegate()
3608 : page_scale_factor_(0.f),
3609 min_page_scale_factor_(-1.f),
3610 max_page_scale_factor_(-1.f) {}
3612 ~TestScrollOffsetDelegate() override {}
3614 gfx::ScrollOffset GetTotalScrollOffset() override {
3615 return getter_return_value_;
3618 bool IsExternalFlingActive() const override { return false; }
3620 void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
3621 const gfx::ScrollOffset& max_scroll_offset,
3622 const gfx::SizeF& scrollable_size,
3623 float page_scale_factor,
3624 float min_page_scale_factor,
3625 float max_page_scale_factor) override {
3626 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
3627 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
3628 last_set_scroll_offset_ = total_scroll_offset;
3629 max_scroll_offset_ = max_scroll_offset;
3630 scrollable_size_ = scrollable_size;
3631 page_scale_factor_ = page_scale_factor;
3632 min_page_scale_factor_ = min_page_scale_factor;
3633 max_page_scale_factor_ = max_page_scale_factor;
3636 gfx::ScrollOffset last_set_scroll_offset() {
3637 return last_set_scroll_offset_;
3640 void set_getter_return_value(const gfx::ScrollOffset& value) {
3641 getter_return_value_ = value;
3644 gfx::ScrollOffset max_scroll_offset() const {
3645 return max_scroll_offset_;
3648 gfx::SizeF scrollable_size() const {
3649 return scrollable_size_;
3652 float page_scale_factor() const {
3653 return page_scale_factor_;
3656 float min_page_scale_factor() const {
3657 return min_page_scale_factor_;
3660 float max_page_scale_factor() const {
3661 return max_page_scale_factor_;
3665 gfx::ScrollOffset last_set_scroll_offset_;
3666 gfx::ScrollOffset getter_return_value_;
3667 gfx::ScrollOffset max_scroll_offset_;
3668 gfx::SizeF scrollable_size_;
3669 float page_scale_factor_;
3670 float min_page_scale_factor_;
3671 float max_page_scale_factor_;
3674 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
3675 TestScrollOffsetDelegate scroll_delegate;
3676 host_impl_->SetViewportSize(gfx::Size(10, 20));
3677 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3678 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3679 clip_layer->SetBounds(gfx::Size(10, 20));
3681 // Setting the delegate results in the current scroll offset being set.
3682 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
3683 scroll_layer->SetScrollOffset(gfx::ScrollOffset());
3684 scroll_layer->SetScrollDelta(initial_scroll_delta);
3685 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3686 EXPECT_EQ(initial_scroll_delta.ToString(),
3687 scroll_delegate.last_set_scroll_offset().ToString());
3689 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3690 // page_scale_factor and {min|max}_page_scale_factor being set.
3691 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
3692 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset());
3693 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3694 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
3695 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
3697 // Updating page scale immediately updates the delegate.
3698 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
3699 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
3700 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3701 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3702 host_impl_->active_tree()->SetPageScaleDelta(1.5f);
3703 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
3704 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3705 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3706 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3707 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3708 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3709 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3710 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3712 // The pinch gesture doesn't put the delegate into a state where the scroll
3713 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3715 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3716 host_impl_->PinchGestureBegin();
3717 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
3718 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
3719 host_impl_->PinchGestureEnd();
3720 host_impl_->ScrollEnd();
3722 // Scrolling should be relative to the offset as returned by the delegate.
3723 gfx::Vector2dF scroll_delta(0.f, 10.f);
3724 gfx::ScrollOffset current_offset(7.f, 8.f);
3726 scroll_delegate.set_getter_return_value(current_offset);
3727 EXPECT_EQ(InputHandler::ScrollStarted,
3728 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3730 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3731 EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
3732 scroll_delegate.last_set_scroll_offset());
3734 current_offset = gfx::ScrollOffset(42.f, 41.f);
3735 scroll_delegate.set_getter_return_value(current_offset);
3736 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3737 EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
3738 scroll_delegate.last_set_scroll_offset());
3739 host_impl_->ScrollEnd();
3740 scroll_delegate.set_getter_return_value(gfx::ScrollOffset());
3742 // Forces a full tree synchronization and ensures that the scroll delegate
3743 // sees the correct size of the new tree.
3744 gfx::Size new_size(42, 24);
3745 host_impl_->CreatePendingTree();
3746 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
3747 host_impl_->ActivateSyncTree();
3748 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
3750 // Un-setting the delegate should propagate the delegate's current offset to
3751 // the root scrollable layer.
3752 current_offset = gfx::ScrollOffset(13.f, 12.f);
3753 scroll_delegate.set_getter_return_value(current_offset);
3754 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3756 EXPECT_EQ(current_offset.ToString(),
3757 scroll_layer->TotalScrollOffset().ToString());
3760 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
3761 const gfx::Transform target_space_transform =
3762 layer->draw_properties().target_space_transform;
3763 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
3764 gfx::Point translated_point;
3765 target_space_transform.TransformPoint(&translated_point);
3766 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
3767 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
3770 TEST_F(LayerTreeHostImplTest,
3771 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
3772 TestScrollOffsetDelegate scroll_delegate;
3773 host_impl_->SetViewportSize(gfx::Size(10, 20));
3774 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3775 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3776 clip_layer->SetBounds(gfx::Size(10, 20));
3777 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3779 // Draw first frame to clear any pending draws and check scroll.
3781 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
3782 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
3784 // Set external scroll delta on delegate and notify LayerTreeHost.
3785 gfx::ScrollOffset scroll_offset(10.f, 10.f);
3786 scroll_delegate.set_getter_return_value(scroll_offset);
3787 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
3789 // Check scroll delta reflected in layer.
3790 LayerTreeHostImpl::FrameData frame;
3791 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3792 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3793 host_impl_->DidDrawAllLayers(frame);
3794 EXPECT_FALSE(frame.has_no_damage);
3795 CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset));
3797 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3800 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
3801 InputHandlerScrollResult scroll_result;
3802 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3803 host_impl_->SetViewportSize(gfx::Size(50, 50));
3804 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3806 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3808 // In-bounds scrolling does not affect overscroll.
3809 EXPECT_EQ(InputHandler::ScrollStarted,
3810 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3811 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3812 EXPECT_TRUE(scroll_result.did_scroll);
3813 EXPECT_FALSE(scroll_result.did_overscroll_root);
3814 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
3815 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3817 // Overscroll events are reflected immediately.
3818 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
3819 EXPECT_TRUE(scroll_result.did_scroll);
3820 EXPECT_TRUE(scroll_result.did_overscroll_root);
3821 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
3822 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3823 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3824 host_impl_->accumulated_root_overscroll());
3826 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
3827 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
3828 EXPECT_TRUE(scroll_result.did_scroll);
3829 EXPECT_FALSE(scroll_result.did_overscroll_root);
3830 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
3831 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3832 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3833 host_impl_->accumulated_root_overscroll());
3835 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
3836 EXPECT_FALSE(scroll_result.did_scroll);
3837 EXPECT_TRUE(scroll_result.did_overscroll_root);
3838 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
3839 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3840 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3841 host_impl_->accumulated_root_overscroll());
3843 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
3844 EXPECT_TRUE(scroll_result.did_scroll);
3845 EXPECT_FALSE(scroll_result.did_overscroll_root);
3846 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
3847 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3848 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3849 host_impl_->accumulated_root_overscroll());
3851 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
3852 EXPECT_TRUE(scroll_result.did_scroll);
3853 EXPECT_TRUE(scroll_result.did_overscroll_root);
3854 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
3855 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
3856 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3857 host_impl_->accumulated_root_overscroll());
3859 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
3860 EXPECT_TRUE(scroll_result.did_scroll);
3861 EXPECT_TRUE(scroll_result.did_overscroll_root);
3862 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
3863 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
3864 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3865 host_impl_->accumulated_root_overscroll());
3867 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
3868 EXPECT_TRUE(scroll_result.did_scroll);
3869 EXPECT_TRUE(scroll_result.did_overscroll_root);
3870 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
3871 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3872 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3873 host_impl_->accumulated_root_overscroll());
3875 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
3876 // as no scroll occurs.
3877 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3878 EXPECT_FALSE(scroll_result.did_scroll);
3879 EXPECT_TRUE(scroll_result.did_overscroll_root);
3880 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
3881 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
3882 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3883 host_impl_->accumulated_root_overscroll());
3885 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3886 EXPECT_FALSE(scroll_result.did_scroll);
3887 EXPECT_TRUE(scroll_result.did_overscroll_root);
3888 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
3889 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
3890 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3891 host_impl_->accumulated_root_overscroll());
3893 // Overscroll resets on valid scroll.
3894 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3895 EXPECT_TRUE(scroll_result.did_scroll);
3896 EXPECT_FALSE(scroll_result.did_overscroll_root);
3897 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
3898 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3899 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3900 host_impl_->accumulated_root_overscroll());
3902 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3903 EXPECT_TRUE(scroll_result.did_scroll);
3904 EXPECT_TRUE(scroll_result.did_overscroll_root);
3905 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
3906 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3907 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3908 host_impl_->accumulated_root_overscroll());
3910 host_impl_->ScrollEnd();
3914 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
3915 // Scroll child layers beyond their maximum scroll range and make sure root
3916 // overscroll does not accumulate.
3917 gfx::Size surface_size(10, 10);
3918 scoped_ptr<LayerImpl> root_clip =
3919 LayerImpl::Create(host_impl_->active_tree(), 4);
3920 scoped_ptr<LayerImpl> root =
3921 CreateScrollableLayer(1, surface_size, root_clip.get());
3923 scoped_ptr<LayerImpl> grand_child =
3924 CreateScrollableLayer(3, surface_size, root_clip.get());
3926 scoped_ptr<LayerImpl> child =
3927 CreateScrollableLayer(2, surface_size, root_clip.get());
3928 LayerImpl* grand_child_layer = grand_child.get();
3929 child->AddChild(grand_child.Pass());
3931 LayerImpl* child_layer = child.get();
3932 root->AddChild(child.Pass());
3933 root_clip->AddChild(root.Pass());
3934 child_layer->SetScrollOffset(gfx::ScrollOffset(0, 3));
3935 grand_child_layer->SetScrollOffset(gfx::ScrollOffset(0, 2));
3936 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3937 host_impl_->active_tree()->DidBecomeActive();
3938 host_impl_->SetViewportSize(surface_size);
3941 gfx::Vector2d scroll_delta(0, -10);
3942 EXPECT_EQ(InputHandler::ScrollStarted,
3943 host_impl_->ScrollBegin(gfx::Point(),
3944 InputHandler::NonBubblingGesture));
3945 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3946 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3947 host_impl_->ScrollEnd();
3949 // The next time we scroll we should only scroll the parent, but overscroll
3950 // should still not reach the root layer.
3951 scroll_delta = gfx::Vector2d(0, -30);
3952 EXPECT_EQ(InputHandler::ScrollStarted,
3953 host_impl_->ScrollBegin(gfx::Point(5, 5),
3954 InputHandler::NonBubblingGesture));
3955 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3956 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3957 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3958 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
3959 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3960 host_impl_->ScrollEnd();
3962 // After scrolling the parent, another scroll on the opposite direction
3963 // should scroll the child.
3964 scroll_delta = gfx::Vector2d(0, 70);
3965 EXPECT_EQ(InputHandler::ScrollStarted,
3966 host_impl_->ScrollBegin(gfx::Point(5, 5),
3967 InputHandler::NonBubblingGesture));
3968 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3969 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3970 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3971 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3972 host_impl_->ScrollEnd();
3976 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
3977 // When we try to scroll a non-scrollable child layer, the scroll delta
3978 // should be applied to one of its ancestors if possible. Overscroll should
3979 // be reflected only when it has bubbled up to the root scrolling layer.
3980 gfx::Size surface_size(10, 10);
3981 gfx::Size content_size(20, 20);
3982 scoped_ptr<LayerImpl> root_clip =
3983 LayerImpl::Create(host_impl_->active_tree(), 3);
3984 scoped_ptr<LayerImpl> root =
3985 CreateScrollableLayer(1, content_size, root_clip.get());
3986 root->SetIsContainerForFixedPositionLayers(true);
3987 scoped_ptr<LayerImpl> child =
3988 CreateScrollableLayer(2, content_size, root_clip.get());
3990 child->SetScrollClipLayer(Layer::INVALID_ID);
3991 root->AddChild(child.Pass());
3992 root_clip->AddChild(root.Pass());
3994 host_impl_->SetViewportSize(surface_size);
3995 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3996 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3997 host_impl_->active_tree()->DidBecomeActive();
4000 gfx::Vector2d scroll_delta(0, 8);
4001 EXPECT_EQ(InputHandler::ScrollStarted,
4002 host_impl_->ScrollBegin(gfx::Point(5, 5),
4003 InputHandler::Wheel));
4004 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4005 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4006 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4007 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
4008 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4009 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
4010 host_impl_->ScrollEnd();
4014 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
4015 LayerTreeSettings settings;
4016 CreateHostImpl(settings, CreateOutputSurface());
4018 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
4019 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4020 clip_layer->SetBounds(gfx::Size(50, 50));
4021 host_impl_->SetViewportSize(gfx::Size(50, 50));
4022 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
4024 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4026 // Even though the layer can't scroll the overscroll still happens.
4027 EXPECT_EQ(InputHandler::ScrollStarted,
4028 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
4029 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4030 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4033 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
4034 gfx::Size surface_size(980, 1439);
4035 gfx::Size content_size(980, 1438);
4036 float device_scale_factor = 1.5f;
4037 scoped_ptr<LayerImpl> root_clip =
4038 LayerImpl::Create(host_impl_->active_tree(), 3);
4039 scoped_ptr<LayerImpl> root =
4040 CreateScrollableLayer(1, content_size, root_clip.get());
4041 root->SetIsContainerForFixedPositionLayers(true);
4042 scoped_ptr<LayerImpl> child =
4043 CreateScrollableLayer(2, content_size, root_clip.get());
4044 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
4045 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
4046 0.326531f, 0.326531f, 5.f);
4047 host_impl_->active_tree()->SetPageScaleDelta(1.f);
4048 child->SetScrollClipLayer(Layer::INVALID_ID);
4049 root->AddChild(child.Pass());
4050 root_clip->AddChild(root.Pass());
4052 host_impl_->SetViewportSize(surface_size);
4053 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4054 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4055 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
4056 host_impl_->active_tree()->DidBecomeActive();
4059 // Horizontal & Vertical GlowEffect should not be applied when
4060 // content size is less then view port size. For Example Horizontal &
4061 // vertical GlowEffect should not be applied in about:blank page.
4062 EXPECT_EQ(InputHandler::ScrollStarted,
4063 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
4064 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
4065 EXPECT_EQ(gfx::Vector2dF().ToString(),
4066 host_impl_->accumulated_root_overscroll().ToString());
4068 host_impl_->ScrollEnd();
4072 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
4073 gfx::Size surface_size(100, 100);
4074 gfx::Size content_size(200, 200);
4075 scoped_ptr<LayerImpl> root_clip =
4076 LayerImpl::Create(host_impl_->active_tree(), 3);
4077 scoped_ptr<LayerImpl> root =
4078 CreateScrollableLayer(1, content_size, root_clip.get());
4079 root->SetIsContainerForFixedPositionLayers(true);
4080 scoped_ptr<LayerImpl> child =
4081 CreateScrollableLayer(2, content_size, root_clip.get());
4083 child->SetScrollClipLayer(Layer::INVALID_ID);
4084 root->AddChild(child.Pass());
4085 root_clip->AddChild(root.Pass());
4087 host_impl_->SetViewportSize(surface_size);
4088 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4089 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
4090 host_impl_->active_tree()->DidBecomeActive();
4093 // Edge glow effect should be applicable only upon reaching Edges
4094 // of the content. unnecessary glow effect calls shouldn't be
4095 // called while scrolling up without reaching the edge of the content.
4096 EXPECT_EQ(InputHandler::ScrollStarted,
4097 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
4098 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4099 EXPECT_EQ(gfx::Vector2dF().ToString(),
4100 host_impl_->accumulated_root_overscroll().ToString());
4101 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
4102 EXPECT_EQ(gfx::Vector2dF().ToString(),
4103 host_impl_->accumulated_root_overscroll().ToString());
4104 host_impl_->ScrollEnd();
4105 // unusedrootDelta should be subtracted from applied delta so that
4106 // unwanted glow effect calls are not called.
4107 EXPECT_EQ(InputHandler::ScrollStarted,
4108 host_impl_->ScrollBegin(gfx::Point(0, 0),
4109 InputHandler::NonBubblingGesture));
4110 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
4111 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4112 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4113 host_impl_->accumulated_root_overscroll().ToString());
4115 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
4116 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4117 host_impl_->accumulated_root_overscroll().ToString());
4118 host_impl_->ScrollEnd();
4119 // TestCase to check kEpsilon, which prevents minute values to trigger
4120 // gloweffect without reaching edge.
4121 EXPECT_EQ(InputHandler::ScrollStarted,
4122 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
4123 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
4124 EXPECT_EQ(gfx::Vector2dF().ToString(),
4125 host_impl_->accumulated_root_overscroll().ToString());
4126 host_impl_->ScrollEnd();
4130 class BlendStateCheckLayer : public LayerImpl {
4132 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
4134 ResourceProvider* resource_provider) {
4135 return make_scoped_ptr(
4136 new BlendStateCheckLayer(tree_impl, id, resource_provider));
4139 void AppendQuads(RenderPass* render_pass,
4140 const Occlusion& occlusion_in_content_space,
4141 AppendQuadsData* append_quads_data) override {
4142 quads_appended_ = true;
4144 gfx::Rect opaque_rect;
4145 if (contents_opaque())
4146 opaque_rect = quad_rect_;
4148 opaque_rect = opaque_content_rect_;
4149 gfx::Rect visible_quad_rect = quad_rect_;
4151 SharedQuadState* shared_quad_state =
4152 render_pass->CreateAndAppendSharedQuadState();
4153 PopulateSharedQuadState(shared_quad_state);
4155 TileDrawQuad* test_blending_draw_quad =
4156 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
4157 test_blending_draw_quad->SetNew(shared_quad_state,
4162 gfx::RectF(0.f, 0.f, 1.f, 1.f),
4165 test_blending_draw_quad->visible_rect = quad_visible_rect_;
4166 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
4167 EXPECT_EQ(has_render_surface_, !!render_surface());
4170 void SetExpectation(bool blend, bool has_render_surface) {
4172 has_render_surface_ = has_render_surface;
4173 quads_appended_ = false;
4176 bool quads_appended() const { return quads_appended_; }
4178 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
4179 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
4180 void SetOpaqueContentRect(const gfx::Rect& rect) {
4181 opaque_content_rect_ = rect;
4185 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
4187 ResourceProvider* resource_provider)
4188 : LayerImpl(tree_impl, id),
4190 has_render_surface_(false),
4191 quads_appended_(false),
4192 quad_rect_(5, 5, 5, 5),
4193 quad_visible_rect_(5, 5, 5, 5),
4194 resource_id_(resource_provider->CreateResource(
4197 ResourceProvider::TextureHintImmutable,
4199 resource_provider->AllocateForTesting(resource_id_);
4200 SetBounds(gfx::Size(10, 10));
4201 SetContentBounds(gfx::Size(10, 10));
4202 SetDrawsContent(true);
4206 bool has_render_surface_;
4207 bool quads_appended_;
4208 gfx::Rect quad_rect_;
4209 gfx::Rect opaque_content_rect_;
4210 gfx::Rect quad_visible_rect_;
4211 ResourceProvider::ResourceId resource_id_;
4214 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
4216 scoped_ptr<LayerImpl> root =
4217 LayerImpl::Create(host_impl_->active_tree(), 1);
4218 root->SetBounds(gfx::Size(10, 10));
4219 root->SetContentBounds(root->bounds());
4220 root->SetDrawsContent(false);
4221 host_impl_->active_tree()->SetRootLayer(root.Pass());
4223 LayerImpl* root = host_impl_->active_tree()->root_layer();
4226 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4228 host_impl_->resource_provider()));
4229 BlendStateCheckLayer* layer1 =
4230 static_cast<BlendStateCheckLayer*>(root->children()[0]);
4231 layer1->SetPosition(gfx::PointF(2.f, 2.f));
4233 LayerTreeHostImpl::FrameData frame;
4235 // Opaque layer, drawn without blending.
4236 layer1->SetContentsOpaque(true);
4237 layer1->SetExpectation(false, false);
4238 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4239 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4240 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4241 EXPECT_TRUE(layer1->quads_appended());
4242 host_impl_->DidDrawAllLayers(frame);
4244 // Layer with translucent content and painting, so drawn with blending.
4245 layer1->SetContentsOpaque(false);
4246 layer1->SetExpectation(true, false);
4247 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4248 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4249 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4250 EXPECT_TRUE(layer1->quads_appended());
4251 host_impl_->DidDrawAllLayers(frame);
4253 // Layer with translucent opacity, drawn with blending.
4254 layer1->SetContentsOpaque(true);
4255 layer1->SetOpacity(0.5f);
4256 layer1->SetExpectation(true, false);
4257 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4258 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4259 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4260 EXPECT_TRUE(layer1->quads_appended());
4261 host_impl_->DidDrawAllLayers(frame);
4263 // Layer with translucent opacity and painting, drawn with blending.
4264 layer1->SetContentsOpaque(true);
4265 layer1->SetOpacity(0.5f);
4266 layer1->SetExpectation(true, false);
4267 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4268 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4269 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4270 EXPECT_TRUE(layer1->quads_appended());
4271 host_impl_->DidDrawAllLayers(frame);
4274 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4276 host_impl_->resource_provider()));
4277 BlendStateCheckLayer* layer2 =
4278 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
4279 layer2->SetPosition(gfx::PointF(4.f, 4.f));
4281 // 2 opaque layers, drawn without blending.
4282 layer1->SetContentsOpaque(true);
4283 layer1->SetOpacity(1.f);
4284 layer1->SetExpectation(false, false);
4285 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4286 layer2->SetContentsOpaque(true);
4287 layer2->SetOpacity(1.f);
4288 layer2->SetExpectation(false, false);
4289 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4290 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4291 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4292 EXPECT_TRUE(layer1->quads_appended());
4293 EXPECT_TRUE(layer2->quads_appended());
4294 host_impl_->DidDrawAllLayers(frame);
4296 // Parent layer with translucent content, drawn with blending.
4297 // Child layer with opaque content, drawn without blending.
4298 layer1->SetContentsOpaque(false);
4299 layer1->SetExpectation(true, false);
4300 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4301 layer2->SetExpectation(false, false);
4302 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4303 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4304 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4305 EXPECT_TRUE(layer1->quads_appended());
4306 EXPECT_TRUE(layer2->quads_appended());
4307 host_impl_->DidDrawAllLayers(frame);
4309 // Parent layer with translucent content but opaque painting, drawn without
4311 // Child layer with opaque content, drawn without blending.
4312 layer1->SetContentsOpaque(true);
4313 layer1->SetExpectation(false, false);
4314 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4315 layer2->SetExpectation(false, false);
4316 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4317 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4318 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4319 EXPECT_TRUE(layer1->quads_appended());
4320 EXPECT_TRUE(layer2->quads_appended());
4321 host_impl_->DidDrawAllLayers(frame);
4323 // Parent layer with translucent opacity and opaque content. Since it has a
4324 // drawing child, it's drawn to a render surface which carries the opacity,
4325 // so it's itself drawn without blending.
4326 // Child layer with opaque content, drawn without blending (parent surface
4327 // carries the inherited opacity).
4328 layer1->SetContentsOpaque(true);
4329 layer1->SetOpacity(0.5f);
4330 layer1->SetExpectation(false, true);
4331 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4332 layer2->SetExpectation(false, false);
4333 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4334 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
4335 host_impl_->active_tree()->root_layer());
4336 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4337 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4338 EXPECT_TRUE(layer1->quads_appended());
4339 EXPECT_TRUE(layer2->quads_appended());
4340 host_impl_->DidDrawAllLayers(frame);
4342 // Draw again, but with child non-opaque, to make sure
4343 // layer1 not culled.
4344 layer1->SetContentsOpaque(true);
4345 layer1->SetOpacity(1.f);
4346 layer1->SetExpectation(false, false);
4347 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4348 layer2->SetContentsOpaque(true);
4349 layer2->SetOpacity(0.5f);
4350 layer2->SetExpectation(true, false);
4351 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4352 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4353 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4354 EXPECT_TRUE(layer1->quads_appended());
4355 EXPECT_TRUE(layer2->quads_appended());
4356 host_impl_->DidDrawAllLayers(frame);
4358 // A second way of making the child non-opaque.
4359 layer1->SetContentsOpaque(true);
4360 layer1->SetOpacity(1.f);
4361 layer1->SetExpectation(false, false);
4362 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4363 layer2->SetContentsOpaque(false);
4364 layer2->SetOpacity(1.f);
4365 layer2->SetExpectation(true, false);
4366 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4367 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4368 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4369 EXPECT_TRUE(layer1->quads_appended());
4370 EXPECT_TRUE(layer2->quads_appended());
4371 host_impl_->DidDrawAllLayers(frame);
4373 // And when the layer says its not opaque but is painted opaque, it is not
4375 layer1->SetContentsOpaque(true);
4376 layer1->SetOpacity(1.f);
4377 layer1->SetExpectation(false, false);
4378 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4379 layer2->SetContentsOpaque(true);
4380 layer2->SetOpacity(1.f);
4381 layer2->SetExpectation(false, false);
4382 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4383 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4384 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4385 EXPECT_TRUE(layer1->quads_appended());
4386 EXPECT_TRUE(layer2->quads_appended());
4387 host_impl_->DidDrawAllLayers(frame);
4389 // Layer with partially opaque contents, drawn with blending.
4390 layer1->SetContentsOpaque(false);
4391 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4392 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
4393 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4394 layer1->SetExpectation(true, false);
4395 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4396 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4397 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4398 EXPECT_TRUE(layer1->quads_appended());
4399 host_impl_->DidDrawAllLayers(frame);
4401 // Layer with partially opaque contents partially culled, drawn with blending.
4402 layer1->SetContentsOpaque(false);
4403 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4404 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
4405 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4406 layer1->SetExpectation(true, false);
4407 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4408 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4409 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4410 EXPECT_TRUE(layer1->quads_appended());
4411 host_impl_->DidDrawAllLayers(frame);
4413 // Layer with partially opaque contents culled, drawn with blending.
4414 layer1->SetContentsOpaque(false);
4415 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4416 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
4417 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4418 layer1->SetExpectation(true, false);
4419 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4420 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4421 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4422 EXPECT_TRUE(layer1->quads_appended());
4423 host_impl_->DidDrawAllLayers(frame);
4425 // Layer with partially opaque contents and translucent contents culled, drawn
4426 // without blending.
4427 layer1->SetContentsOpaque(false);
4428 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4429 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
4430 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4431 layer1->SetExpectation(false, false);
4432 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4433 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4434 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4435 EXPECT_TRUE(layer1->quads_appended());
4436 host_impl_->DidDrawAllLayers(frame);
4439 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
4441 LayerTreeHostImplViewportCoveredTest() :
4442 gutter_quad_material_(DrawQuad::SOLID_COLOR),
4444 did_activate_pending_tree_(false) {}
4446 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
4448 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
4450 return FakeOutputSurface::Create3d();
4453 void SetupActiveTreeLayers() {
4454 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
4455 host_impl_->active_tree()->SetRootLayer(
4456 LayerImpl::Create(host_impl_->active_tree(), 1));
4457 host_impl_->active_tree()->root_layer()->AddChild(
4458 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4460 host_impl_->resource_provider()));
4461 child_ = static_cast<BlendStateCheckLayer*>(
4462 host_impl_->active_tree()->root_layer()->children()[0]);
4463 child_->SetExpectation(false, false);
4464 child_->SetContentsOpaque(true);
4467 // Expect no gutter rects.
4468 void TestLayerCoversFullViewport() {
4469 gfx::Rect layer_rect(viewport_size_);
4470 child_->SetPosition(layer_rect.origin());
4471 child_->SetBounds(layer_rect.size());
4472 child_->SetContentBounds(layer_rect.size());
4473 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4474 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4476 LayerTreeHostImpl::FrameData frame;
4477 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4478 ASSERT_EQ(1u, frame.render_passes.size());
4480 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
4481 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4482 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4484 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4485 host_impl_->DidDrawAllLayers(frame);
4488 // Expect fullscreen gutter rect.
4489 void TestEmptyLayer() {
4490 gfx::Rect layer_rect(0, 0, 0, 0);
4491 child_->SetPosition(layer_rect.origin());
4492 child_->SetBounds(layer_rect.size());
4493 child_->SetContentBounds(layer_rect.size());
4494 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4495 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4497 LayerTreeHostImpl::FrameData frame;
4498 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4499 ASSERT_EQ(1u, frame.render_passes.size());
4501 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
4502 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4503 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4505 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4506 host_impl_->DidDrawAllLayers(frame);
4509 // Expect four surrounding gutter rects.
4510 void TestLayerInMiddleOfViewport() {
4511 gfx::Rect layer_rect(500, 500, 200, 200);
4512 child_->SetPosition(layer_rect.origin());
4513 child_->SetBounds(layer_rect.size());
4514 child_->SetContentBounds(layer_rect.size());
4515 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4516 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4518 LayerTreeHostImpl::FrameData frame;
4519 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4520 ASSERT_EQ(1u, frame.render_passes.size());
4522 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
4523 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
4524 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4526 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4527 host_impl_->DidDrawAllLayers(frame);
4530 // Expect no gutter rects.
4531 void TestLayerIsLargerThanViewport() {
4532 gfx::Rect layer_rect(viewport_size_.width() + 10,
4533 viewport_size_.height() + 10);
4534 child_->SetPosition(layer_rect.origin());
4535 child_->SetBounds(layer_rect.size());
4536 child_->SetContentBounds(layer_rect.size());
4537 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4538 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4540 LayerTreeHostImpl::FrameData frame;
4541 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4542 ASSERT_EQ(1u, frame.render_passes.size());
4544 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
4545 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4546 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4548 host_impl_->DidDrawAllLayers(frame);
4551 void DidActivateSyncTree() override { did_activate_pending_tree_ = true; }
4553 void set_gutter_quad_material(DrawQuad::Material material) {
4554 gutter_quad_material_ = material;
4556 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
4557 gutter_texture_size_ = gutter_texture_size;
4561 size_t CountGutterQuads(const QuadList& quad_list) {
4562 size_t num_gutter_quads = 0;
4563 for (const auto& quad : quad_list) {
4564 num_gutter_quads += (quad->material == gutter_quad_material_) ? 1 : 0;
4566 return num_gutter_quads;
4569 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
4570 LayerTestCommon::VerifyQuadsExactlyCoverRect(
4571 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
4574 // Make sure that the texture coordinates match their expectations.
4575 void ValidateTextureDrawQuads(const QuadList& quad_list) {
4576 for (const auto& quad : quad_list) {
4577 if (quad->material != DrawQuad::TEXTURE_CONTENT)
4579 const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
4580 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
4581 gutter_texture_size_, host_impl_->device_scale_factor());
4582 EXPECT_EQ(texture_quad->uv_top_left.x(),
4583 texture_quad->rect.x() / gutter_texture_size_pixels.width());
4584 EXPECT_EQ(texture_quad->uv_top_left.y(),
4585 texture_quad->rect.y() / gutter_texture_size_pixels.height());
4587 texture_quad->uv_bottom_right.x(),
4588 texture_quad->rect.right() / gutter_texture_size_pixels.width());
4590 texture_quad->uv_bottom_right.y(),
4591 texture_quad->rect.bottom() / gutter_texture_size_pixels.height());
4595 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
4596 return gfx::ToRoundedSize(
4597 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
4600 DrawQuad::Material gutter_quad_material_;
4601 gfx::Size gutter_texture_size_;
4602 gfx::Size viewport_size_;
4603 BlendStateCheckLayer* child_;
4604 bool did_activate_pending_tree_;
4607 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
4608 viewport_size_ = gfx::Size(1000, 1000);
4610 bool always_draw = false;
4611 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4613 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4614 SetupActiveTreeLayers();
4615 TestLayerCoversFullViewport();
4617 TestLayerInMiddleOfViewport();
4618 TestLayerIsLargerThanViewport();
4621 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
4622 viewport_size_ = gfx::Size(1000, 1000);
4624 bool always_draw = false;
4625 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4627 host_impl_->SetDeviceScaleFactor(2.f);
4628 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4629 SetupActiveTreeLayers();
4630 TestLayerCoversFullViewport();
4632 TestLayerInMiddleOfViewport();
4633 TestLayerIsLargerThanViewport();
4636 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
4637 viewport_size_ = gfx::Size(1000, 1000);
4639 bool always_draw = false;
4640 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4642 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4643 SetupActiveTreeLayers();
4645 // Specify an overhang bitmap to use.
4646 bool is_opaque = false;
4647 UIResourceBitmap ui_resource_bitmap(gfx::Size(2, 2), is_opaque);
4648 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
4649 UIResourceId ui_resource_id = 12345;
4650 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
4651 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
4652 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
4653 set_gutter_texture_size(gfx::Size(32, 32));
4655 TestLayerCoversFullViewport();
4657 TestLayerInMiddleOfViewport();
4658 TestLayerIsLargerThanViewport();
4660 // Change the resource size.
4661 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
4662 set_gutter_texture_size(gfx::Size(128, 16));
4664 TestLayerCoversFullViewport();
4666 TestLayerInMiddleOfViewport();
4667 TestLayerIsLargerThanViewport();
4669 // Change the device scale factor
4670 host_impl_->SetDeviceScaleFactor(2.f);
4671 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4673 TestLayerCoversFullViewport();
4675 TestLayerInMiddleOfViewport();
4676 TestLayerIsLargerThanViewport();
4679 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
4680 viewport_size_ = gfx::Size(1000, 1000);
4682 bool always_draw = true;
4683 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4685 // Pending tree to force active_tree size invalid. Not used otherwise.
4686 host_impl_->CreatePendingTree();
4687 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4688 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4690 SetupActiveTreeLayers();
4692 TestLayerInMiddleOfViewport();
4693 TestLayerIsLargerThanViewport();
4696 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
4697 viewport_size_ = gfx::Size(1000, 1000);
4699 bool always_draw = true;
4700 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4702 // Set larger viewport and activate it to active tree.
4703 host_impl_->CreatePendingTree();
4704 gfx::Size larger_viewport(viewport_size_.width() + 100,
4705 viewport_size_.height() + 100);
4706 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
4707 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4708 host_impl_->ActivateSyncTree();
4709 EXPECT_TRUE(did_activate_pending_tree_);
4710 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
4712 // Shrink pending tree viewport without activating.
4713 host_impl_->CreatePendingTree();
4714 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4715 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4717 SetupActiveTreeLayers();
4719 TestLayerInMiddleOfViewport();
4720 TestLayerIsLargerThanViewport();
4723 class FakeDrawableLayerImpl: public LayerImpl {
4725 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4726 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl, id));
4729 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
4730 : LayerImpl(tree_impl, id) {}
4733 // Only reshape when we know we are going to draw. Otherwise, the reshape
4734 // can leave the window at the wrong size if we never draw and the proper
4735 // viewport size is never set.
4736 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
4737 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4738 scoped_ptr<OutputSurface> output_surface(
4739 FakeOutputSurface::Create3d(provider));
4740 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4742 scoped_ptr<LayerImpl> root =
4743 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4744 root->SetBounds(gfx::Size(10, 10));
4745 root->SetContentBounds(gfx::Size(10, 10));
4746 root->SetDrawsContent(true);
4747 host_impl_->active_tree()->SetRootLayer(root.Pass());
4748 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
4749 provider->TestContext3d()->clear_reshape_called();
4751 LayerTreeHostImpl::FrameData frame;
4752 host_impl_->SetViewportSize(gfx::Size(10, 10));
4753 host_impl_->SetDeviceScaleFactor(1.f);
4754 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4755 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4756 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4757 EXPECT_EQ(provider->TestContext3d()->width(), 10);
4758 EXPECT_EQ(provider->TestContext3d()->height(), 10);
4759 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4760 host_impl_->DidDrawAllLayers(frame);
4761 provider->TestContext3d()->clear_reshape_called();
4763 host_impl_->SetViewportSize(gfx::Size(20, 30));
4764 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4765 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4766 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4767 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4768 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4769 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4770 host_impl_->DidDrawAllLayers(frame);
4771 provider->TestContext3d()->clear_reshape_called();
4773 host_impl_->SetDeviceScaleFactor(2.f);
4774 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4775 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4776 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4777 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4778 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4779 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
4780 host_impl_->DidDrawAllLayers(frame);
4781 provider->TestContext3d()->clear_reshape_called();
4784 // Make sure damage tracking propagates all the way to the graphics context,
4785 // where it should request to swap only the sub-buffer that is damaged.
4786 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
4787 scoped_refptr<TestContextProvider> context_provider(
4788 TestContextProvider::Create());
4789 context_provider->BindToCurrentThread();
4790 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
4792 scoped_ptr<FakeOutputSurface> output_surface(
4793 FakeOutputSurface::Create3d(context_provider));
4794 FakeOutputSurface* fake_output_surface = output_surface.get();
4796 // This test creates its own LayerTreeHostImpl, so
4797 // that we can force partial swap enabled.
4798 LayerTreeSettings settings;
4799 settings.partial_swap_enabled = true;
4800 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4801 new TestSharedBitmapManager());
4802 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
4803 LayerTreeHostImpl::Create(settings,
4806 &stats_instrumentation_,
4807 shared_bitmap_manager.get(),
4810 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
4811 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
4813 scoped_ptr<LayerImpl> root =
4814 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
4815 scoped_ptr<LayerImpl> child =
4816 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
4817 child->SetPosition(gfx::PointF(12.f, 13.f));
4818 child->SetBounds(gfx::Size(14, 15));
4819 child->SetContentBounds(gfx::Size(14, 15));
4820 child->SetDrawsContent(true);
4821 root->SetBounds(gfx::Size(500, 500));
4822 root->SetContentBounds(gfx::Size(500, 500));
4823 root->SetDrawsContent(true);
4824 root->AddChild(child.Pass());
4825 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
4827 LayerTreeHostImpl::FrameData frame;
4829 // First frame, the entire screen should get swapped.
4830 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4831 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4832 layer_tree_host_impl->DidDrawAllLayers(frame);
4833 layer_tree_host_impl->SwapBuffers(frame);
4834 gfx::Rect expected_swap_rect(0, 0, 500, 500);
4835 EXPECT_EQ(expected_swap_rect.ToString(),
4836 fake_output_surface->last_swap_rect().ToString());
4838 // Second frame, only the damaged area should get swapped. Damage should be
4839 // the union of old and new child rects.
4840 // expected damage rect: gfx::Rect(26, 28);
4841 // expected swap rect: vertically flipped, with origin at bottom left corner.
4842 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
4844 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4845 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4846 host_impl_->DidDrawAllLayers(frame);
4847 layer_tree_host_impl->SwapBuffers(frame);
4849 // Make sure that partial swap is constrained to the viewport dimensions
4850 // expected damage rect: gfx::Rect(500, 500);
4851 // expected swap rect: flipped damage rect, but also clamped to viewport
4852 expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
4853 EXPECT_EQ(expected_swap_rect.ToString(),
4854 fake_output_surface->last_swap_rect().ToString());
4856 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
4857 // This will damage everything.
4858 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
4860 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4861 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4862 host_impl_->DidDrawAllLayers(frame);
4863 layer_tree_host_impl->SwapBuffers(frame);
4865 expected_swap_rect = gfx::Rect(0, 0, 10, 10);
4866 EXPECT_EQ(expected_swap_rect.ToString(),
4867 fake_output_surface->last_swap_rect().ToString());
4870 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
4871 scoped_ptr<LayerImpl> root =
4872 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4873 scoped_ptr<LayerImpl> child =
4874 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
4875 child->SetBounds(gfx::Size(10, 10));
4876 child->SetContentBounds(gfx::Size(10, 10));
4877 child->SetDrawsContent(true);
4878 root->SetBounds(gfx::Size(10, 10));
4879 root->SetContentBounds(gfx::Size(10, 10));
4880 root->SetDrawsContent(true);
4881 root->SetForceRenderSurface(true);
4882 root->AddChild(child.Pass());
4884 host_impl_->active_tree()->SetRootLayer(root.Pass());
4886 LayerTreeHostImpl::FrameData frame;
4888 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4889 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
4890 EXPECT_EQ(1u, frame.render_passes.size());
4891 host_impl_->DidDrawAllLayers(frame);
4894 class FakeLayerWithQuads : public LayerImpl {
4896 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4897 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl, id));
4900 void AppendQuads(RenderPass* render_pass,
4901 const Occlusion& occlusion_in_content_space,
4902 AppendQuadsData* append_quads_data) override {
4903 SharedQuadState* shared_quad_state =
4904 render_pass->CreateAndAppendSharedQuadState();
4905 PopulateSharedQuadState(shared_quad_state);
4907 SkColor gray = SkColorSetRGB(100, 100, 100);
4908 gfx::Rect quad_rect(content_bounds());
4909 gfx::Rect visible_quad_rect(quad_rect);
4910 SolidColorDrawQuad* my_quad =
4911 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4913 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
4917 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
4918 : LayerImpl(tree_impl, id) {}
4921 class MockContext : public TestWebGraphicsContext3D {
4923 MOCK_METHOD1(useProgram, void(GLuint program));
4924 MOCK_METHOD5(uniform4f, void(GLint location,
4929 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
4931 GLboolean transpose,
4932 const GLfloat* value));
4933 MOCK_METHOD4(drawElements, void(GLenum mode,
4937 MOCK_METHOD1(enable, void(GLenum cap));
4938 MOCK_METHOD1(disable, void(GLenum cap));
4939 MOCK_METHOD4(scissor, void(GLint x,
4945 class MockContextHarness {
4947 MockContext* context_;
4950 explicit MockContextHarness(MockContext* context)
4951 : context_(context) {
4952 context_->set_have_post_sub_buffer(true);
4954 // Catch "uninteresting" calls
4955 EXPECT_CALL(*context_, useProgram(_))
4958 EXPECT_CALL(*context_, drawElements(_, _, _, _))
4961 // These are not asserted
4962 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
4963 .WillRepeatedly(Return());
4965 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
4966 .WillRepeatedly(Return());
4968 // Any un-sanctioned calls to enable() are OK
4969 EXPECT_CALL(*context_, enable(_))
4970 .WillRepeatedly(Return());
4972 // Any un-sanctioned calls to disable() are OK
4973 EXPECT_CALL(*context_, disable(_))
4974 .WillRepeatedly(Return());
4977 void MustDrawSolidQuad() {
4978 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
4980 .RetiresOnSaturation();
4982 EXPECT_CALL(*context_, useProgram(_))
4984 .RetiresOnSaturation();
4987 void MustSetScissor(int x, int y, int width, int height) {
4988 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4989 .WillRepeatedly(Return());
4991 EXPECT_CALL(*context_, scissor(x, y, width, height))
4993 .WillRepeatedly(Return());
4996 void MustSetNoScissor() {
4997 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
4998 .WillRepeatedly(Return());
5000 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5003 EXPECT_CALL(*context_, scissor(_, _, _, _))
5008 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
5009 scoped_ptr<MockContext> mock_context_owned(new MockContext);
5010 MockContext* mock_context = mock_context_owned.get();
5011 MockContextHarness harness(mock_context);
5014 LayerTreeSettings settings = DefaultSettings();
5015 settings.partial_swap_enabled = false;
5016 CreateHostImpl(settings,
5017 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5018 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5020 // Without partial swap, and no clipping, no scissor is set.
5021 harness.MustDrawSolidQuad();
5022 harness.MustSetNoScissor();
5024 LayerTreeHostImpl::FrameData frame;
5025 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5026 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5027 host_impl_->DidDrawAllLayers(frame);
5029 Mock::VerifyAndClearExpectations(&mock_context);
5031 // Without partial swap, but a layer does clip its subtree, one scissor is
5033 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
5034 harness.MustDrawSolidQuad();
5035 harness.MustSetScissor(0, 0, 10, 10);
5037 LayerTreeHostImpl::FrameData frame;
5038 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5039 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5040 host_impl_->DidDrawAllLayers(frame);
5042 Mock::VerifyAndClearExpectations(&mock_context);
5045 TEST_F(LayerTreeHostImplTest, PartialSwap) {
5046 scoped_ptr<MockContext> context_owned(new MockContext);
5047 MockContext* mock_context = context_owned.get();
5048 MockContextHarness harness(mock_context);
5050 LayerTreeSettings settings = DefaultSettings();
5051 settings.partial_swap_enabled = true;
5052 CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass()));
5053 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5055 // The first frame is not a partially-swapped one.
5056 harness.MustSetScissor(0, 0, 10, 10);
5057 harness.MustDrawSolidQuad();
5059 LayerTreeHostImpl::FrameData frame;
5060 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5061 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5062 host_impl_->DidDrawAllLayers(frame);
5064 Mock::VerifyAndClearExpectations(&mock_context);
5066 // Damage a portion of the frame.
5067 host_impl_->active_tree()->root_layer()->SetUpdateRect(
5068 gfx::Rect(0, 0, 2, 3));
5070 // The second frame will be partially-swapped (the y coordinates are flipped).
5071 harness.MustSetScissor(0, 7, 2, 3);
5072 harness.MustDrawSolidQuad();
5074 LayerTreeHostImpl::FrameData frame;
5075 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5076 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5077 host_impl_->DidDrawAllLayers(frame);
5079 Mock::VerifyAndClearExpectations(&mock_context);
5082 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
5084 LayerTreeHostImplClient* client,
5086 SharedBitmapManager* manager,
5087 RenderingStatsInstrumentation* stats_instrumentation) {
5088 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5089 scoped_ptr<OutputSurface> output_surface(
5090 FakeOutputSurface::Create3d(provider));
5091 provider->BindToCurrentThread();
5092 provider->TestContext3d()->set_have_post_sub_buffer(true);
5094 LayerTreeSettings settings;
5095 settings.partial_swap_enabled = partial_swap;
5096 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
5097 settings, client, proxy, stats_instrumentation, manager, NULL, 0);
5098 my_host_impl->InitializeRenderer(output_surface.Pass());
5099 my_host_impl->SetViewportSize(gfx::Size(100, 100));
5102 Layers are created as follows:
5104 +--------------------+
5108 | | +-------------------+
5110 | | +-------------------+
5115 +--------------------+
5117 Layers 1, 2 have render surfaces
5119 scoped_ptr<LayerImpl> root =
5120 LayerImpl::Create(my_host_impl->active_tree(), 1);
5121 scoped_ptr<LayerImpl> child =
5122 LayerImpl::Create(my_host_impl->active_tree(), 2);
5123 scoped_ptr<LayerImpl> grand_child =
5124 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
5126 gfx::Rect root_rect(0, 0, 100, 100);
5127 gfx::Rect child_rect(10, 10, 50, 50);
5128 gfx::Rect grand_child_rect(5, 5, 150, 150);
5130 root->CreateRenderSurface();
5131 root->SetPosition(root_rect.origin());
5132 root->SetBounds(root_rect.size());
5133 root->SetContentBounds(root->bounds());
5134 root->draw_properties().visible_content_rect = root_rect;
5135 root->SetDrawsContent(false);
5136 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
5138 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
5139 child->SetOpacity(0.5f);
5140 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
5141 child->SetContentBounds(child->bounds());
5142 child->draw_properties().visible_content_rect = child_rect;
5143 child->SetDrawsContent(false);
5144 child->SetForceRenderSurface(true);
5146 grand_child->SetPosition(grand_child_rect.origin());
5147 grand_child->SetBounds(grand_child_rect.size());
5148 grand_child->SetContentBounds(grand_child->bounds());
5149 grand_child->draw_properties().visible_content_rect = grand_child_rect;
5150 grand_child->SetDrawsContent(true);
5152 child->AddChild(grand_child.Pass());
5153 root->AddChild(child.Pass());
5155 my_host_impl->active_tree()->SetRootLayer(root.Pass());
5156 return my_host_impl.Pass();
5159 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
5160 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
5161 new TestSharedBitmapManager());
5162 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5163 SetupLayersForOpacity(true,
5166 shared_bitmap_manager.get(),
5167 &stats_instrumentation_);
5169 LayerTreeHostImpl::FrameData frame;
5170 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5172 // Verify all quads have been computed
5173 ASSERT_EQ(2U, frame.render_passes.size());
5174 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5175 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5176 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5177 frame.render_passes[0]->quad_list.front()->material);
5178 EXPECT_EQ(DrawQuad::RENDER_PASS,
5179 frame.render_passes[1]->quad_list.front()->material);
5181 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5182 my_host_impl->DidDrawAllLayers(frame);
5186 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
5187 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
5188 new TestSharedBitmapManager());
5189 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5190 SetupLayersForOpacity(false,
5193 shared_bitmap_manager.get(),
5194 &stats_instrumentation_);
5196 LayerTreeHostImpl::FrameData frame;
5197 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5199 // Verify all quads have been computed
5200 ASSERT_EQ(2U, frame.render_passes.size());
5201 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5202 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5203 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5204 frame.render_passes[0]->quad_list.front()->material);
5205 EXPECT_EQ(DrawQuad::RENDER_PASS,
5206 frame.render_passes[1]->quad_list.front()->material);
5208 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5209 my_host_impl->DidDrawAllLayers(frame);
5213 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
5214 scoped_ptr<TestWebGraphicsContext3D> context =
5215 TestWebGraphicsContext3D::Create();
5216 TestWebGraphicsContext3D* context3d = context.get();
5217 scoped_ptr<OutputSurface> output_surface(
5218 FakeOutputSurface::Create3d(context.Pass()));
5219 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5221 scoped_ptr<LayerImpl> root_layer =
5222 LayerImpl::Create(host_impl_->active_tree(), 1);
5223 root_layer->SetBounds(gfx::Size(10, 10));
5225 scoped_refptr<VideoFrame> softwareFrame =
5226 media::VideoFrame::CreateColorFrame(
5227 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5228 FakeVideoFrameProvider provider;
5229 provider.set_frame(softwareFrame);
5230 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
5231 host_impl_->active_tree(), 4, &provider, media::VIDEO_ROTATION_0);
5232 video_layer->SetBounds(gfx::Size(10, 10));
5233 video_layer->SetContentBounds(gfx::Size(10, 10));
5234 video_layer->SetDrawsContent(true);
5235 root_layer->AddChild(video_layer.Pass());
5237 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
5238 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
5239 io_surface_layer->SetBounds(gfx::Size(10, 10));
5240 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
5241 io_surface_layer->SetDrawsContent(true);
5242 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5243 root_layer->AddChild(io_surface_layer.Pass());
5245 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
5247 EXPECT_EQ(0u, context3d->NumTextures());
5249 LayerTreeHostImpl::FrameData frame;
5250 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5251 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5252 host_impl_->DidDrawAllLayers(frame);
5253 host_impl_->SwapBuffers(frame);
5255 EXPECT_GT(context3d->NumTextures(), 0u);
5257 // Kill the layer tree.
5258 host_impl_->active_tree()->SetRootLayer(
5259 LayerImpl::Create(host_impl_->active_tree(), 100));
5260 // There should be no textures left in use after.
5261 EXPECT_EQ(0u, context3d->NumTextures());
5264 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
5266 MOCK_METHOD1(useProgram, void(GLuint program));
5267 MOCK_METHOD4(drawElements, void(GLenum mode,
5273 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
5274 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
5275 new MockDrawQuadsToFillScreenContext);
5276 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
5279 LayerTreeSettings settings = DefaultSettings();
5280 settings.partial_swap_enabled = false;
5281 CreateHostImpl(settings,
5282 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5283 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5284 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
5286 // Verify one quad is drawn when transparent background set is not set.
5287 host_impl_->active_tree()->set_has_transparent_background(false);
5288 EXPECT_CALL(*mock_context, useProgram(_))
5290 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
5292 LayerTreeHostImpl::FrameData frame;
5293 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5294 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5295 host_impl_->DidDrawAllLayers(frame);
5296 Mock::VerifyAndClearExpectations(&mock_context);
5298 // Verify no quads are drawn when transparent background is set.
5299 host_impl_->active_tree()->set_has_transparent_background(true);
5300 host_impl_->SetFullRootLayerDamage();
5301 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5302 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5303 host_impl_->DidDrawAllLayers(frame);
5304 Mock::VerifyAndClearExpectations(&mock_context);
5307 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
5308 set_reduce_memory_result(false);
5310 // If changing the memory limit wouldn't result in changing what was
5311 // committed, then no commit should be requested.
5312 set_reduce_memory_result(false);
5313 host_impl_->set_max_memory_needed_bytes(
5314 host_impl_->memory_allocation_limit_bytes() - 1);
5315 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5316 host_impl_->memory_allocation_limit_bytes() - 1));
5317 EXPECT_FALSE(did_request_commit_);
5318 did_request_commit_ = false;
5320 // If changing the memory limit would result in changing what was
5321 // committed, then a commit should be requested, even though nothing was
5323 set_reduce_memory_result(false);
5324 host_impl_->set_max_memory_needed_bytes(
5325 host_impl_->memory_allocation_limit_bytes());
5326 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5327 host_impl_->memory_allocation_limit_bytes() - 1));
5328 EXPECT_TRUE(did_request_commit_);
5329 did_request_commit_ = false;
5331 // Especially if changing the memory limit caused evictions, we need
5333 set_reduce_memory_result(true);
5334 host_impl_->set_max_memory_needed_bytes(1);
5335 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5336 host_impl_->memory_allocation_limit_bytes() - 1));
5337 EXPECT_TRUE(did_request_commit_);
5338 did_request_commit_ = false;
5340 // But if we set it to the same value that it was before, we shouldn't
5342 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5343 host_impl_->memory_allocation_limit_bytes()));
5344 EXPECT_FALSE(did_request_commit_);
5347 class LayerTreeHostImplTestWithDelegatingRenderer
5348 : public LayerTreeHostImplTest {
5350 scoped_ptr<OutputSurface> CreateOutputSurface() override {
5351 return FakeOutputSurface::CreateDelegating3d();
5354 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
5355 bool expect_to_draw = !expected_damage.IsEmpty();
5357 LayerTreeHostImpl::FrameData frame;
5358 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5360 if (!expect_to_draw) {
5361 // With no damage, we don't draw, and no quads are created.
5362 ASSERT_EQ(0u, frame.render_passes.size());
5364 ASSERT_EQ(1u, frame.render_passes.size());
5366 // Verify the damage rect for the root render pass.
5367 const RenderPass* root_render_pass = frame.render_passes.back();
5368 EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
5370 // Verify the root and child layers' quads are generated and not being
5372 ASSERT_EQ(2u, root_render_pass->quad_list.size());
5374 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
5375 gfx::RectF expected_child_visible_rect(child->content_bounds());
5376 EXPECT_RECT_EQ(expected_child_visible_rect,
5377 root_render_pass->quad_list.front()->visible_rect);
5379 LayerImpl* root = host_impl_->active_tree()->root_layer();
5380 gfx::RectF expected_root_visible_rect(root->content_bounds());
5381 EXPECT_RECT_EQ(expected_root_visible_rect,
5382 root_render_pass->quad_list.ElementAt(1)->visible_rect);
5385 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5386 host_impl_->DidDrawAllLayers(frame);
5387 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
5391 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
5392 scoped_ptr<SolidColorLayerImpl> root =
5393 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5394 root->SetPosition(gfx::PointF());
5395 root->SetBounds(gfx::Size(10, 10));
5396 root->SetContentBounds(gfx::Size(10, 10));
5397 root->SetDrawsContent(true);
5399 // Child layer is in the bottom right corner.
5400 scoped_ptr<SolidColorLayerImpl> child =
5401 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
5402 child->SetPosition(gfx::PointF(9.f, 9.f));
5403 child->SetBounds(gfx::Size(1, 1));
5404 child->SetContentBounds(gfx::Size(1, 1));
5405 child->SetDrawsContent(true);
5406 root->AddChild(child.Pass());
5408 host_impl_->active_tree()->SetRootLayer(root.Pass());
5410 // Draw a frame. In the first frame, the entire viewport should be damaged.
5411 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
5412 DrawFrameAndTestDamage(full_frame_damage);
5414 // The second frame has damage that doesn't touch the child layer. Its quads
5415 // should still be generated.
5416 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
5417 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
5418 DrawFrameAndTestDamage(small_damage);
5420 // The third frame should have no damage, so no quads should be generated.
5421 gfx::Rect no_damage;
5422 DrawFrameAndTestDamage(no_damage);
5425 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5426 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5427 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
5428 LayerTreeSettings settings;
5429 CreateHostImpl(settings, CreateOutputSurface());
5430 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
5433 class FakeMaskLayerImpl : public LayerImpl {
5435 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
5437 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
5440 void GetContentsResourceId(ResourceProvider::ResourceId* resource_id,
5441 gfx::Size* resource_size) const override {
5446 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
5447 : LayerImpl(tree_impl, id) {}
5450 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
5451 LayerTreeSettings settings;
5452 settings.layer_transforms_should_scale_layer_contents = true;
5453 CreateHostImpl(settings, CreateOutputSurface());
5457 // +-- Scaling Layer (adds a 2x scale)
5459 // +-- Content Layer
5461 scoped_ptr<LayerImpl> scoped_root =
5462 LayerImpl::Create(host_impl_->active_tree(), 1);
5463 LayerImpl* root = scoped_root.get();
5464 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5466 scoped_ptr<LayerImpl> scoped_scaling_layer =
5467 LayerImpl::Create(host_impl_->active_tree(), 2);
5468 LayerImpl* scaling_layer = scoped_scaling_layer.get();
5469 root->AddChild(scoped_scaling_layer.Pass());
5471 scoped_ptr<LayerImpl> scoped_content_layer =
5472 LayerImpl::Create(host_impl_->active_tree(), 3);
5473 LayerImpl* content_layer = scoped_content_layer.get();
5474 scaling_layer->AddChild(scoped_content_layer.Pass());
5476 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5477 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5478 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5479 content_layer->SetMaskLayer(scoped_mask_layer.Pass());
5481 gfx::Size root_size(100, 100);
5482 root->SetBounds(root_size);
5483 root->SetContentBounds(root_size);
5484 root->SetPosition(gfx::PointF());
5486 gfx::Size scaling_layer_size(50, 50);
5487 scaling_layer->SetBounds(scaling_layer_size);
5488 scaling_layer->SetContentBounds(scaling_layer_size);
5489 scaling_layer->SetPosition(gfx::PointF());
5490 gfx::Transform scale;
5491 scale.Scale(2.f, 2.f);
5492 scaling_layer->SetTransform(scale);
5494 content_layer->SetBounds(scaling_layer_size);
5495 content_layer->SetContentBounds(scaling_layer_size);
5496 content_layer->SetPosition(gfx::PointF());
5497 content_layer->SetDrawsContent(true);
5499 mask_layer->SetBounds(scaling_layer_size);
5500 mask_layer->SetContentBounds(scaling_layer_size);
5501 mask_layer->SetPosition(gfx::PointF());
5502 mask_layer->SetDrawsContent(true);
5505 // Check that the tree scaling is correctly taken into account for the mask,
5506 // that should fully map onto the quad.
5507 float device_scale_factor = 1.f;
5508 host_impl_->SetViewportSize(root_size);
5509 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5511 LayerTreeHostImpl::FrameData frame;
5512 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5514 ASSERT_EQ(1u, frame.render_passes.size());
5515 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5516 ASSERT_EQ(DrawQuad::RENDER_PASS,
5517 frame.render_passes[0]->quad_list.front()->material);
5518 const RenderPassDrawQuad* render_pass_quad =
5519 RenderPassDrawQuad::MaterialCast(
5520 frame.render_passes[0]->quad_list.front());
5521 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5522 render_pass_quad->rect.ToString());
5523 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5524 render_pass_quad->MaskUVRect().ToString());
5525 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5526 render_pass_quad->mask_uv_scale.ToString());
5528 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5529 host_impl_->DidDrawAllLayers(frame);
5533 // Applying a DSF should change the render surface size, but won't affect
5534 // which part of the mask is used.
5535 device_scale_factor = 2.f;
5536 gfx::Size device_viewport =
5537 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5538 host_impl_->SetViewportSize(device_viewport);
5539 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5540 host_impl_->active_tree()->set_needs_update_draw_properties();
5542 LayerTreeHostImpl::FrameData frame;
5543 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5545 ASSERT_EQ(1u, frame.render_passes.size());
5546 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5547 ASSERT_EQ(DrawQuad::RENDER_PASS,
5548 frame.render_passes[0]->quad_list.front()->material);
5549 const RenderPassDrawQuad* render_pass_quad =
5550 RenderPassDrawQuad::MaterialCast(
5551 frame.render_passes[0]->quad_list.front());
5552 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
5553 render_pass_quad->rect.ToString());
5554 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5555 render_pass_quad->MaskUVRect().ToString());
5556 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5557 render_pass_quad->mask_uv_scale.ToString());
5559 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5560 host_impl_->DidDrawAllLayers(frame);
5564 // Applying an equivalent content scale on the content layer and the mask
5565 // should still result in the same part of the mask being used.
5566 gfx::Size content_bounds =
5567 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
5568 device_scale_factor));
5569 content_layer->SetContentBounds(content_bounds);
5570 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5571 mask_layer->SetContentBounds(content_bounds);
5572 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5573 host_impl_->active_tree()->set_needs_update_draw_properties();
5575 LayerTreeHostImpl::FrameData frame;
5576 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5578 ASSERT_EQ(1u, frame.render_passes.size());
5579 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5580 ASSERT_EQ(DrawQuad::RENDER_PASS,
5581 frame.render_passes[0]->quad_list.front()->material);
5582 const RenderPassDrawQuad* render_pass_quad =
5583 RenderPassDrawQuad::MaterialCast(
5584 frame.render_passes[0]->quad_list.front());
5585 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
5586 render_pass_quad->rect.ToString());
5587 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5588 render_pass_quad->MaskUVRect().ToString());
5589 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5590 render_pass_quad->mask_uv_scale.ToString());
5592 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5593 host_impl_->DidDrawAllLayers(frame);
5597 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
5598 // The mask layer has bounds 100x100 but is attached to a layer with bounds
5601 scoped_ptr<LayerImpl> scoped_root =
5602 LayerImpl::Create(host_impl_->active_tree(), 1);
5603 LayerImpl* root = scoped_root.get();
5604 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5606 scoped_ptr<LayerImpl> scoped_content_layer =
5607 LayerImpl::Create(host_impl_->active_tree(), 3);
5608 LayerImpl* content_layer = scoped_content_layer.get();
5609 root->AddChild(scoped_content_layer.Pass());
5611 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5612 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5613 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5614 content_layer->SetMaskLayer(scoped_mask_layer.Pass());
5616 gfx::Size root_size(100, 100);
5617 root->SetBounds(root_size);
5618 root->SetContentBounds(root_size);
5619 root->SetPosition(gfx::PointF());
5621 gfx::Size layer_size(50, 50);
5622 content_layer->SetBounds(layer_size);
5623 content_layer->SetContentBounds(layer_size);
5624 content_layer->SetPosition(gfx::PointF());
5625 content_layer->SetDrawsContent(true);
5627 gfx::Size mask_size(100, 100);
5628 mask_layer->SetBounds(mask_size);
5629 mask_layer->SetContentBounds(mask_size);
5630 mask_layer->SetPosition(gfx::PointF());
5631 mask_layer->SetDrawsContent(true);
5633 // Check that the mask fills the surface.
5634 float device_scale_factor = 1.f;
5635 host_impl_->SetViewportSize(root_size);
5636 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5638 LayerTreeHostImpl::FrameData frame;
5639 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5641 ASSERT_EQ(1u, frame.render_passes.size());
5642 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5643 ASSERT_EQ(DrawQuad::RENDER_PASS,
5644 frame.render_passes[0]->quad_list.front()->material);
5645 const RenderPassDrawQuad* render_pass_quad =
5646 RenderPassDrawQuad::MaterialCast(
5647 frame.render_passes[0]->quad_list.front());
5648 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5649 render_pass_quad->rect.ToString());
5650 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5651 render_pass_quad->MaskUVRect().ToString());
5652 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5653 render_pass_quad->mask_uv_scale.ToString());
5655 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5656 host_impl_->DidDrawAllLayers(frame);
5659 // Applying a DSF should change the render surface size, but won't affect
5660 // which part of the mask is used.
5661 device_scale_factor = 2.f;
5662 gfx::Size device_viewport =
5663 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5664 host_impl_->SetViewportSize(device_viewport);
5665 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5666 host_impl_->active_tree()->set_needs_update_draw_properties();
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());
5673 ASSERT_EQ(DrawQuad::RENDER_PASS,
5674 frame.render_passes[0]->quad_list.front()->material);
5675 const RenderPassDrawQuad* render_pass_quad =
5676 RenderPassDrawQuad::MaterialCast(
5677 frame.render_passes[0]->quad_list.front());
5678 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5679 render_pass_quad->rect.ToString());
5680 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5681 render_pass_quad->MaskUVRect().ToString());
5682 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5683 render_pass_quad->mask_uv_scale.ToString());
5685 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5686 host_impl_->DidDrawAllLayers(frame);
5689 // Applying an equivalent content scale on the content layer and the mask
5690 // should still result in the same part of the mask being used.
5691 gfx::Size layer_size_large =
5692 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5693 content_layer->SetContentBounds(layer_size_large);
5694 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5695 gfx::Size mask_size_large =
5696 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5697 mask_layer->SetContentBounds(mask_size_large);
5698 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5699 host_impl_->active_tree()->set_needs_update_draw_properties();
5701 LayerTreeHostImpl::FrameData frame;
5702 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5704 ASSERT_EQ(1u, frame.render_passes.size());
5705 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5706 ASSERT_EQ(DrawQuad::RENDER_PASS,
5707 frame.render_passes[0]->quad_list.front()->material);
5708 const RenderPassDrawQuad* render_pass_quad =
5709 RenderPassDrawQuad::MaterialCast(
5710 frame.render_passes[0]->quad_list.front());
5711 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5712 render_pass_quad->rect.ToString());
5713 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5714 render_pass_quad->MaskUVRect().ToString());
5715 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5716 render_pass_quad->mask_uv_scale.ToString());
5718 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5719 host_impl_->DidDrawAllLayers(frame);
5722 // Applying a different contents scale to the mask layer means it will have
5723 // a larger texture, but it should use the same tex coords to cover the
5725 mask_layer->SetContentBounds(mask_size);
5726 mask_layer->SetContentsScale(1.f, 1.f);
5727 host_impl_->active_tree()->set_needs_update_draw_properties();
5729 LayerTreeHostImpl::FrameData frame;
5730 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5732 ASSERT_EQ(1u, frame.render_passes.size());
5733 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5734 ASSERT_EQ(DrawQuad::RENDER_PASS,
5735 frame.render_passes[0]->quad_list.front()->material);
5736 const RenderPassDrawQuad* render_pass_quad =
5737 RenderPassDrawQuad::MaterialCast(
5738 frame.render_passes[0]->quad_list.front());
5739 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5740 render_pass_quad->rect.ToString());
5741 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5742 render_pass_quad->MaskUVRect().ToString());
5743 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5744 render_pass_quad->mask_uv_scale.ToString());
5746 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5747 host_impl_->DidDrawAllLayers(frame);
5751 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
5752 // The replica's mask layer has bounds 100x100 but the replica is of a
5753 // layer with bounds 50x50.
5755 scoped_ptr<LayerImpl> scoped_root =
5756 LayerImpl::Create(host_impl_->active_tree(), 1);
5757 LayerImpl* root = scoped_root.get();
5758 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5760 scoped_ptr<LayerImpl> scoped_content_layer =
5761 LayerImpl::Create(host_impl_->active_tree(), 3);
5762 LayerImpl* content_layer = scoped_content_layer.get();
5763 root->AddChild(scoped_content_layer.Pass());
5765 scoped_ptr<LayerImpl> scoped_replica_layer =
5766 LayerImpl::Create(host_impl_->active_tree(), 2);
5767 LayerImpl* replica_layer = scoped_replica_layer.get();
5768 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5770 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5771 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5772 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5773 replica_layer->SetMaskLayer(scoped_mask_layer.Pass());
5775 gfx::Size root_size(100, 100);
5776 root->SetBounds(root_size);
5777 root->SetContentBounds(root_size);
5778 root->SetPosition(gfx::PointF());
5780 gfx::Size layer_size(50, 50);
5781 content_layer->SetBounds(layer_size);
5782 content_layer->SetContentBounds(layer_size);
5783 content_layer->SetPosition(gfx::PointF());
5784 content_layer->SetDrawsContent(true);
5786 gfx::Size mask_size(100, 100);
5787 mask_layer->SetBounds(mask_size);
5788 mask_layer->SetContentBounds(mask_size);
5789 mask_layer->SetPosition(gfx::PointF());
5790 mask_layer->SetDrawsContent(true);
5792 // Check that the mask fills the surface.
5793 float device_scale_factor = 1.f;
5794 host_impl_->SetViewportSize(root_size);
5795 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5797 LayerTreeHostImpl::FrameData frame;
5798 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5800 ASSERT_EQ(1u, frame.render_passes.size());
5801 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5802 ASSERT_EQ(DrawQuad::RENDER_PASS,
5803 frame.render_passes[0]->quad_list.ElementAt(1)->material);
5804 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
5805 frame.render_passes[0]->quad_list.ElementAt(1));
5806 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5807 replica_quad->rect.ToString());
5808 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5809 replica_quad->MaskUVRect().ToString());
5810 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5811 replica_quad->mask_uv_scale.ToString());
5813 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5814 host_impl_->DidDrawAllLayers(frame);
5817 // Applying a DSF should change the render surface size, but won't affect
5818 // which part of the mask is used.
5819 device_scale_factor = 2.f;
5820 gfx::Size device_viewport =
5821 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5822 host_impl_->SetViewportSize(device_viewport);
5823 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5824 host_impl_->active_tree()->set_needs_update_draw_properties();
5826 LayerTreeHostImpl::FrameData frame;
5827 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5829 ASSERT_EQ(1u, frame.render_passes.size());
5830 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5831 ASSERT_EQ(DrawQuad::RENDER_PASS,
5832 frame.render_passes[0]->quad_list.ElementAt(1)->material);
5833 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
5834 frame.render_passes[0]->quad_list.ElementAt(1));
5835 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5836 replica_quad->rect.ToString());
5837 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5838 replica_quad->MaskUVRect().ToString());
5839 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5840 replica_quad->mask_uv_scale.ToString());
5842 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5843 host_impl_->DidDrawAllLayers(frame);
5846 // Applying an equivalent content scale on the content layer and the mask
5847 // should still result in the same part of the mask being used.
5848 gfx::Size layer_size_large =
5849 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5850 content_layer->SetContentBounds(layer_size_large);
5851 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5852 gfx::Size mask_size_large =
5853 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5854 mask_layer->SetContentBounds(mask_size_large);
5855 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5856 host_impl_->active_tree()->set_needs_update_draw_properties();
5858 LayerTreeHostImpl::FrameData frame;
5859 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5861 ASSERT_EQ(1u, frame.render_passes.size());
5862 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5863 ASSERT_EQ(DrawQuad::RENDER_PASS,
5864 frame.render_passes[0]->quad_list.ElementAt(1)->material);
5865 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
5866 frame.render_passes[0]->quad_list.ElementAt(1));
5867 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5868 replica_quad->rect.ToString());
5869 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5870 replica_quad->MaskUVRect().ToString());
5871 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5872 replica_quad->mask_uv_scale.ToString());
5874 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5875 host_impl_->DidDrawAllLayers(frame);
5878 // Applying a different contents scale to the mask layer means it will have
5879 // a larger texture, but it should use the same tex coords to cover the
5881 mask_layer->SetContentBounds(mask_size);
5882 mask_layer->SetContentsScale(1.f, 1.f);
5883 host_impl_->active_tree()->set_needs_update_draw_properties();
5885 LayerTreeHostImpl::FrameData frame;
5886 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5888 ASSERT_EQ(1u, frame.render_passes.size());
5889 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5890 ASSERT_EQ(DrawQuad::RENDER_PASS,
5891 frame.render_passes[0]->quad_list.ElementAt(1)->material);
5892 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
5893 frame.render_passes[0]->quad_list.ElementAt(1));
5894 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5895 replica_quad->rect.ToString());
5896 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5897 replica_quad->MaskUVRect().ToString());
5898 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5899 replica_quad->mask_uv_scale.ToString());
5901 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5902 host_impl_->DidDrawAllLayers(frame);
5906 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
5907 // The replica is of a layer with bounds 50x50, but it has a child that causes
5908 // the surface bounds to be larger.
5910 scoped_ptr<LayerImpl> scoped_root =
5911 LayerImpl::Create(host_impl_->active_tree(), 1);
5912 LayerImpl* root = scoped_root.get();
5913 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5915 scoped_ptr<LayerImpl> scoped_content_layer =
5916 LayerImpl::Create(host_impl_->active_tree(), 2);
5917 LayerImpl* content_layer = scoped_content_layer.get();
5918 root->AddChild(scoped_content_layer.Pass());
5920 scoped_ptr<LayerImpl> scoped_content_child_layer =
5921 LayerImpl::Create(host_impl_->active_tree(), 3);
5922 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5923 content_layer->AddChild(scoped_content_child_layer.Pass());
5925 scoped_ptr<LayerImpl> scoped_replica_layer =
5926 LayerImpl::Create(host_impl_->active_tree(), 4);
5927 LayerImpl* replica_layer = scoped_replica_layer.get();
5928 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5930 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5931 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
5932 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5933 replica_layer->SetMaskLayer(scoped_mask_layer.Pass());
5935 gfx::Size root_size(100, 100);
5936 root->SetBounds(root_size);
5937 root->SetContentBounds(root_size);
5938 root->SetPosition(gfx::PointF());
5940 gfx::Size layer_size(50, 50);
5941 content_layer->SetBounds(layer_size);
5942 content_layer->SetContentBounds(layer_size);
5943 content_layer->SetPosition(gfx::PointF());
5944 content_layer->SetDrawsContent(true);
5946 gfx::Size child_size(50, 50);
5947 content_child_layer->SetBounds(child_size);
5948 content_child_layer->SetContentBounds(child_size);
5949 content_child_layer->SetPosition(gfx::Point(50, 0));
5950 content_child_layer->SetDrawsContent(true);
5952 gfx::Size mask_size(50, 50);
5953 mask_layer->SetBounds(mask_size);
5954 mask_layer->SetContentBounds(mask_size);
5955 mask_layer->SetPosition(gfx::PointF());
5956 mask_layer->SetDrawsContent(true);
5958 float device_scale_factor = 1.f;
5959 host_impl_->SetViewportSize(root_size);
5960 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5962 LayerTreeHostImpl::FrameData frame;
5963 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5965 ASSERT_EQ(1u, frame.render_passes.size());
5966 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5968 // The surface is 100x50.
5969 ASSERT_EQ(DrawQuad::RENDER_PASS,
5970 frame.render_passes[0]->quad_list.front()->material);
5971 const RenderPassDrawQuad* render_pass_quad =
5972 RenderPassDrawQuad::MaterialCast(
5973 frame.render_passes[0]->quad_list.front());
5974 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5975 render_pass_quad->rect.ToString());
5977 // The mask covers the owning layer only.
5978 ASSERT_EQ(DrawQuad::RENDER_PASS,
5979 frame.render_passes[0]->quad_list.ElementAt(1)->material);
5980 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
5981 frame.render_passes[0]->quad_list.ElementAt(1));
5982 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5983 replica_quad->rect.ToString());
5984 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
5985 replica_quad->MaskUVRect().ToString());
5986 EXPECT_EQ(gfx::Vector2dF(2.f, 1.f).ToString(),
5987 replica_quad->mask_uv_scale.ToString());
5989 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5990 host_impl_->DidDrawAllLayers(frame);
5993 // Move the child to (-50, 0) instead. Now the mask should be moved to still
5994 // cover the layer being replicated.
5995 content_child_layer->SetPosition(gfx::Point(-50, 0));
5997 LayerTreeHostImpl::FrameData frame;
5998 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6000 ASSERT_EQ(1u, frame.render_passes.size());
6001 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
6003 // The surface is 100x50 with its origin at (-50, 0).
6004 ASSERT_EQ(DrawQuad::RENDER_PASS,
6005 frame.render_passes[0]->quad_list.front()->material);
6006 const RenderPassDrawQuad* render_pass_quad =
6007 RenderPassDrawQuad::MaterialCast(
6008 frame.render_passes[0]->quad_list.front());
6009 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
6010 render_pass_quad->rect.ToString());
6012 // The mask covers the owning layer only.
6013 ASSERT_EQ(DrawQuad::RENDER_PASS,
6014 frame.render_passes[0]->quad_list.ElementAt(1)->material);
6015 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
6016 frame.render_passes[0]->quad_list.ElementAt(1));
6017 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
6018 replica_quad->rect.ToString());
6019 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
6020 replica_quad->MaskUVRect().ToString());
6021 EXPECT_EQ(gfx::Vector2dF(2.f, 1.f).ToString(),
6022 replica_quad->mask_uv_scale.ToString());
6024 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6025 host_impl_->DidDrawAllLayers(frame);
6029 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
6030 // The masked layer has bounds 50x50, but it has a child that causes
6031 // the surface bounds to be larger. It also has a parent that clips the
6032 // masked layer and its surface.
6034 scoped_ptr<LayerImpl> scoped_root =
6035 LayerImpl::Create(host_impl_->active_tree(), 1);
6036 LayerImpl* root = scoped_root.get();
6037 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
6039 scoped_ptr<LayerImpl> scoped_clipping_layer =
6040 LayerImpl::Create(host_impl_->active_tree(), 2);
6041 LayerImpl* clipping_layer = scoped_clipping_layer.get();
6042 root->AddChild(scoped_clipping_layer.Pass());
6044 scoped_ptr<LayerImpl> scoped_content_layer =
6045 LayerImpl::Create(host_impl_->active_tree(), 3);
6046 LayerImpl* content_layer = scoped_content_layer.get();
6047 clipping_layer->AddChild(scoped_content_layer.Pass());
6049 scoped_ptr<LayerImpl> scoped_content_child_layer =
6050 LayerImpl::Create(host_impl_->active_tree(), 4);
6051 LayerImpl* content_child_layer = scoped_content_child_layer.get();
6052 content_layer->AddChild(scoped_content_child_layer.Pass());
6054 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
6055 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
6056 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
6057 content_layer->SetMaskLayer(scoped_mask_layer.Pass());
6059 gfx::Size root_size(100, 100);
6060 root->SetBounds(root_size);
6061 root->SetContentBounds(root_size);
6062 root->SetPosition(gfx::PointF());
6064 gfx::Rect clipping_rect(20, 10, 10, 20);
6065 clipping_layer->SetBounds(clipping_rect.size());
6066 clipping_layer->SetContentBounds(clipping_rect.size());
6067 clipping_layer->SetPosition(clipping_rect.origin());
6068 clipping_layer->SetMasksToBounds(true);
6070 gfx::Size layer_size(50, 50);
6071 content_layer->SetBounds(layer_size);
6072 content_layer->SetContentBounds(layer_size);
6073 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
6074 content_layer->SetDrawsContent(true);
6076 gfx::Size child_size(50, 50);
6077 content_child_layer->SetBounds(child_size);
6078 content_child_layer->SetContentBounds(child_size);
6079 content_child_layer->SetPosition(gfx::Point(50, 0));
6080 content_child_layer->SetDrawsContent(true);
6082 gfx::Size mask_size(100, 100);
6083 mask_layer->SetBounds(mask_size);
6084 mask_layer->SetContentBounds(mask_size);
6085 mask_layer->SetPosition(gfx::PointF());
6086 mask_layer->SetDrawsContent(true);
6088 float device_scale_factor = 1.f;
6089 host_impl_->SetViewportSize(root_size);
6090 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6092 LayerTreeHostImpl::FrameData frame;
6093 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6095 ASSERT_EQ(1u, frame.render_passes.size());
6096 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
6098 // The surface is clipped to 10x20.
6099 ASSERT_EQ(DrawQuad::RENDER_PASS,
6100 frame.render_passes[0]->quad_list.front()->material);
6101 const RenderPassDrawQuad* render_pass_quad =
6102 RenderPassDrawQuad::MaterialCast(
6103 frame.render_passes[0]->quad_list.front());
6104 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
6105 render_pass_quad->rect.ToString());
6106 // The masked layer is 50x50, but the surface size is 10x20. So the texture
6107 // coords in the mask are scaled by 10/50 and 20/50.
6108 // The surface is clipped to (20,10) so the mask texture coords are offset
6109 // by 20/50 and 10/50
6110 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f)
6112 render_pass_quad->MaskUVRect().ToString());
6113 EXPECT_EQ(gfx::Vector2dF(10.f / 50.f, 20.f / 50.f).ToString(),
6114 render_pass_quad->mask_uv_scale.ToString());
6116 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6117 host_impl_->DidDrawAllLayers(frame);
6121 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
6123 using GLRenderer::ShouldAntialiasQuad;
6126 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
6127 // Due to precision issues (especially on Android), sometimes far
6128 // away quads can end up thinking they need AA.
6129 float device_scale_factor = 4.f / 3.f;
6130 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6131 gfx::Size root_size(2000, 1000);
6132 gfx::Size device_viewport_size =
6133 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
6134 host_impl_->SetViewportSize(device_viewport_size);
6136 host_impl_->CreatePendingTree();
6137 host_impl_->pending_tree()
6138 ->SetPageScaleFactorAndLimits(1.f, 1.f / 16.f, 16.f);
6140 scoped_ptr<LayerImpl> scoped_root =
6141 LayerImpl::Create(host_impl_->pending_tree(), 1);
6142 LayerImpl* root = scoped_root.get();
6144 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
6146 scoped_ptr<LayerImpl> scoped_scrolling_layer =
6147 LayerImpl::Create(host_impl_->pending_tree(), 2);
6148 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
6149 root->AddChild(scoped_scrolling_layer.Pass());
6151 gfx::Size content_layer_bounds(100000, 100);
6152 gfx::Size pile_tile_size(3000, 3000);
6153 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
6154 pile_tile_size, content_layer_bounds));
6156 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
6157 FakePictureLayerImpl::CreateWithPile(host_impl_->pending_tree(), 3, pile);
6158 LayerImpl* content_layer = scoped_content_layer.get();
6159 scrolling_layer->AddChild(scoped_content_layer.Pass());
6160 content_layer->SetBounds(content_layer_bounds);
6161 content_layer->SetDrawsContent(true);
6163 root->SetBounds(root_size);
6165 gfx::ScrollOffset scroll_offset(100000, 0);
6166 scrolling_layer->SetScrollClipLayer(root->id());
6167 scrolling_layer->SetScrollOffset(scroll_offset);
6169 host_impl_->ActivateSyncTree();
6171 host_impl_->active_tree()->UpdateDrawProperties();
6172 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
6174 LayerTreeHostImpl::FrameData frame;
6175 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6177 ASSERT_EQ(1u, frame.render_passes.size());
6178 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
6179 const DrawQuad* quad = frame.render_passes[0]->quad_list.front();
6182 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6183 quad->quadTransform(), quad, false);
6184 EXPECT_FALSE(antialiased);
6186 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6187 host_impl_->DidDrawAllLayers(frame);
6191 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
6193 CompositorFrameMetadataTest()
6194 : swap_buffers_complete_(0) {}
6196 void DidSwapBuffersCompleteOnImplThread() override {
6197 swap_buffers_complete_++;
6200 int swap_buffers_complete_;
6203 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
6204 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
6206 LayerTreeHostImpl::FrameData frame;
6207 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6208 host_impl_->DrawLayers(&frame, base::TimeTicks());
6209 host_impl_->DidDrawAllLayers(frame);
6211 CompositorFrameAck ack;
6212 host_impl_->ReclaimResources(&ack);
6213 host_impl_->DidSwapBuffersComplete();
6214 EXPECT_EQ(swap_buffers_complete_, 1);
6217 class CountingSoftwareDevice : public SoftwareOutputDevice {
6219 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6221 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
6223 return SoftwareOutputDevice::BeginPaint(damage_rect);
6225 void EndPaint(SoftwareFrameData* frame_data) override {
6227 SoftwareOutputDevice::EndPaint(frame_data);
6230 int frames_began_, frames_ended_;
6233 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
6234 // No main thread evictions in resourceless software mode.
6235 set_reduce_memory_result(false);
6236 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
6237 bool delegated_rendering = false;
6238 FakeOutputSurface* output_surface =
6239 FakeOutputSurface::CreateDeferredGL(
6240 scoped_ptr<SoftwareOutputDevice>(software_device),
6241 delegated_rendering).release();
6242 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6243 scoped_ptr<OutputSurface>(output_surface)));
6244 host_impl_->SetViewportSize(gfx::Size(50, 50));
6246 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6248 const gfx::Transform external_transform;
6249 const gfx::Rect external_viewport;
6250 const gfx::Rect external_clip;
6251 const bool resourceless_software_draw = true;
6252 host_impl_->SetExternalDrawConstraints(external_transform,
6257 resourceless_software_draw);
6259 EXPECT_EQ(0, software_device->frames_began_);
6260 EXPECT_EQ(0, software_device->frames_ended_);
6264 EXPECT_EQ(1, software_device->frames_began_);
6265 EXPECT_EQ(1, software_device->frames_ended_);
6267 // Call other API methods that are likely to hit NULL pointer in this mode.
6268 EXPECT_TRUE(host_impl_->AsValue().get());
6269 EXPECT_TRUE(host_impl_->ActivationStateAsValue().get());
6272 TEST_F(LayerTreeHostImplTest,
6273 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
6274 set_reduce_memory_result(false);
6275 bool delegated_rendering = false;
6276 FakeOutputSurface* output_surface =
6277 FakeOutputSurface::CreateDeferredGL(
6278 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
6279 delegated_rendering).release();
6280 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6281 scoped_ptr<OutputSurface>(output_surface)));
6283 const gfx::Transform external_transform;
6284 const gfx::Rect external_viewport;
6285 const gfx::Rect external_clip;
6286 const bool resourceless_software_draw = true;
6287 host_impl_->SetExternalDrawConstraints(external_transform,
6292 resourceless_software_draw);
6294 // SolidColorLayerImpl will be drawn.
6295 scoped_ptr<SolidColorLayerImpl> root_layer =
6296 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6298 // VideoLayerImpl will not be drawn.
6299 FakeVideoFrameProvider provider;
6300 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
6301 host_impl_->active_tree(), 2, &provider, media::VIDEO_ROTATION_0);
6302 video_layer->SetBounds(gfx::Size(10, 10));
6303 video_layer->SetContentBounds(gfx::Size(10, 10));
6304 video_layer->SetDrawsContent(true);
6305 root_layer->AddChild(video_layer.Pass());
6306 SetupRootLayerImpl(root_layer.Pass());
6308 LayerTreeHostImpl::FrameData frame;
6309 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6310 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6311 host_impl_->DidDrawAllLayers(frame);
6313 EXPECT_EQ(1u, frame.will_draw_layers.size());
6314 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
6317 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
6319 virtual void SetUp() override {
6320 LayerTreeHostImplTest::SetUp();
6322 set_reduce_memory_result(false);
6324 bool delegated_rendering = false;
6325 scoped_ptr<FakeOutputSurface> output_surface(
6326 FakeOutputSurface::CreateDeferredGL(
6327 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
6328 delegated_rendering));
6329 output_surface_ = output_surface.get();
6331 EXPECT_TRUE(CreateHostImpl(DefaultSettings(), output_surface.Pass()));
6333 scoped_ptr<SolidColorLayerImpl> root_layer =
6334 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6335 SetupRootLayerImpl(root_layer.Pass());
6337 onscreen_context_provider_ = TestContextProvider::Create();
6340 void UpdateRendererCapabilitiesOnImplThread() override {
6341 did_update_renderer_capabilities_ = true;
6344 FakeOutputSurface* output_surface_;
6345 scoped_refptr<TestContextProvider> onscreen_context_provider_;
6346 bool did_update_renderer_capabilities_;
6350 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
6354 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6356 // DeferredInitialize and hardware draw.
6357 did_update_renderer_capabilities_ = false;
6359 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
6360 EXPECT_EQ(onscreen_context_provider_.get(),
6361 host_impl_->output_surface()->context_provider());
6362 EXPECT_TRUE(did_update_renderer_capabilities_);
6364 // Defer intialized GL draw.
6367 // Revert back to software.
6368 did_update_renderer_capabilities_ = false;
6369 output_surface_->ReleaseGL();
6370 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6371 EXPECT_TRUE(did_update_renderer_capabilities_);
6373 // Software draw again.
6377 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails) {
6381 // Fail initialization of the onscreen context before the OutputSurface binds
6382 // it to the thread.
6383 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
6385 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6387 // DeferredInitialize fails.
6388 did_update_renderer_capabilities_ = false;
6390 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
6391 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6392 EXPECT_FALSE(did_update_renderer_capabilities_);
6394 // Software draw again.
6398 // Checks that we have a non-0 default allocation if we pass a context that
6399 // doesn't support memory management extensions.
6400 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
6401 LayerTreeSettings settings;
6402 host_impl_ = LayerTreeHostImpl::Create(settings,
6405 &stats_instrumentation_,
6406 shared_bitmap_manager_.get(),
6407 gpu_memory_buffer_manager_.get(),
6410 scoped_ptr<OutputSurface> output_surface(
6411 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6412 host_impl_->InitializeRenderer(output_surface.Pass());
6413 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
6416 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
6417 ManagedMemoryPolicy policy1(
6418 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
6419 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
6420 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
6421 int allow_nice_to_have_cutoff_value =
6422 ManagedMemoryPolicy::PriorityCutoffToValue(
6423 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
6424 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
6425 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
6427 // GPU rasterization should be disabled by default on the tree(s)
6428 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
6429 EXPECT_TRUE(host_impl_->pending_tree() == NULL);
6431 host_impl_->SetVisible(true);
6432 host_impl_->SetMemoryPolicy(policy1);
6433 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
6434 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
6436 host_impl_->SetVisible(false);
6437 EXPECT_EQ(0u, current_limit_bytes_);
6438 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
6440 host_impl_->SetVisible(true);
6441 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
6442 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
6444 // Now enable GPU rasterization and test if we get nice to have cutoff,
6446 LayerTreeSettings settings;
6447 settings.gpu_rasterization_enabled = true;
6448 host_impl_ = LayerTreeHostImpl::Create(
6449 settings, this, &proxy_, &stats_instrumentation_, NULL, NULL, 0);
6450 host_impl_->SetUseGpuRasterization(true);
6451 host_impl_->SetVisible(true);
6452 host_impl_->SetMemoryPolicy(policy1);
6453 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
6454 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
6456 host_impl_->SetVisible(false);
6457 EXPECT_EQ(0u, current_limit_bytes_);
6458 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
6461 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
6462 ASSERT_TRUE(host_impl_->active_tree());
6464 // RequiresHighResToDraw is set when new output surface is used.
6465 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6467 host_impl_->ResetRequiresHighResToDraw();
6469 host_impl_->SetVisible(false);
6470 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6471 host_impl_->SetVisible(true);
6472 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6473 host_impl_->SetVisible(false);
6474 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6476 host_impl_->ResetRequiresHighResToDraw();
6478 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6479 host_impl_->SetVisible(true);
6480 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6483 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
6484 ASSERT_TRUE(host_impl_->active_tree());
6485 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
6487 // RequiresHighResToDraw is set when new output surface is used.
6488 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6490 host_impl_->ResetRequiresHighResToDraw();
6492 host_impl_->SetUseGpuRasterization(false);
6493 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6494 host_impl_->SetUseGpuRasterization(true);
6495 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6496 host_impl_->SetUseGpuRasterization(false);
6497 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6499 host_impl_->ResetRequiresHighResToDraw();
6501 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6502 host_impl_->SetUseGpuRasterization(true);
6503 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6506 class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
6508 virtual void SetUp() override {
6509 LayerTreeSettings settings;
6510 settings.impl_side_painting = true;
6512 fake_host_impl_ = new FakeLayerTreeHostImpl(
6513 settings, &proxy_, shared_bitmap_manager_.get());
6514 host_impl_.reset(fake_host_impl_);
6515 host_impl_->InitializeRenderer(CreateOutputSurface());
6516 host_impl_->SetViewportSize(gfx::Size(10, 10));
6519 FakeLayerTreeHostImpl* fake_host_impl_;
6522 TEST_F(LayerTreeHostImplTestManageTiles, ManageTilesWhenInvisible) {
6523 fake_host_impl_->DidModifyTilePriorities();
6524 EXPECT_TRUE(fake_host_impl_->manage_tiles_needed());
6525 fake_host_impl_->SetVisible(false);
6526 EXPECT_FALSE(fake_host_impl_->manage_tiles_needed());
6529 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
6530 scoped_ptr<TestWebGraphicsContext3D> context =
6531 TestWebGraphicsContext3D::Create();
6532 TestWebGraphicsContext3D* context3d = context.get();
6533 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
6534 CreateHostImpl(DefaultSettings(), output_surface.Pass());
6536 EXPECT_EQ(0u, context3d->NumTextures());
6538 UIResourceId ui_resource_id = 1;
6539 bool is_opaque = false;
6540 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
6541 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6542 EXPECT_EQ(1u, context3d->NumTextures());
6543 ResourceProvider::ResourceId id1 =
6544 host_impl_->ResourceIdForUIResource(ui_resource_id);
6547 // Multiple requests with the same id is allowed. The previous texture is
6549 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6550 EXPECT_EQ(1u, context3d->NumTextures());
6551 ResourceProvider::ResourceId id2 =
6552 host_impl_->ResourceIdForUIResource(ui_resource_id);
6554 EXPECT_NE(id1, id2);
6556 // Deleting invalid UIResourceId is allowed and does not change state.
6557 host_impl_->DeleteUIResource(-1);
6558 EXPECT_EQ(1u, context3d->NumTextures());
6560 // Should return zero for invalid UIResourceId. Number of textures should
6562 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
6563 EXPECT_EQ(1u, context3d->NumTextures());
6565 host_impl_->DeleteUIResource(ui_resource_id);
6566 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
6567 EXPECT_EQ(0u, context3d->NumTextures());
6569 // Should not change state for multiple deletion on one UIResourceId
6570 host_impl_->DeleteUIResource(ui_resource_id);
6571 EXPECT_EQ(0u, context3d->NumTextures());
6574 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
6575 scoped_ptr<TestWebGraphicsContext3D> context =
6576 TestWebGraphicsContext3D::Create();
6577 TestWebGraphicsContext3D* context3d = context.get();
6578 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6580 EXPECT_EQ(0u, context3d->NumTextures());
6582 gfx::Size size(4, 4);
6583 // SkImageInfo has no support for ETC1. The |info| below contains the right
6584 // total pixel size for the bitmap but not the right height and width. The
6585 // correct width/height are passed directly to UIResourceBitmap.
6587 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
6588 skia::RefPtr<SkPixelRef> pixel_ref =
6589 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
6590 pixel_ref->setImmutable();
6591 UIResourceBitmap bitmap(pixel_ref, size);
6592 UIResourceId ui_resource_id = 1;
6593 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6594 EXPECT_EQ(1u, context3d->NumTextures());
6595 ResourceProvider::ResourceId id1 =
6596 host_impl_->ResourceIdForUIResource(ui_resource_id);
6600 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
6603 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
6604 scoped_refptr<TestContextProvider> context_provider =
6605 TestContextProvider::Create();
6607 CreateHostImpl(DefaultSettings(),
6608 FakeOutputSurface::Create3d(context_provider));
6610 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
6612 ScopedPtrVector<CopyOutputRequest> requests;
6613 requests.push_back(CopyOutputRequest::CreateRequest(
6614 base::Bind(&ShutdownReleasesContext_Callback)));
6616 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
6618 LayerTreeHostImpl::FrameData frame;
6619 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6620 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6621 host_impl_->DidDrawAllLayers(frame);
6623 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6624 // texture in a texture mailbox.
6625 EXPECT_FALSE(context_provider->HasOneRef());
6626 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
6628 host_impl_ = nullptr;
6630 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6631 // released, and the texture deleted.
6632 EXPECT_TRUE(context_provider->HasOneRef());
6633 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
6636 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
6637 // When flinging via touch, only the child should scroll (we should not
6639 gfx::Size surface_size(10, 10);
6640 gfx::Size content_size(20, 20);
6641 scoped_ptr<LayerImpl> root_clip =
6642 LayerImpl::Create(host_impl_->active_tree(), 3);
6643 scoped_ptr<LayerImpl> root =
6644 CreateScrollableLayer(1, content_size, root_clip.get());
6645 root->SetIsContainerForFixedPositionLayers(true);
6646 scoped_ptr<LayerImpl> child =
6647 CreateScrollableLayer(2, content_size, root_clip.get());
6649 root->AddChild(child.Pass());
6650 int root_id = root->id();
6651 root_clip->AddChild(root.Pass());
6653 host_impl_->SetViewportSize(surface_size);
6654 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6655 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
6656 host_impl_->active_tree()->DidBecomeActive();
6659 EXPECT_EQ(InputHandler::ScrollStarted,
6660 host_impl_->ScrollBegin(gfx::Point(),
6661 InputHandler::Gesture));
6663 EXPECT_EQ(InputHandler::ScrollStarted,
6664 host_impl_->FlingScrollBegin());
6666 gfx::Vector2d scroll_delta(0, 100);
6667 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6668 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6670 host_impl_->ScrollEnd();
6672 scoped_ptr<ScrollAndScaleSet> scroll_info =
6673 host_impl_->ProcessScrollDeltas();
6675 // Only the child should have scrolled.
6676 ASSERT_EQ(1u, scroll_info->scrolls.size());
6677 ExpectNone(*scroll_info.get(), root_id);
6681 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
6682 // Scroll a child layer beyond its maximum scroll range and make sure the
6683 // the scroll doesn't bubble up to the parent layer.
6684 gfx::Size surface_size(10, 10);
6685 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
6686 scoped_ptr<LayerImpl> root_scrolling =
6687 CreateScrollableLayer(2, surface_size, root.get());
6689 scoped_ptr<LayerImpl> grand_child =
6690 CreateScrollableLayer(4, surface_size, root.get());
6691 grand_child->SetScrollOffset(gfx::ScrollOffset(0, 2));
6693 scoped_ptr<LayerImpl> child =
6694 CreateScrollableLayer(3, surface_size, root.get());
6695 child->SetScrollOffset(gfx::ScrollOffset(0, 4));
6696 child->AddChild(grand_child.Pass());
6698 root_scrolling->AddChild(child.Pass());
6699 root->AddChild(root_scrolling.Pass());
6700 host_impl_->active_tree()->SetRootLayer(root.Pass());
6701 host_impl_->active_tree()->DidBecomeActive();
6702 host_impl_->SetViewportSize(surface_size);
6705 scoped_ptr<ScrollAndScaleSet> scroll_info;
6707 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6708 LayerImpl* grand_child = child->children()[0];
6710 gfx::Vector2d scroll_delta(0, -2);
6711 EXPECT_EQ(InputHandler::ScrollStarted,
6712 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6713 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6715 // The grand child should have scrolled up to its limit.
6716 scroll_info = host_impl_->ProcessScrollDeltas();
6717 ASSERT_EQ(1u, scroll_info->scrolls.size());
6718 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6719 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6721 // The child should have received the bubbled delta, but the locked
6722 // scrolling layer should remain set as the grand child.
6723 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6724 scroll_info = host_impl_->ProcessScrollDeltas();
6725 ASSERT_EQ(2u, scroll_info->scrolls.size());
6726 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6727 ExpectContains(*scroll_info, child->id(), scroll_delta);
6728 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6730 // The first |ScrollBy| after the fling should re-lock the scrolling
6731 // layer to the first layer that scrolled, which is the child.
6732 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6733 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6734 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6736 // The child should have scrolled up to its limit.
6737 scroll_info = host_impl_->ProcessScrollDeltas();
6738 ASSERT_EQ(2u, scroll_info->scrolls.size());
6739 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6740 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
6742 // As the locked layer is at it's limit, no further scrolling can occur.
6743 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6744 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6745 host_impl_->ScrollEnd();
6749 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6750 // When flinging via wheel, the root should eventually scroll (we should
6752 gfx::Size surface_size(10, 10);
6753 gfx::Size content_size(20, 20);
6754 scoped_ptr<LayerImpl> root_clip =
6755 LayerImpl::Create(host_impl_->active_tree(), 3);
6756 scoped_ptr<LayerImpl> root_scroll =
6757 CreateScrollableLayer(1, content_size, root_clip.get());
6758 int root_scroll_id = root_scroll->id();
6759 scoped_ptr<LayerImpl> child =
6760 CreateScrollableLayer(2, content_size, root_clip.get());
6762 root_scroll->AddChild(child.Pass());
6763 root_clip->AddChild(root_scroll.Pass());
6765 host_impl_->SetViewportSize(surface_size);
6766 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6767 host_impl_->active_tree()->DidBecomeActive();
6770 EXPECT_EQ(InputHandler::ScrollStarted,
6771 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6773 EXPECT_EQ(InputHandler::ScrollStarted,
6774 host_impl_->FlingScrollBegin());
6776 gfx::Vector2d scroll_delta(0, 100);
6777 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6778 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6780 host_impl_->ScrollEnd();
6782 scoped_ptr<ScrollAndScaleSet> scroll_info =
6783 host_impl_->ProcessScrollDeltas();
6785 // The root should have scrolled.
6786 ASSERT_EQ(2u, scroll_info->scrolls.size());
6787 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
6791 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6792 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6793 // we should return ScrollUnknown.
6794 gfx::Size content_size(100, 100);
6795 SetupScrollAndContentsLayers(content_size);
6797 int scroll_layer_id = 2;
6798 LayerImpl* scroll_layer =
6799 host_impl_->active_tree()->LayerById(scroll_layer_id);
6800 scroll_layer->SetDrawsContent(true);
6802 int page_scale_layer_id = 5;
6803 LayerImpl* page_scale_layer =
6804 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6806 int occluder_layer_id = 6;
6807 scoped_ptr<LayerImpl> occluder_layer =
6808 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6809 occluder_layer->SetDrawsContent(true);
6810 occluder_layer->SetBounds(content_size);
6811 occluder_layer->SetContentBounds(content_size);
6812 occluder_layer->SetPosition(gfx::PointF());
6814 // The parent of the occluder is *above* the scroller.
6815 page_scale_layer->AddChild(occluder_layer.Pass());
6819 EXPECT_EQ(InputHandler::ScrollUnknown,
6820 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6823 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6824 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6825 // is not the first scroller we encounter when walking up from the layer, we
6826 // should also return ScrollUnknown.
6827 gfx::Size content_size(100, 100);
6828 SetupScrollAndContentsLayers(content_size);
6830 int scroll_layer_id = 2;
6831 LayerImpl* scroll_layer =
6832 host_impl_->active_tree()->LayerById(scroll_layer_id);
6833 scroll_layer->SetDrawsContent(true);
6835 int occluder_layer_id = 6;
6836 scoped_ptr<LayerImpl> occluder_layer =
6837 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6838 occluder_layer->SetDrawsContent(true);
6839 occluder_layer->SetBounds(content_size);
6840 occluder_layer->SetContentBounds(content_size);
6841 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6843 int child_scroll_clip_layer_id = 7;
6844 scoped_ptr<LayerImpl> child_scroll_clip =
6845 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6847 int child_scroll_layer_id = 8;
6848 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6849 child_scroll_layer_id, content_size, child_scroll_clip.get());
6851 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6853 child_scroll->AddChild(occluder_layer.Pass());
6854 scroll_layer->AddChild(child_scroll.Pass());
6858 EXPECT_EQ(InputHandler::ScrollUnknown,
6859 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6862 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) {
6863 gfx::Size content_size(100, 100);
6864 SetupScrollAndContentsLayers(content_size);
6866 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6868 int scroll_layer_id = 2;
6869 LayerImpl* scroll_layer =
6870 host_impl_->active_tree()->LayerById(scroll_layer_id);
6872 int child_scroll_layer_id = 7;
6873 scoped_ptr<LayerImpl> child_scroll =
6874 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6875 child_scroll->SetDrawsContent(false);
6877 scroll_layer->AddChild(child_scroll.Pass());
6881 // We should not have scrolled |child_scroll| even though we technically "hit"
6882 // it. The reason for this is that if the scrolling the scroll would not move
6883 // any layer that is a drawn RSLL member, then we can ignore the hit.
6885 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6886 // overscrolling the inner viewport.
6887 EXPECT_EQ(InputHandler::ScrollStarted,
6888 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6890 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6893 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6894 // This test case is very similar to the one above with one key difference:
6895 // the invisible scroller has a scroll child that is indeed draw contents.
6896 // If we attempt to initiate a gesture scroll off of the visible scroll child
6897 // we should still start the scroll child.
6898 gfx::Size content_size(100, 100);
6899 SetupScrollAndContentsLayers(content_size);
6901 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6903 int scroll_layer_id = 2;
6904 LayerImpl* scroll_layer =
6905 host_impl_->active_tree()->LayerById(scroll_layer_id);
6907 int scroll_child_id = 6;
6908 scoped_ptr<LayerImpl> scroll_child =
6909 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6910 scroll_child->SetDrawsContent(true);
6911 scroll_child->SetBounds(content_size);
6912 scroll_child->SetContentBounds(content_size);
6913 // Move the scroll child so it's not hit by our test point.
6914 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6916 int invisible_scroll_layer_id = 7;
6917 scoped_ptr<LayerImpl> invisible_scroll =
6918 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6919 invisible_scroll->SetDrawsContent(false);
6921 int container_id = 8;
6922 scoped_ptr<LayerImpl> container =
6923 LayerImpl::Create(host_impl_->active_tree(), container_id);
6925 scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
6926 scroll_children->insert(scroll_child.get());
6927 invisible_scroll->SetScrollChildren(scroll_children.release());
6929 scroll_child->SetScrollParent(invisible_scroll.get());
6931 container->AddChild(invisible_scroll.Pass());
6932 container->AddChild(scroll_child.Pass());
6934 scroll_layer->AddChild(container.Pass());
6938 // We should not have scrolled |child_scroll| even though we technically "hit"
6939 // it. The reason for this is that if the scrolling the scroll would not move
6940 // any layer that is a drawn RSLL member, then we can ignore the hit.
6942 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6943 // overscrolling the inner viewport.
6944 EXPECT_EQ(InputHandler::ScrollStarted,
6945 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6947 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6950 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6951 // to CompositorFrameMetadata after SwapBuffers();
6952 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6953 scoped_ptr<SolidColorLayerImpl> root =
6954 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6955 root->SetPosition(gfx::PointF());
6956 root->SetBounds(gfx::Size(10, 10));
6957 root->SetContentBounds(gfx::Size(10, 10));
6958 root->SetDrawsContent(true);
6960 host_impl_->active_tree()->SetRootLayer(root.Pass());
6962 FakeOutputSurface* fake_output_surface =
6963 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6965 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6966 fake_output_surface->last_sent_frame().metadata.latency_info;
6967 EXPECT_TRUE(metadata_latency_before.empty());
6969 ui::LatencyInfo latency_info;
6970 latency_info.AddLatencyNumber(
6971 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6972 scoped_ptr<SwapPromise> swap_promise(
6973 new LatencyInfoSwapPromise(latency_info));
6974 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
6975 host_impl_->SetNeedsRedraw();
6977 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6978 LayerTreeHostImpl::FrameData frame;
6979 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6980 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6981 host_impl_->DidDrawAllLayers(frame);
6982 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6984 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6985 fake_output_surface->last_sent_frame().metadata.latency_info;
6986 EXPECT_EQ(1u, metadata_latency_after.size());
6987 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6988 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6991 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
6992 int root_layer_id = 1;
6993 scoped_ptr<SolidColorLayerImpl> root =
6994 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
6995 root->SetPosition(gfx::PointF());
6996 root->SetBounds(gfx::Size(10, 10));
6997 root->SetContentBounds(gfx::Size(10, 10));
6998 root->SetDrawsContent(true);
7000 host_impl_->active_tree()->SetRootLayer(root.Pass());
7002 // Ensure the default frame selection bounds are empty.
7003 FakeOutputSurface* fake_output_surface =
7004 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
7005 const ViewportSelectionBound& selection_start_before =
7006 fake_output_surface->last_sent_frame().metadata.selection_start;
7007 const ViewportSelectionBound& selection_end_before =
7008 fake_output_surface->last_sent_frame().metadata.selection_end;
7009 EXPECT_EQ(ViewportSelectionBound(), selection_start_before);
7010 EXPECT_EQ(ViewportSelectionBound(), selection_end_before);
7012 // Plumb the layer-local selection bounds.
7013 gfx::PointF selection_top(5, 0);
7014 gfx::PointF selection_bottom(5, 5);
7015 LayerSelectionBound start, end;
7016 start.type = SELECTION_BOUND_CENTER;
7017 start.layer_id = root_layer_id;
7018 start.edge_bottom = selection_bottom;
7019 start.edge_top = selection_top;
7021 host_impl_->active_tree()->RegisterSelection(start, end);
7023 // Trigger a draw-swap sequence.
7024 host_impl_->SetNeedsRedraw();
7026 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
7027 LayerTreeHostImpl::FrameData frame;
7028 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
7029 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
7030 host_impl_->DidDrawAllLayers(frame);
7031 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
7033 // Ensure the selection bounds have propagated to the frame metadata.
7034 const ViewportSelectionBound& selection_start_after =
7035 fake_output_surface->last_sent_frame().metadata.selection_start;
7036 const ViewportSelectionBound& selection_end_after =
7037 fake_output_surface->last_sent_frame().metadata.selection_end;
7038 EXPECT_EQ(start.type, selection_start_after.type);
7039 EXPECT_EQ(end.type, selection_end_after.type);
7040 EXPECT_EQ(selection_bottom, selection_start_after.edge_bottom);
7041 EXPECT_EQ(selection_top, selection_start_after.edge_top);
7042 EXPECT_TRUE(selection_start_after.visible);
7043 EXPECT_TRUE(selection_start_after.visible);
7046 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
7048 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
7049 LayerTreeHostImpl* layer_tree_host_impl,
7050 int* set_needs_commit_count,
7051 int* set_needs_redraw_count,
7052 int* forward_to_main_count)
7053 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
7054 set_needs_commit_count_(set_needs_commit_count),
7055 set_needs_redraw_count_(set_needs_redraw_count),
7056 forward_to_main_count_(forward_to_main_count) {}
7058 ~SimpleSwapPromiseMonitor() override {}
7060 void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
7062 void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; }
7064 void OnForwardScrollUpdateToMainThreadOnImpl() override {
7065 (*forward_to_main_count_)++;
7069 int* set_needs_commit_count_;
7070 int* set_needs_redraw_count_;
7071 int* forward_to_main_count_;
7074 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
7075 int set_needs_commit_count = 0;
7076 int set_needs_redraw_count = 0;
7077 int forward_to_main_count = 0;
7080 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7081 new SimpleSwapPromiseMonitor(NULL,
7083 &set_needs_commit_count,
7084 &set_needs_redraw_count,
7085 &forward_to_main_count));
7086 host_impl_->SetNeedsRedraw();
7087 EXPECT_EQ(0, set_needs_commit_count);
7088 EXPECT_EQ(1, set_needs_redraw_count);
7089 EXPECT_EQ(0, forward_to_main_count);
7092 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
7094 host_impl_->SetNeedsRedraw();
7095 EXPECT_EQ(0, set_needs_commit_count);
7096 EXPECT_EQ(1, set_needs_redraw_count);
7097 EXPECT_EQ(0, forward_to_main_count);
7100 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7101 new SimpleSwapPromiseMonitor(NULL,
7103 &set_needs_commit_count,
7104 &set_needs_redraw_count,
7105 &forward_to_main_count));
7106 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
7107 EXPECT_EQ(0, set_needs_commit_count);
7108 EXPECT_EQ(2, set_needs_redraw_count);
7109 EXPECT_EQ(0, forward_to_main_count);
7113 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7114 new SimpleSwapPromiseMonitor(NULL,
7116 &set_needs_commit_count,
7117 &set_needs_redraw_count,
7118 &forward_to_main_count));
7119 // Empty damage rect won't signal the monitor.
7120 host_impl_->SetNeedsRedrawRect(gfx::Rect());
7121 EXPECT_EQ(0, set_needs_commit_count);
7122 EXPECT_EQ(2, set_needs_redraw_count);
7123 EXPECT_EQ(0, forward_to_main_count);
7127 set_needs_commit_count = 0;
7128 set_needs_redraw_count = 0;
7129 forward_to_main_count = 0;
7130 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7131 new SimpleSwapPromiseMonitor(NULL,
7133 &set_needs_commit_count,
7134 &set_needs_redraw_count,
7135 &forward_to_main_count));
7136 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
7138 // Scrolling normally should not trigger any forwarding.
7139 EXPECT_EQ(InputHandler::ScrollStarted,
7140 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7142 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
7143 host_impl_->ScrollEnd();
7145 EXPECT_EQ(0, set_needs_commit_count);
7146 EXPECT_EQ(1, set_needs_redraw_count);
7147 EXPECT_EQ(0, forward_to_main_count);
7149 // Scrolling with a scroll handler should defer the swap to the main
7151 scroll_layer->SetHaveScrollEventHandlers(true);
7152 EXPECT_EQ(InputHandler::ScrollStarted,
7153 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7155 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
7156 host_impl_->ScrollEnd();
7158 EXPECT_EQ(0, set_needs_commit_count);
7159 EXPECT_EQ(2, set_needs_redraw_count);
7160 EXPECT_EQ(1, forward_to_main_count);
7164 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
7166 virtual void SetUp() override {
7167 LayerTreeSettings settings = DefaultSettings();
7168 settings.calculate_top_controls_position = true;
7169 settings.top_controls_height = top_controls_height_;
7170 CreateHostImpl(settings, CreateOutputSurface());
7174 static const int top_controls_height_;
7177 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
7179 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
7180 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7181 ->SetScrollOffset(gfx::ScrollOffset(0, 10));
7182 host_impl_->Animate(base::TimeTicks());
7183 EXPECT_FALSE(did_request_redraw_);
7186 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
7187 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7188 ->SetScrollOffset(gfx::ScrollOffset(0, 10));
7189 host_impl_->DidChangeTopControlsPosition();
7190 EXPECT_TRUE(did_request_animate_);
7191 EXPECT_TRUE(did_request_redraw_);
7194 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
7195 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7196 host_impl_->SetViewportSize(gfx::Size(100, 100));
7197 host_impl_->top_controls_manager()->UpdateTopControlsState(
7198 BOTH, SHOWN, false);
7201 EXPECT_EQ(InputHandler::ScrollStarted,
7202 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7203 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7204 EXPECT_EQ(gfx::Vector2dF().ToString(),
7205 scroll_layer->TotalScrollOffset().ToString());
7207 // Scroll just the top controls and verify that the scroll succeeds.
7208 const float residue = 10;
7209 float offset = top_controls_height_ - residue;
7211 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7212 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7213 EXPECT_EQ(gfx::Vector2dF().ToString(),
7214 scroll_layer->TotalScrollOffset().ToString());
7216 // Scroll across the boundary
7217 const float content_scroll = 20;
7218 offset = residue + content_scroll;
7220 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7221 EXPECT_EQ(-top_controls_height_,
7222 host_impl_->top_controls_manager()->ControlsTopOffset());
7223 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
7224 scroll_layer->TotalScrollOffset().ToString());
7226 // Now scroll back to the top of the content
7227 offset = -content_scroll;
7229 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7230 EXPECT_EQ(-top_controls_height_,
7231 host_impl_->top_controls_manager()->ControlsTopOffset());
7232 EXPECT_EQ(gfx::Vector2dF().ToString(),
7233 scroll_layer->TotalScrollOffset().ToString());
7235 // And scroll the top controls completely into view
7236 offset = -top_controls_height_;
7238 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7239 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7240 EXPECT_EQ(gfx::Vector2dF().ToString(),
7241 scroll_layer->TotalScrollOffset().ToString());
7243 // And attempt to scroll past the end
7245 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7246 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7247 EXPECT_EQ(gfx::Vector2dF().ToString(),
7248 scroll_layer->TotalScrollOffset().ToString());
7250 host_impl_->ScrollEnd();
7253 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
7254 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7255 host_impl_->SetViewportSize(gfx::Size(100, 200));
7256 host_impl_->top_controls_manager()->UpdateTopControlsState(
7257 BOTH, SHOWN, false);
7260 EXPECT_EQ(InputHandler::ScrollStarted,
7261 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7262 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7263 EXPECT_EQ(gfx::Vector2dF().ToString(),
7264 scroll_layer->TotalScrollOffset().ToString());
7266 // Scroll the top controls partially.
7267 const float residue = 35;
7268 float offset = top_controls_height_ - residue;
7270 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7271 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7272 EXPECT_EQ(gfx::Vector2dF().ToString(),
7273 scroll_layer->TotalScrollOffset().ToString());
7275 did_request_redraw_ = false;
7276 did_request_animate_ = false;
7277 did_request_commit_ = false;
7279 // End the scroll while the controls are still offset from their limit.
7280 host_impl_->ScrollEnd();
7281 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7282 EXPECT_TRUE(did_request_animate_);
7283 EXPECT_TRUE(did_request_redraw_);
7284 EXPECT_FALSE(did_request_commit_);
7286 // The top controls should properly animate until finished, despite the scroll
7287 // offset being at the origin.
7288 base::TimeTicks animation_time = gfx::FrameTime::Now();
7289 while (did_request_animate_) {
7290 did_request_redraw_ = false;
7291 did_request_animate_ = false;
7292 did_request_commit_ = false;
7295 host_impl_->top_controls_manager()->ControlsTopOffset();
7297 animation_time += base::TimeDelta::FromMilliseconds(5);
7298 host_impl_->Animate(animation_time);
7299 EXPECT_EQ(gfx::Vector2dF().ToString(),
7300 scroll_layer->TotalScrollOffset().ToString());
7303 host_impl_->top_controls_manager()->ControlsTopOffset();
7305 // No commit is needed as the controls are animating the content offset,
7306 // not the scroll offset.
7307 EXPECT_FALSE(did_request_commit_);
7309 if (new_offset != old_offset)
7310 EXPECT_TRUE(did_request_redraw_);
7312 if (new_offset != 0) {
7313 EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
7314 EXPECT_TRUE(did_request_animate_);
7317 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7320 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
7321 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7322 host_impl_->SetViewportSize(gfx::Size(100, 100));
7323 host_impl_->top_controls_manager()->UpdateTopControlsState(
7324 BOTH, SHOWN, false);
7325 float initial_scroll_offset = 50;
7326 scroll_layer->SetScrollOffset(gfx::ScrollOffset(0, initial_scroll_offset));
7329 EXPECT_EQ(InputHandler::ScrollStarted,
7330 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7331 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7332 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7333 scroll_layer->TotalScrollOffset().ToString());
7335 // Scroll the top controls partially.
7336 const float residue = 15;
7337 float offset = top_controls_height_ - residue;
7339 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7340 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7341 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7342 scroll_layer->TotalScrollOffset().ToString());
7344 did_request_redraw_ = false;
7345 did_request_animate_ = false;
7346 did_request_commit_ = false;
7348 // End the scroll while the controls are still offset from the limit.
7349 host_impl_->ScrollEnd();
7350 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7351 EXPECT_TRUE(did_request_animate_);
7352 EXPECT_TRUE(did_request_redraw_);
7353 EXPECT_FALSE(did_request_commit_);
7355 // Animate the top controls to the limit.
7356 base::TimeTicks animation_time = gfx::FrameTime::Now();
7357 while (did_request_animate_) {
7358 did_request_redraw_ = false;
7359 did_request_animate_ = false;
7360 did_request_commit_ = false;
7363 host_impl_->top_controls_manager()->ControlsTopOffset();
7365 animation_time += base::TimeDelta::FromMilliseconds(5);
7366 host_impl_->Animate(animation_time);
7369 host_impl_->top_controls_manager()->ControlsTopOffset();
7371 if (new_offset != old_offset) {
7372 EXPECT_TRUE(did_request_redraw_);
7373 EXPECT_TRUE(did_request_commit_);
7376 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7379 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
7381 void SetupVirtualViewportLayers(const gfx::Size& content_size,
7382 const gfx::Size& outer_viewport,
7383 const gfx::Size& inner_viewport) {
7384 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
7385 const int kOuterViewportClipLayerId = 6;
7386 const int kOuterViewportScrollLayerId = 7;
7387 const int kInnerViewportScrollLayerId = 2;
7388 const int kInnerViewportClipLayerId = 4;
7389 const int kPageScaleLayerId = 5;
7391 scoped_ptr<LayerImpl> inner_scroll =
7392 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
7393 inner_scroll->SetIsContainerForFixedPositionLayers(true);
7394 inner_scroll->SetScrollOffset(gfx::ScrollOffset());
7396 scoped_ptr<LayerImpl> inner_clip =
7397 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
7398 inner_clip->SetBounds(inner_viewport);
7400 scoped_ptr<LayerImpl> page_scale =
7401 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
7403 inner_scroll->SetScrollClipLayer(inner_clip->id());
7404 inner_scroll->SetBounds(outer_viewport);
7405 inner_scroll->SetContentBounds(outer_viewport);
7406 inner_scroll->SetPosition(gfx::PointF());
7408 scoped_ptr<LayerImpl> outer_clip =
7409 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
7410 outer_clip->SetBounds(outer_viewport);
7411 outer_clip->SetIsContainerForFixedPositionLayers(true);
7413 scoped_ptr<LayerImpl> outer_scroll =
7414 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
7415 outer_scroll->SetScrollClipLayer(outer_clip->id());
7416 outer_scroll->SetScrollOffset(gfx::ScrollOffset());
7417 outer_scroll->SetBounds(content_size);
7418 outer_scroll->SetContentBounds(content_size);
7419 outer_scroll->SetPosition(gfx::PointF());
7421 scoped_ptr<LayerImpl> contents =
7422 LayerImpl::Create(layer_tree_impl, 8);
7423 contents->SetDrawsContent(true);
7424 contents->SetBounds(content_size);
7425 contents->SetContentBounds(content_size);
7426 contents->SetPosition(gfx::PointF());
7428 outer_scroll->AddChild(contents.Pass());
7429 outer_clip->AddChild(outer_scroll.Pass());
7430 inner_scroll->AddChild(outer_clip.Pass());
7431 page_scale->AddChild(inner_scroll.Pass());
7432 inner_clip->AddChild(page_scale.Pass());
7434 layer_tree_impl->SetRootLayer(inner_clip.Pass());
7435 layer_tree_impl->SetViewportLayersFromIds(kPageScaleLayerId,
7436 kInnerViewportScrollLayerId, kOuterViewportScrollLayerId);
7438 host_impl_->active_tree()->DidBecomeActive();
7442 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
7443 gfx::Size content_size = gfx::Size(100, 160);
7444 gfx::Size outer_viewport = gfx::Size(50, 80);
7445 gfx::Size inner_viewport = gfx::Size(25, 40);
7447 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7449 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7450 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7453 gfx::Vector2dF inner_expected;
7454 gfx::Vector2dF outer_expected;
7455 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7456 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7458 // Make sure the fling goes to the outer viewport first
7459 EXPECT_EQ(InputHandler::ScrollStarted,
7460 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7461 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
7463 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7464 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7465 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7467 host_impl_->ScrollEnd();
7469 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7470 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7472 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7473 EXPECT_EQ(InputHandler::ScrollStarted,
7474 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7475 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
7477 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7478 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7480 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7481 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7483 host_impl_->ScrollEnd();
7485 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7486 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7490 TEST_F(LayerTreeHostImplVirtualViewportTest,
7491 DiagonalScrollBubblesPerfectlyToInner) {
7492 gfx::Size content_size = gfx::Size(100, 160);
7493 gfx::Size outer_viewport = gfx::Size(50, 80);
7494 gfx::Size inner_viewport = gfx::Size(25, 40);
7496 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7498 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7499 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7502 gfx::Vector2dF inner_expected;
7503 gfx::Vector2dF outer_expected;
7504 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7505 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7507 // Make sure the scroll goes to the outer viewport first.
7508 EXPECT_EQ(InputHandler::ScrollStarted,
7509 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7510 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
7512 // Scroll near the edge of the outer viewport.
7513 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7514 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7515 outer_expected += scroll_delta;
7517 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7518 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7520 // Now diagonal scroll across the outer viewport boundary in a single event.
7521 // The entirety of the scroll should be consumed, as bubbling between inner
7522 // and outer viewport layers is perfect.
7523 host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2));
7524 outer_expected += scroll_delta;
7525 inner_expected += scroll_delta;
7526 host_impl_->ScrollEnd();
7528 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7529 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7533 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
7535 virtual void SetUp() override {
7536 LayerTreeSettings settings = DefaultSettings();
7537 settings.max_memory_for_prepaint_percentage = 50;
7538 CreateHostImpl(settings, CreateOutputSurface());
7542 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
7543 // Set up a memory policy and percentages which could cause
7544 // 32-bit integer overflows.
7545 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
7547 // Verify implicit limits are calculated correctly with no overflows
7548 host_impl_->SetMemoryPolicy(mem_policy);
7549 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
7550 300u * 1024u * 1024u);
7551 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
7552 150u * 1024u * 1024u);
7555 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
7556 const gfx::Size layer_size(100, 100);
7557 gfx::Transform external_transform;
7558 const gfx::Rect external_viewport(layer_size);
7559 const gfx::Rect external_clip(layer_size);
7560 const bool resourceless_software_draw = false;
7561 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
7563 host_impl_->SetExternalDrawConstraints(external_transform,
7568 resourceless_software_draw);
7570 EXPECT_TRANSFORMATION_MATRIX_EQ(
7571 external_transform, layer->draw_properties().target_space_transform);
7573 external_transform.Translate(20, 20);
7574 host_impl_->SetExternalDrawConstraints(external_transform,
7579 resourceless_software_draw);
7581 EXPECT_TRANSFORMATION_MATRIX_EQ(
7582 external_transform, layer->draw_properties().target_space_transform);
7585 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
7586 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7589 base::TimeTicks start_time =
7590 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7592 EXPECT_EQ(InputHandler::ScrollStarted,
7593 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7595 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
7597 host_impl_->Animate(start_time);
7598 host_impl_->UpdateAnimationState(true);
7600 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->TotalScrollOffset());
7602 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
7603 host_impl_->UpdateAnimationState(true);
7605 float y = scrolling_layer->TotalScrollOffset().y();
7606 EXPECT_TRUE(y > 1 && y < 49);
7609 EXPECT_EQ(InputHandler::ScrollStarted,
7610 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7612 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
7613 host_impl_->UpdateAnimationState(true);
7615 y = scrolling_layer->TotalScrollOffset().y();
7616 EXPECT_TRUE(y > 50 && y < 100);
7617 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
7619 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
7620 host_impl_->UpdateAnimationState(true);
7622 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7623 scrolling_layer->TotalScrollOffset());
7624 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
7627 TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairs) {
7628 host_impl_->CreatePendingTree();
7629 host_impl_->pending_tree()->SetRootLayer(
7630 PictureLayerImpl::Create(host_impl_->pending_tree(), 10));
7632 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
7633 LayerImpl* pending_layer = pending_tree->root_layer();
7635 std::vector<PictureLayerImpl::Pair> layer_pairs;
7636 host_impl_->GetPictureLayerImplPairs(&layer_pairs);
7637 EXPECT_EQ(1u, layer_pairs.size());
7638 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7639 EXPECT_EQ(nullptr, layer_pairs[0].active);
7641 host_impl_->ActivateSyncTree();
7643 LayerTreeImpl* active_tree = host_impl_->active_tree();
7644 LayerImpl* active_layer = active_tree->root_layer();
7645 EXPECT_NE(active_tree, pending_tree);
7646 EXPECT_NE(active_layer, pending_layer);
7647 EXPECT_NE(nullptr, active_tree);
7648 EXPECT_NE(nullptr, active_layer);
7650 host_impl_->CreatePendingTree();
7652 layer_pairs.clear();
7653 host_impl_->GetPictureLayerImplPairs(&layer_pairs);
7654 EXPECT_EQ(1u, layer_pairs.size());
7655 EXPECT_EQ(active_layer, layer_pairs[0].active);
7656 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7658 // Activate, the active layer has no twin now.
7659 host_impl_->ActivateSyncTree();
7661 layer_pairs.clear();
7662 host_impl_->GetPictureLayerImplPairs(&layer_pairs);
7663 EXPECT_EQ(1u, layer_pairs.size());
7664 EXPECT_EQ(active_layer, layer_pairs[0].active);
7665 EXPECT_EQ(nullptr, layer_pairs[0].pending);
7667 // Create another layer in the pending tree that's not in the active tree. We
7668 // should get two pairs.
7669 host_impl_->CreatePendingTree();
7670 host_impl_->pending_tree()->root_layer()->AddChild(
7671 PictureLayerImpl::Create(host_impl_->pending_tree(), 11));
7673 LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[0];
7675 layer_pairs.clear();
7676 host_impl_->GetPictureLayerImplPairs(&layer_pairs);
7677 EXPECT_EQ(2u, layer_pairs.size());
7679 // The pair ordering is flaky, so make it consistent.
7680 if (layer_pairs[0].active != active_layer)
7681 std::swap(layer_pairs[0], layer_pairs[1]);
7683 EXPECT_EQ(active_layer, layer_pairs[0].active);
7684 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7685 EXPECT_EQ(new_pending_layer, layer_pairs[1].pending);
7686 EXPECT_EQ(nullptr, layer_pairs[1].active);
7689 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
7690 host_impl_->CreatePendingTree();
7691 host_impl_->ActivateSyncTree();
7692 host_impl_->CreatePendingTree();
7694 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
7696 scoped_ptr<FakePictureLayerImpl> pending_layer =
7697 FakePictureLayerImpl::Create(pending_tree, 10);
7698 pending_layer->DoPostCommitInitializationIfNeeded();
7699 FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
7700 pending_tree->SetRootLayer(pending_layer.Pass());
7701 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
7703 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
7704 pending_tree->DidBecomeActive();
7705 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7707 scoped_ptr<FakePictureLayerImpl> mask_layer =
7708 FakePictureLayerImpl::Create(pending_tree, 11);
7709 mask_layer->DoPostCommitInitializationIfNeeded();
7710 FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
7711 raw_pending_layer->SetMaskLayer(mask_layer.Pass());
7712 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
7714 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7715 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
7716 pending_tree->DidBecomeActive();
7717 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7718 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7720 scoped_ptr<FakePictureLayerImpl> replica_layer =
7721 FakePictureLayerImpl::Create(pending_tree, 12);
7722 scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
7723 FakePictureLayerImpl::Create(pending_tree, 13);
7724 replica_mask_layer->DoPostCommitInitializationIfNeeded();
7725 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
7726 replica_layer->SetMaskLayer(replica_mask_layer.Pass());
7727 raw_pending_layer->SetReplicaLayer(replica_layer.Pass());
7728 ASSERT_EQ(raw_replica_mask_layer,
7729 raw_pending_layer->replica_layer()->mask_layer());
7731 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7732 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7733 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
7734 pending_tree->DidBecomeActive();
7735 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
7736 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
7737 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
7740 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
7742 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7743 void DidLoseOutputSurfaceOnImplThread() override { num_lost_surfaces_++; }
7746 int num_lost_surfaces_;
7749 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
7750 // Really we just need at least one client notification each time
7751 // we go from having a valid output surface to not having a valid output
7753 EXPECT_EQ(0, num_lost_surfaces_);
7754 host_impl_->DidLoseOutputSurface();
7755 EXPECT_EQ(1, num_lost_surfaces_);
7756 host_impl_->DidLoseOutputSurface();
7757 EXPECT_LE(1, num_lost_surfaces_);