cc: Make a FakeResourceProvider and use it in tests to construct.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blob5c7488cbff7dbb3b31aa5095593a3c482b7e55ec
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"
7 #include <algorithm>
8 #include <cmath>
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/containers/scoped_ptr_hash_map.h"
14 #include "base/location.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "cc/animation/scrollbar_animation_controller_thinning.h"
17 #include "cc/base/math_util.h"
18 #include "cc/input/page_scale_animation.h"
19 #include "cc/input/top_controls_manager.h"
20 #include "cc/layers/append_quads_data.h"
21 #include "cc/layers/delegated_renderer_layer_impl.h"
22 #include "cc/layers/heads_up_display_layer_impl.h"
23 #include "cc/layers/io_surface_layer_impl.h"
24 #include "cc/layers/layer_impl.h"
25 #include "cc/layers/painted_scrollbar_layer_impl.h"
26 #include "cc/layers/render_surface_impl.h"
27 #include "cc/layers/solid_color_layer_impl.h"
28 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
29 #include "cc/layers/texture_layer_impl.h"
30 #include "cc/layers/tiled_layer_impl.h"
31 #include "cc/layers/video_layer_impl.h"
32 #include "cc/output/begin_frame_args.h"
33 #include "cc/output/compositor_frame_ack.h"
34 #include "cc/output/compositor_frame_metadata.h"
35 #include "cc/output/copy_output_request.h"
36 #include "cc/output/copy_output_result.h"
37 #include "cc/output/gl_renderer.h"
38 #include "cc/output/latency_info_swap_promise.h"
39 #include "cc/quads/render_pass_draw_quad.h"
40 #include "cc/quads/solid_color_draw_quad.h"
41 #include "cc/quads/texture_draw_quad.h"
42 #include "cc/quads/tile_draw_quad.h"
43 #include "cc/test/animation_test_common.h"
44 #include "cc/test/begin_frame_args_test.h"
45 #include "cc/test/fake_layer_tree_host_impl.h"
46 #include "cc/test/fake_output_surface.h"
47 #include "cc/test/fake_output_surface_client.h"
48 #include "cc/test/fake_picture_layer_impl.h"
49 #include "cc/test/fake_picture_pile_impl.h"
50 #include "cc/test/fake_proxy.h"
51 #include "cc/test/fake_video_frame_provider.h"
52 #include "cc/test/geometry_test_utils.h"
53 #include "cc/test/gpu_rasterization_enabled_settings.h"
54 #include "cc/test/layer_test_common.h"
55 #include "cc/test/layer_tree_test.h"
56 #include "cc/test/render_pass_test_common.h"
57 #include "cc/test/test_gpu_memory_buffer_manager.h"
58 #include "cc/test/test_shared_bitmap_manager.h"
59 #include "cc/test/test_task_graph_runner.h"
60 #include "cc/test/test_web_graphics_context_3d.h"
61 #include "cc/tiles/layer_tiling_data.h"
62 #include "cc/trees/layer_tree_impl.h"
63 #include "cc/trees/single_thread_proxy.h"
64 #include "media/base/media.h"
65 #include "testing/gmock/include/gmock/gmock.h"
66 #include "testing/gtest/include/gtest/gtest.h"
67 #include "third_party/skia/include/core/SkMallocPixelRef.h"
68 #include "ui/gfx/geometry/rect_conversions.h"
69 #include "ui/gfx/geometry/size_conversions.h"
70 #include "ui/gfx/geometry/vector2d_conversions.h"
72 using ::testing::Mock;
73 using ::testing::Return;
74 using ::testing::AnyNumber;
75 using ::testing::AtLeast;
76 using ::testing::_;
77 using media::VideoFrame;
79 namespace cc {
80 namespace {
82 class LayerTreeHostImplTest : public testing::Test,
83 public LayerTreeHostImplClient {
84 public:
85 LayerTreeHostImplTest()
86 : proxy_(base::ThreadTaskRunnerHandle::Get(),
87 base::ThreadTaskRunnerHandle::Get()),
88 always_impl_thread_(&proxy_),
89 always_main_thread_blocked_(&proxy_),
90 shared_bitmap_manager_(new TestSharedBitmapManager),
91 gpu_memory_buffer_manager_(new TestGpuMemoryBufferManager),
92 task_graph_runner_(new TestTaskGraphRunner),
93 on_can_draw_state_changed_called_(false),
94 did_notify_ready_to_activate_(false),
95 did_request_commit_(false),
96 did_request_redraw_(false),
97 did_request_animate_(false),
98 did_request_prepare_tiles_(false),
99 did_complete_page_scale_animation_(false),
100 reduce_memory_result_(true),
101 current_limit_bytes_(0),
102 current_priority_cutoff_value_(0) {
103 media::InitializeMediaLibraryForTesting();
106 LayerTreeSettings DefaultSettings() {
107 LayerTreeSettings settings;
108 settings.minimum_occlusion_tracking_size = gfx::Size();
109 settings.impl_side_painting = true;
110 settings.renderer_settings.texture_id_allocation_chunk_size = 1;
111 settings.report_overscroll_only_for_scrollable_axes = true;
112 settings.use_pinch_virtual_viewport = true;
113 settings.gpu_rasterization_enabled = true;
114 return settings;
117 void SetUp() override {
118 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
121 void TearDown() override {}
123 void UpdateRendererCapabilitiesOnImplThread() override {}
124 void DidLoseOutputSurfaceOnImplThread() override {}
125 void CommitVSyncParameters(base::TimeTicks timebase,
126 base::TimeDelta interval) override {}
127 void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {}
128 void SetMaxSwapsPendingOnImplThread(int max) override {}
129 void DidSwapBuffersOnImplThread() override {}
130 void DidSwapBuffersCompleteOnImplThread() override {}
131 void OnCanDrawStateChanged(bool can_draw) override {
132 on_can_draw_state_changed_called_ = true;
134 void NotifyReadyToActivate() override {
135 did_notify_ready_to_activate_ = true;
136 host_impl_->ActivateSyncTree();
138 void NotifyReadyToDraw() override {}
139 void SetNeedsRedrawOnImplThread() override { did_request_redraw_ = true; }
140 void SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) override {
141 did_request_redraw_ = true;
143 void SetNeedsAnimateOnImplThread() override { did_request_animate_ = true; }
144 void SetNeedsPrepareTilesOnImplThread() override {
145 did_request_prepare_tiles_ = true;
147 void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; }
148 void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
149 void PostAnimationEventsToMainThreadOnImplThread(
150 scoped_ptr<AnimationEventsVector> events) override {}
151 bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
152 int priority_cutoff) override {
153 current_limit_bytes_ = limit_bytes;
154 current_priority_cutoff_value_ = priority_cutoff;
155 return reduce_memory_result_;
157 bool IsInsideDraw() override { return false; }
158 void RenewTreePriority() override {}
159 void PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
160 base::TimeDelta delay) override {
161 animation_task_ = task;
162 requested_animation_delay_ = delay;
164 void DidActivateSyncTree() override {}
165 void DidPrepareTiles() override {}
166 void DidCompletePageScaleAnimationOnImplThread() override {
167 did_complete_page_scale_animation_ = true;
169 void OnDrawForOutputSurface() override {}
171 void set_reduce_memory_result(bool reduce_memory_result) {
172 reduce_memory_result_ = reduce_memory_result;
175 virtual bool CreateHostImpl(const LayerTreeSettings& settings,
176 scoped_ptr<OutputSurface> output_surface) {
177 host_impl_ = LayerTreeHostImpl::Create(
178 settings, this, &proxy_, &stats_instrumentation_,
179 shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(),
180 task_graph_runner_.get(), 0);
181 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
182 host_impl_->SetViewportSize(gfx::Size(10, 10));
183 return init;
186 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
187 root->SetPosition(gfx::PointF());
188 root->SetBounds(gfx::Size(10, 10));
189 root->SetContentBounds(gfx::Size(10, 10));
190 root->SetDrawsContent(true);
191 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
192 root->SetHasRenderSurface(true);
193 host_impl_->active_tree()->SetRootLayer(root.Pass());
196 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
197 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
198 for (size_t i = 0; i < layer->children().size(); ++i)
199 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
202 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
203 int id,
204 const gfx::Vector2d& scroll_delta) {
205 int times_encountered = 0;
207 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
208 if (scroll_info.scrolls[i].layer_id != id)
209 continue;
210 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
211 times_encountered++;
214 ASSERT_EQ(1, times_encountered);
217 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
218 int times_encountered = 0;
220 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
221 if (scroll_info.scrolls[i].layer_id != id)
222 continue;
223 times_encountered++;
226 ASSERT_EQ(0, times_encountered);
229 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
230 const gfx::Size& content_size) {
231 // Create both an inner viewport scroll layer and an outer viewport scroll
232 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
233 // 0x0, so the scrolls will be applied directly to the inner viewport.
234 const int kOuterViewportClipLayerId = 116;
235 const int kOuterViewportScrollLayerId = 117;
236 const int kContentLayerId = 118;
237 const int kInnerViewportScrollLayerId = 2;
238 const int kInnerViewportClipLayerId = 4;
239 const int kPageScaleLayerId = 5;
241 scoped_ptr<LayerImpl> root =
242 LayerImpl::Create(layer_tree_impl, 1);
243 root->SetBounds(content_size);
244 root->SetContentBounds(content_size);
245 root->SetPosition(gfx::PointF());
246 root->SetHasRenderSurface(true);
248 scoped_ptr<LayerImpl> inner_scroll =
249 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
250 inner_scroll->SetIsContainerForFixedPositionLayers(true);
251 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
253 scoped_ptr<LayerImpl> inner_clip =
254 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
255 inner_clip->SetBounds(
256 gfx::Size(content_size.width() / 2, content_size.height() / 2));
258 scoped_ptr<LayerImpl> page_scale =
259 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
261 inner_scroll->SetScrollClipLayer(inner_clip->id());
262 inner_scroll->SetBounds(content_size);
263 inner_scroll->SetContentBounds(content_size);
264 inner_scroll->SetPosition(gfx::PointF());
266 scoped_ptr<LayerImpl> outer_clip =
267 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
268 outer_clip->SetBounds(content_size);
269 outer_clip->SetIsContainerForFixedPositionLayers(true);
271 scoped_ptr<LayerImpl> outer_scroll =
272 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
273 outer_scroll->SetScrollClipLayer(outer_clip->id());
274 outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
275 outer_scroll->SetBounds(content_size);
276 outer_scroll->SetContentBounds(content_size);
277 outer_scroll->SetPosition(gfx::PointF());
279 scoped_ptr<LayerImpl> contents =
280 LayerImpl::Create(layer_tree_impl, kContentLayerId);
281 contents->SetDrawsContent(true);
282 contents->SetBounds(content_size);
283 contents->SetContentBounds(content_size);
284 contents->SetPosition(gfx::PointF());
286 outer_scroll->AddChild(contents.Pass());
287 outer_clip->AddChild(outer_scroll.Pass());
288 inner_scroll->AddChild(outer_clip.Pass());
289 page_scale->AddChild(inner_scroll.Pass());
290 inner_clip->AddChild(page_scale.Pass());
291 root->AddChild(inner_clip.Pass());
293 layer_tree_impl->SetRootLayer(root.Pass());
294 layer_tree_impl->SetViewportLayersFromIds(
295 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
296 kOuterViewportScrollLayerId);
298 layer_tree_impl->DidBecomeActive();
299 return layer_tree_impl->InnerViewportScrollLayer();
302 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
303 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
304 host_impl_->active_tree(), content_size);
305 host_impl_->active_tree()->DidBecomeActive();
306 return scroll_layer;
309 // TODO(wjmaclean) Add clip-layer pointer to parameters.
310 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
311 const gfx::Size& size,
312 LayerImpl* clip_layer) {
313 DCHECK(clip_layer);
314 DCHECK(id != clip_layer->id());
315 scoped_ptr<LayerImpl> layer =
316 LayerImpl::Create(host_impl_->active_tree(), id);
317 layer->SetScrollClipLayer(clip_layer->id());
318 layer->SetDrawsContent(true);
319 layer->SetBounds(size);
320 layer->SetContentBounds(size);
321 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
322 return layer.Pass();
325 void DrawFrame() {
326 LayerTreeHostImpl::FrameData frame;
327 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
328 host_impl_->DrawLayers(&frame);
329 host_impl_->DidDrawAllLayers(frame);
332 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
333 void pinch_zoom_pan_viewport_test(float device_scale_factor);
334 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
335 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
336 float device_scale_factor);
338 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
339 // Note: It is not possible to disable the renderer once it has been set,
340 // so we do not need to test that disabling the renderer notifies us
341 // that can_draw changed.
342 EXPECT_FALSE(host_impl_->CanDraw());
343 on_can_draw_state_changed_called_ = false;
345 // Set up the root layer, which allows us to draw.
346 SetupScrollAndContentsLayers(gfx::Size(100, 100));
347 EXPECT_TRUE(host_impl_->CanDraw());
348 EXPECT_TRUE(on_can_draw_state_changed_called_);
349 on_can_draw_state_changed_called_ = false;
351 // Toggle the root layer to make sure it toggles can_draw
352 host_impl_->active_tree()->SetRootLayer(nullptr);
353 EXPECT_FALSE(host_impl_->CanDraw());
354 EXPECT_TRUE(on_can_draw_state_changed_called_);
355 on_can_draw_state_changed_called_ = false;
357 SetupScrollAndContentsLayers(gfx::Size(100, 100));
358 EXPECT_TRUE(host_impl_->CanDraw());
359 EXPECT_TRUE(on_can_draw_state_changed_called_);
360 on_can_draw_state_changed_called_ = false;
362 // Toggle the device viewport size to make sure it toggles can_draw.
363 host_impl_->SetViewportSize(gfx::Size());
364 if (always_draw) {
365 EXPECT_TRUE(host_impl_->CanDraw());
366 } else {
367 EXPECT_FALSE(host_impl_->CanDraw());
369 EXPECT_TRUE(on_can_draw_state_changed_called_);
370 on_can_draw_state_changed_called_ = false;
372 host_impl_->SetViewportSize(gfx::Size(100, 100));
373 EXPECT_TRUE(host_impl_->CanDraw());
374 EXPECT_TRUE(on_can_draw_state_changed_called_);
375 on_can_draw_state_changed_called_ = false;
377 // Toggle contents textures purged without causing any evictions,
378 // and make sure that it does not change can_draw.
379 set_reduce_memory_result(false);
380 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
381 host_impl_->memory_allocation_limit_bytes() - 1));
382 EXPECT_TRUE(host_impl_->CanDraw());
383 EXPECT_FALSE(on_can_draw_state_changed_called_);
384 on_can_draw_state_changed_called_ = false;
386 // Toggle contents textures purged to make sure it toggles can_draw.
387 set_reduce_memory_result(true);
388 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
389 host_impl_->memory_allocation_limit_bytes() - 1));
390 if (always_draw) {
391 EXPECT_TRUE(host_impl_->CanDraw());
392 } else {
393 EXPECT_FALSE(host_impl_->CanDraw());
395 EXPECT_TRUE(on_can_draw_state_changed_called_);
396 on_can_draw_state_changed_called_ = false;
398 host_impl_->active_tree()->ResetContentsTexturesPurged();
399 EXPECT_TRUE(host_impl_->CanDraw());
400 EXPECT_TRUE(on_can_draw_state_changed_called_);
401 on_can_draw_state_changed_called_ = false;
404 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
406 protected:
407 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
408 return FakeOutputSurface::Create3d();
411 void DrawOneFrame() {
412 LayerTreeHostImpl::FrameData frame_data;
413 host_impl_->PrepareToDraw(&frame_data);
414 host_impl_->DidDrawAllLayers(frame_data);
417 FakeProxy proxy_;
418 DebugScopedSetImplThread always_impl_thread_;
419 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
421 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
422 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
423 scoped_ptr<TestTaskGraphRunner> task_graph_runner_;
424 scoped_ptr<LayerTreeHostImpl> host_impl_;
425 FakeRenderingStatsInstrumentation stats_instrumentation_;
426 bool on_can_draw_state_changed_called_;
427 bool did_notify_ready_to_activate_;
428 bool did_request_commit_;
429 bool did_request_redraw_;
430 bool did_request_animate_;
431 bool did_request_prepare_tiles_;
432 bool did_complete_page_scale_animation_;
433 bool reduce_memory_result_;
434 base::Closure animation_task_;
435 base::TimeDelta requested_animation_delay_;
436 size_t current_limit_bytes_;
437 int current_priority_cutoff_value_;
440 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
441 bool always_draw = false;
442 CheckNotifyCalledIfCanDrawChanged(always_draw);
445 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
446 CreateHostImpl(DefaultSettings(),
447 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
449 bool always_draw = true;
450 CheckNotifyCalledIfCanDrawChanged(always_draw);
453 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
454 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
456 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
457 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
460 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
462 scoped_ptr<LayerImpl> root =
463 LayerImpl::Create(host_impl_->active_tree(), 1);
464 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
465 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
466 root->children()[1]->AddChild(
467 LayerImpl::Create(host_impl_->active_tree(), 4));
468 root->children()[1]->AddChild(
469 LayerImpl::Create(host_impl_->active_tree(), 5));
470 root->children()[1]->children()[0]->AddChild(
471 LayerImpl::Create(host_impl_->active_tree(), 6));
472 host_impl_->active_tree()->SetRootLayer(root.Pass());
474 LayerImpl* root = host_impl_->active_tree()->root_layer();
476 ExpectClearedScrollDeltasRecursive(root);
478 scoped_ptr<ScrollAndScaleSet> scroll_info;
480 scroll_info = host_impl_->ProcessScrollDeltas();
481 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
482 ExpectClearedScrollDeltasRecursive(root);
484 scroll_info = host_impl_->ProcessScrollDeltas();
485 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
486 ExpectClearedScrollDeltasRecursive(root);
489 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
490 gfx::ScrollOffset scroll_offset(20, 30);
491 gfx::Vector2d scroll_delta(11, -15);
493 scoped_ptr<LayerImpl> root_clip =
494 LayerImpl::Create(host_impl_->active_tree(), 2);
495 scoped_ptr<LayerImpl> root =
496 LayerImpl::Create(host_impl_->active_tree(), 1);
497 root_clip->SetBounds(gfx::Size(10, 10));
498 LayerImpl* root_layer = root.get();
499 root_clip->AddChild(root.Pass());
500 root_layer->SetBounds(gfx::Size(110, 110));
501 root_layer->SetScrollClipLayer(root_clip->id());
502 root_layer->PushScrollOffsetFromMainThread(scroll_offset);
503 root_layer->ScrollBy(scroll_delta);
504 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
506 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
508 scoped_ptr<ScrollAndScaleSet> scroll_info;
510 scroll_info = host_impl_->ProcessScrollDeltas();
511 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
512 ExpectContains(*scroll_info, root->id(), scroll_delta);
514 gfx::Vector2d scroll_delta2(-5, 27);
515 root->ScrollBy(scroll_delta2);
516 scroll_info = host_impl_->ProcessScrollDeltas();
517 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
518 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
520 root->ScrollBy(gfx::Vector2d());
521 scroll_info = host_impl_->ProcessScrollDeltas();
522 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
525 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
526 SetupScrollAndContentsLayers(gfx::Size(100, 100));
527 host_impl_->SetViewportSize(gfx::Size(50, 50));
528 DrawFrame();
530 EXPECT_EQ(InputHandler::SCROLL_STARTED,
531 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
532 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
533 InputHandler::WHEEL));
534 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
535 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
536 InputHandler::WHEEL));
537 host_impl_->ScrollEnd();
538 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
539 InputHandler::WHEEL));
540 EXPECT_TRUE(did_request_redraw_);
541 EXPECT_TRUE(did_request_commit_);
544 TEST_F(LayerTreeHostImplTest, ScrollActiveOnlyAfterScrollMovement) {
545 SetupScrollAndContentsLayers(gfx::Size(100, 100));
546 host_impl_->SetViewportSize(gfx::Size(50, 50));
547 DrawFrame();
549 EXPECT_EQ(InputHandler::SCROLL_STARTED,
550 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
551 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
552 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
553 EXPECT_TRUE(host_impl_->IsActivelyScrolling());
554 host_impl_->ScrollEnd();
555 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
558 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
559 // We should not crash when trying to scroll an empty layer tree.
560 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
561 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
564 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
565 scoped_ptr<TestWebGraphicsContext3D> context_owned =
566 TestWebGraphicsContext3D::Create();
567 context_owned->set_context_lost(true);
569 // Initialization will fail.
570 EXPECT_FALSE(CreateHostImpl(
571 DefaultSettings(), FakeOutputSurface::Create3d(context_owned.Pass())));
573 SetupScrollAndContentsLayers(gfx::Size(100, 100));
575 // We should not crash when trying to scroll after the renderer initialization
576 // fails.
577 EXPECT_EQ(InputHandler::SCROLL_STARTED,
578 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
581 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
582 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
583 host_impl_->SetViewportSize(gfx::Size(50, 50));
584 DrawFrame();
586 // We should not crash if the tree is replaced while we are scrolling.
587 EXPECT_EQ(InputHandler::SCROLL_STARTED,
588 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
589 host_impl_->active_tree()->DetachLayerTree();
591 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
593 // We should still be scrolling, because the scrolled layer also exists in the
594 // new tree.
595 gfx::Vector2d scroll_delta(0, 10);
596 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
597 host_impl_->ScrollEnd();
598 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
599 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
602 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
603 SetupScrollAndContentsLayers(gfx::Size(100, 100));
604 host_impl_->SetViewportSize(gfx::Size(50, 50));
605 DrawFrame();
606 LayerImpl* root = host_impl_->active_tree()->root_layer();
608 // With registered event handlers, wheel scrolls don't necessarily
609 // have to go to the main thread.
610 root->SetHaveWheelEventHandlers(true);
611 EXPECT_EQ(InputHandler::SCROLL_STARTED,
612 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
613 host_impl_->ScrollEnd();
615 // But typically the scroll-blocks-on mode will require them to.
616 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
617 SCROLL_BLOCKS_ON_START_TOUCH);
618 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
619 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
621 // But gesture scrolls can still be handled.
622 EXPECT_EQ(InputHandler::SCROLL_STARTED,
623 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
624 host_impl_->ScrollEnd();
626 // And if the handlers go away, wheel scrolls can again be processed
627 // on impl (despite the scroll-blocks-on mode).
628 root->SetHaveWheelEventHandlers(false);
629 EXPECT_EQ(InputHandler::SCROLL_STARTED,
630 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
631 host_impl_->ScrollEnd();
634 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
635 LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
636 host_impl_->SetViewportSize(gfx::Size(50, 50));
637 DrawFrame();
638 LayerImpl* root = host_impl_->active_tree()->root_layer();
640 LayerImpl* child = 0;
642 scoped_ptr<LayerImpl> child_layer =
643 LayerImpl::Create(host_impl_->active_tree(), 6);
644 child = child_layer.get();
645 child_layer->SetDrawsContent(true);
646 child_layer->SetPosition(gfx::PointF(0, 20));
647 child_layer->SetBounds(gfx::Size(50, 50));
648 child_layer->SetContentBounds(gfx::Size(50, 50));
649 scroll->AddChild(child_layer.Pass());
652 // Touch handler regions determine whether touch events block scroll.
653 root->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
654 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
655 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH |
656 SCROLL_BLOCKS_ON_WHEEL_EVENT);
657 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
659 // But they don't influence the actual handling of the scroll gestures.
660 EXPECT_EQ(InputHandler::SCROLL_STARTED,
661 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
662 host_impl_->ScrollEnd();
664 // It's the union of scroll-blocks-on mode bits across all layers in the
665 // scroll paret chain that matters.
666 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
667 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE);
668 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
669 child->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH);
670 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
673 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnScrollEventHandlers) {
674 SetupScrollAndContentsLayers(gfx::Size(100, 100));
675 host_impl_->SetViewportSize(gfx::Size(50, 50));
676 DrawFrame();
677 LayerImpl* root = host_impl_->active_tree()->root_layer();
679 // With registered scroll handlers, scrolls don't generally have to go
680 // to the main thread.
681 root->SetHaveScrollEventHandlers(true);
682 EXPECT_EQ(InputHandler::SCROLL_STARTED,
683 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
684 host_impl_->ScrollEnd();
686 // Even the default scroll blocks on mode doesn't require this.
687 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
688 SCROLL_BLOCKS_ON_START_TOUCH);
689 EXPECT_EQ(InputHandler::SCROLL_STARTED,
690 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
691 host_impl_->ScrollEnd();
693 // But the page can opt in to blocking on scroll event handlers.
694 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
695 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
696 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
698 // GESTURE and WHEEL scrolls behave identically in this regard.
699 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
700 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
702 // And if the handlers go away, scrolls can again be processed on impl
703 // (despite the scroll-blocks-on mode).
704 root->SetHaveScrollEventHandlers(false);
705 EXPECT_EQ(InputHandler::SCROLL_STARTED,
706 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
707 host_impl_->ScrollEnd();
710 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) {
711 host_impl_->SetViewportSize(gfx::Size(50, 50));
713 // Create a normal scrollable root layer
714 LayerImpl* root_scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
715 LayerImpl* root_child = root_scroll->children()[0];
716 LayerImpl* root = host_impl_->active_tree()->root_layer();
717 DrawFrame();
719 // Create two child scrollable layers
720 LayerImpl* child1 = 0;
722 scoped_ptr<LayerImpl> scrollable_child_clip_1 =
723 LayerImpl::Create(host_impl_->active_tree(), 6);
724 scoped_ptr<LayerImpl> scrollable_child_1 = CreateScrollableLayer(
725 7, gfx::Size(10, 10), scrollable_child_clip_1.get());
726 child1 = scrollable_child_1.get();
727 scrollable_child_1->SetPosition(gfx::Point(5, 5));
728 scrollable_child_1->SetHaveWheelEventHandlers(true);
729 scrollable_child_1->SetHaveScrollEventHandlers(true);
730 scrollable_child_clip_1->AddChild(scrollable_child_1.Pass());
731 root_child->AddChild(scrollable_child_clip_1.Pass());
734 LayerImpl* child2 = 0;
736 scoped_ptr<LayerImpl> scrollable_child_clip_2 =
737 LayerImpl::Create(host_impl_->active_tree(), 8);
738 scoped_ptr<LayerImpl> scrollable_child_2 = CreateScrollableLayer(
739 9, gfx::Size(10, 10), scrollable_child_clip_2.get());
740 child2 = scrollable_child_2.get();
741 scrollable_child_2->SetPosition(gfx::Point(5, 20));
742 scrollable_child_2->SetHaveWheelEventHandlers(true);
743 scrollable_child_2->SetHaveScrollEventHandlers(true);
744 scrollable_child_clip_2->AddChild(scrollable_child_2.Pass());
745 root_child->AddChild(scrollable_child_clip_2.Pass());
748 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
749 EXPECT_EQ(InputHandler::SCROLL_STARTED,
750 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
751 host_impl_->ScrollEnd();
752 child1->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
753 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
754 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
756 // But not those that hit only other layers.
757 EXPECT_EQ(InputHandler::SCROLL_STARTED,
758 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
759 host_impl_->ScrollEnd();
761 // It's the union of bits set across the scroll ancestor chain that matters.
762 EXPECT_EQ(InputHandler::SCROLL_STARTED,
763 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
764 host_impl_->ScrollEnd();
765 EXPECT_EQ(InputHandler::SCROLL_STARTED,
766 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
767 host_impl_->ScrollEnd();
768 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT);
769 EXPECT_EQ(InputHandler::SCROLL_STARTED,
770 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
771 host_impl_->ScrollEnd();
772 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
773 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
774 child2->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
775 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
776 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
777 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
778 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
781 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
782 SetupScrollAndContentsLayers(gfx::Size(100, 100));
783 host_impl_->SetViewportSize(gfx::Size(50, 50));
784 DrawFrame();
786 // Ignore the fling since no layer is being scrolled
787 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
789 // Start scrolling a layer
790 EXPECT_EQ(InputHandler::SCROLL_STARTED,
791 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
793 // Now the fling should go ahead since we've started scrolling a layer
794 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
797 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
798 SetupScrollAndContentsLayers(gfx::Size(100, 100));
799 host_impl_->SetViewportSize(gfx::Size(50, 50));
800 DrawFrame();
802 // Ignore the fling since no layer is being scrolled
803 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
805 // Start scrolling a layer
806 EXPECT_EQ(InputHandler::SCROLL_STARTED,
807 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
809 // Now the fling should go ahead since we've started scrolling a layer
810 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
813 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
814 SetupScrollAndContentsLayers(gfx::Size(100, 100));
815 host_impl_->SetViewportSize(gfx::Size(50, 50));
816 DrawFrame();
817 LayerImpl* root = host_impl_->active_tree()->root_layer();
819 root->SetShouldScrollOnMainThread(true);
821 // Start scrolling a layer
822 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
823 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
825 // The fling should be ignored since there's no layer being scrolled impl-side
826 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
829 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
830 SetupScrollAndContentsLayers(gfx::Size(100, 100));
831 host_impl_->SetViewportSize(gfx::Size(50, 50));
832 DrawFrame();
833 LayerImpl* root = host_impl_->active_tree()->root_layer();
835 root->SetShouldScrollOnMainThread(true);
837 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
838 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
839 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
840 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
843 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
844 SetupScrollAndContentsLayers(gfx::Size(200, 200));
845 host_impl_->SetViewportSize(gfx::Size(100, 100));
847 LayerImpl* root = host_impl_->active_tree()->root_layer();
848 root->SetContentsScale(2.f, 2.f);
849 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
851 DrawFrame();
853 // All scroll types inside the non-fast scrollable region should fail.
854 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
855 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL));
856 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
857 InputHandler::WHEEL));
858 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
859 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE));
860 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
861 InputHandler::GESTURE));
863 // All scroll types outside this region should succeed.
864 EXPECT_EQ(InputHandler::SCROLL_STARTED,
865 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL));
866 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
867 InputHandler::GESTURE));
868 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
869 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
870 InputHandler::GESTURE));
871 host_impl_->ScrollEnd();
872 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
873 InputHandler::GESTURE));
874 EXPECT_EQ(InputHandler::SCROLL_STARTED,
875 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE));
876 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
877 InputHandler::GESTURE));
878 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
879 host_impl_->ScrollEnd();
880 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
881 InputHandler::GESTURE));
884 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
885 SetupScrollAndContentsLayers(gfx::Size(200, 200));
886 host_impl_->SetViewportSize(gfx::Size(100, 100));
888 LayerImpl* root = host_impl_->active_tree()->root_layer();
889 root->SetContentsScale(2.f, 2.f);
890 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
891 root->SetPosition(gfx::PointF(-25.f, 0.f));
893 DrawFrame();
895 // This point would fall into the non-fast scrollable region except that we've
896 // moved the layer down by 25 pixels.
897 EXPECT_EQ(InputHandler::SCROLL_STARTED,
898 host_impl_->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL));
899 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
900 InputHandler::WHEEL));
901 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
902 host_impl_->ScrollEnd();
904 // This point is still inside the non-fast region.
905 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
906 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL));
909 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
910 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
911 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
912 host_impl_->SetViewportSize(gfx::Size(50, 50));
913 DrawFrame();
915 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
916 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
917 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
918 host_impl_->ScrollEnd();
919 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
922 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
923 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
924 scroll_layer->SetHaveScrollEventHandlers(true);
925 host_impl_->SetViewportSize(gfx::Size(50, 50));
926 DrawFrame();
928 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
929 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
930 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
931 host_impl_->ScrollEnd();
932 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
935 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
936 SetupScrollAndContentsLayers(gfx::Size(200, 200));
937 host_impl_->SetViewportSize(gfx::Size(100, 100));
939 DrawFrame();
941 EXPECT_EQ(InputHandler::SCROLL_STARTED,
942 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
944 // Trying to scroll to the left/top will not succeed.
945 EXPECT_FALSE(
946 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
947 EXPECT_FALSE(
948 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
949 EXPECT_FALSE(
950 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
952 // Scrolling to the right/bottom will succeed.
953 EXPECT_TRUE(
954 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll);
955 EXPECT_TRUE(
956 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
957 EXPECT_TRUE(
958 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll);
960 // Scrolling to left/top will now succeed.
961 EXPECT_TRUE(
962 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
963 EXPECT_TRUE(
964 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
965 EXPECT_TRUE(
966 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
968 // Scrolling diagonally against an edge will succeed.
969 EXPECT_TRUE(
970 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll);
971 EXPECT_TRUE(
972 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
973 EXPECT_TRUE(
974 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll);
976 // Trying to scroll more than the available space will also succeed.
977 EXPECT_TRUE(
978 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll);
981 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
982 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
983 host_impl_->SetViewportSize(gfx::Size(100, 1000));
985 DrawFrame();
987 EXPECT_EQ(InputHandler::SCROLL_STARTED,
988 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
990 // Trying to scroll without a vertical scrollbar will fail.
991 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
992 gfx::Point(), SCROLL_FORWARD));
993 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
994 gfx::Point(), SCROLL_BACKWARD));
996 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
997 PaintedScrollbarLayerImpl::Create(
998 host_impl_->active_tree(),
1000 VERTICAL));
1001 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
1002 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
1003 vertical_scrollbar.get());
1005 // Trying to scroll with a vertical scrollbar will succeed.
1006 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
1007 gfx::Point(), SCROLL_FORWARD));
1008 EXPECT_FLOAT_EQ(875.f,
1009 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
1010 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
1011 gfx::Point(), SCROLL_BACKWARD));
1014 TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
1015 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
1016 host_impl_->SetViewportSize(gfx::Size(100, 100));
1018 gfx::Size overflow_size(400, 400);
1019 ASSERT_EQ(1u, scroll_layer->children().size());
1020 LayerImpl* overflow = scroll_layer->children()[0];
1021 overflow->SetBounds(overflow_size);
1022 overflow->SetContentBounds(overflow_size);
1023 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
1024 overflow->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1025 overflow->SetPosition(gfx::PointF());
1027 DrawFrame();
1028 gfx::Point scroll_position(10, 10);
1030 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1031 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1032 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1033 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->CurrentScrollOffset());
1035 gfx::Vector2dF scroll_delta(10, 10);
1036 host_impl_->ScrollBy(scroll_position, scroll_delta);
1037 host_impl_->ScrollEnd();
1038 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1039 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1041 overflow->set_user_scrollable_horizontal(false);
1043 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1044 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1045 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1046 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1048 host_impl_->ScrollBy(scroll_position, scroll_delta);
1049 host_impl_->ScrollEnd();
1050 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1051 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1053 overflow->set_user_scrollable_vertical(false);
1055 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1056 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1057 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1058 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1060 host_impl_->ScrollBy(scroll_position, scroll_delta);
1061 host_impl_->ScrollEnd();
1062 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->CurrentScrollOffset());
1063 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1066 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
1067 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
1068 host_impl_->SetViewportSize(gfx::Size(50, 50));
1069 DrawFrame();
1071 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
1072 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
1073 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1075 float min_page_scale = 1.f, max_page_scale = 4.f;
1076 float page_scale_factor = 1.f;
1078 // The impl-based pinch zoom should adjust the max scroll position.
1080 host_impl_->active_tree()->PushPageScaleFromMainThread(
1081 page_scale_factor, min_page_scale, max_page_scale);
1082 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1083 scroll_layer->SetScrollDelta(gfx::Vector2d());
1085 float page_scale_delta = 2.f;
1087 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1088 host_impl_->PinchGestureBegin();
1089 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1090 host_impl_->PinchGestureEnd();
1091 host_impl_->ScrollEnd();
1092 EXPECT_FALSE(did_request_animate_);
1093 EXPECT_TRUE(did_request_redraw_);
1094 EXPECT_TRUE(did_request_commit_);
1095 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1097 scoped_ptr<ScrollAndScaleSet> scroll_info =
1098 host_impl_->ProcessScrollDeltas();
1099 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1101 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1102 scroll_layer->MaxScrollOffset().ToString());
1105 // Scrolling after a pinch gesture should always be in local space. The
1106 // scroll deltas have the page scale factor applied.
1108 host_impl_->active_tree()->PushPageScaleFromMainThread(
1109 page_scale_factor, min_page_scale, max_page_scale);
1110 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1111 scroll_layer->SetScrollDelta(gfx::Vector2d());
1113 float page_scale_delta = 2.f;
1114 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1115 host_impl_->PinchGestureBegin();
1116 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1117 host_impl_->PinchGestureEnd();
1118 host_impl_->ScrollEnd();
1120 gfx::Vector2d scroll_delta(0, 10);
1121 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1122 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
1123 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
1124 host_impl_->ScrollEnd();
1126 scoped_ptr<ScrollAndScaleSet> scroll_info =
1127 host_impl_->ProcessScrollDeltas();
1128 ExpectContains(*scroll_info.get(), scroll_layer->id(),
1129 gfx::Vector2d(0, scroll_delta.y() / page_scale_delta));
1133 TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) {
1134 LayerImpl* inner_scroll_layer =
1135 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1137 // Adjust the content layer to be larger than the outer viewport container so
1138 // that we get scrolling in both viewports.
1139 LayerImpl* content_layer =
1140 host_impl_->OuterViewportScrollLayer()->children().back();
1141 LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
1142 LayerImpl* inner_clip_layer =
1143 host_impl_->InnerViewportScrollLayer()->parent()->parent();
1144 inner_clip_layer->SetBounds(gfx::Size(100, 100));
1145 inner_clip_layer->SetContentBounds(gfx::Size(100, 100));
1146 outer_scroll_layer->SetBounds(gfx::Size(200, 200));
1147 outer_scroll_layer->SetContentBounds(gfx::Size(200, 200));
1148 content_layer->SetBounds(gfx::Size(200, 200));
1149 content_layer->SetContentBounds(gfx::Size(200, 200));
1151 host_impl_->SetViewportSize(gfx::Size(100, 100));
1153 DrawFrame();
1155 // Zoom into the page by a 2X factor
1156 float min_page_scale = 1.f, max_page_scale = 4.f;
1157 float page_scale_factor = 2.f;
1158 host_impl_->active_tree()->PushPageScaleFromMainThread(
1159 page_scale_factor, min_page_scale, max_page_scale);
1160 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1162 // Scroll by a small amount, there should be no bubbling up to the inner
1163 // viewport.
1164 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1165 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f, 20.f));
1166 host_impl_->ScrollEnd();
1168 EXPECT_VECTOR_EQ(
1169 gfx::Vector2dF(5, 10),
1170 outer_scroll_layer->CurrentScrollOffset());
1171 EXPECT_VECTOR_EQ(
1172 gfx::Vector2dF(),
1173 inner_scroll_layer->CurrentScrollOffset());
1175 // Scroll by the outer viewport's max scroll extent, there the remainder
1176 // should bubble up to the inner viewport.
1177 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1178 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(200.f, 200.f));
1179 host_impl_->ScrollEnd();
1181 EXPECT_VECTOR_EQ(
1182 gfx::Vector2dF(100, 100),
1183 outer_scroll_layer->CurrentScrollOffset());
1184 EXPECT_VECTOR_EQ(
1185 gfx::Vector2dF(5, 10),
1186 inner_scroll_layer->CurrentScrollOffset());
1188 // Scroll by the inner viewport's max scroll extent, it should all go to the
1189 // inner viewport.
1190 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1191 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(90.f, 80.f));
1192 host_impl_->ScrollEnd();
1194 EXPECT_VECTOR_EQ(
1195 gfx::Vector2dF(100, 100),
1196 outer_scroll_layer->CurrentScrollOffset());
1197 EXPECT_VECTOR_EQ(
1198 gfx::Vector2dF(50, 50),
1199 inner_scroll_layer->CurrentScrollOffset());
1202 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
1203 ui::LatencyInfo latency_info;
1204 latency_info.trace_id = 1234;
1205 scoped_ptr<SwapPromise> swap_promise(
1206 new LatencyInfoSwapPromise(latency_info));
1208 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1209 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1210 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
1211 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1212 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
1213 host_impl_->ScrollEnd();
1215 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
1216 EXPECT_EQ(1u, scroll_info->swap_promises.size());
1217 EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId());
1220 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1221 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1222 host_impl_->SetViewportSize(gfx::Size(50, 50));
1223 DrawFrame();
1225 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1226 DCHECK(scroll_layer);
1228 float min_page_scale = 1.f;
1229 float max_page_scale = 4.f;
1231 // Basic pinch zoom in gesture
1233 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1234 max_page_scale);
1235 scroll_layer->SetScrollDelta(gfx::Vector2d());
1237 float page_scale_delta = 2.f;
1238 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1239 host_impl_->PinchGestureBegin();
1240 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1241 host_impl_->PinchGestureEnd();
1242 host_impl_->ScrollEnd();
1243 EXPECT_FALSE(did_request_animate_);
1244 EXPECT_TRUE(did_request_redraw_);
1245 EXPECT_TRUE(did_request_commit_);
1247 scoped_ptr<ScrollAndScaleSet> scroll_info =
1248 host_impl_->ProcessScrollDeltas();
1249 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1252 // Zoom-in clamping
1254 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1255 max_page_scale);
1256 scroll_layer->SetScrollDelta(gfx::Vector2d());
1257 float page_scale_delta = 10.f;
1259 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1260 host_impl_->PinchGestureBegin();
1261 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1262 host_impl_->PinchGestureEnd();
1263 host_impl_->ScrollEnd();
1265 scoped_ptr<ScrollAndScaleSet> scroll_info =
1266 host_impl_->ProcessScrollDeltas();
1267 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1270 // Zoom-out clamping
1272 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1273 max_page_scale);
1274 scroll_layer->SetScrollDelta(gfx::Vector2d());
1275 scroll_layer->PullDeltaForMainThread();
1276 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1278 float page_scale_delta = 0.1f;
1279 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1280 host_impl_->PinchGestureBegin();
1281 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1282 host_impl_->PinchGestureEnd();
1283 host_impl_->ScrollEnd();
1285 scoped_ptr<ScrollAndScaleSet> scroll_info =
1286 host_impl_->ProcessScrollDeltas();
1287 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1289 EXPECT_TRUE(scroll_info->scrolls.empty());
1292 // Two-finger panning should not happen based on pinch events only
1294 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1295 max_page_scale);
1296 scroll_layer->SetScrollDelta(gfx::Vector2d());
1297 scroll_layer->PullDeltaForMainThread();
1298 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1300 float page_scale_delta = 1.f;
1301 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1302 host_impl_->PinchGestureBegin();
1303 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1304 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1305 host_impl_->PinchGestureEnd();
1306 host_impl_->ScrollEnd();
1308 scoped_ptr<ScrollAndScaleSet> scroll_info =
1309 host_impl_->ProcessScrollDeltas();
1310 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1311 EXPECT_TRUE(scroll_info->scrolls.empty());
1314 // Two-finger panning should work with interleaved scroll events
1316 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1317 max_page_scale);
1318 scroll_layer->SetScrollDelta(gfx::Vector2d());
1319 scroll_layer->PullDeltaForMainThread();
1320 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1322 float page_scale_delta = 1.f;
1323 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1324 host_impl_->PinchGestureBegin();
1325 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1326 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1327 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1328 host_impl_->PinchGestureEnd();
1329 host_impl_->ScrollEnd();
1331 scoped_ptr<ScrollAndScaleSet> scroll_info =
1332 host_impl_->ProcessScrollDeltas();
1333 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1334 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1337 // Two-finger panning should work when starting fully zoomed out.
1339 host_impl_->active_tree()->PushPageScaleFromMainThread(0.5f, 0.5f, 4.f);
1340 scroll_layer->SetScrollDelta(gfx::Vector2d());
1341 scroll_layer->PullDeltaForMainThread();
1342 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1344 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1345 host_impl_->PinchGestureBegin();
1346 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1347 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1348 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1349 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1350 host_impl_->PinchGestureEnd();
1351 host_impl_->ScrollEnd();
1353 scoped_ptr<ScrollAndScaleSet> scroll_info =
1354 host_impl_->ProcessScrollDeltas();
1355 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1356 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1360 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1361 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1362 host_impl_->SetViewportSize(gfx::Size(50, 50));
1363 DrawFrame();
1365 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1366 DCHECK(scroll_layer);
1368 float min_page_scale = 0.5f;
1369 float max_page_scale = 4.f;
1370 base::TimeTicks start_time = base::TimeTicks() +
1371 base::TimeDelta::FromSeconds(1);
1372 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1373 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1374 base::TimeTicks end_time = start_time + duration;
1376 // Non-anchor zoom-in
1378 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1379 max_page_scale);
1380 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1382 did_request_redraw_ = false;
1383 did_request_animate_ = false;
1384 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1385 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1386 gfx::Vector2d(),
1387 false,
1388 2.f,
1389 duration)));
1390 host_impl_->ActivateSyncTree();
1391 EXPECT_FALSE(did_request_redraw_);
1392 EXPECT_TRUE(did_request_animate_);
1394 did_request_redraw_ = false;
1395 did_request_animate_ = false;
1396 host_impl_->Animate(start_time);
1397 EXPECT_TRUE(did_request_redraw_);
1398 EXPECT_TRUE(did_request_animate_);
1400 did_request_redraw_ = false;
1401 did_request_animate_ = false;
1402 host_impl_->Animate(halfway_through_animation);
1403 EXPECT_TRUE(did_request_redraw_);
1404 EXPECT_TRUE(did_request_animate_);
1406 did_request_redraw_ = false;
1407 did_request_animate_ = false;
1408 did_request_commit_ = false;
1409 host_impl_->Animate(end_time);
1410 EXPECT_TRUE(did_request_commit_);
1411 EXPECT_FALSE(did_request_animate_);
1413 scoped_ptr<ScrollAndScaleSet> scroll_info =
1414 host_impl_->ProcessScrollDeltas();
1415 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1416 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1419 // Anchor zoom-out
1421 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1422 max_page_scale);
1423 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1425 did_request_redraw_ = false;
1426 did_request_animate_ = false;
1427 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1428 scoped_ptr<PendingPageScaleAnimation> (new PendingPageScaleAnimation(
1429 gfx::Vector2d(25, 25),
1430 true,
1431 min_page_scale,
1432 duration)));
1433 host_impl_->ActivateSyncTree();
1434 EXPECT_FALSE(did_request_redraw_);
1435 EXPECT_TRUE(did_request_animate_);
1437 did_request_redraw_ = false;
1438 did_request_animate_ = false;
1439 host_impl_->Animate(start_time);
1440 EXPECT_TRUE(did_request_redraw_);
1441 EXPECT_TRUE(did_request_animate_);
1443 did_request_redraw_ = false;
1444 did_request_commit_ = false;
1445 did_request_animate_ = false;
1446 host_impl_->Animate(end_time);
1447 EXPECT_TRUE(did_request_redraw_);
1448 EXPECT_FALSE(did_request_animate_);
1449 EXPECT_TRUE(did_request_commit_);
1451 scoped_ptr<ScrollAndScaleSet> scroll_info =
1452 host_impl_->ProcessScrollDeltas();
1453 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1454 // Pushed to (0,0) via clamping against contents layer size.
1455 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1459 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1460 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1461 host_impl_->SetViewportSize(gfx::Size(50, 50));
1462 DrawFrame();
1464 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1465 DCHECK(scroll_layer);
1467 float min_page_scale = 0.5f;
1468 float max_page_scale = 4.f;
1469 base::TimeTicks start_time = base::TimeTicks() +
1470 base::TimeDelta::FromSeconds(1);
1471 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1472 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1473 base::TimeTicks end_time = start_time + duration;
1475 // Anchor zoom with unchanged page scale should not change scroll or scale.
1477 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1478 max_page_scale);
1479 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1481 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1482 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1483 gfx::Vector2d(),
1484 true,
1485 1.f,
1486 duration)));
1487 host_impl_->ActivateSyncTree();
1488 host_impl_->Animate(start_time);
1489 host_impl_->Animate(halfway_through_animation);
1490 EXPECT_TRUE(did_request_redraw_);
1491 host_impl_->Animate(end_time);
1492 EXPECT_TRUE(did_request_commit_);
1494 scoped_ptr<ScrollAndScaleSet> scroll_info =
1495 host_impl_->ProcessScrollDeltas();
1496 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1497 ExpectNone(*scroll_info, scroll_layer->id());
1501 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
1502 host_impl_->CreatePendingTree();
1503 CreateScrollAndContentsLayers(
1504 host_impl_->pending_tree(),
1505 gfx::Size(100, 100));
1506 host_impl_->ActivateSyncTree();
1507 DrawFrame();
1509 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1510 DCHECK(scroll_layer);
1512 float min_page_scale = 0.5f;
1513 float max_page_scale = 4.f;
1514 host_impl_->sync_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1515 max_page_scale);
1516 host_impl_->ActivateSyncTree();
1518 base::TimeTicks start_time = base::TimeTicks() +
1519 base::TimeDelta::FromSeconds(1);
1520 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1521 base::TimeTicks third_through_animation = start_time + duration / 3;
1522 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1523 base::TimeTicks end_time = start_time + duration;
1524 float target_scale = 2.f;
1526 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1528 // Make sure TakePageScaleAnimation works properly.
1530 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1531 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1532 gfx::Vector2d(),
1533 false,
1534 target_scale,
1535 duration)));
1536 scoped_ptr<PendingPageScaleAnimation> psa =
1537 host_impl_->sync_tree()->TakePendingPageScaleAnimation();
1538 EXPECT_EQ(target_scale, psa->scale);
1539 EXPECT_EQ(duration, psa->duration);
1540 EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePendingPageScaleAnimation());
1542 // Recreate the PSA. Nothing should happen here since the tree containing the
1543 // PSA hasn't been activated yet.
1544 did_request_redraw_ = false;
1545 did_request_animate_ = false;
1546 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1547 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1548 gfx::Vector2d(),
1549 false,
1550 target_scale,
1551 duration)));
1552 host_impl_->Animate(halfway_through_animation);
1553 EXPECT_FALSE(did_request_animate_);
1554 EXPECT_FALSE(did_request_redraw_);
1556 // Activate the sync tree. This should cause the animation to become enabled.
1557 // It should also clear the pointer on the sync tree.
1558 host_impl_->ActivateSyncTree();
1559 EXPECT_EQ(nullptr,
1560 host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
1561 EXPECT_FALSE(did_request_redraw_);
1562 EXPECT_TRUE(did_request_animate_);
1564 // From here on, make sure the animation runs as normal.
1565 did_request_redraw_ = false;
1566 did_request_animate_ = false;
1567 host_impl_->Animate(start_time);
1568 EXPECT_TRUE(did_request_redraw_);
1569 EXPECT_TRUE(did_request_animate_);
1571 did_request_redraw_ = false;
1572 did_request_animate_ = false;
1573 host_impl_->Animate(third_through_animation);
1574 EXPECT_TRUE(did_request_redraw_);
1575 EXPECT_TRUE(did_request_animate_);
1577 // Another activation shouldn't have any effect on the animation.
1578 host_impl_->ActivateSyncTree();
1580 did_request_redraw_ = false;
1581 did_request_animate_ = false;
1582 host_impl_->Animate(halfway_through_animation);
1583 EXPECT_TRUE(did_request_redraw_);
1584 EXPECT_TRUE(did_request_animate_);
1586 did_request_redraw_ = false;
1587 did_request_animate_ = false;
1588 did_request_commit_ = false;
1589 host_impl_->Animate(end_time);
1590 EXPECT_TRUE(did_request_commit_);
1591 EXPECT_FALSE(did_request_animate_);
1593 scoped_ptr<ScrollAndScaleSet> scroll_info =
1594 host_impl_->ProcessScrollDeltas();
1595 EXPECT_EQ(scroll_info->page_scale_delta, target_scale);
1596 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1599 TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) {
1600 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1601 host_impl_->SetViewportSize(gfx::Size(50, 50));
1602 DrawFrame();
1604 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1605 DCHECK(scroll_layer);
1607 base::TimeTicks start_time =
1608 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
1609 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1610 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1611 base::TimeTicks end_time = start_time + duration;
1613 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
1614 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1616 did_complete_page_scale_animation_ = false;
1617 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1618 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1619 gfx::Vector2d(), false, 2.f, duration)));
1620 host_impl_->ActivateSyncTree();
1621 host_impl_->Animate(start_time);
1622 EXPECT_FALSE(did_complete_page_scale_animation_);
1624 host_impl_->Animate(halfway_through_animation);
1625 EXPECT_FALSE(did_complete_page_scale_animation_);
1627 host_impl_->Animate(end_time);
1628 EXPECT_TRUE(did_complete_page_scale_animation_);
1631 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1632 public:
1633 LayerTreeHostImplOverridePhysicalTime(
1634 const LayerTreeSettings& settings,
1635 LayerTreeHostImplClient* client,
1636 Proxy* proxy,
1637 SharedBitmapManager* manager,
1638 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1639 : LayerTreeHostImpl(settings,
1640 client,
1641 proxy,
1642 rendering_stats_instrumentation,
1643 manager,
1644 NULL,
1645 NULL,
1646 0) {}
1648 BeginFrameArgs CurrentBeginFrameArgs() const override {
1649 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
1650 fake_current_physical_time_);
1653 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1654 fake_current_physical_time_ = fake_now;
1657 private:
1658 base::TimeTicks fake_current_physical_time_;
1661 class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
1662 protected:
1663 void SetupLayers(LayerTreeSettings settings) {
1664 gfx::Size viewport_size(10, 10);
1665 gfx::Size content_size(100, 100);
1667 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
1668 new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_,
1669 shared_bitmap_manager_.get(),
1670 &stats_instrumentation_);
1671 host_impl_ = make_scoped_ptr(host_impl_override_time);
1672 host_impl_->InitializeRenderer(CreateOutputSurface());
1673 host_impl_->SetViewportSize(viewport_size);
1675 scoped_ptr<LayerImpl> root =
1676 LayerImpl::Create(host_impl_->active_tree(), 1);
1677 root->SetBounds(viewport_size);
1679 scoped_ptr<LayerImpl> scroll =
1680 LayerImpl::Create(host_impl_->active_tree(), 2);
1681 scroll->SetScrollClipLayer(root->id());
1682 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1683 root->SetBounds(viewport_size);
1684 scroll->SetBounds(content_size);
1685 scroll->SetContentBounds(content_size);
1686 scroll->SetIsContainerForFixedPositionLayers(true);
1688 scoped_ptr<LayerImpl> contents =
1689 LayerImpl::Create(host_impl_->active_tree(), 3);
1690 contents->SetDrawsContent(true);
1691 contents->SetBounds(content_size);
1692 contents->SetContentBounds(content_size);
1694 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
1695 SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4,
1696 VERTICAL, 10, 0, false, true);
1697 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());
1699 scroll->AddChild(contents.Pass());
1700 root->AddChild(scroll.Pass());
1701 root->SetHasRenderSurface(true);
1702 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1703 root->AddChild(scrollbar.Pass());
1705 host_impl_->active_tree()->SetRootLayer(root.Pass());
1706 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
1707 Layer::INVALID_ID);
1708 host_impl_->active_tree()->DidBecomeActive();
1709 DrawFrame();
1712 void RunTest(LayerTreeSettings::ScrollbarAnimator animator) {
1713 LayerTreeSettings settings;
1714 settings.scrollbar_animator = animator;
1715 settings.scrollbar_fade_delay_ms = 20;
1716 settings.scrollbar_fade_duration_ms = 20;
1718 SetupLayers(settings);
1720 base::TimeTicks fake_now = base::TimeTicks::Now();
1722 EXPECT_FALSE(did_request_animate_);
1723 EXPECT_FALSE(did_request_redraw_);
1724 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1725 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1727 // If no scroll happened during a scroll gesture, it should have no effect.
1728 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1729 host_impl_->ScrollEnd();
1730 EXPECT_FALSE(did_request_animate_);
1731 EXPECT_FALSE(did_request_redraw_);
1732 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1733 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1735 // After a scroll, a scrollbar animation should be scheduled about 20ms from
1736 // now.
1737 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1738 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1739 EXPECT_FALSE(did_request_animate_);
1740 EXPECT_TRUE(did_request_redraw_);
1741 did_request_redraw_ = false;
1742 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1743 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1745 host_impl_->ScrollEnd();
1746 EXPECT_FALSE(did_request_animate_);
1747 EXPECT_FALSE(did_request_redraw_);
1748 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1749 requested_animation_delay_);
1750 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1752 fake_now += requested_animation_delay_;
1753 requested_animation_delay_ = base::TimeDelta();
1754 animation_task_.Run();
1755 animation_task_ = base::Closure();
1756 EXPECT_TRUE(did_request_animate_);
1757 did_request_animate_ = false;
1758 EXPECT_FALSE(did_request_redraw_);
1760 // After the scrollbar animation begins, we should start getting redraws.
1761 host_impl_->Animate(fake_now);
1762 EXPECT_TRUE(did_request_animate_);
1763 did_request_animate_ = false;
1764 EXPECT_TRUE(did_request_redraw_);
1765 did_request_redraw_ = false;
1766 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1767 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1769 // Setting the scroll offset outside a scroll should also cause the
1770 // scrollbar to appear and to schedule a scrollbar animation.
1771 host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
1772 gfx::ScrollOffset(5, 5));
1773 EXPECT_FALSE(did_request_animate_);
1774 EXPECT_FALSE(did_request_redraw_);
1775 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1776 requested_animation_delay_);
1777 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1778 requested_animation_delay_ = base::TimeDelta();
1779 animation_task_ = base::Closure();
1781 // Scrollbar animation is not triggered unnecessarily.
1782 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1783 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1784 EXPECT_FALSE(did_request_animate_);
1785 EXPECT_TRUE(did_request_redraw_);
1786 did_request_redraw_ = false;
1787 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1788 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1790 host_impl_->ScrollEnd();
1791 EXPECT_FALSE(did_request_animate_);
1792 EXPECT_FALSE(did_request_redraw_);
1793 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1794 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1796 // Changing page scale triggers scrollbar animation.
1797 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
1798 host_impl_->SetPageScaleOnActiveTree(1.1f);
1799 EXPECT_FALSE(did_request_animate_);
1800 EXPECT_FALSE(did_request_redraw_);
1801 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1802 requested_animation_delay_);
1803 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1804 requested_animation_delay_ = base::TimeDelta();
1805 animation_task_ = base::Closure();
1809 TEST_F(LayerTreeHostImplTestScrollbarAnimation, LinearFade) {
1810 RunTest(LayerTreeSettings::LINEAR_FADE);
1813 TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) {
1814 RunTest(LayerTreeSettings::THINNING);
1817 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1818 float device_scale_factor) {
1819 LayerTreeSettings settings;
1820 settings.scrollbar_fade_delay_ms = 500;
1821 settings.scrollbar_fade_duration_ms = 300;
1822 settings.scrollbar_animator = LayerTreeSettings::THINNING;
1824 gfx::Size viewport_size(300, 200);
1825 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1826 gfx::ScaleSize(viewport_size, device_scale_factor));
1827 gfx::Size content_size(1000, 1000);
1829 CreateHostImpl(settings, CreateOutputSurface());
1830 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1831 host_impl_->SetViewportSize(device_viewport_size);
1833 scoped_ptr<LayerImpl> root =
1834 LayerImpl::Create(host_impl_->active_tree(), 1);
1835 root->SetBounds(viewport_size);
1836 root->SetHasRenderSurface(true);
1838 scoped_ptr<LayerImpl> scroll =
1839 LayerImpl::Create(host_impl_->active_tree(), 2);
1840 scroll->SetScrollClipLayer(root->id());
1841 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1842 scroll->SetBounds(content_size);
1843 scroll->SetContentBounds(content_size);
1844 scroll->SetIsContainerForFixedPositionLayers(true);
1846 scoped_ptr<LayerImpl> contents =
1847 LayerImpl::Create(host_impl_->active_tree(), 3);
1848 contents->SetDrawsContent(true);
1849 contents->SetBounds(content_size);
1850 contents->SetContentBounds(content_size);
1852 // The scrollbar is on the right side.
1853 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1854 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1855 scrollbar->SetDrawsContent(true);
1856 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1857 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1858 scrollbar->SetPosition(gfx::Point(285, 0));
1860 scroll->AddChild(contents.Pass());
1861 root->AddChild(scroll.Pass());
1862 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1863 root->AddChild(scrollbar.Pass());
1865 host_impl_->active_tree()->SetRootLayer(root.Pass());
1866 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
1867 Layer::INVALID_ID);
1868 host_impl_->active_tree()->DidBecomeActive();
1869 DrawFrame();
1871 LayerImpl* root_scroll =
1872 host_impl_->active_tree()->InnerViewportScrollLayer();
1873 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1874 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1875 static_cast<ScrollbarAnimationControllerThinning*>(
1876 root_scroll->scrollbar_animation_controller());
1877 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1879 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1880 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1882 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1883 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1885 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1886 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1888 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1889 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1890 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1892 did_request_redraw_ = false;
1893 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1894 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1895 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1896 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1897 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1898 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1899 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1902 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1903 SetupMouseMoveAtWithDeviceScale(1.f);
1906 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1907 SetupMouseMoveAtWithDeviceScale(2.f);
1910 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1911 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1912 host_impl_->SetViewportSize(gfx::Size(50, 50));
1913 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
1914 DrawFrame();
1916 CompositorFrameMetadata metadata =
1917 host_impl_->MakeCompositorFrameMetadata();
1918 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1919 EXPECT_EQ(1.f, metadata.page_scale_factor);
1920 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
1921 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1922 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1923 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1924 EXPECT_FALSE(metadata.root_overflow_x_hidden);
1925 EXPECT_FALSE(metadata.root_overflow_y_hidden);
1928 // Scrolling should update metadata immediately.
1929 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1930 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
1931 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1933 CompositorFrameMetadata metadata =
1934 host_impl_->MakeCompositorFrameMetadata();
1935 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1937 host_impl_->ScrollEnd();
1939 CompositorFrameMetadata metadata =
1940 host_impl_->MakeCompositorFrameMetadata();
1941 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1944 // Root "overflow: hidden" properties should be reflected on the outer
1945 // viewport scroll layer.
1947 host_impl_->active_tree()
1948 ->OuterViewportScrollLayer()
1949 ->set_user_scrollable_horizontal(false);
1950 CompositorFrameMetadata metadata =
1951 host_impl_->MakeCompositorFrameMetadata();
1952 EXPECT_TRUE(metadata.root_overflow_x_hidden);
1953 EXPECT_FALSE(metadata.root_overflow_y_hidden);
1955 host_impl_->active_tree()
1956 ->OuterViewportScrollLayer()
1957 ->set_user_scrollable_vertical(false);
1958 metadata = host_impl_->MakeCompositorFrameMetadata();
1959 EXPECT_TRUE(metadata.root_overflow_x_hidden);
1960 EXPECT_TRUE(metadata.root_overflow_y_hidden);
1963 // Page scale should update metadata correctly (shrinking only the viewport).
1964 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1965 host_impl_->PinchGestureBegin();
1966 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1967 host_impl_->PinchGestureEnd();
1968 host_impl_->ScrollEnd();
1970 CompositorFrameMetadata metadata =
1971 host_impl_->MakeCompositorFrameMetadata();
1972 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1973 EXPECT_EQ(2.f, metadata.page_scale_factor);
1974 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
1975 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1976 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1977 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1980 // Likewise if set from the main thread.
1981 host_impl_->ProcessScrollDeltas();
1982 host_impl_->active_tree()->PushPageScaleFromMainThread(4.f, 0.5f, 4.f);
1983 host_impl_->SetPageScaleOnActiveTree(4.f);
1985 CompositorFrameMetadata metadata =
1986 host_impl_->MakeCompositorFrameMetadata();
1987 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1988 EXPECT_EQ(4.f, metadata.page_scale_factor);
1989 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
1990 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1991 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1992 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1996 class DidDrawCheckLayer : public LayerImpl {
1997 public:
1998 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1999 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl, id));
2002 bool WillDraw(DrawMode draw_mode, ResourceProvider* provider) override {
2003 will_draw_called_ = true;
2004 if (will_draw_returns_false_)
2005 return false;
2006 return LayerImpl::WillDraw(draw_mode, provider);
2009 void AppendQuads(RenderPass* render_pass,
2010 AppendQuadsData* append_quads_data) override {
2011 append_quads_called_ = true;
2012 LayerImpl::AppendQuads(render_pass, append_quads_data);
2015 void DidDraw(ResourceProvider* provider) override {
2016 did_draw_called_ = true;
2017 LayerImpl::DidDraw(provider);
2020 bool will_draw_called() const { return will_draw_called_; }
2021 bool append_quads_called() const { return append_quads_called_; }
2022 bool did_draw_called() const { return did_draw_called_; }
2024 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
2026 void ClearDidDrawCheck() {
2027 will_draw_called_ = false;
2028 append_quads_called_ = false;
2029 did_draw_called_ = false;
2032 static void IgnoreResult(scoped_ptr<CopyOutputResult> result) {}
2034 void AddCopyRequest() {
2035 ScopedPtrVector<CopyOutputRequest> requests;
2036 requests.push_back(
2037 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult)));
2038 SetHasRenderSurface(true);
2039 PassCopyRequests(&requests);
2042 protected:
2043 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
2044 : LayerImpl(tree_impl, id),
2045 will_draw_returns_false_(false),
2046 will_draw_called_(false),
2047 append_quads_called_(false),
2048 did_draw_called_(false) {
2049 SetBounds(gfx::Size(10, 10));
2050 SetContentBounds(gfx::Size(10, 10));
2051 SetDrawsContent(true);
2052 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
2055 private:
2056 bool will_draw_returns_false_;
2057 bool will_draw_called_;
2058 bool append_quads_called_;
2059 bool did_draw_called_;
2062 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
2063 // The root layer is always drawn, so run this test on a child layer that
2064 // will be masked out by the root layer's bounds.
2065 host_impl_->active_tree()->SetRootLayer(
2066 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2067 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2068 host_impl_->active_tree()->root_layer());
2070 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2071 root->SetHasRenderSurface(true);
2072 DidDrawCheckLayer* layer =
2073 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2076 LayerTreeHostImpl::FrameData frame;
2077 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2078 host_impl_->DrawLayers(&frame);
2079 host_impl_->DidDrawAllLayers(frame);
2081 EXPECT_TRUE(layer->will_draw_called());
2082 EXPECT_TRUE(layer->append_quads_called());
2083 EXPECT_TRUE(layer->did_draw_called());
2086 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
2089 LayerTreeHostImpl::FrameData frame;
2091 layer->set_will_draw_returns_false();
2092 layer->ClearDidDrawCheck();
2094 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2095 host_impl_->DrawLayers(&frame);
2096 host_impl_->DidDrawAllLayers(frame);
2098 EXPECT_TRUE(layer->will_draw_called());
2099 EXPECT_FALSE(layer->append_quads_called());
2100 EXPECT_FALSE(layer->did_draw_called());
2104 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
2105 // The root layer is always drawn, so run this test on a child layer that
2106 // will be masked out by the root layer's bounds.
2107 host_impl_->active_tree()->SetRootLayer(
2108 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2109 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2110 host_impl_->active_tree()->root_layer());
2111 root->SetMasksToBounds(true);
2112 root->SetHasRenderSurface(true);
2113 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2114 DidDrawCheckLayer* layer =
2115 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2116 // Ensure visible_content_rect for layer is empty.
2117 layer->SetPosition(gfx::PointF(100.f, 100.f));
2118 layer->SetBounds(gfx::Size(10, 10));
2119 layer->SetContentBounds(gfx::Size(10, 10));
2121 LayerTreeHostImpl::FrameData frame;
2123 EXPECT_FALSE(layer->will_draw_called());
2124 EXPECT_FALSE(layer->did_draw_called());
2126 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2127 host_impl_->DrawLayers(&frame);
2128 host_impl_->DidDrawAllLayers(frame);
2130 EXPECT_FALSE(layer->will_draw_called());
2131 EXPECT_FALSE(layer->did_draw_called());
2133 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
2135 // Ensure visible_content_rect for layer is not empty
2136 layer->SetPosition(gfx::PointF());
2138 EXPECT_FALSE(layer->will_draw_called());
2139 EXPECT_FALSE(layer->did_draw_called());
2141 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2142 host_impl_->DrawLayers(&frame);
2143 host_impl_->DidDrawAllLayers(frame);
2145 EXPECT_TRUE(layer->will_draw_called());
2146 EXPECT_TRUE(layer->did_draw_called());
2148 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
2151 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
2152 gfx::Size big_size(1000, 1000);
2153 host_impl_->SetViewportSize(big_size);
2155 host_impl_->active_tree()->SetRootLayer(
2156 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2157 DidDrawCheckLayer* root =
2158 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2160 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2161 DidDrawCheckLayer* occluded_layer =
2162 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2164 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2165 root->SetHasRenderSurface(true);
2166 DidDrawCheckLayer* top_layer =
2167 static_cast<DidDrawCheckLayer*>(root->children()[1]);
2168 // This layer covers the occluded_layer above. Make this layer large so it can
2169 // occlude.
2170 top_layer->SetBounds(big_size);
2171 top_layer->SetContentBounds(big_size);
2172 top_layer->SetContentsOpaque(true);
2174 LayerTreeHostImpl::FrameData frame;
2176 EXPECT_FALSE(occluded_layer->will_draw_called());
2177 EXPECT_FALSE(occluded_layer->did_draw_called());
2178 EXPECT_FALSE(top_layer->will_draw_called());
2179 EXPECT_FALSE(top_layer->did_draw_called());
2181 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2182 host_impl_->DrawLayers(&frame);
2183 host_impl_->DidDrawAllLayers(frame);
2185 EXPECT_FALSE(occluded_layer->will_draw_called());
2186 EXPECT_FALSE(occluded_layer->did_draw_called());
2187 EXPECT_TRUE(top_layer->will_draw_called());
2188 EXPECT_TRUE(top_layer->did_draw_called());
2191 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
2192 host_impl_->active_tree()->SetRootLayer(
2193 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2194 DidDrawCheckLayer* root =
2195 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2197 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2198 root->SetHasRenderSurface(true);
2199 DidDrawCheckLayer* layer1 =
2200 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2202 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2203 DidDrawCheckLayer* layer2 =
2204 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
2206 layer1->SetHasRenderSurface(true);
2207 layer1->SetShouldFlattenTransform(true);
2209 EXPECT_FALSE(root->did_draw_called());
2210 EXPECT_FALSE(layer1->did_draw_called());
2211 EXPECT_FALSE(layer2->did_draw_called());
2213 LayerTreeHostImpl::FrameData frame;
2214 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2215 host_impl_->active_tree()->root_layer());
2216 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2217 host_impl_->DrawLayers(&frame);
2218 host_impl_->DidDrawAllLayers(frame);
2220 EXPECT_TRUE(root->did_draw_called());
2221 EXPECT_TRUE(layer1->did_draw_called());
2222 EXPECT_TRUE(layer2->did_draw_called());
2224 EXPECT_NE(root->render_surface(), layer1->render_surface());
2225 EXPECT_TRUE(layer1->render_surface());
2228 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
2229 public:
2230 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
2231 int id,
2232 bool tile_missing,
2233 bool had_incomplete_tile,
2234 bool animating,
2235 ResourceProvider* resource_provider) {
2236 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl,
2238 tile_missing,
2239 had_incomplete_tile,
2240 animating,
2241 resource_provider));
2244 void AppendQuads(RenderPass* render_pass,
2245 AppendQuadsData* append_quads_data) override {
2246 LayerImpl::AppendQuads(render_pass, append_quads_data);
2247 if (had_incomplete_tile_)
2248 append_quads_data->num_incomplete_tiles++;
2249 if (tile_missing_)
2250 append_quads_data->num_missing_tiles++;
2253 private:
2254 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
2255 int id,
2256 bool tile_missing,
2257 bool had_incomplete_tile,
2258 bool animating,
2259 ResourceProvider* resource_provider)
2260 : DidDrawCheckLayer(tree_impl, id),
2261 tile_missing_(tile_missing),
2262 had_incomplete_tile_(had_incomplete_tile) {
2263 if (animating)
2264 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2267 bool tile_missing_;
2268 bool had_incomplete_tile_;
2271 struct PrepareToDrawSuccessTestCase {
2272 struct State {
2273 bool has_missing_tile = false;
2274 bool has_incomplete_tile = false;
2275 bool is_animating = false;
2276 bool has_copy_request = false;
2278 bool high_res_required = false;
2279 State layer_before;
2280 State layer_between;
2281 State layer_after;
2282 DrawResult expected_result;
2284 explicit PrepareToDrawSuccessTestCase(DrawResult result)
2285 : expected_result(result) {}
2288 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) {
2289 std::vector<PrepareToDrawSuccessTestCase> cases;
2291 // 0. Default case.
2292 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2293 // 1. Animated layer first.
2294 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2295 cases.back().layer_before.is_animating = true;
2296 // 2. Animated layer between.
2297 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2298 cases.back().layer_between.is_animating = true;
2299 // 3. Animated layer last.
2300 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2301 cases.back().layer_after.is_animating = true;
2302 // 4. Missing tile first.
2303 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2304 cases.back().layer_before.has_missing_tile = true;
2305 // 5. Missing tile between.
2306 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2307 cases.back().layer_between.has_missing_tile = true;
2308 // 6. Missing tile last.
2309 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2310 cases.back().layer_after.has_missing_tile = true;
2311 // 7. Incomplete tile first.
2312 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2313 cases.back().layer_before.has_incomplete_tile = true;
2314 // 8. Incomplete tile between.
2315 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2316 cases.back().layer_between.has_incomplete_tile = true;
2317 // 9. Incomplete tile last.
2318 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2319 cases.back().layer_after.has_incomplete_tile = true;
2320 // 10. Animation with missing tile.
2321 cases.push_back(
2322 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS));
2323 cases.back().layer_between.has_missing_tile = true;
2324 cases.back().layer_between.is_animating = true;
2325 // 11. Animation with incomplete tile.
2326 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2327 cases.back().layer_between.has_incomplete_tile = true;
2328 cases.back().layer_between.is_animating = true;
2330 // 12. High res required.
2331 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2332 cases.back().high_res_required = true;
2333 // 13. High res required with incomplete tile.
2334 cases.push_back(
2335 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2336 cases.back().high_res_required = true;
2337 cases.back().layer_between.has_incomplete_tile = true;
2338 // 14. High res required with missing tile.
2339 cases.push_back(
2340 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2341 cases.back().high_res_required = true;
2342 cases.back().layer_between.has_missing_tile = true;
2344 // 15. High res required is higher priority than animating missing tiles.
2345 cases.push_back(
2346 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2347 cases.back().high_res_required = true;
2348 cases.back().layer_between.has_missing_tile = true;
2349 cases.back().layer_after.has_missing_tile = true;
2350 cases.back().layer_after.is_animating = true;
2351 // 16. High res required is higher priority than animating missing tiles.
2352 cases.push_back(
2353 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2354 cases.back().high_res_required = true;
2355 cases.back().layer_between.has_missing_tile = true;
2356 cases.back().layer_before.has_missing_tile = true;
2357 cases.back().layer_before.is_animating = true;
2359 host_impl_->active_tree()->SetRootLayer(
2360 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2361 DidDrawCheckLayer* root =
2362 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2363 root->SetHasRenderSurface(true);
2365 LayerTreeHostImpl::FrameData frame;
2366 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2367 host_impl_->DrawLayers(&frame);
2368 host_impl_->DidDrawAllLayers(frame);
2369 host_impl_->SwapBuffers(frame);
2371 for (size_t i = 0; i < cases.size(); ++i) {
2372 const auto& testcase = cases[i];
2373 std::vector<LayerImpl*> to_remove;
2374 for (auto* child : root->children())
2375 to_remove.push_back(child);
2376 for (auto* child : to_remove)
2377 root->RemoveChild(child);
2379 std::ostringstream scope;
2380 scope << "Test case: " << i;
2381 SCOPED_TRACE(scope.str());
2383 root->AddChild(MissingTextureAnimatingLayer::Create(
2384 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2385 testcase.layer_before.has_incomplete_tile,
2386 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2387 DidDrawCheckLayer* before =
2388 static_cast<DidDrawCheckLayer*>(root->children().back());
2389 if (testcase.layer_before.has_copy_request)
2390 before->AddCopyRequest();
2392 root->AddChild(MissingTextureAnimatingLayer::Create(
2393 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2394 testcase.layer_between.has_incomplete_tile,
2395 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2396 DidDrawCheckLayer* between =
2397 static_cast<DidDrawCheckLayer*>(root->children().back());
2398 if (testcase.layer_between.has_copy_request)
2399 between->AddCopyRequest();
2401 root->AddChild(MissingTextureAnimatingLayer::Create(
2402 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2403 testcase.layer_after.has_incomplete_tile,
2404 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2405 DidDrawCheckLayer* after =
2406 static_cast<DidDrawCheckLayer*>(root->children().back());
2407 if (testcase.layer_after.has_copy_request)
2408 after->AddCopyRequest();
2410 if (testcase.high_res_required)
2411 host_impl_->SetRequiresHighResToDraw();
2413 LayerTreeHostImpl::FrameData frame;
2414 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2415 host_impl_->DrawLayers(&frame);
2416 host_impl_->DidDrawAllLayers(frame);
2417 host_impl_->SwapBuffers(frame);
2421 TEST_F(LayerTreeHostImplTest,
2422 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) {
2423 CreateHostImpl(DefaultSettings(),
2424 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2425 EXPECT_TRUE(host_impl_->output_surface()
2426 ->capabilities()
2427 .draw_and_swap_full_viewport_every_frame);
2429 std::vector<PrepareToDrawSuccessTestCase> cases;
2431 // 0. Default case.
2432 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2433 // 1. Animation with missing tile.
2434 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2435 cases.back().layer_between.has_missing_tile = true;
2436 cases.back().layer_between.is_animating = true;
2437 // 2. High res required with incomplete tile.
2438 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2439 cases.back().high_res_required = true;
2440 cases.back().layer_between.has_incomplete_tile = true;
2441 // 3. High res required with missing tile.
2442 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2443 cases.back().high_res_required = true;
2444 cases.back().layer_between.has_missing_tile = true;
2446 host_impl_->active_tree()->SetRootLayer(
2447 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2448 DidDrawCheckLayer* root =
2449 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2450 root->SetHasRenderSurface(true);
2452 LayerTreeHostImpl::FrameData frame;
2453 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2454 host_impl_->DrawLayers(&frame);
2455 host_impl_->DidDrawAllLayers(frame);
2456 host_impl_->SwapBuffers(frame);
2458 for (size_t i = 0; i < cases.size(); ++i) {
2459 const auto& testcase = cases[i];
2460 std::vector<LayerImpl*> to_remove;
2461 for (auto* child : root->children())
2462 to_remove.push_back(child);
2463 for (auto* child : to_remove)
2464 root->RemoveChild(child);
2466 std::ostringstream scope;
2467 scope << "Test case: " << i;
2468 SCOPED_TRACE(scope.str());
2470 root->AddChild(MissingTextureAnimatingLayer::Create(
2471 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2472 testcase.layer_before.has_incomplete_tile,
2473 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2474 DidDrawCheckLayer* before =
2475 static_cast<DidDrawCheckLayer*>(root->children().back());
2476 if (testcase.layer_before.has_copy_request)
2477 before->AddCopyRequest();
2479 root->AddChild(MissingTextureAnimatingLayer::Create(
2480 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2481 testcase.layer_between.has_incomplete_tile,
2482 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2483 DidDrawCheckLayer* between =
2484 static_cast<DidDrawCheckLayer*>(root->children().back());
2485 if (testcase.layer_between.has_copy_request)
2486 between->AddCopyRequest();
2488 root->AddChild(MissingTextureAnimatingLayer::Create(
2489 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2490 testcase.layer_after.has_incomplete_tile,
2491 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2492 DidDrawCheckLayer* after =
2493 static_cast<DidDrawCheckLayer*>(root->children().back());
2494 if (testcase.layer_after.has_copy_request)
2495 after->AddCopyRequest();
2497 if (testcase.high_res_required)
2498 host_impl_->SetRequiresHighResToDraw();
2500 LayerTreeHostImpl::FrameData frame;
2501 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2502 host_impl_->DrawLayers(&frame);
2503 host_impl_->DidDrawAllLayers(frame);
2504 host_impl_->SwapBuffers(frame);
2508 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2509 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2510 root->SetScrollClipLayer(Layer::INVALID_ID);
2511 root->SetHasRenderSurface(true);
2512 host_impl_->active_tree()->SetRootLayer(root.Pass());
2513 DrawFrame();
2515 // Scroll event is ignored because layer is not scrollable.
2516 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
2517 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
2518 EXPECT_FALSE(did_request_redraw_);
2519 EXPECT_FALSE(did_request_commit_);
2522 // TODO(bokan): Convert these tests to create inner and outer viewports.
2523 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2524 public:
2525 LayerTreeHostImplTopControlsTest()
2526 // Make the clip size the same as the layer (content) size so the layer is
2527 // non-scrollable.
2528 : layer_size_(10, 10),
2529 clip_size_(layer_size_),
2530 top_controls_height_(50) {
2531 settings_.use_pinch_virtual_viewport = true;
2533 viewport_size_ = gfx::Size(clip_size_.width(),
2534 clip_size_.height() + top_controls_height_);
2537 bool CreateHostImpl(const LayerTreeSettings& settings,
2538 scoped_ptr<OutputSurface> output_surface) override {
2539 bool init =
2540 LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass());
2541 if (init) {
2542 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
2543 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
2545 return init;
2548 void SetupTopControlsAndScrollLayer() {
2549 scoped_ptr<LayerImpl> root =
2550 LayerImpl::Create(host_impl_->active_tree(), 1);
2551 scoped_ptr<LayerImpl> root_clip =
2552 LayerImpl::Create(host_impl_->active_tree(), 2);
2553 root_clip->SetBounds(clip_size_);
2554 root->SetScrollClipLayer(root_clip->id());
2555 root->SetBounds(layer_size_);
2556 root->SetContentBounds(layer_size_);
2557 root->SetPosition(gfx::PointF());
2558 root->SetDrawsContent(false);
2559 root->SetIsContainerForFixedPositionLayers(true);
2560 int inner_viewport_scroll_layer_id = root->id();
2561 int page_scale_layer_id = root_clip->id();
2562 root_clip->SetHasRenderSurface(true);
2563 root_clip->AddChild(root.Pass());
2564 root_clip->SetHasRenderSurface(true);
2565 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2566 host_impl_->active_tree()->SetViewportLayersFromIds(
2567 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2568 Layer::INVALID_ID);
2569 // Set a viewport size that is large enough to contain both the top controls
2570 // and some content.
2571 host_impl_->SetViewportSize(viewport_size_);
2572 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2574 host_impl_->DidChangeTopControlsPosition();
2576 host_impl_->CreatePendingTree();
2577 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
2578 root =
2579 LayerImpl::Create(host_impl_->sync_tree(), 1);
2580 root_clip =
2581 LayerImpl::Create(host_impl_->sync_tree(), 2);
2582 root_clip->SetBounds(clip_size_);
2583 root->SetScrollClipLayer(root_clip->id());
2584 root->SetBounds(layer_size_);
2585 root->SetContentBounds(layer_size_);
2586 root->SetPosition(gfx::PointF());
2587 root->SetDrawsContent(false);
2588 root->SetIsContainerForFixedPositionLayers(true);
2589 inner_viewport_scroll_layer_id = root->id();
2590 page_scale_layer_id = root_clip->id();
2591 root_clip->AddChild(root.Pass());
2592 host_impl_->sync_tree()->SetRootLayer(root_clip.Pass());
2593 host_impl_->sync_tree()->SetViewportLayersFromIds(
2594 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2595 Layer::INVALID_ID);
2596 // Set a viewport size that is large enough to contain both the top controls
2597 // and some content.
2598 host_impl_->SetViewportSize(viewport_size_);
2599 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2600 host_impl_->DidChangeTopControlsPosition();
2603 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2604 const gfx::Size& inner_viewport_size,
2605 const gfx::Size& outer_viewport_size,
2606 const gfx::Size& scroll_layer_size) {
2607 CreateHostImpl(settings_, CreateOutputSurface());
2608 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2609 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
2610 host_impl_->DidChangeTopControlsPosition();
2612 scoped_ptr<LayerImpl> root =
2613 LayerImpl::Create(host_impl_->active_tree(), 1);
2614 scoped_ptr<LayerImpl> root_clip =
2615 LayerImpl::Create(host_impl_->active_tree(), 2);
2616 scoped_ptr<LayerImpl> page_scale =
2617 LayerImpl::Create(host_impl_->active_tree(), 3);
2619 scoped_ptr<LayerImpl> outer_scroll =
2620 LayerImpl::Create(host_impl_->active_tree(), 4);
2621 scoped_ptr<LayerImpl> outer_clip =
2622 LayerImpl::Create(host_impl_->active_tree(), 5);
2624 root_clip->SetBounds(inner_viewport_size);
2625 root->SetScrollClipLayer(root_clip->id());
2626 root->SetBounds(outer_viewport_size);
2627 root->SetContentBounds(outer_viewport_size);
2628 root->SetPosition(gfx::PointF());
2629 root->SetDrawsContent(false);
2630 root->SetIsContainerForFixedPositionLayers(true);
2631 root_clip->SetHasRenderSurface(true);
2632 outer_clip->SetBounds(outer_viewport_size);
2633 outer_scroll->SetScrollClipLayer(outer_clip->id());
2634 outer_scroll->SetBounds(scroll_layer_size);
2635 outer_scroll->SetContentBounds(scroll_layer_size);
2636 outer_scroll->SetPosition(gfx::PointF());
2637 outer_scroll->SetDrawsContent(false);
2638 outer_scroll->SetIsContainerForFixedPositionLayers(true);
2640 int inner_viewport_scroll_layer_id = root->id();
2641 int outer_viewport_scroll_layer_id = outer_scroll->id();
2642 int page_scale_layer_id = page_scale->id();
2644 outer_clip->AddChild(outer_scroll.Pass());
2645 root->AddChild(outer_clip.Pass());
2646 page_scale->AddChild(root.Pass());
2647 root_clip->AddChild(page_scale.Pass());
2649 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2650 host_impl_->active_tree()->SetViewportLayersFromIds(
2651 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2652 outer_viewport_scroll_layer_id);
2654 host_impl_->SetViewportSize(inner_viewport_size);
2655 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2656 EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds());
2659 protected:
2660 gfx::Size layer_size_;
2661 gfx::Size clip_size_;
2662 gfx::Size viewport_size_;
2663 float top_controls_height_;
2665 LayerTreeSettings settings_;
2666 }; // class LayerTreeHostImplTopControlsTest
2668 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2669 SetupTopControlsAndScrollLayerWithVirtualViewport(
2670 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2671 DrawFrame();
2673 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2674 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2676 // Make the test scroll delta a fractional amount, to verify that the
2677 // fixed container size delta is (1) non-zero, and (2) fractional, and
2678 // (3) matches the movement of the top controls.
2679 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2680 host_impl_->top_controls_manager()->ScrollBegin();
2681 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2682 host_impl_->top_controls_manager()->ScrollEnd();
2684 LayerImpl* inner_viewport_scroll_layer =
2685 host_impl_->active_tree()->InnerViewportScrollLayer();
2686 DCHECK(inner_viewport_scroll_layer);
2687 host_impl_->ScrollEnd();
2688 EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
2689 inner_viewport_scroll_layer->FixedContainerSizeDelta().y());
2692 // In this test, the outer viewport is initially unscrollable. We test that a
2693 // scroll initiated on the inner viewport, causing the top controls to show and
2694 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2695 TEST_F(LayerTreeHostImplTopControlsTest,
2696 TopControlsOuterViewportBecomesScrollable) {
2697 SetupTopControlsAndScrollLayerWithVirtualViewport(
2698 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2699 DrawFrame();
2701 LayerImpl* inner_scroll =
2702 host_impl_->active_tree()->InnerViewportScrollLayer();
2703 LayerImpl* inner_container =
2704 host_impl_->active_tree()->InnerViewportContainerLayer();
2705 LayerImpl* outer_scroll =
2706 host_impl_->active_tree()->OuterViewportScrollLayer();
2707 LayerImpl* outer_container =
2708 host_impl_->active_tree()->OuterViewportContainerLayer();
2710 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2711 outer_scroll->SetDrawsContent(true);
2712 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 1.f, 2.f);
2714 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2715 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2716 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 50.f));
2718 // The entire scroll delta should have been used to hide the top controls.
2719 // The viewport layers should be resized back to their full sizes.
2720 EXPECT_EQ(0.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2721 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
2722 EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height());
2723 EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height());
2725 // The inner viewport should be scrollable by 50px * page_scale.
2726 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 100.f));
2727 EXPECT_EQ(50.f, inner_scroll->CurrentScrollOffset().y());
2728 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2729 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset());
2731 host_impl_->ScrollEnd();
2733 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2734 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2735 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
2737 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2739 // The entire scroll delta should have been used to show the top controls.
2740 // The outer viewport should be resized to accomodate and scrolled to the
2741 // bottom of the document to keep the viewport in place.
2742 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2743 EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height());
2744 EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height());
2745 EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
2746 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2748 // Now when we continue scrolling, make sure the outer viewport gets scrolled
2749 // since it wasn't scrollable when the scroll began.
2750 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f));
2751 EXPECT_EQ(15.f, outer_scroll->CurrentScrollOffset().y());
2752 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2754 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f));
2755 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2756 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2758 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2759 host_impl_->ScrollEnd();
2761 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2762 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
2765 // Test that the fixed position container delta is appropriately adjusted
2766 // by the top controls showing/hiding and page scale doesn't affect it.
2767 TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
2768 SetupTopControlsAndScrollLayerWithVirtualViewport(
2769 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
2770 DrawFrame();
2772 float page_scale = 1.5f;
2773 LayerImpl* outer_viewport_scroll_layer =
2774 host_impl_->active_tree()->OuterViewportScrollLayer();
2776 // Zoom in, since the fixed container is the outer viewport, the delta should
2777 // not be scaled.
2778 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
2780 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2781 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2783 // Scroll down, the top controls hiding should expand the viewport size so
2784 // the delta should be equal to the scroll distance.
2785 gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
2786 host_impl_->top_controls_manager()->ScrollBegin();
2787 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2788 EXPECT_FLOAT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
2789 host_impl_->top_controls_manager()->ContentTopOffset());
2790 EXPECT_VECTOR_EQ(top_controls_scroll_delta,
2791 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2792 host_impl_->ScrollEnd();
2794 // Scroll past the maximum extent. The delta shouldn't be greater than the
2795 // top controls height.
2796 host_impl_->top_controls_manager()->ScrollBegin();
2797 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2798 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2799 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2800 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2801 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_),
2802 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2803 host_impl_->ScrollEnd();
2805 // Scroll in the direction to make the top controls show.
2806 host_impl_->top_controls_manager()->ScrollBegin();
2807 host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta);
2808 EXPECT_EQ(top_controls_scroll_delta.y(),
2809 host_impl_->top_controls_manager()->ContentTopOffset());
2810 EXPECT_VECTOR_EQ(
2811 gfx::Vector2dF(0, top_controls_height_ - top_controls_scroll_delta.y()),
2812 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2813 host_impl_->top_controls_manager()->ScrollEnd();
2816 // Test that if a scrollable sublayer doesn't consume the scroll,
2817 // top controls should hide when scrolling down.
2818 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) {
2819 gfx::Size sub_content_size(100, 400);
2820 gfx::Size sub_content_layer_size(100, 300);
2821 SetupTopControlsAndScrollLayerWithVirtualViewport(
2822 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
2823 DrawFrame();
2825 // Show top controls
2826 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2828 LayerImpl* outer_viewport_scroll_layer =
2829 host_impl_->active_tree()->OuterViewportScrollLayer();
2830 int id = outer_viewport_scroll_layer->id();
2832 scoped_ptr<LayerImpl> child =
2833 LayerImpl::Create(host_impl_->active_tree(), id + 2);
2834 scoped_ptr<LayerImpl> child_clip =
2835 LayerImpl::Create(host_impl_->active_tree(), id + 3);
2837 child_clip->SetBounds(sub_content_layer_size);
2838 child->SetScrollClipLayer(child_clip->id());
2839 child->SetBounds(sub_content_size);
2840 child->SetContentBounds(sub_content_size);
2841 child->SetPosition(gfx::PointF());
2842 child->SetDrawsContent(true);
2843 child->SetIsContainerForFixedPositionLayers(true);
2845 // scroll child to limit
2846 child->SetScrollDelta(gfx::Vector2dF(0, 100.f));
2847 child_clip->AddChild(child.Pass());
2848 outer_viewport_scroll_layer->AddChild(child_clip.Pass());
2850 // Scroll 25px to hide top controls
2851 gfx::Vector2dF scroll_delta(0.f, 25.f);
2852 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2853 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2854 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2855 host_impl_->ScrollEnd();
2857 // Top controls should be hidden
2858 EXPECT_EQ(scroll_delta.y(),
2859 top_controls_height_ -
2860 host_impl_->top_controls_manager()->ContentTopOffset());
2863 // Ensure setting the top controls position explicitly using the setters on the
2864 // TreeImpl correctly affects the top controls manager and viewport bounds.
2865 TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
2866 CreateHostImpl(settings_, CreateOutputSurface());
2867 SetupTopControlsAndScrollLayer();
2868 DrawFrame();
2870 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2871 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2872 30.f / top_controls_height_);
2873 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2874 EXPECT_FLOAT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
2875 EXPECT_FLOAT_EQ(-20.f,
2876 host_impl_->top_controls_manager()->ControlsTopOffset());
2878 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2879 EXPECT_FLOAT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2880 EXPECT_FLOAT_EQ(-50.f,
2881 host_impl_->top_controls_manager()->ControlsTopOffset());
2883 host_impl_->DidChangeTopControlsPosition();
2885 // Now that top controls have moved, expect the clip to resize.
2886 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2887 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2890 // Test that the top_controls delta and sent delta are appropriately
2891 // applied on sync tree activation. The total top controls offset shouldn't
2892 // change after the activation.
2893 TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
2894 CreateHostImpl(settings_, CreateOutputSurface());
2895 SetupTopControlsAndScrollLayer();
2896 DrawFrame();
2898 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2899 20.f / top_controls_height_);
2900 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2901 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(
2902 15.f / top_controls_height_);
2903 host_impl_->active_tree()
2904 ->top_controls_shown_ratio()
2905 ->PullDeltaForMainThread();
2906 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2907 host_impl_->sync_tree()->PushTopControlsFromMainThread(15.f /
2908 top_controls_height_);
2910 host_impl_->DidChangeTopControlsPosition();
2911 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2912 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2913 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2915 host_impl_->ActivateSyncTree();
2917 root_clip_ptr = host_impl_->active_tree()->root_layer();
2918 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2919 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2921 EXPECT_FLOAT_EQ(
2922 -15.f, host_impl_->active_tree()->top_controls_shown_ratio()->Delta() *
2923 top_controls_height_);
2924 EXPECT_FLOAT_EQ(
2925 15.f,
2926 host_impl_->active_tree()->top_controls_shown_ratio()->ActiveBase() *
2927 top_controls_height_);
2930 // Test that changing the top controls layout height is correctly applied to
2931 // the inner viewport container bounds. That is, the top controls layout
2932 // height is the amount that the inner viewport container was shrunk outside
2933 // the compositor to accommodate the top controls.
2934 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
2935 CreateHostImpl(settings_, CreateOutputSurface());
2936 SetupTopControlsAndScrollLayer();
2937 DrawFrame();
2939 host_impl_->sync_tree()->PushTopControlsFromMainThread(1.f);
2940 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2942 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2943 1.f);
2944 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2945 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2947 host_impl_->DidChangeTopControlsPosition();
2948 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2949 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2950 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2952 host_impl_->sync_tree()->root_layer()->SetBounds(
2953 gfx::Size(root_clip_ptr->bounds().width(),
2954 root_clip_ptr->bounds().height() - 50.f));
2956 host_impl_->ActivateSyncTree();
2958 root_clip_ptr = host_impl_->active_tree()->root_layer();
2959 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2961 // The total bounds should remain unchanged since the bounds delta should
2962 // account for the difference between the layout height and the current
2963 // top controls offset.
2964 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2965 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), root_clip_ptr->bounds_delta());
2967 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
2968 host_impl_->DidChangeTopControlsPosition();
2970 EXPECT_EQ(1.f, host_impl_->top_controls_manager()->TopControlsShownRatio());
2971 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->TopControlsHeight());
2972 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset());
2973 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), root_clip_ptr->bounds_delta());
2974 EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f),
2975 root_clip_ptr->bounds());
2978 // Test that showing/hiding the top controls when the viewport is fully scrolled
2979 // doesn't incorrectly change the viewport offset due to clamping from changing
2980 // viewport bounds.
2981 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) {
2982 SetupTopControlsAndScrollLayerWithVirtualViewport(
2983 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2984 DrawFrame();
2986 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2988 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
2989 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
2991 // Scroll the viewports to max scroll offset.
2992 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
2993 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
2995 gfx::ScrollOffset viewport_offset =
2996 host_impl_->active_tree()->TotalScrollOffset();
2997 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset);
2999 // Hide the top controls by 25px.
3000 gfx::Vector2dF scroll_delta(0.f, 25.f);
3001 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3002 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3003 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3005 // scrolling down at the max extents no longer hides the top controls
3006 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3008 // forcefully hide the top controls by 25px
3009 host_impl_->top_controls_manager()->ScrollBy(scroll_delta);
3010 host_impl_->ScrollEnd();
3012 EXPECT_FLOAT_EQ(scroll_delta.y(),
3013 top_controls_height_ -
3014 host_impl_->top_controls_manager()->ContentTopOffset());
3016 inner_scroll->ClampScrollToMaxScrollOffset();
3017 outer_scroll->ClampScrollToMaxScrollOffset();
3019 // We should still be fully scrolled.
3020 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
3021 host_impl_->active_tree()->TotalScrollOffset());
3023 viewport_offset = host_impl_->active_tree()->TotalScrollOffset();
3025 // Bring the top controls down by 25px.
3026 scroll_delta = gfx::Vector2dF(0.f, -25.f);
3027 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3028 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3029 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3030 host_impl_->ScrollEnd();
3032 // The viewport offset shouldn't have changed.
3033 EXPECT_EQ(viewport_offset,
3034 host_impl_->active_tree()->TotalScrollOffset());
3036 // Scroll the viewports to max scroll offset.
3037 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
3038 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
3039 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
3040 host_impl_->active_tree()->TotalScrollOffset());
3043 // Test that the top controls coming in and out maintains the same aspect ratio
3044 // between the inner and outer viewports.
3045 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
3046 SetupTopControlsAndScrollLayerWithVirtualViewport(
3047 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3048 DrawFrame();
3050 EXPECT_FLOAT_EQ(top_controls_height_,
3051 host_impl_->top_controls_manager()->ContentTopOffset());
3053 gfx::Vector2dF scroll_delta(0.f, 25.f);
3054 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3055 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3056 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3057 host_impl_->ScrollEnd();
3059 EXPECT_FLOAT_EQ(scroll_delta.y(),
3060 top_controls_height_ -
3061 host_impl_->top_controls_manager()->ContentTopOffset());
3063 // Top controls were hidden by 25px so the inner viewport should have expanded
3064 // by that much.
3065 LayerImpl* outer_container =
3066 host_impl_->active_tree()->OuterViewportContainerLayer();
3067 LayerImpl* inner_container =
3068 host_impl_->active_tree()->InnerViewportContainerLayer();
3069 EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling());
3071 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3072 float aspect_ratio = inner_container->BoundsForScrolling().width() /
3073 inner_container->BoundsForScrolling().height();
3074 gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio));
3075 EXPECT_EQ(expected, outer_container->BoundsForScrolling());
3076 EXPECT_EQ(expected,
3077 host_impl_->InnerViewportScrollLayer()->BoundsForScrolling());
3080 // Test that scrolling the outer viewport affects the top controls.
3081 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
3082 SetupTopControlsAndScrollLayerWithVirtualViewport(
3083 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3084 DrawFrame();
3086 EXPECT_EQ(top_controls_height_,
3087 host_impl_->top_controls_manager()->ContentTopOffset());
3089 // Send a gesture scroll that will scroll the outer viewport, make sure the
3090 // top controls get scrolled.
3091 gfx::Vector2dF scroll_delta(0.f, 15.f);
3092 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3093 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3094 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3095 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3096 host_impl_->CurrentlyScrollingLayer());
3097 host_impl_->ScrollEnd();
3099 EXPECT_FLOAT_EQ(scroll_delta.y(),
3100 top_controls_height_ -
3101 host_impl_->top_controls_manager()->ContentTopOffset());
3103 scroll_delta = gfx::Vector2dF(0.f, 50.f);
3104 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3105 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3106 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3108 EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset());
3109 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3110 host_impl_->CurrentlyScrollingLayer());
3112 host_impl_->ScrollEnd();
3114 // Position the viewports such that the inner viewport will be scrolled.
3115 gfx::Vector2dF inner_viewport_offset(0.f, 25.f);
3116 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3117 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset);
3119 scroll_delta = gfx::Vector2dF(0.f, -65.f);
3120 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3121 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3122 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3124 EXPECT_EQ(top_controls_height_,
3125 host_impl_->top_controls_manager()->ContentTopOffset());
3126 EXPECT_FLOAT_EQ(
3127 inner_viewport_offset.y() + (scroll_delta.y() + top_controls_height_),
3128 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
3130 host_impl_->ScrollEnd();
3133 TEST_F(LayerTreeHostImplTopControlsTest,
3134 ScrollNonScrollableRootWithTopControls) {
3135 CreateHostImpl(settings_, CreateOutputSurface());
3136 SetupTopControlsAndScrollLayer();
3137 DrawFrame();
3139 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3140 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3142 host_impl_->top_controls_manager()->ScrollBegin();
3143 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
3144 host_impl_->top_controls_manager()->ScrollEnd();
3145 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3146 // Now that top controls have moved, expect the clip to resize.
3147 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
3148 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
3150 host_impl_->ScrollEnd();
3152 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3153 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3155 float scroll_increment_y = -25.f;
3156 host_impl_->top_controls_manager()->ScrollBegin();
3157 host_impl_->top_controls_manager()->ScrollBy(
3158 gfx::Vector2dF(0.f, scroll_increment_y));
3159 EXPECT_FLOAT_EQ(-scroll_increment_y,
3160 host_impl_->top_controls_manager()->ContentTopOffset());
3161 // Now that top controls have moved, expect the clip to resize.
3162 EXPECT_EQ(gfx::Size(viewport_size_.width(),
3163 viewport_size_.height() + scroll_increment_y),
3164 root_clip_ptr->bounds());
3166 host_impl_->top_controls_manager()->ScrollBy(
3167 gfx::Vector2dF(0.f, scroll_increment_y));
3168 host_impl_->top_controls_manager()->ScrollEnd();
3169 EXPECT_FLOAT_EQ(-2 * scroll_increment_y,
3170 host_impl_->top_controls_manager()->ContentTopOffset());
3171 // Now that top controls have moved, expect the clip to resize.
3172 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
3174 host_impl_->ScrollEnd();
3176 // Verify the layer is once-again non-scrollable.
3177 EXPECT_EQ(
3178 gfx::ScrollOffset(),
3179 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3181 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3182 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3185 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
3186 // Test the configuration where a non-composited root layer is embedded in a
3187 // scrollable outer layer.
3188 gfx::Size surface_size(10, 10);
3189 gfx::Size contents_size(20, 20);
3191 scoped_ptr<LayerImpl> content_layer =
3192 LayerImpl::Create(host_impl_->active_tree(), 1);
3193 content_layer->SetDrawsContent(true);
3194 content_layer->SetPosition(gfx::PointF());
3195 content_layer->SetBounds(contents_size);
3196 content_layer->SetContentBounds(contents_size);
3197 content_layer->SetContentsScale(2.f, 2.f);
3199 scoped_ptr<LayerImpl> scroll_clip_layer =
3200 LayerImpl::Create(host_impl_->active_tree(), 3);
3201 scroll_clip_layer->SetBounds(surface_size);
3203 scoped_ptr<LayerImpl> scroll_layer =
3204 LayerImpl::Create(host_impl_->active_tree(), 2);
3205 scroll_layer->SetScrollClipLayer(3);
3206 scroll_layer->SetBounds(contents_size);
3207 scroll_layer->SetContentBounds(contents_size);
3208 scroll_layer->SetPosition(gfx::PointF());
3209 scroll_layer->AddChild(content_layer.Pass());
3210 scroll_clip_layer->AddChild(scroll_layer.Pass());
3212 scroll_clip_layer->SetHasRenderSurface(true);
3213 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
3214 host_impl_->SetViewportSize(surface_size);
3215 DrawFrame();
3217 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3218 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3219 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3220 host_impl_->ScrollEnd();
3221 EXPECT_TRUE(did_request_redraw_);
3222 EXPECT_TRUE(did_request_commit_);
3225 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
3226 gfx::Size surface_size(10, 10);
3227 gfx::Size contents_size(20, 20);
3228 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3229 root->SetBounds(surface_size);
3230 root->SetContentBounds(contents_size);
3231 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
3232 root->SetHasRenderSurface(true);
3233 host_impl_->active_tree()->SetRootLayer(root.Pass());
3234 host_impl_->SetViewportSize(surface_size);
3235 DrawFrame();
3237 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3238 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3239 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3240 host_impl_->ScrollEnd();
3241 EXPECT_TRUE(did_request_redraw_);
3242 EXPECT_TRUE(did_request_commit_);
3245 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
3246 gfx::Size surface_size(10, 10);
3247 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3248 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
3249 root->SetHasRenderSurface(true);
3250 host_impl_->active_tree()->SetRootLayer(root.Pass());
3251 host_impl_->SetViewportSize(surface_size);
3252 DrawFrame();
3254 // Scroll event is ignored because the input coordinate is outside the layer
3255 // boundaries.
3256 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3257 host_impl_->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL));
3258 EXPECT_FALSE(did_request_redraw_);
3259 EXPECT_FALSE(did_request_commit_);
3262 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
3263 gfx::Size surface_size(10, 10);
3264 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3265 root->SetHasRenderSurface(true);
3266 scoped_ptr<LayerImpl> child =
3267 CreateScrollableLayer(2, surface_size, root.get());
3268 host_impl_->SetViewportSize(surface_size);
3270 gfx::Transform matrix;
3271 matrix.RotateAboutXAxis(180.0);
3272 child->SetTransform(matrix);
3273 child->SetDoubleSided(false);
3275 root->AddChild(child.Pass());
3276 host_impl_->active_tree()->SetRootLayer(root.Pass());
3277 DrawFrame();
3279 // Scroll event is ignored because the scrollable layer is not facing the
3280 // viewer and there is nothing scrollable behind it.
3281 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3282 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3283 EXPECT_FALSE(did_request_redraw_);
3284 EXPECT_FALSE(did_request_commit_);
3287 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
3288 gfx::Size surface_size(10, 10);
3289 scoped_ptr<LayerImpl> clip_layer =
3290 LayerImpl::Create(host_impl_->active_tree(), 3);
3291 scoped_ptr<LayerImpl> content_layer =
3292 CreateScrollableLayer(1, surface_size, clip_layer.get());
3293 content_layer->SetShouldScrollOnMainThread(true);
3294 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
3296 // Note: we can use the same clip layer for both since both calls to
3297 // CreateScrollableLayer() use the same surface size.
3298 scoped_ptr<LayerImpl> scroll_layer =
3299 CreateScrollableLayer(2, surface_size, clip_layer.get());
3300 scroll_layer->AddChild(content_layer.Pass());
3301 clip_layer->AddChild(scroll_layer.Pass());
3302 clip_layer->SetHasRenderSurface(true);
3304 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
3305 host_impl_->SetViewportSize(surface_size);
3306 DrawFrame();
3308 // Scrolling fails because the content layer is asking to be scrolled on the
3309 // main thread.
3310 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
3311 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3314 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
3315 gfx::Size surface_size(20, 20);
3316 gfx::Size viewport_size(10, 10);
3317 float page_scale = 2.f;
3318 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3319 scoped_ptr<LayerImpl> root_clip =
3320 LayerImpl::Create(host_impl_->active_tree(), 2);
3321 scoped_ptr<LayerImpl> root_scrolling =
3322 CreateScrollableLayer(3, surface_size, root_clip.get());
3323 EXPECT_EQ(viewport_size, root_clip->bounds());
3324 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3325 root_clip->AddChild(root_scrolling.Pass());
3326 root->AddChild(root_clip.Pass());
3327 root->SetHasRenderSurface(true);
3328 host_impl_->active_tree()->SetRootLayer(root.Pass());
3329 // The behaviour in this test assumes the page scale is applied at a layer
3330 // above the clip layer.
3331 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
3332 Layer::INVALID_ID);
3333 host_impl_->active_tree()->DidBecomeActive();
3334 host_impl_->SetViewportSize(viewport_size);
3335 DrawFrame();
3337 LayerImpl* root_scroll =
3338 host_impl_->active_tree()->InnerViewportScrollLayer();
3339 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3341 gfx::Vector2d scroll_delta(0, 10);
3342 gfx::Vector2d expected_scroll_delta = scroll_delta;
3343 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3344 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3345 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3346 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3347 host_impl_->ScrollEnd();
3349 // Set new page scale from main thread.
3350 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, page_scale,
3351 page_scale);
3353 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3354 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
3356 // The scroll range should also have been updated.
3357 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3359 // The page scale delta remains constant because the impl thread did not
3360 // scale.
3361 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3364 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
3365 gfx::Size surface_size(20, 20);
3366 gfx::Size viewport_size(10, 10);
3367 float page_scale = 2.f;
3368 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3369 scoped_ptr<LayerImpl> root_clip =
3370 LayerImpl::Create(host_impl_->active_tree(), 2);
3371 scoped_ptr<LayerImpl> root_scrolling =
3372 CreateScrollableLayer(3, surface_size, root_clip.get());
3373 EXPECT_EQ(viewport_size, root_clip->bounds());
3374 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3375 root_clip->AddChild(root_scrolling.Pass());
3376 root->AddChild(root_clip.Pass());
3377 root->SetHasRenderSurface(true);
3378 host_impl_->active_tree()->SetRootLayer(root.Pass());
3379 // The behaviour in this test assumes the page scale is applied at a layer
3380 // above the clip layer.
3381 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
3382 Layer::INVALID_ID);
3383 host_impl_->active_tree()->DidBecomeActive();
3384 host_impl_->SetViewportSize(viewport_size);
3385 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, page_scale);
3386 DrawFrame();
3388 LayerImpl* root_scroll =
3389 host_impl_->active_tree()->InnerViewportScrollLayer();
3390 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3392 gfx::Vector2d scroll_delta(0, 10);
3393 gfx::Vector2d expected_scroll_delta = scroll_delta;
3394 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3395 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3396 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3397 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3398 host_impl_->ScrollEnd();
3400 // Set new page scale on impl thread by pinching.
3401 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3402 host_impl_->PinchGestureBegin();
3403 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
3404 host_impl_->PinchGestureEnd();
3405 host_impl_->ScrollEnd();
3406 DrawOneFrame();
3408 // The scroll delta is not scaled because the main thread did not scale.
3409 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3410 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
3412 // The scroll range should also have been updated.
3413 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3415 // The page scale delta should match the new scale on the impl side.
3416 EXPECT_EQ(page_scale, host_impl_->active_tree()->current_page_scale_factor());
3419 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
3420 gfx::Size surface_size(10, 10);
3421 float default_page_scale = 1.f;
3422 gfx::Transform default_page_scale_matrix;
3423 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
3425 float new_page_scale = 2.f;
3426 gfx::Transform new_page_scale_matrix;
3427 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
3429 // Create a normal scrollable root layer and another scrollable child layer.
3430 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
3431 LayerImpl* root = host_impl_->active_tree()->root_layer();
3432 LayerImpl* child = scroll->children()[0];
3434 scoped_ptr<LayerImpl> scrollable_child_clip =
3435 LayerImpl::Create(host_impl_->active_tree(), 6);
3436 scoped_ptr<LayerImpl> scrollable_child =
3437 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
3438 scrollable_child_clip->AddChild(scrollable_child.Pass());
3439 child->AddChild(scrollable_child_clip.Pass());
3440 LayerImpl* grand_child = child->children()[0];
3442 // Set new page scale on impl thread by pinching.
3443 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3444 host_impl_->PinchGestureBegin();
3445 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
3446 host_impl_->PinchGestureEnd();
3447 host_impl_->ScrollEnd();
3448 DrawOneFrame();
3450 EXPECT_EQ(1.f, root->contents_scale_x());
3451 EXPECT_EQ(1.f, root->contents_scale_y());
3452 EXPECT_EQ(1.f, scroll->contents_scale_x());
3453 EXPECT_EQ(1.f, scroll->contents_scale_y());
3454 EXPECT_EQ(1.f, child->contents_scale_x());
3455 EXPECT_EQ(1.f, child->contents_scale_y());
3456 EXPECT_EQ(1.f, grand_child->contents_scale_x());
3457 EXPECT_EQ(1.f, grand_child->contents_scale_y());
3459 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3460 // the page scale delta on the root layer is applied hierarchically.
3461 LayerTreeHostImpl::FrameData frame;
3462 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3463 host_impl_->DrawLayers(&frame);
3464 host_impl_->DidDrawAllLayers(frame);
3466 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
3467 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
3468 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
3469 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
3470 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
3471 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
3472 EXPECT_EQ(new_page_scale,
3473 grand_child->draw_transform().matrix().getDouble(0, 0));
3474 EXPECT_EQ(new_page_scale,
3475 grand_child->draw_transform().matrix().getDouble(1, 1));
3478 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
3479 gfx::Size surface_size(30, 30);
3480 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3481 root->SetBounds(gfx::Size(5, 5));
3482 root->SetHasRenderSurface(true);
3483 scoped_ptr<LayerImpl> root_scrolling =
3484 LayerImpl::Create(host_impl_->active_tree(), 2);
3485 root_scrolling->SetBounds(surface_size);
3486 root_scrolling->SetContentBounds(surface_size);
3487 root_scrolling->SetScrollClipLayer(root->id());
3488 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3489 LayerImpl* root_scrolling_ptr = root_scrolling.get();
3490 root->AddChild(root_scrolling.Pass());
3491 int child_scroll_layer_id = 3;
3492 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
3493 child_scroll_layer_id, surface_size, root_scrolling_ptr);
3494 LayerImpl* child = child_scrolling.get();
3495 root_scrolling_ptr->AddChild(child_scrolling.Pass());
3496 host_impl_->active_tree()->SetRootLayer(root.Pass());
3497 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3498 Layer::INVALID_ID);
3499 host_impl_->active_tree()->DidBecomeActive();
3500 host_impl_->SetViewportSize(surface_size);
3501 DrawFrame();
3503 gfx::Vector2d scroll_delta(0, 10);
3504 gfx::Vector2d expected_scroll_delta(scroll_delta);
3505 gfx::ScrollOffset expected_max_scroll(child->MaxScrollOffset());
3506 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3507 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3508 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3509 host_impl_->ScrollEnd();
3511 float page_scale = 2.f;
3512 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f,
3513 page_scale);
3515 DrawOneFrame();
3517 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3518 ExpectContains(
3519 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
3521 // The scroll range should not have changed.
3522 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
3524 // The page scale delta remains constant because the impl thread did not
3525 // scale.
3526 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3529 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
3530 // Scroll a child layer beyond its maximum scroll range and make sure the
3531 // parent layer is scrolled on the axis on which the child was unable to
3532 // scroll.
3533 gfx::Size surface_size(10, 10);
3534 gfx::Size content_size(20, 20);
3535 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3536 root->SetBounds(surface_size);
3537 root->SetHasRenderSurface(true);
3538 scoped_ptr<LayerImpl> grand_child =
3539 CreateScrollableLayer(3, content_size, root.get());
3541 scoped_ptr<LayerImpl> child =
3542 CreateScrollableLayer(2, content_size, root.get());
3543 LayerImpl* grand_child_layer = grand_child.get();
3544 child->AddChild(grand_child.Pass());
3546 LayerImpl* child_layer = child.get();
3547 root->AddChild(child.Pass());
3548 host_impl_->active_tree()->SetRootLayer(root.Pass());
3549 host_impl_->active_tree()->DidBecomeActive();
3550 host_impl_->SetViewportSize(surface_size);
3551 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
3552 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
3554 DrawFrame();
3556 gfx::Vector2d scroll_delta(-8, -7);
3557 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3558 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3559 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3560 host_impl_->ScrollEnd();
3562 scoped_ptr<ScrollAndScaleSet> scroll_info =
3563 host_impl_->ProcessScrollDeltas();
3565 // The grand child should have scrolled up to its limit.
3566 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
3567 LayerImpl* grand_child = child->children()[0];
3568 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
3570 // The child should have only scrolled on the other axis.
3571 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
3575 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
3576 // Scroll a child layer beyond its maximum scroll range and make sure the
3577 // the scroll doesn't bubble up to the parent layer.
3578 gfx::Size surface_size(20, 20);
3579 gfx::Size viewport_size(10, 10);
3580 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3581 root->SetHasRenderSurface(true);
3582 scoped_ptr<LayerImpl> root_scrolling =
3583 CreateScrollableLayer(2, surface_size, root.get());
3584 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3586 scoped_ptr<LayerImpl> grand_child =
3587 CreateScrollableLayer(4, surface_size, root.get());
3589 scoped_ptr<LayerImpl> child =
3590 CreateScrollableLayer(3, surface_size, root.get());
3591 LayerImpl* grand_child_layer = grand_child.get();
3592 child->AddChild(grand_child.Pass());
3594 LayerImpl* child_layer = child.get();
3595 root_scrolling->AddChild(child.Pass());
3596 root->AddChild(root_scrolling.Pass());
3597 EXPECT_EQ(viewport_size, root->bounds());
3598 host_impl_->active_tree()->SetRootLayer(root.Pass());
3599 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3600 Layer::INVALID_ID);
3601 host_impl_->active_tree()->DidBecomeActive();
3602 host_impl_->SetViewportSize(viewport_size);
3604 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
3605 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
3607 DrawFrame();
3609 gfx::Vector2d scroll_delta(0, -10);
3610 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3611 host_impl_->ScrollBegin(gfx::Point(),
3612 InputHandler::NON_BUBBLING_GESTURE));
3613 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3614 host_impl_->ScrollEnd();
3616 scoped_ptr<ScrollAndScaleSet> scroll_info =
3617 host_impl_->ProcessScrollDeltas();
3619 // The grand child should have scrolled up to its limit.
3620 LayerImpl* child =
3621 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
3622 LayerImpl* grand_child = child->children()[0];
3623 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
3625 // The child should not have scrolled.
3626 ExpectNone(*scroll_info.get(), child->id());
3628 // The next time we scroll we should only scroll the parent.
3629 scroll_delta = gfx::Vector2d(0, -3);
3630 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3631 host_impl_->ScrollBegin(gfx::Point(5, 5),
3632 InputHandler::NON_BUBBLING_GESTURE));
3633 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3634 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3635 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
3636 host_impl_->ScrollEnd();
3638 scroll_info = host_impl_->ProcessScrollDeltas();
3640 // The child should have scrolled up to its limit.
3641 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
3643 // The grand child should not have scrolled.
3644 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
3646 // After scrolling the parent, another scroll on the opposite direction
3647 // should still scroll the child.
3648 scroll_delta = gfx::Vector2d(0, 7);
3649 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3650 host_impl_->ScrollBegin(gfx::Point(5, 5),
3651 InputHandler::NON_BUBBLING_GESTURE));
3652 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3653 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3654 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3655 host_impl_->ScrollEnd();
3657 scroll_info = host_impl_->ProcessScrollDeltas();
3659 // The grand child should have scrolled.
3660 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
3662 // The child should not have scrolled.
3663 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
3666 // Scrolling should be adjusted from viewport space.
3667 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 2.f, 2.f);
3668 host_impl_->SetPageScaleOnActiveTree(2.f);
3670 scroll_delta = gfx::Vector2d(0, -2);
3671 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3672 host_impl_->ScrollBegin(gfx::Point(1, 1),
3673 InputHandler::NON_BUBBLING_GESTURE));
3674 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
3675 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3676 host_impl_->ScrollEnd();
3678 scroll_info = host_impl_->ProcessScrollDeltas();
3680 // Should have scrolled by half the amount in layer space (5 - 2/2)
3681 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
3684 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
3685 // When we try to scroll a non-scrollable child layer, the scroll delta
3686 // should be applied to one of its ancestors if possible.
3687 gfx::Size surface_size(10, 10);
3688 gfx::Size content_size(20, 20);
3689 scoped_ptr<LayerImpl> root_clip =
3690 LayerImpl::Create(host_impl_->active_tree(), 3);
3691 root_clip->SetHasRenderSurface(true);
3692 scoped_ptr<LayerImpl> root =
3693 CreateScrollableLayer(1, content_size, root_clip.get());
3694 // Make 'root' the clip layer for child: since they have the same sizes the
3695 // child will have zero max_scroll_offset and scrolls will bubble.
3696 scoped_ptr<LayerImpl> child =
3697 CreateScrollableLayer(2, content_size, root.get());
3698 child->SetIsContainerForFixedPositionLayers(true);
3699 root->SetBounds(content_size);
3701 int root_scroll_id = root->id();
3702 root->AddChild(child.Pass());
3703 root_clip->AddChild(root.Pass());
3705 host_impl_->SetViewportSize(surface_size);
3706 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3707 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 2,
3708 Layer::INVALID_ID);
3709 host_impl_->active_tree()->DidBecomeActive();
3710 DrawFrame();
3712 gfx::Vector2d scroll_delta(0, 4);
3713 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3714 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3715 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3716 host_impl_->ScrollEnd();
3718 scoped_ptr<ScrollAndScaleSet> scroll_info =
3719 host_impl_->ProcessScrollDeltas();
3721 // Only the root scroll should have scrolled.
3722 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
3723 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
3727 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
3728 gfx::Size surface_size(10, 10);
3729 scoped_ptr<LayerImpl> root_clip =
3730 LayerImpl::Create(host_impl_->active_tree(), 1);
3731 scoped_ptr<LayerImpl> root_scroll =
3732 CreateScrollableLayer(2, surface_size, root_clip.get());
3733 root_scroll->SetIsContainerForFixedPositionLayers(true);
3734 root_clip->SetHasRenderSurface(true);
3735 root_clip->AddChild(root_scroll.Pass());
3736 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3737 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3738 Layer::INVALID_ID);
3739 host_impl_->active_tree()->DidBecomeActive();
3740 host_impl_->SetViewportSize(surface_size);
3742 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3743 // synchronization.
3744 DrawFrame();
3745 host_impl_->active_tree()->DetachLayerTree();
3746 scoped_ptr<LayerImpl> root_clip2 =
3747 LayerImpl::Create(host_impl_->active_tree(), 3);
3748 scoped_ptr<LayerImpl> root_scroll2 =
3749 CreateScrollableLayer(4, surface_size, root_clip2.get());
3750 root_scroll2->SetIsContainerForFixedPositionLayers(true);
3751 root_clip2->AddChild(root_scroll2.Pass());
3752 root_clip2->SetHasRenderSurface(true);
3753 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
3754 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 4,
3755 Layer::INVALID_ID);
3756 host_impl_->active_tree()->DidBecomeActive();
3758 // Scrolling should still work even though we did not draw yet.
3759 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3760 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3763 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
3764 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3766 // Rotate the root layer 90 degrees counter-clockwise about its center.
3767 gfx::Transform rotate_transform;
3768 rotate_transform.Rotate(-90.0);
3769 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
3771 gfx::Size surface_size(50, 50);
3772 host_impl_->SetViewportSize(surface_size);
3773 DrawFrame();
3775 // Scroll to the right in screen coordinates with a gesture.
3776 gfx::Vector2d gesture_scroll_delta(10, 0);
3777 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3778 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3779 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3780 host_impl_->ScrollEnd();
3782 // The layer should have scrolled down in its local coordinates.
3783 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3784 ExpectContains(*scroll_info.get(), scroll_layer->id(),
3785 gfx::Vector2d(0, gesture_scroll_delta.x()));
3787 // Reset and scroll down with the wheel.
3788 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3789 gfx::Vector2d wheel_scroll_delta(0, 10);
3790 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3791 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3792 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3793 host_impl_->ScrollEnd();
3795 // The layer should have scrolled down in its local coordinates.
3796 scroll_info = host_impl_->ProcessScrollDeltas();
3797 ExpectContains(*scroll_info.get(),
3798 scroll_layer->id(),
3799 wheel_scroll_delta);
3802 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
3803 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3804 int child_clip_layer_id = 6;
3805 int child_layer_id = 7;
3806 float child_layer_angle = -20.f;
3808 // Create a child layer that is rotated to a non-axis-aligned angle.
3809 scoped_ptr<LayerImpl> clip_layer =
3810 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
3811 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
3812 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
3813 gfx::Transform rotate_transform;
3814 rotate_transform.Translate(-50.0, -50.0);
3815 rotate_transform.Rotate(child_layer_angle);
3816 rotate_transform.Translate(50.0, 50.0);
3817 clip_layer->SetTransform(rotate_transform);
3819 // Only allow vertical scrolling.
3820 clip_layer->SetBounds(
3821 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
3822 // The rotation depends on the layer's transform origin, and the child layer
3823 // is a different size than the clip, so make sure the clip layer's origin
3824 // lines up over the child.
3825 clip_layer->SetTransformOrigin(gfx::Point3F(
3826 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
3827 LayerImpl* child_ptr = child.get();
3828 clip_layer->AddChild(child.Pass());
3829 scroll_layer->AddChild(clip_layer.Pass());
3831 gfx::Size surface_size(50, 50);
3832 host_impl_->SetViewportSize(surface_size);
3833 DrawFrame();
3835 // Scroll down in screen coordinates with a gesture.
3836 gfx::Vector2d gesture_scroll_delta(0, 10);
3837 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3838 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
3839 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3840 host_impl_->ScrollEnd();
3842 // The child layer should have scrolled down in its local coordinates an
3843 // amount proportional to the angle between it and the input scroll delta.
3844 gfx::Vector2d expected_scroll_delta(
3845 0, gesture_scroll_delta.y() *
3846 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
3847 scoped_ptr<ScrollAndScaleSet> scroll_info =
3848 host_impl_->ProcessScrollDeltas();
3849 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
3851 // The root scroll layer should not have scrolled, because the input delta
3852 // was close to the layer's axis of movement.
3853 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
3856 // Now reset and scroll the same amount horizontally.
3857 child_ptr->SetScrollDelta(gfx::Vector2dF());
3858 gfx::Vector2d gesture_scroll_delta(10, 0);
3859 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3860 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
3861 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3862 host_impl_->ScrollEnd();
3864 // The child layer should have scrolled down in its local coordinates an
3865 // amount proportional to the angle between it and the input scroll delta.
3866 gfx::Vector2d expected_scroll_delta(
3867 0, -gesture_scroll_delta.x() *
3868 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
3869 scoped_ptr<ScrollAndScaleSet> scroll_info =
3870 host_impl_->ProcessScrollDeltas();
3871 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
3873 // The root scroll layer should have scrolled more, since the input scroll
3874 // delta was mostly orthogonal to the child layer's vertical scroll axis.
3875 gfx::Vector2d expected_root_scroll_delta(
3876 gesture_scroll_delta.x() *
3877 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
3879 ExpectContains(*scroll_info.get(),
3880 scroll_layer->id(),
3881 expected_root_scroll_delta);
3885 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
3886 LayerImpl* scroll_layer =
3887 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3889 // Scale the layer to twice its normal size.
3890 int scale = 2;
3891 gfx::Transform scale_transform;
3892 scale_transform.Scale(scale, scale);
3893 scroll_layer->SetTransform(scale_transform);
3895 gfx::Size surface_size(50, 50);
3896 host_impl_->SetViewportSize(surface_size);
3897 DrawFrame();
3899 // Scroll down in screen coordinates with a gesture.
3900 gfx::Vector2d scroll_delta(0, 10);
3901 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3902 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3903 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3904 host_impl_->ScrollEnd();
3906 // The layer should have scrolled down in its local coordinates, but half the
3907 // amount.
3908 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3909 ExpectContains(*scroll_info.get(),
3910 scroll_layer->id(),
3911 gfx::Vector2d(0, scroll_delta.y() / scale));
3913 // Reset and scroll down with the wheel.
3914 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3915 gfx::Vector2d wheel_scroll_delta(0, 10);
3916 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3917 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3918 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3919 host_impl_->ScrollEnd();
3921 // It should apply the scale factor to the scroll delta for the wheel event.
3922 scroll_info = host_impl_->ProcessScrollDeltas();
3923 ExpectContains(*scroll_info.get(),
3924 scroll_layer->id(),
3925 wheel_scroll_delta);
3928 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
3929 int width = 332;
3930 int height = 20;
3931 int scale = 3;
3932 SetupScrollAndContentsLayers(gfx::Size(width, height));
3933 host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
3934 gfx::Size(width * scale - 1, height * scale));
3935 host_impl_->SetDeviceScaleFactor(scale);
3936 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
3938 LayerImpl* inner_viewport_scroll_layer =
3939 host_impl_->active_tree()->InnerViewportScrollLayer();
3940 EXPECT_EQ(gfx::ScrollOffset(0, 0),
3941 inner_viewport_scroll_layer->MaxScrollOffset());
3944 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
3945 public:
3946 TestScrollOffsetDelegate()
3947 : page_scale_factor_(0.f),
3948 min_page_scale_factor_(-1.f),
3949 max_page_scale_factor_(-1.f) {}
3951 ~TestScrollOffsetDelegate() override {}
3953 gfx::ScrollOffset GetTotalScrollOffset() override {
3954 return getter_return_value_;
3957 bool IsExternalFlingActive() const override { return false; }
3959 void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
3960 const gfx::ScrollOffset& max_scroll_offset,
3961 const gfx::SizeF& scrollable_size,
3962 float page_scale_factor,
3963 float min_page_scale_factor,
3964 float max_page_scale_factor) override {
3965 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
3966 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
3967 last_set_scroll_offset_ = total_scroll_offset;
3968 max_scroll_offset_ = max_scroll_offset;
3969 scrollable_size_ = scrollable_size;
3970 page_scale_factor_ = page_scale_factor;
3971 min_page_scale_factor_ = min_page_scale_factor;
3972 max_page_scale_factor_ = max_page_scale_factor;
3974 set_getter_return_value(last_set_scroll_offset_);
3977 gfx::ScrollOffset last_set_scroll_offset() {
3978 return last_set_scroll_offset_;
3981 void set_getter_return_value(const gfx::ScrollOffset& value) {
3982 getter_return_value_ = value;
3985 gfx::ScrollOffset max_scroll_offset() const {
3986 return max_scroll_offset_;
3989 gfx::SizeF scrollable_size() const {
3990 return scrollable_size_;
3993 float page_scale_factor() const {
3994 return page_scale_factor_;
3997 float min_page_scale_factor() const {
3998 return min_page_scale_factor_;
4001 float max_page_scale_factor() const {
4002 return max_page_scale_factor_;
4005 private:
4006 gfx::ScrollOffset last_set_scroll_offset_;
4007 gfx::ScrollOffset getter_return_value_;
4008 gfx::ScrollOffset max_scroll_offset_;
4009 gfx::SizeF scrollable_size_;
4010 float page_scale_factor_;
4011 float min_page_scale_factor_;
4012 float max_page_scale_factor_;
4015 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
4016 TestScrollOffsetDelegate scroll_delegate;
4017 host_impl_->SetViewportSize(gfx::Size(10, 20));
4018 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4019 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4020 clip_layer->SetBounds(gfx::Size(10, 20));
4022 // Setting the delegate results in the current scroll offset being set.
4023 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
4024 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4025 scroll_layer->SetScrollDelta(initial_scroll_delta);
4026 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4027 EXPECT_EQ(initial_scroll_delta.ToString(),
4028 scroll_delegate.last_set_scroll_offset().ToString());
4030 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4031 // page_scale_factor and {min|max}_page_scale_factor being set.
4032 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
4033 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset());
4034 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
4035 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
4036 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
4038 // Updating page scale immediately updates the delegate.
4039 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 0.5f, 4.f);
4040 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
4041 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4042 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4043 host_impl_->SetPageScaleOnActiveTree(2.f * 1.5f);
4044 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
4045 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4046 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4047 host_impl_->SetPageScaleOnActiveTree(2.f);
4048 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4049 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
4050 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4051 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4053 // The pinch gesture doesn't put the delegate into a state where the scroll
4054 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4055 // delegate).
4056 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
4057 host_impl_->PinchGestureBegin();
4058 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
4059 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
4060 host_impl_->PinchGestureEnd();
4061 host_impl_->ScrollEnd();
4063 // Scrolling should be relative to the offset as returned by the delegate.
4064 gfx::Vector2dF scroll_delta(0.f, 10.f);
4065 gfx::ScrollOffset current_offset(7.f, 8.f);
4067 scroll_delegate.set_getter_return_value(current_offset);
4068 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4069 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4070 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4072 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4073 EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
4074 scroll_delegate.last_set_scroll_offset());
4076 current_offset = gfx::ScrollOffset(42.f, 41.f);
4077 scroll_delegate.set_getter_return_value(current_offset);
4078 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4079 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4080 EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
4081 scroll_delegate.last_set_scroll_offset());
4082 host_impl_->ScrollEnd();
4083 scroll_delegate.set_getter_return_value(gfx::ScrollOffset());
4084 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4086 // Forces a full tree synchronization and ensures that the scroll delegate
4087 // sees the correct size of the new tree.
4088 gfx::Size new_size(42, 24);
4089 host_impl_->CreatePendingTree();
4090 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
4091 host_impl_->ActivateSyncTree();
4092 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
4094 // Un-setting the delegate should propagate the delegate's current offset to
4095 // the root scrollable layer.
4096 current_offset = gfx::ScrollOffset(13.f, 12.f);
4097 scroll_delegate.set_getter_return_value(current_offset);
4098 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4099 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4101 EXPECT_EQ(current_offset.ToString(),
4102 scroll_layer->CurrentScrollOffset().ToString());
4105 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
4106 const gfx::Transform target_space_transform =
4107 layer->draw_properties().target_space_transform;
4108 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
4109 gfx::Point translated_point;
4110 target_space_transform.TransformPoint(&translated_point);
4111 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
4112 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
4115 TEST_F(LayerTreeHostImplTest,
4116 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
4117 TestScrollOffsetDelegate scroll_delegate;
4118 host_impl_->SetViewportSize(gfx::Size(10, 20));
4119 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4120 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4121 clip_layer->SetBounds(gfx::Size(10, 20));
4122 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4124 // Draw first frame to clear any pending draws and check scroll.
4125 DrawFrame();
4126 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
4127 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
4129 // Set external scroll delta on delegate and notify LayerTreeHost.
4130 gfx::ScrollOffset scroll_offset(10.f, 10.f);
4131 scroll_delegate.set_getter_return_value(scroll_offset);
4132 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4134 // Check scroll delta reflected in layer.
4135 LayerTreeHostImpl::FrameData frame;
4136 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4137 host_impl_->DrawLayers(&frame);
4138 host_impl_->DidDrawAllLayers(frame);
4139 EXPECT_FALSE(frame.has_no_damage);
4140 CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset));
4142 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4145 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
4146 InputHandlerScrollResult scroll_result;
4147 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4148 host_impl_->SetViewportSize(gfx::Size(50, 50));
4149 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4150 DrawFrame();
4151 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4153 // In-bounds scrolling does not affect overscroll.
4154 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4155 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4156 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4157 EXPECT_TRUE(scroll_result.did_scroll);
4158 EXPECT_FALSE(scroll_result.did_overscroll_root);
4159 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4160 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4162 // Overscroll events are reflected immediately.
4163 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4164 EXPECT_TRUE(scroll_result.did_scroll);
4165 EXPECT_TRUE(scroll_result.did_overscroll_root);
4166 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4167 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4168 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4169 host_impl_->accumulated_root_overscroll());
4171 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4172 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4173 EXPECT_TRUE(scroll_result.did_scroll);
4174 EXPECT_FALSE(scroll_result.did_overscroll_root);
4175 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4176 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4177 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4178 host_impl_->accumulated_root_overscroll());
4180 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4181 EXPECT_FALSE(scroll_result.did_scroll);
4182 EXPECT_TRUE(scroll_result.did_overscroll_root);
4183 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4184 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4185 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4186 host_impl_->accumulated_root_overscroll());
4188 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4189 EXPECT_TRUE(scroll_result.did_scroll);
4190 EXPECT_FALSE(scroll_result.did_overscroll_root);
4191 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4192 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4193 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4194 host_impl_->accumulated_root_overscroll());
4196 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4197 EXPECT_TRUE(scroll_result.did_scroll);
4198 EXPECT_TRUE(scroll_result.did_overscroll_root);
4199 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
4200 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
4201 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4202 host_impl_->accumulated_root_overscroll());
4204 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4205 EXPECT_TRUE(scroll_result.did_scroll);
4206 EXPECT_TRUE(scroll_result.did_overscroll_root);
4207 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4208 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
4209 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4210 host_impl_->accumulated_root_overscroll());
4212 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4213 EXPECT_TRUE(scroll_result.did_scroll);
4214 EXPECT_TRUE(scroll_result.did_overscroll_root);
4215 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4216 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4217 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4218 host_impl_->accumulated_root_overscroll());
4220 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4221 // as no scroll occurs.
4222 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4223 EXPECT_FALSE(scroll_result.did_scroll);
4224 EXPECT_TRUE(scroll_result.did_overscroll_root);
4225 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4226 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
4227 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4228 host_impl_->accumulated_root_overscroll());
4230 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4231 EXPECT_FALSE(scroll_result.did_scroll);
4232 EXPECT_TRUE(scroll_result.did_overscroll_root);
4233 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4234 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
4235 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4236 host_impl_->accumulated_root_overscroll());
4238 // Overscroll resets on valid scroll.
4239 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4240 EXPECT_TRUE(scroll_result.did_scroll);
4241 EXPECT_FALSE(scroll_result.did_overscroll_root);
4242 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4243 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4244 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4245 host_impl_->accumulated_root_overscroll());
4247 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4248 EXPECT_TRUE(scroll_result.did_scroll);
4249 EXPECT_TRUE(scroll_result.did_overscroll_root);
4250 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4251 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4252 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4253 host_impl_->accumulated_root_overscroll());
4255 host_impl_->ScrollEnd();
4259 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
4260 // Scroll child layers beyond their maximum scroll range and make sure root
4261 // overscroll does not accumulate.
4262 gfx::Size surface_size(10, 10);
4263 scoped_ptr<LayerImpl> root_clip =
4264 LayerImpl::Create(host_impl_->active_tree(), 4);
4265 root_clip->SetHasRenderSurface(true);
4267 scoped_ptr<LayerImpl> root =
4268 CreateScrollableLayer(1, surface_size, root_clip.get());
4270 scoped_ptr<LayerImpl> grand_child =
4271 CreateScrollableLayer(3, surface_size, root_clip.get());
4273 scoped_ptr<LayerImpl> child =
4274 CreateScrollableLayer(2, surface_size, root_clip.get());
4275 LayerImpl* grand_child_layer = grand_child.get();
4276 child->AddChild(grand_child.Pass());
4278 LayerImpl* child_layer = child.get();
4279 root->AddChild(child.Pass());
4280 root_clip->AddChild(root.Pass());
4281 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4282 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4283 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4284 host_impl_->active_tree()->DidBecomeActive();
4285 host_impl_->SetViewportSize(surface_size);
4286 DrawFrame();
4288 gfx::Vector2d scroll_delta(0, -10);
4289 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4290 host_impl_->ScrollBegin(gfx::Point(),
4291 InputHandler::NON_BUBBLING_GESTURE));
4292 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4293 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4294 host_impl_->ScrollEnd();
4296 // The next time we scroll we should only scroll the parent, but overscroll
4297 // should still not reach the root layer.
4298 scroll_delta = gfx::Vector2d(0, -30);
4299 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4300 host_impl_->ScrollBegin(gfx::Point(5, 5),
4301 InputHandler::NON_BUBBLING_GESTURE));
4302 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4303 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4304 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4305 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
4306 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4307 host_impl_->ScrollEnd();
4309 // After scrolling the parent, another scroll on the opposite direction
4310 // should scroll the child.
4311 scroll_delta = gfx::Vector2d(0, 70);
4312 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4313 host_impl_->ScrollBegin(gfx::Point(5, 5),
4314 InputHandler::NON_BUBBLING_GESTURE));
4315 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4316 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4317 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4318 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4319 host_impl_->ScrollEnd();
4323 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
4324 // When we try to scroll a non-scrollable child layer, the scroll delta
4325 // should be applied to one of its ancestors if possible. Overscroll should
4326 // be reflected only when it has bubbled up to the root scrolling layer.
4327 gfx::Size surface_size(10, 10);
4328 gfx::Size content_size(20, 20);
4329 scoped_ptr<LayerImpl> root_clip =
4330 LayerImpl::Create(host_impl_->active_tree(), 3);
4331 root_clip->SetHasRenderSurface(true);
4333 scoped_ptr<LayerImpl> root =
4334 CreateScrollableLayer(1, content_size, root_clip.get());
4335 root->SetIsContainerForFixedPositionLayers(true);
4336 scoped_ptr<LayerImpl> child =
4337 CreateScrollableLayer(2, content_size, root_clip.get());
4339 child->SetScrollClipLayer(Layer::INVALID_ID);
4340 root->AddChild(child.Pass());
4341 root_clip->AddChild(root.Pass());
4343 host_impl_->SetViewportSize(surface_size);
4344 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4345 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4346 Layer::INVALID_ID);
4347 host_impl_->active_tree()->DidBecomeActive();
4348 DrawFrame();
4350 gfx::Vector2d scroll_delta(0, 8);
4351 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4352 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4353 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4354 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4355 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4356 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
4357 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4358 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
4359 host_impl_->ScrollEnd();
4363 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
4364 LayerTreeSettings settings;
4365 CreateHostImpl(settings, CreateOutputSurface());
4367 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
4368 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4369 clip_layer->SetBounds(gfx::Size(50, 50));
4370 host_impl_->SetViewportSize(gfx::Size(50, 50));
4371 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4372 DrawFrame();
4373 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4375 // Even though the layer can't scroll the overscroll still happens.
4376 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4377 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4378 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4379 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4382 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
4383 gfx::Size surface_size(980, 1439);
4384 gfx::Size content_size(980, 1438);
4385 float device_scale_factor = 1.5f;
4386 scoped_ptr<LayerImpl> root_clip =
4387 LayerImpl::Create(host_impl_->active_tree(), 3);
4388 root_clip->SetHasRenderSurface(true);
4390 scoped_ptr<LayerImpl> root =
4391 CreateScrollableLayer(1, content_size, root_clip.get());
4392 root->SetIsContainerForFixedPositionLayers(true);
4393 scoped_ptr<LayerImpl> child =
4394 CreateScrollableLayer(2, content_size, root_clip.get());
4395 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
4396 host_impl_->active_tree()->PushPageScaleFromMainThread(0.326531f, 0.326531f,
4397 5.f);
4398 host_impl_->SetPageScaleOnActiveTree(0.326531f);
4399 child->SetScrollClipLayer(Layer::INVALID_ID);
4400 root->AddChild(child.Pass());
4401 root_clip->AddChild(root.Pass());
4403 host_impl_->SetViewportSize(surface_size);
4404 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4405 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4406 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4407 Layer::INVALID_ID);
4408 host_impl_->active_tree()->DidBecomeActive();
4409 DrawFrame();
4411 // Horizontal & Vertical GlowEffect should not be applied when
4412 // content size is less then view port size. For Example Horizontal &
4413 // vertical GlowEffect should not be applied in about:blank page.
4414 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4415 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4416 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
4417 EXPECT_EQ(gfx::Vector2dF().ToString(),
4418 host_impl_->accumulated_root_overscroll().ToString());
4420 host_impl_->ScrollEnd();
4424 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
4425 gfx::Size surface_size(100, 100);
4426 gfx::Size content_size(200, 200);
4427 scoped_ptr<LayerImpl> root_clip =
4428 LayerImpl::Create(host_impl_->active_tree(), 3);
4429 root_clip->SetHasRenderSurface(true);
4431 scoped_ptr<LayerImpl> root =
4432 CreateScrollableLayer(1, content_size, root_clip.get());
4433 root->SetIsContainerForFixedPositionLayers(true);
4434 scoped_ptr<LayerImpl> child =
4435 CreateScrollableLayer(2, content_size, root_clip.get());
4437 child->SetScrollClipLayer(Layer::INVALID_ID);
4438 root->AddChild(child.Pass());
4439 root_clip->AddChild(root.Pass());
4441 host_impl_->SetViewportSize(surface_size);
4442 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4443 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4444 Layer::INVALID_ID);
4445 host_impl_->active_tree()->DidBecomeActive();
4446 DrawFrame();
4448 // Edge glow effect should be applicable only upon reaching Edges
4449 // of the content. unnecessary glow effect calls shouldn't be
4450 // called while scrolling up without reaching the edge of the content.
4451 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4452 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4453 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4454 EXPECT_EQ(gfx::Vector2dF().ToString(),
4455 host_impl_->accumulated_root_overscroll().ToString());
4456 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
4457 EXPECT_EQ(gfx::Vector2dF().ToString(),
4458 host_impl_->accumulated_root_overscroll().ToString());
4459 host_impl_->ScrollEnd();
4460 // unusedrootDelta should be subtracted from applied delta so that
4461 // unwanted glow effect calls are not called.
4462 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4463 host_impl_->ScrollBegin(gfx::Point(0, 0),
4464 InputHandler::NON_BUBBLING_GESTURE));
4465 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
4466 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4467 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4468 host_impl_->accumulated_root_overscroll().ToString());
4470 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
4471 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4472 host_impl_->accumulated_root_overscroll().ToString());
4473 host_impl_->ScrollEnd();
4474 // TestCase to check kEpsilon, which prevents minute values to trigger
4475 // gloweffect without reaching edge.
4476 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4477 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4478 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
4479 EXPECT_EQ(gfx::Vector2dF().ToString(),
4480 host_impl_->accumulated_root_overscroll().ToString());
4481 host_impl_->ScrollEnd();
4485 class BlendStateCheckLayer : public LayerImpl {
4486 public:
4487 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
4488 int id,
4489 ResourceProvider* resource_provider) {
4490 return make_scoped_ptr(
4491 new BlendStateCheckLayer(tree_impl, id, resource_provider));
4494 void AppendQuads(RenderPass* render_pass,
4495 AppendQuadsData* append_quads_data) override {
4496 quads_appended_ = true;
4498 gfx::Rect opaque_rect;
4499 if (contents_opaque())
4500 opaque_rect = quad_rect_;
4501 else
4502 opaque_rect = opaque_content_rect_;
4503 gfx::Rect visible_quad_rect = quad_rect_;
4505 SharedQuadState* shared_quad_state =
4506 render_pass->CreateAndAppendSharedQuadState();
4507 PopulateSharedQuadState(shared_quad_state);
4509 TileDrawQuad* test_blending_draw_quad =
4510 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
4511 test_blending_draw_quad->SetNew(shared_quad_state,
4512 quad_rect_,
4513 opaque_rect,
4514 visible_quad_rect,
4515 resource_id_,
4516 gfx::RectF(0.f, 0.f, 1.f, 1.f),
4517 gfx::Size(1, 1),
4518 false,
4519 false);
4520 test_blending_draw_quad->visible_rect = quad_visible_rect_;
4521 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
4522 EXPECT_EQ(has_render_surface_, !!render_surface());
4525 void SetExpectation(bool blend, bool has_render_surface) {
4526 blend_ = blend;
4527 has_render_surface_ = has_render_surface;
4528 quads_appended_ = false;
4531 bool quads_appended() const { return quads_appended_; }
4533 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
4534 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
4535 void SetOpaqueContentRect(const gfx::Rect& rect) {
4536 opaque_content_rect_ = rect;
4539 private:
4540 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
4541 int id,
4542 ResourceProvider* resource_provider)
4543 : LayerImpl(tree_impl, id),
4544 blend_(false),
4545 has_render_surface_(false),
4546 quads_appended_(false),
4547 quad_rect_(5, 5, 5, 5),
4548 quad_visible_rect_(5, 5, 5, 5),
4549 resource_id_(resource_provider->CreateResource(
4550 gfx::Size(1, 1),
4551 GL_CLAMP_TO_EDGE,
4552 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
4553 RGBA_8888)) {
4554 resource_provider->AllocateForTesting(resource_id_);
4555 SetBounds(gfx::Size(10, 10));
4556 SetContentBounds(gfx::Size(10, 10));
4557 SetDrawsContent(true);
4560 bool blend_;
4561 bool has_render_surface_;
4562 bool quads_appended_;
4563 gfx::Rect quad_rect_;
4564 gfx::Rect opaque_content_rect_;
4565 gfx::Rect quad_visible_rect_;
4566 ResourceId resource_id_;
4569 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
4571 scoped_ptr<LayerImpl> root =
4572 LayerImpl::Create(host_impl_->active_tree(), 1);
4573 root->SetBounds(gfx::Size(10, 10));
4574 root->SetContentBounds(root->bounds());
4575 root->SetDrawsContent(false);
4576 root->SetHasRenderSurface(true);
4577 host_impl_->active_tree()->SetRootLayer(root.Pass());
4579 LayerImpl* root = host_impl_->active_tree()->root_layer();
4581 root->AddChild(
4582 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4584 host_impl_->resource_provider()));
4585 BlendStateCheckLayer* layer1 =
4586 static_cast<BlendStateCheckLayer*>(root->children()[0]);
4587 layer1->SetPosition(gfx::PointF(2.f, 2.f));
4589 LayerTreeHostImpl::FrameData frame;
4591 // Opaque layer, drawn without blending.
4592 layer1->SetContentsOpaque(true);
4593 layer1->SetExpectation(false, false);
4594 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4595 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4596 host_impl_->DrawLayers(&frame);
4597 EXPECT_TRUE(layer1->quads_appended());
4598 host_impl_->DidDrawAllLayers(frame);
4600 // Layer with translucent content and painting, so drawn with blending.
4601 layer1->SetContentsOpaque(false);
4602 layer1->SetExpectation(true, false);
4603 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4604 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4605 host_impl_->DrawLayers(&frame);
4606 EXPECT_TRUE(layer1->quads_appended());
4607 host_impl_->DidDrawAllLayers(frame);
4609 // Layer with translucent opacity, drawn with blending.
4610 layer1->SetContentsOpaque(true);
4611 layer1->SetOpacity(0.5f);
4612 layer1->SetExpectation(true, false);
4613 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4614 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4615 host_impl_->DrawLayers(&frame);
4616 EXPECT_TRUE(layer1->quads_appended());
4617 host_impl_->DidDrawAllLayers(frame);
4619 // Layer with translucent opacity and painting, drawn with blending.
4620 layer1->SetContentsOpaque(true);
4621 layer1->SetOpacity(0.5f);
4622 layer1->SetExpectation(true, false);
4623 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4624 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4625 host_impl_->DrawLayers(&frame);
4626 EXPECT_TRUE(layer1->quads_appended());
4627 host_impl_->DidDrawAllLayers(frame);
4629 layer1->AddChild(
4630 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4632 host_impl_->resource_provider()));
4633 BlendStateCheckLayer* layer2 =
4634 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
4635 layer2->SetPosition(gfx::PointF(4.f, 4.f));
4637 // 2 opaque layers, drawn without blending.
4638 layer1->SetContentsOpaque(true);
4639 layer1->SetOpacity(1.f);
4640 layer1->SetExpectation(false, false);
4641 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4642 layer2->SetContentsOpaque(true);
4643 layer2->SetOpacity(1.f);
4644 layer2->SetExpectation(false, false);
4645 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4646 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4647 host_impl_->DrawLayers(&frame);
4648 EXPECT_TRUE(layer1->quads_appended());
4649 EXPECT_TRUE(layer2->quads_appended());
4650 host_impl_->DidDrawAllLayers(frame);
4652 // Parent layer with translucent content, drawn with blending.
4653 // Child layer with opaque content, drawn without blending.
4654 layer1->SetContentsOpaque(false);
4655 layer1->SetExpectation(true, false);
4656 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4657 layer2->SetExpectation(false, false);
4658 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4659 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4660 host_impl_->DrawLayers(&frame);
4661 EXPECT_TRUE(layer1->quads_appended());
4662 EXPECT_TRUE(layer2->quads_appended());
4663 host_impl_->DidDrawAllLayers(frame);
4665 // Parent layer with translucent content but opaque painting, drawn without
4666 // blending.
4667 // Child layer with opaque content, drawn without blending.
4668 layer1->SetContentsOpaque(true);
4669 layer1->SetExpectation(false, false);
4670 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4671 layer2->SetExpectation(false, false);
4672 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4673 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4674 host_impl_->DrawLayers(&frame);
4675 EXPECT_TRUE(layer1->quads_appended());
4676 EXPECT_TRUE(layer2->quads_appended());
4677 host_impl_->DidDrawAllLayers(frame);
4679 // Parent layer with translucent opacity and opaque content. Since it has a
4680 // drawing child, it's drawn to a render surface which carries the opacity,
4681 // so it's itself drawn without blending.
4682 // Child layer with opaque content, drawn without blending (parent surface
4683 // carries the inherited opacity).
4684 layer1->SetContentsOpaque(true);
4685 layer1->SetOpacity(0.5f);
4686 layer1->SetHasRenderSurface(true);
4687 layer1->SetExpectation(false, true);
4688 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4689 layer2->SetExpectation(false, false);
4690 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4691 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
4692 host_impl_->active_tree()->root_layer());
4693 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4694 host_impl_->DrawLayers(&frame);
4695 EXPECT_TRUE(layer1->quads_appended());
4696 EXPECT_TRUE(layer2->quads_appended());
4697 host_impl_->DidDrawAllLayers(frame);
4698 layer1->SetHasRenderSurface(false);
4700 // Draw again, but with child non-opaque, to make sure
4701 // layer1 not culled.
4702 layer1->SetContentsOpaque(true);
4703 layer1->SetOpacity(1.f);
4704 layer1->SetExpectation(false, false);
4705 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4706 layer2->SetContentsOpaque(true);
4707 layer2->SetOpacity(0.5f);
4708 layer2->SetExpectation(true, false);
4709 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4710 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4711 host_impl_->DrawLayers(&frame);
4712 EXPECT_TRUE(layer1->quads_appended());
4713 EXPECT_TRUE(layer2->quads_appended());
4714 host_impl_->DidDrawAllLayers(frame);
4716 // A second way of making the child non-opaque.
4717 layer1->SetContentsOpaque(true);
4718 layer1->SetOpacity(1.f);
4719 layer1->SetExpectation(false, false);
4720 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4721 layer2->SetContentsOpaque(false);
4722 layer2->SetOpacity(1.f);
4723 layer2->SetExpectation(true, false);
4724 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4725 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4726 host_impl_->DrawLayers(&frame);
4727 EXPECT_TRUE(layer1->quads_appended());
4728 EXPECT_TRUE(layer2->quads_appended());
4729 host_impl_->DidDrawAllLayers(frame);
4731 // And when the layer says its not opaque but is painted opaque, it is not
4732 // blended.
4733 layer1->SetContentsOpaque(true);
4734 layer1->SetOpacity(1.f);
4735 layer1->SetExpectation(false, false);
4736 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4737 layer2->SetContentsOpaque(true);
4738 layer2->SetOpacity(1.f);
4739 layer2->SetExpectation(false, false);
4740 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4741 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4742 host_impl_->DrawLayers(&frame);
4743 EXPECT_TRUE(layer1->quads_appended());
4744 EXPECT_TRUE(layer2->quads_appended());
4745 host_impl_->DidDrawAllLayers(frame);
4747 // Layer with partially opaque contents, drawn with blending.
4748 layer1->SetContentsOpaque(false);
4749 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4750 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
4751 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4752 layer1->SetExpectation(true, false);
4753 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4754 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4755 host_impl_->DrawLayers(&frame);
4756 EXPECT_TRUE(layer1->quads_appended());
4757 host_impl_->DidDrawAllLayers(frame);
4759 // Layer with partially opaque contents partially culled, drawn with blending.
4760 layer1->SetContentsOpaque(false);
4761 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4762 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
4763 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4764 layer1->SetExpectation(true, false);
4765 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4766 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4767 host_impl_->DrawLayers(&frame);
4768 EXPECT_TRUE(layer1->quads_appended());
4769 host_impl_->DidDrawAllLayers(frame);
4771 // Layer with partially opaque contents culled, drawn with blending.
4772 layer1->SetContentsOpaque(false);
4773 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4774 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
4775 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4776 layer1->SetExpectation(true, false);
4777 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4778 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4779 host_impl_->DrawLayers(&frame);
4780 EXPECT_TRUE(layer1->quads_appended());
4781 host_impl_->DidDrawAllLayers(frame);
4783 // Layer with partially opaque contents and translucent contents culled, drawn
4784 // without blending.
4785 layer1->SetContentsOpaque(false);
4786 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4787 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
4788 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4789 layer1->SetExpectation(false, false);
4790 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4791 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4792 host_impl_->DrawLayers(&frame);
4793 EXPECT_TRUE(layer1->quads_appended());
4794 host_impl_->DidDrawAllLayers(frame);
4797 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
4798 protected:
4799 LayerTreeHostImplViewportCoveredTest() :
4800 gutter_quad_material_(DrawQuad::SOLID_COLOR),
4801 child_(NULL),
4802 did_activate_pending_tree_(false) {}
4804 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
4805 if (always_draw) {
4806 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
4808 return FakeOutputSurface::Create3d();
4811 void SetupActiveTreeLayers() {
4812 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
4813 host_impl_->active_tree()->SetRootLayer(
4814 LayerImpl::Create(host_impl_->active_tree(), 1));
4815 host_impl_->active_tree()->root_layer()->SetHasRenderSurface(true);
4816 host_impl_->active_tree()->root_layer()->AddChild(
4817 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4819 host_impl_->resource_provider()));
4820 child_ = static_cast<BlendStateCheckLayer*>(
4821 host_impl_->active_tree()->root_layer()->children()[0]);
4822 child_->SetExpectation(false, false);
4823 child_->SetContentsOpaque(true);
4826 // Expect no gutter rects.
4827 void TestLayerCoversFullViewport() {
4828 gfx::Rect layer_rect(viewport_size_);
4829 child_->SetPosition(layer_rect.origin());
4830 child_->SetBounds(layer_rect.size());
4831 child_->SetContentBounds(layer_rect.size());
4832 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4833 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4835 LayerTreeHostImpl::FrameData frame;
4836 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4837 ASSERT_EQ(1u, frame.render_passes.size());
4839 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
4840 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4841 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4843 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4844 host_impl_->DidDrawAllLayers(frame);
4847 // Expect fullscreen gutter rect.
4848 void TestEmptyLayer() {
4849 gfx::Rect layer_rect(0, 0, 0, 0);
4850 child_->SetPosition(layer_rect.origin());
4851 child_->SetBounds(layer_rect.size());
4852 child_->SetContentBounds(layer_rect.size());
4853 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4854 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4856 LayerTreeHostImpl::FrameData frame;
4857 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4858 ASSERT_EQ(1u, frame.render_passes.size());
4860 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
4861 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4862 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4864 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4865 host_impl_->DidDrawAllLayers(frame);
4868 // Expect four surrounding gutter rects.
4869 void TestLayerInMiddleOfViewport() {
4870 gfx::Rect layer_rect(500, 500, 200, 200);
4871 child_->SetPosition(layer_rect.origin());
4872 child_->SetBounds(layer_rect.size());
4873 child_->SetContentBounds(layer_rect.size());
4874 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4875 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4877 LayerTreeHostImpl::FrameData frame;
4878 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4879 ASSERT_EQ(1u, frame.render_passes.size());
4881 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
4882 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
4883 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4885 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4886 host_impl_->DidDrawAllLayers(frame);
4889 // Expect no gutter rects.
4890 void TestLayerIsLargerThanViewport() {
4891 gfx::Rect layer_rect(viewport_size_.width() + 10,
4892 viewport_size_.height() + 10);
4893 child_->SetPosition(layer_rect.origin());
4894 child_->SetBounds(layer_rect.size());
4895 child_->SetContentBounds(layer_rect.size());
4896 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4897 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4899 LayerTreeHostImpl::FrameData frame;
4900 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4901 ASSERT_EQ(1u, frame.render_passes.size());
4903 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
4904 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4905 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4907 host_impl_->DidDrawAllLayers(frame);
4910 void DidActivateSyncTree() override { did_activate_pending_tree_ = true; }
4912 void set_gutter_quad_material(DrawQuad::Material material) {
4913 gutter_quad_material_ = material;
4915 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
4916 gutter_texture_size_ = gutter_texture_size;
4919 protected:
4920 size_t CountGutterQuads(const QuadList& quad_list) {
4921 size_t num_gutter_quads = 0;
4922 for (const auto& quad : quad_list) {
4923 num_gutter_quads += (quad->material == gutter_quad_material_) ? 1 : 0;
4925 return num_gutter_quads;
4928 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
4929 LayerTestCommon::VerifyQuadsExactlyCoverRect(
4930 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
4933 // Make sure that the texture coordinates match their expectations.
4934 void ValidateTextureDrawQuads(const QuadList& quad_list) {
4935 for (const auto& quad : quad_list) {
4936 if (quad->material != DrawQuad::TEXTURE_CONTENT)
4937 continue;
4938 const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
4939 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
4940 gutter_texture_size_, host_impl_->device_scale_factor());
4941 EXPECT_EQ(texture_quad->uv_top_left.x(),
4942 texture_quad->rect.x() / gutter_texture_size_pixels.width());
4943 EXPECT_EQ(texture_quad->uv_top_left.y(),
4944 texture_quad->rect.y() / gutter_texture_size_pixels.height());
4945 EXPECT_EQ(
4946 texture_quad->uv_bottom_right.x(),
4947 texture_quad->rect.right() / gutter_texture_size_pixels.width());
4948 EXPECT_EQ(
4949 texture_quad->uv_bottom_right.y(),
4950 texture_quad->rect.bottom() / gutter_texture_size_pixels.height());
4954 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
4955 return gfx::ToRoundedSize(
4956 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
4959 DrawQuad::Material gutter_quad_material_;
4960 gfx::Size gutter_texture_size_;
4961 gfx::Size viewport_size_;
4962 BlendStateCheckLayer* child_;
4963 bool did_activate_pending_tree_;
4966 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
4967 viewport_size_ = gfx::Size(1000, 1000);
4969 bool always_draw = false;
4970 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4972 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4973 SetupActiveTreeLayers();
4974 TestLayerCoversFullViewport();
4975 TestEmptyLayer();
4976 TestLayerInMiddleOfViewport();
4977 TestLayerIsLargerThanViewport();
4980 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
4981 viewport_size_ = gfx::Size(1000, 1000);
4983 bool always_draw = false;
4984 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4986 host_impl_->SetDeviceScaleFactor(2.f);
4987 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4988 SetupActiveTreeLayers();
4989 TestLayerCoversFullViewport();
4990 TestEmptyLayer();
4991 TestLayerInMiddleOfViewport();
4992 TestLayerIsLargerThanViewport();
4995 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
4996 viewport_size_ = gfx::Size(1000, 1000);
4998 bool always_draw = true;
4999 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5001 // Pending tree to force active_tree size invalid. Not used otherwise.
5002 host_impl_->CreatePendingTree();
5003 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5004 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5006 SetupActiveTreeLayers();
5007 TestEmptyLayer();
5008 TestLayerInMiddleOfViewport();
5009 TestLayerIsLargerThanViewport();
5012 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
5013 viewport_size_ = gfx::Size(1000, 1000);
5015 bool always_draw = true;
5016 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5018 // Set larger viewport and activate it to active tree.
5019 host_impl_->CreatePendingTree();
5020 gfx::Size larger_viewport(viewport_size_.width() + 100,
5021 viewport_size_.height() + 100);
5022 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
5023 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5024 host_impl_->ActivateSyncTree();
5025 EXPECT_TRUE(did_activate_pending_tree_);
5026 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
5028 // Shrink pending tree viewport without activating.
5029 host_impl_->CreatePendingTree();
5030 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5031 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5033 SetupActiveTreeLayers();
5034 TestEmptyLayer();
5035 TestLayerInMiddleOfViewport();
5036 TestLayerIsLargerThanViewport();
5039 class FakeDrawableLayerImpl: public LayerImpl {
5040 public:
5041 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5042 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl, id));
5044 protected:
5045 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
5046 : LayerImpl(tree_impl, id) {}
5049 // Only reshape when we know we are going to draw. Otherwise, the reshape
5050 // can leave the window at the wrong size if we never draw and the proper
5051 // viewport size is never set.
5052 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
5053 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5054 scoped_ptr<OutputSurface> output_surface(
5055 FakeOutputSurface::Create3d(provider));
5056 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5058 scoped_ptr<LayerImpl> root =
5059 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5060 root->SetBounds(gfx::Size(10, 10));
5061 root->SetContentBounds(gfx::Size(10, 10));
5062 root->SetDrawsContent(true);
5063 root->SetHasRenderSurface(true);
5064 host_impl_->active_tree()->SetRootLayer(root.Pass());
5065 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
5066 provider->TestContext3d()->clear_reshape_called();
5068 LayerTreeHostImpl::FrameData frame;
5069 host_impl_->SetViewportSize(gfx::Size(10, 10));
5070 host_impl_->SetDeviceScaleFactor(1.f);
5071 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5072 host_impl_->DrawLayers(&frame);
5073 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5074 EXPECT_EQ(provider->TestContext3d()->width(), 10);
5075 EXPECT_EQ(provider->TestContext3d()->height(), 10);
5076 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5077 host_impl_->DidDrawAllLayers(frame);
5078 provider->TestContext3d()->clear_reshape_called();
5080 host_impl_->SetViewportSize(gfx::Size(20, 30));
5081 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5082 host_impl_->DrawLayers(&frame);
5083 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5084 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5085 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5086 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5087 host_impl_->DidDrawAllLayers(frame);
5088 provider->TestContext3d()->clear_reshape_called();
5090 host_impl_->SetDeviceScaleFactor(2.f);
5091 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5092 host_impl_->DrawLayers(&frame);
5093 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5094 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5095 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5096 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
5097 host_impl_->DidDrawAllLayers(frame);
5098 provider->TestContext3d()->clear_reshape_called();
5101 // Make sure damage tracking propagates all the way to the graphics context,
5102 // where it should request to swap only the sub-buffer that is damaged.
5103 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
5104 scoped_refptr<TestContextProvider> context_provider(
5105 TestContextProvider::Create());
5106 context_provider->BindToCurrentThread();
5107 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
5109 scoped_ptr<FakeOutputSurface> output_surface(
5110 FakeOutputSurface::Create3d(context_provider));
5111 FakeOutputSurface* fake_output_surface = output_surface.get();
5113 // This test creates its own LayerTreeHostImpl, so
5114 // that we can force partial swap enabled.
5115 LayerTreeSettings settings;
5116 settings.renderer_settings.partial_swap_enabled = true;
5117 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
5118 LayerTreeHostImpl::Create(
5119 settings, this, &proxy_, &stats_instrumentation_,
5120 shared_bitmap_manager_.get(), NULL, task_graph_runner_.get(), 0);
5121 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
5122 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
5124 scoped_ptr<LayerImpl> root =
5125 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
5126 root->SetHasRenderSurface(true);
5127 scoped_ptr<LayerImpl> child =
5128 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
5129 child->SetPosition(gfx::PointF(12.f, 13.f));
5130 child->SetBounds(gfx::Size(14, 15));
5131 child->SetContentBounds(gfx::Size(14, 15));
5132 child->SetDrawsContent(true);
5133 root->SetBounds(gfx::Size(500, 500));
5134 root->SetContentBounds(gfx::Size(500, 500));
5135 root->SetDrawsContent(true);
5136 root->AddChild(child.Pass());
5137 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
5139 LayerTreeHostImpl::FrameData frame;
5141 // First frame, the entire screen should get swapped.
5142 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5143 layer_tree_host_impl->DrawLayers(&frame);
5144 layer_tree_host_impl->DidDrawAllLayers(frame);
5145 layer_tree_host_impl->SwapBuffers(frame);
5146 gfx::Rect expected_swap_rect(0, 0, 500, 500);
5147 EXPECT_EQ(expected_swap_rect.ToString(),
5148 fake_output_surface->last_swap_rect().ToString());
5150 // Second frame, only the damaged area should get swapped. Damage should be
5151 // the union of old and new child rects.
5152 // expected damage rect: gfx::Rect(26, 28);
5153 // expected swap rect: vertically flipped, with origin at bottom left corner.
5154 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
5155 gfx::PointF());
5156 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5157 layer_tree_host_impl->DrawLayers(&frame);
5158 host_impl_->DidDrawAllLayers(frame);
5159 layer_tree_host_impl->SwapBuffers(frame);
5161 // Make sure that partial swap is constrained to the viewport dimensions
5162 // expected damage rect: gfx::Rect(500, 500);
5163 // expected swap rect: flipped damage rect, but also clamped to viewport
5164 expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
5165 EXPECT_EQ(expected_swap_rect.ToString(),
5166 fake_output_surface->last_swap_rect().ToString());
5168 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
5169 // This will damage everything.
5170 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
5171 SK_ColorBLACK);
5172 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5173 layer_tree_host_impl->DrawLayers(&frame);
5174 host_impl_->DidDrawAllLayers(frame);
5175 layer_tree_host_impl->SwapBuffers(frame);
5177 expected_swap_rect = gfx::Rect(0, 0, 10, 10);
5178 EXPECT_EQ(expected_swap_rect.ToString(),
5179 fake_output_surface->last_swap_rect().ToString());
5182 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
5183 scoped_ptr<LayerImpl> root =
5184 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5185 scoped_ptr<LayerImpl> child =
5186 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
5187 child->SetBounds(gfx::Size(10, 10));
5188 child->SetContentBounds(gfx::Size(10, 10));
5189 child->SetDrawsContent(true);
5190 root->SetBounds(gfx::Size(10, 10));
5191 root->SetContentBounds(gfx::Size(10, 10));
5192 root->SetDrawsContent(true);
5193 root->SetHasRenderSurface(true);
5194 root->AddChild(child.Pass());
5196 host_impl_->active_tree()->SetRootLayer(root.Pass());
5198 LayerTreeHostImpl::FrameData frame;
5200 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5201 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
5202 EXPECT_EQ(1u, frame.render_passes.size());
5203 host_impl_->DidDrawAllLayers(frame);
5206 class FakeLayerWithQuads : public LayerImpl {
5207 public:
5208 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5209 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl, id));
5212 void AppendQuads(RenderPass* render_pass,
5213 AppendQuadsData* append_quads_data) override {
5214 SharedQuadState* shared_quad_state =
5215 render_pass->CreateAndAppendSharedQuadState();
5216 PopulateSharedQuadState(shared_quad_state);
5218 SkColor gray = SkColorSetRGB(100, 100, 100);
5219 gfx::Rect quad_rect(content_bounds());
5220 gfx::Rect visible_quad_rect(quad_rect);
5221 SolidColorDrawQuad* my_quad =
5222 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
5223 my_quad->SetNew(
5224 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
5227 private:
5228 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
5229 : LayerImpl(tree_impl, id) {}
5232 class MockContext : public TestWebGraphicsContext3D {
5233 public:
5234 MOCK_METHOD1(useProgram, void(GLuint program));
5235 MOCK_METHOD5(uniform4f, void(GLint location,
5236 GLfloat x,
5237 GLfloat y,
5238 GLfloat z,
5239 GLfloat w));
5240 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
5241 GLsizei count,
5242 GLboolean transpose,
5243 const GLfloat* value));
5244 MOCK_METHOD4(drawElements, void(GLenum mode,
5245 GLsizei count,
5246 GLenum type,
5247 GLintptr offset));
5248 MOCK_METHOD1(enable, void(GLenum cap));
5249 MOCK_METHOD1(disable, void(GLenum cap));
5250 MOCK_METHOD4(scissor, void(GLint x,
5251 GLint y,
5252 GLsizei width,
5253 GLsizei height));
5256 class MockContextHarness {
5257 private:
5258 MockContext* context_;
5260 public:
5261 explicit MockContextHarness(MockContext* context)
5262 : context_(context) {
5263 context_->set_have_post_sub_buffer(true);
5265 // Catch "uninteresting" calls
5266 EXPECT_CALL(*context_, useProgram(_))
5267 .Times(0);
5269 EXPECT_CALL(*context_, drawElements(_, _, _, _))
5270 .Times(0);
5272 // These are not asserted
5273 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
5274 .WillRepeatedly(Return());
5276 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
5277 .WillRepeatedly(Return());
5279 // Any un-sanctioned calls to enable() are OK
5280 EXPECT_CALL(*context_, enable(_))
5281 .WillRepeatedly(Return());
5283 // Any un-sanctioned calls to disable() are OK
5284 EXPECT_CALL(*context_, disable(_))
5285 .WillRepeatedly(Return());
5288 void MustDrawSolidQuad() {
5289 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
5290 .WillOnce(Return())
5291 .RetiresOnSaturation();
5293 EXPECT_CALL(*context_, useProgram(_))
5294 .WillOnce(Return())
5295 .RetiresOnSaturation();
5298 void MustSetScissor(int x, int y, int width, int height) {
5299 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5300 .WillRepeatedly(Return());
5302 EXPECT_CALL(*context_, scissor(x, y, width, height))
5303 .Times(AtLeast(1))
5304 .WillRepeatedly(Return());
5307 void MustSetNoScissor() {
5308 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
5309 .WillRepeatedly(Return());
5311 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5312 .Times(0);
5314 EXPECT_CALL(*context_, scissor(_, _, _, _))
5315 .Times(0);
5319 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
5320 scoped_ptr<MockContext> mock_context_owned(new MockContext);
5321 MockContext* mock_context = mock_context_owned.get();
5322 MockContextHarness harness(mock_context);
5324 // Run test case
5325 LayerTreeSettings settings = DefaultSettings();
5326 settings.renderer_settings.partial_swap_enabled = false;
5327 CreateHostImpl(settings,
5328 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5329 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5331 // Without partial swap, and no clipping, no scissor is set.
5332 harness.MustDrawSolidQuad();
5333 harness.MustSetNoScissor();
5335 LayerTreeHostImpl::FrameData frame;
5336 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5337 host_impl_->DrawLayers(&frame);
5338 host_impl_->DidDrawAllLayers(frame);
5340 Mock::VerifyAndClearExpectations(&mock_context);
5342 // Without partial swap, but a layer does clip its subtree, one scissor is
5343 // set.
5344 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
5345 harness.MustDrawSolidQuad();
5346 harness.MustSetScissor(0, 0, 10, 10);
5348 LayerTreeHostImpl::FrameData frame;
5349 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5350 host_impl_->DrawLayers(&frame);
5351 host_impl_->DidDrawAllLayers(frame);
5353 Mock::VerifyAndClearExpectations(&mock_context);
5356 TEST_F(LayerTreeHostImplTest, PartialSwap) {
5357 scoped_ptr<MockContext> context_owned(new MockContext);
5358 MockContext* mock_context = context_owned.get();
5359 MockContextHarness harness(mock_context);
5361 LayerTreeSettings settings = DefaultSettings();
5362 settings.renderer_settings.partial_swap_enabled = true;
5363 CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass()));
5364 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5366 // The first frame is not a partially-swapped one. No scissor should be set.
5367 harness.MustSetNoScissor();
5368 harness.MustDrawSolidQuad();
5370 LayerTreeHostImpl::FrameData frame;
5371 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5372 host_impl_->DrawLayers(&frame);
5373 host_impl_->DidDrawAllLayers(frame);
5375 Mock::VerifyAndClearExpectations(&mock_context);
5377 // Damage a portion of the frame.
5378 host_impl_->active_tree()->root_layer()->SetUpdateRect(
5379 gfx::Rect(0, 0, 2, 3));
5381 // The second frame will be partially-swapped (the y coordinates are flipped).
5382 harness.MustSetScissor(0, 7, 2, 3);
5383 harness.MustDrawSolidQuad();
5385 LayerTreeHostImpl::FrameData frame;
5386 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5387 host_impl_->DrawLayers(&frame);
5388 host_impl_->DidDrawAllLayers(frame);
5390 Mock::VerifyAndClearExpectations(&mock_context);
5393 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
5394 bool partial_swap,
5395 LayerTreeHostImplClient* client,
5396 Proxy* proxy,
5397 SharedBitmapManager* manager,
5398 RenderingStatsInstrumentation* stats_instrumentation) {
5399 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5400 scoped_ptr<OutputSurface> output_surface(
5401 FakeOutputSurface::Create3d(provider));
5402 provider->BindToCurrentThread();
5403 provider->TestContext3d()->set_have_post_sub_buffer(true);
5405 LayerTreeSettings settings;
5406 settings.renderer_settings.partial_swap_enabled = partial_swap;
5407 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
5408 settings, client, proxy, stats_instrumentation, manager, NULL, NULL, 0);
5409 my_host_impl->InitializeRenderer(output_surface.Pass());
5410 my_host_impl->SetViewportSize(gfx::Size(100, 100));
5413 Layers are created as follows:
5415 +--------------------+
5416 | 1 |
5417 | +-----------+ |
5418 | | 2 | |
5419 | | +-------------------+
5420 | | | 3 |
5421 | | +-------------------+
5422 | | | |
5423 | +-----------+ |
5426 +--------------------+
5428 Layers 1, 2 have render surfaces
5430 scoped_ptr<LayerImpl> root =
5431 LayerImpl::Create(my_host_impl->active_tree(), 1);
5432 scoped_ptr<LayerImpl> child =
5433 LayerImpl::Create(my_host_impl->active_tree(), 2);
5434 scoped_ptr<LayerImpl> grand_child =
5435 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
5437 gfx::Rect root_rect(0, 0, 100, 100);
5438 gfx::Rect child_rect(10, 10, 50, 50);
5439 gfx::Rect grand_child_rect(5, 5, 150, 150);
5441 root->SetHasRenderSurface(true);
5442 root->SetPosition(root_rect.origin());
5443 root->SetBounds(root_rect.size());
5444 root->SetContentBounds(root->bounds());
5445 root->draw_properties().visible_content_rect = root_rect;
5446 root->SetDrawsContent(false);
5447 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
5449 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
5450 child->SetOpacity(0.5f);
5451 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
5452 child->SetContentBounds(child->bounds());
5453 child->draw_properties().visible_content_rect = child_rect;
5454 child->SetDrawsContent(false);
5455 child->SetHasRenderSurface(true);
5457 grand_child->SetPosition(grand_child_rect.origin());
5458 grand_child->SetBounds(grand_child_rect.size());
5459 grand_child->SetContentBounds(grand_child->bounds());
5460 grand_child->draw_properties().visible_content_rect = grand_child_rect;
5461 grand_child->SetDrawsContent(true);
5463 child->AddChild(grand_child.Pass());
5464 root->AddChild(child.Pass());
5466 my_host_impl->active_tree()->SetRootLayer(root.Pass());
5467 return my_host_impl.Pass();
5470 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
5471 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
5472 new TestSharedBitmapManager());
5473 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5474 SetupLayersForOpacity(true,
5475 this,
5476 &proxy_,
5477 shared_bitmap_manager.get(),
5478 &stats_instrumentation_);
5480 LayerTreeHostImpl::FrameData frame;
5481 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5483 // Verify all quads have been computed
5484 ASSERT_EQ(2U, frame.render_passes.size());
5485 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5486 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5487 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5488 frame.render_passes[0]->quad_list.front()->material);
5489 EXPECT_EQ(DrawQuad::RENDER_PASS,
5490 frame.render_passes[1]->quad_list.front()->material);
5492 my_host_impl->DrawLayers(&frame);
5493 my_host_impl->DidDrawAllLayers(frame);
5497 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
5498 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
5499 new TestSharedBitmapManager());
5500 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5501 SetupLayersForOpacity(false,
5502 this,
5503 &proxy_,
5504 shared_bitmap_manager.get(),
5505 &stats_instrumentation_);
5507 LayerTreeHostImpl::FrameData frame;
5508 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5510 // Verify all quads have been computed
5511 ASSERT_EQ(2U, frame.render_passes.size());
5512 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5513 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5514 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5515 frame.render_passes[0]->quad_list.front()->material);
5516 EXPECT_EQ(DrawQuad::RENDER_PASS,
5517 frame.render_passes[1]->quad_list.front()->material);
5519 my_host_impl->DrawLayers(&frame);
5520 my_host_impl->DidDrawAllLayers(frame);
5524 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
5525 scoped_ptr<TestWebGraphicsContext3D> context =
5526 TestWebGraphicsContext3D::Create();
5527 TestWebGraphicsContext3D* context3d = context.get();
5528 scoped_ptr<OutputSurface> output_surface(
5529 FakeOutputSurface::Create3d(context.Pass()));
5530 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5532 scoped_ptr<LayerImpl> root_layer =
5533 LayerImpl::Create(host_impl_->active_tree(), 1);
5534 root_layer->SetBounds(gfx::Size(10, 10));
5535 root_layer->SetHasRenderSurface(true);
5537 scoped_refptr<VideoFrame> softwareFrame =
5538 media::VideoFrame::CreateColorFrame(
5539 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5540 FakeVideoFrameProvider provider;
5541 provider.set_frame(softwareFrame);
5542 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
5543 host_impl_->active_tree(), 4, &provider, media::VIDEO_ROTATION_0);
5544 video_layer->SetBounds(gfx::Size(10, 10));
5545 video_layer->SetContentBounds(gfx::Size(10, 10));
5546 video_layer->SetDrawsContent(true);
5547 root_layer->AddChild(video_layer.Pass());
5549 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
5550 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
5551 io_surface_layer->SetBounds(gfx::Size(10, 10));
5552 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
5553 io_surface_layer->SetDrawsContent(true);
5554 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5555 root_layer->AddChild(io_surface_layer.Pass());
5557 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
5559 EXPECT_EQ(0u, context3d->NumTextures());
5561 LayerTreeHostImpl::FrameData frame;
5562 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5563 host_impl_->DrawLayers(&frame);
5564 host_impl_->DidDrawAllLayers(frame);
5565 host_impl_->SwapBuffers(frame);
5567 EXPECT_GT(context3d->NumTextures(), 0u);
5569 // Kill the layer tree.
5570 host_impl_->active_tree()->SetRootLayer(
5571 LayerImpl::Create(host_impl_->active_tree(), 100));
5572 // There should be no textures left in use after.
5573 EXPECT_EQ(0u, context3d->NumTextures());
5576 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
5577 public:
5578 MOCK_METHOD1(useProgram, void(GLuint program));
5579 MOCK_METHOD4(drawElements, void(GLenum mode,
5580 GLsizei count,
5581 GLenum type,
5582 GLintptr offset));
5585 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
5586 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
5587 new MockDrawQuadsToFillScreenContext);
5588 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
5590 // Run test case
5591 LayerTreeSettings settings = DefaultSettings();
5592 settings.renderer_settings.partial_swap_enabled = false;
5593 CreateHostImpl(settings,
5594 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5595 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5596 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
5598 // Verify one quad is drawn when transparent background set is not set.
5599 host_impl_->active_tree()->set_has_transparent_background(false);
5600 EXPECT_CALL(*mock_context, useProgram(_))
5601 .Times(1);
5602 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
5603 .Times(1);
5604 LayerTreeHostImpl::FrameData frame;
5605 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5606 host_impl_->DrawLayers(&frame);
5607 host_impl_->DidDrawAllLayers(frame);
5608 Mock::VerifyAndClearExpectations(&mock_context);
5610 // Verify no quads are drawn when transparent background is set.
5611 host_impl_->active_tree()->set_has_transparent_background(true);
5612 host_impl_->SetFullRootLayerDamage();
5613 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5614 host_impl_->DrawLayers(&frame);
5615 host_impl_->DidDrawAllLayers(frame);
5616 Mock::VerifyAndClearExpectations(&mock_context);
5619 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
5620 set_reduce_memory_result(false);
5622 // If changing the memory limit wouldn't result in changing what was
5623 // committed, then no commit should be requested.
5624 set_reduce_memory_result(false);
5625 host_impl_->set_max_memory_needed_bytes(
5626 host_impl_->memory_allocation_limit_bytes() - 1);
5627 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5628 host_impl_->memory_allocation_limit_bytes() - 1));
5629 EXPECT_FALSE(did_request_commit_);
5630 did_request_commit_ = false;
5632 // If changing the memory limit would result in changing what was
5633 // committed, then a commit should be requested, even though nothing was
5634 // evicted.
5635 set_reduce_memory_result(false);
5636 host_impl_->set_max_memory_needed_bytes(
5637 host_impl_->memory_allocation_limit_bytes());
5638 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5639 host_impl_->memory_allocation_limit_bytes() - 1));
5640 EXPECT_TRUE(did_request_commit_);
5641 did_request_commit_ = false;
5643 // Especially if changing the memory limit caused evictions, we need
5644 // to re-commit.
5645 set_reduce_memory_result(true);
5646 host_impl_->set_max_memory_needed_bytes(1);
5647 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5648 host_impl_->memory_allocation_limit_bytes() - 1));
5649 EXPECT_TRUE(did_request_commit_);
5650 did_request_commit_ = false;
5652 // But if we set it to the same value that it was before, we shouldn't
5653 // re-commit.
5654 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5655 host_impl_->memory_allocation_limit_bytes()));
5656 EXPECT_FALSE(did_request_commit_);
5659 class LayerTreeHostImplTestWithDelegatingRenderer
5660 : public LayerTreeHostImplTest {
5661 protected:
5662 scoped_ptr<OutputSurface> CreateOutputSurface() override {
5663 return FakeOutputSurface::CreateDelegating3d();
5666 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
5667 bool expect_to_draw = !expected_damage.IsEmpty();
5669 LayerTreeHostImpl::FrameData frame;
5670 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5672 if (!expect_to_draw) {
5673 // With no damage, we don't draw, and no quads are created.
5674 ASSERT_EQ(0u, frame.render_passes.size());
5675 } else {
5676 ASSERT_EQ(1u, frame.render_passes.size());
5678 // Verify the damage rect for the root render pass.
5679 const RenderPass* root_render_pass = frame.render_passes.back();
5680 EXPECT_EQ(expected_damage, root_render_pass->damage_rect);
5682 // Verify the root and child layers' quads are generated and not being
5683 // culled.
5684 ASSERT_EQ(2u, root_render_pass->quad_list.size());
5686 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
5687 gfx::RectF expected_child_visible_rect(child->content_bounds());
5688 EXPECT_EQ(expected_child_visible_rect,
5689 root_render_pass->quad_list.front()->visible_rect);
5691 LayerImpl* root = host_impl_->active_tree()->root_layer();
5692 gfx::RectF expected_root_visible_rect(root->content_bounds());
5693 EXPECT_EQ(expected_root_visible_rect,
5694 root_render_pass->quad_list.ElementAt(1)->visible_rect);
5697 host_impl_->DrawLayers(&frame);
5698 host_impl_->DidDrawAllLayers(frame);
5699 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
5703 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
5704 scoped_ptr<SolidColorLayerImpl> root =
5705 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5706 root->SetPosition(gfx::PointF());
5707 root->SetBounds(gfx::Size(10, 10));
5708 root->SetContentBounds(gfx::Size(10, 10));
5709 root->SetDrawsContent(true);
5710 root->SetHasRenderSurface(true);
5712 // Child layer is in the bottom right corner.
5713 scoped_ptr<SolidColorLayerImpl> child =
5714 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
5715 child->SetPosition(gfx::PointF(9.f, 9.f));
5716 child->SetBounds(gfx::Size(1, 1));
5717 child->SetContentBounds(gfx::Size(1, 1));
5718 child->SetDrawsContent(true);
5719 root->AddChild(child.Pass());
5721 host_impl_->active_tree()->SetRootLayer(root.Pass());
5723 // Draw a frame. In the first frame, the entire viewport should be damaged.
5724 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
5725 DrawFrameAndTestDamage(full_frame_damage);
5727 // The second frame has damage that doesn't touch the child layer. Its quads
5728 // should still be generated.
5729 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
5730 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
5731 DrawFrameAndTestDamage(small_damage);
5733 // The third frame should have no damage, so no quads should be generated.
5734 gfx::Rect no_damage;
5735 DrawFrameAndTestDamage(no_damage);
5738 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5739 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5740 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
5741 LayerTreeSettings settings;
5742 CreateHostImpl(settings, CreateOutputSurface());
5743 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
5746 class FakeMaskLayerImpl : public LayerImpl {
5747 public:
5748 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
5749 int id) {
5750 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
5753 void GetContentsResourceId(ResourceId* resource_id,
5754 gfx::Size* resource_size) const override {
5755 *resource_id = 0;
5758 private:
5759 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
5760 : LayerImpl(tree_impl, id) {}
5763 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
5764 public:
5765 using GLRenderer::ShouldAntialiasQuad;
5768 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
5769 // Due to precision issues (especially on Android), sometimes far
5770 // away quads can end up thinking they need AA.
5771 float device_scale_factor = 4.f / 3.f;
5772 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5773 gfx::Size root_size(2000, 1000);
5774 gfx::Size device_viewport_size =
5775 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
5776 host_impl_->SetViewportSize(device_viewport_size);
5778 host_impl_->CreatePendingTree();
5779 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f,
5780 16.f);
5782 scoped_ptr<LayerImpl> scoped_root =
5783 LayerImpl::Create(host_impl_->pending_tree(), 1);
5784 LayerImpl* root = scoped_root.get();
5785 root->SetHasRenderSurface(true);
5787 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
5789 scoped_ptr<LayerImpl> scoped_scrolling_layer =
5790 LayerImpl::Create(host_impl_->pending_tree(), 2);
5791 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
5792 root->AddChild(scoped_scrolling_layer.Pass());
5794 gfx::Size content_layer_bounds(100000, 100);
5795 gfx::Size pile_tile_size(3000, 3000);
5796 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
5797 pile_tile_size, content_layer_bounds));
5799 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
5800 FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(),
5801 3, pile);
5802 LayerImpl* content_layer = scoped_content_layer.get();
5803 scrolling_layer->AddChild(scoped_content_layer.Pass());
5804 content_layer->SetBounds(content_layer_bounds);
5805 content_layer->SetDrawsContent(true);
5807 root->SetBounds(root_size);
5809 gfx::ScrollOffset scroll_offset(100000, 0);
5810 scrolling_layer->SetScrollClipLayer(root->id());
5811 scrolling_layer->PushScrollOffsetFromMainThread(scroll_offset);
5813 host_impl_->ActivateSyncTree();
5815 bool update_lcd_text = false;
5816 host_impl_->active_tree()->UpdateDrawProperties(update_lcd_text);
5817 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
5819 LayerTreeHostImpl::FrameData frame;
5820 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5822 ASSERT_EQ(1u, frame.render_passes.size());
5823 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
5824 const DrawQuad* quad = frame.render_passes[0]->quad_list.front();
5826 bool antialiased =
5827 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
5828 quad->quadTransform(), quad, false);
5829 EXPECT_FALSE(antialiased);
5831 host_impl_->DrawLayers(&frame);
5832 host_impl_->DidDrawAllLayers(frame);
5836 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
5837 public:
5838 CompositorFrameMetadataTest()
5839 : swap_buffers_complete_(0) {}
5841 void DidSwapBuffersCompleteOnImplThread() override {
5842 swap_buffers_complete_++;
5845 int swap_buffers_complete_;
5848 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
5849 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5851 LayerTreeHostImpl::FrameData frame;
5852 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5853 host_impl_->DrawLayers(&frame);
5854 host_impl_->DidDrawAllLayers(frame);
5856 CompositorFrameAck ack;
5857 host_impl_->ReclaimResources(&ack);
5858 host_impl_->DidSwapBuffersComplete();
5859 EXPECT_EQ(swap_buffers_complete_, 1);
5862 class CountingSoftwareDevice : public SoftwareOutputDevice {
5863 public:
5864 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5866 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
5867 ++frames_began_;
5868 return SoftwareOutputDevice::BeginPaint(damage_rect);
5870 void EndPaint(SoftwareFrameData* frame_data) override {
5871 ++frames_ended_;
5872 SoftwareOutputDevice::EndPaint(frame_data);
5875 int frames_began_, frames_ended_;
5878 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
5879 // No main thread evictions in resourceless software mode.
5880 set_reduce_memory_result(false);
5881 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
5882 EXPECT_TRUE(CreateHostImpl(
5883 DefaultSettings(),
5884 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device))));
5885 host_impl_->SetViewportSize(gfx::Size(50, 50));
5887 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5889 const gfx::Transform external_transform;
5890 const gfx::Rect external_viewport;
5891 const gfx::Rect external_clip;
5892 const bool resourceless_software_draw = true;
5893 host_impl_->SetExternalDrawConstraints(external_transform,
5894 external_viewport,
5895 external_clip,
5896 external_viewport,
5897 external_transform,
5898 resourceless_software_draw);
5900 EXPECT_EQ(0, software_device->frames_began_);
5901 EXPECT_EQ(0, software_device->frames_ended_);
5903 DrawFrame();
5905 EXPECT_EQ(1, software_device->frames_began_);
5906 EXPECT_EQ(1, software_device->frames_ended_);
5908 // Call another API method that is likely to hit nullptr in this mode.
5909 scoped_refptr<base::trace_event::TracedValue> state =
5910 make_scoped_refptr(new base::trace_event::TracedValue());
5911 host_impl_->ActivationStateAsValueInto(state.get());
5914 TEST_F(LayerTreeHostImplTest,
5915 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
5916 set_reduce_memory_result(false);
5917 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5918 FakeOutputSurface::CreateSoftware(
5919 make_scoped_ptr(new CountingSoftwareDevice))));
5921 const gfx::Transform external_transform;
5922 const gfx::Rect external_viewport;
5923 const gfx::Rect external_clip;
5924 const bool resourceless_software_draw = true;
5925 host_impl_->SetExternalDrawConstraints(external_transform,
5926 external_viewport,
5927 external_clip,
5928 external_viewport,
5929 external_transform,
5930 resourceless_software_draw);
5932 // SolidColorLayerImpl will be drawn.
5933 scoped_ptr<SolidColorLayerImpl> root_layer =
5934 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5936 // VideoLayerImpl will not be drawn.
5937 FakeVideoFrameProvider provider;
5938 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
5939 host_impl_->active_tree(), 2, &provider, media::VIDEO_ROTATION_0);
5940 video_layer->SetBounds(gfx::Size(10, 10));
5941 video_layer->SetContentBounds(gfx::Size(10, 10));
5942 video_layer->SetDrawsContent(true);
5943 root_layer->AddChild(video_layer.Pass());
5944 SetupRootLayerImpl(root_layer.Pass());
5946 LayerTreeHostImpl::FrameData frame;
5947 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5948 host_impl_->DrawLayers(&frame);
5949 host_impl_->DidDrawAllLayers(frame);
5951 EXPECT_EQ(1u, frame.will_draw_layers.size());
5952 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
5955 // Checks that we have a non-0 default allocation if we pass a context that
5956 // doesn't support memory management extensions.
5957 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5958 LayerTreeSettings settings;
5959 host_impl_ = LayerTreeHostImpl::Create(
5960 settings, this, &proxy_, &stats_instrumentation_,
5961 shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(),
5962 task_graph_runner_.get(), 0);
5964 scoped_ptr<OutputSurface> output_surface(
5965 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5966 host_impl_->InitializeRenderer(output_surface.Pass());
5967 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5970 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5971 ManagedMemoryPolicy policy1(
5972 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5973 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5974 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5975 int allow_nice_to_have_cutoff_value =
5976 ManagedMemoryPolicy::PriorityCutoffToValue(
5977 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
5978 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5979 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5981 // GPU rasterization should be disabled by default on the tree(s)
5982 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
5983 EXPECT_TRUE(host_impl_->pending_tree() == NULL);
5985 host_impl_->SetVisible(true);
5986 host_impl_->SetMemoryPolicy(policy1);
5987 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5988 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5990 host_impl_->SetVisible(false);
5991 EXPECT_EQ(0u, current_limit_bytes_);
5992 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5994 host_impl_->SetVisible(true);
5995 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5996 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5998 // Now enable GPU rasterization and test if we get nice to have cutoff,
5999 // when visible.
6000 LayerTreeSettings settings;
6001 settings.gpu_rasterization_enabled = true;
6002 CreateHostImpl(settings, CreateOutputSurface());
6003 host_impl_->SetContentIsSuitableForGpuRasterization(true);
6004 host_impl_->SetHasGpuRasterizationTrigger(true);
6005 host_impl_->SetVisible(true);
6006 host_impl_->SetMemoryPolicy(policy1);
6007 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
6008 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
6010 host_impl_->SetVisible(false);
6011 EXPECT_EQ(0u, current_limit_bytes_);
6012 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
6015 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
6016 ASSERT_TRUE(host_impl_->active_tree());
6018 // RequiresHighResToDraw is set when new output surface is used.
6019 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6021 host_impl_->ResetRequiresHighResToDraw();
6023 host_impl_->SetVisible(false);
6024 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6025 host_impl_->SetVisible(true);
6026 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6027 host_impl_->SetVisible(false);
6028 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6030 host_impl_->ResetRequiresHighResToDraw();
6032 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6033 host_impl_->SetVisible(true);
6034 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6037 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
6038 ASSERT_TRUE(host_impl_->active_tree());
6039 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
6041 // RequiresHighResToDraw is set when new output surface is used.
6042 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6044 host_impl_->ResetRequiresHighResToDraw();
6046 host_impl_->SetContentIsSuitableForGpuRasterization(true);
6047 host_impl_->SetHasGpuRasterizationTrigger(false);
6048 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6049 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6050 host_impl_->SetHasGpuRasterizationTrigger(true);
6051 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6052 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6053 host_impl_->SetHasGpuRasterizationTrigger(false);
6054 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6055 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6057 host_impl_->ResetRequiresHighResToDraw();
6059 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6060 host_impl_->SetHasGpuRasterizationTrigger(true);
6061 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6062 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6065 class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest {
6066 public:
6067 void SetUp() override {
6068 LayerTreeSettings settings;
6069 settings.impl_side_painting = true;
6071 fake_host_impl_ = new FakeLayerTreeHostImpl(settings, &proxy_,
6072 shared_bitmap_manager_.get(),
6073 task_graph_runner_.get());
6074 host_impl_.reset(fake_host_impl_);
6075 host_impl_->InitializeRenderer(CreateOutputSurface());
6076 host_impl_->SetViewportSize(gfx::Size(10, 10));
6079 FakeLayerTreeHostImpl* fake_host_impl_;
6082 TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) {
6083 fake_host_impl_->DidModifyTilePriorities();
6084 EXPECT_TRUE(fake_host_impl_->prepare_tiles_needed());
6085 fake_host_impl_->SetVisible(false);
6086 EXPECT_FALSE(fake_host_impl_->prepare_tiles_needed());
6089 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
6090 scoped_ptr<TestWebGraphicsContext3D> context =
6091 TestWebGraphicsContext3D::Create();
6092 TestWebGraphicsContext3D* context3d = context.get();
6093 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
6094 CreateHostImpl(DefaultSettings(), output_surface.Pass());
6096 EXPECT_EQ(0u, context3d->NumTextures());
6098 UIResourceId ui_resource_id = 1;
6099 bool is_opaque = false;
6100 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
6101 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6102 EXPECT_EQ(1u, context3d->NumTextures());
6103 ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6104 EXPECT_NE(0u, id1);
6106 // Multiple requests with the same id is allowed. The previous texture is
6107 // deleted.
6108 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6109 EXPECT_EQ(1u, context3d->NumTextures());
6110 ResourceId id2 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6111 EXPECT_NE(0u, id2);
6112 EXPECT_NE(id1, id2);
6114 // Deleting invalid UIResourceId is allowed and does not change state.
6115 host_impl_->DeleteUIResource(-1);
6116 EXPECT_EQ(1u, context3d->NumTextures());
6118 // Should return zero for invalid UIResourceId. Number of textures should
6119 // not change.
6120 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
6121 EXPECT_EQ(1u, context3d->NumTextures());
6123 host_impl_->DeleteUIResource(ui_resource_id);
6124 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
6125 EXPECT_EQ(0u, context3d->NumTextures());
6127 // Should not change state for multiple deletion on one UIResourceId
6128 host_impl_->DeleteUIResource(ui_resource_id);
6129 EXPECT_EQ(0u, context3d->NumTextures());
6132 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
6133 scoped_ptr<TestWebGraphicsContext3D> context =
6134 TestWebGraphicsContext3D::Create();
6135 TestWebGraphicsContext3D* context3d = context.get();
6136 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6138 EXPECT_EQ(0u, context3d->NumTextures());
6140 gfx::Size size(4, 4);
6141 // SkImageInfo has no support for ETC1. The |info| below contains the right
6142 // total pixel size for the bitmap but not the right height and width. The
6143 // correct width/height are passed directly to UIResourceBitmap.
6144 SkImageInfo info =
6145 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
6146 skia::RefPtr<SkPixelRef> pixel_ref =
6147 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
6148 pixel_ref->setImmutable();
6149 UIResourceBitmap bitmap(pixel_ref, size);
6150 UIResourceId ui_resource_id = 1;
6151 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6152 EXPECT_EQ(1u, context3d->NumTextures());
6153 ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6154 EXPECT_NE(0u, id1);
6157 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
6160 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
6161 scoped_refptr<TestContextProvider> context_provider =
6162 TestContextProvider::Create();
6164 CreateHostImpl(DefaultSettings(),
6165 FakeOutputSurface::Create3d(context_provider));
6167 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
6169 ScopedPtrVector<CopyOutputRequest> requests;
6170 requests.push_back(CopyOutputRequest::CreateRequest(
6171 base::Bind(&ShutdownReleasesContext_Callback)));
6173 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
6175 LayerTreeHostImpl::FrameData frame;
6176 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6177 host_impl_->DrawLayers(&frame);
6178 host_impl_->DidDrawAllLayers(frame);
6180 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6181 // texture in a texture mailbox.
6182 EXPECT_FALSE(context_provider->HasOneRef());
6183 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
6185 host_impl_ = nullptr;
6187 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6188 // released, and the texture deleted.
6189 EXPECT_TRUE(context_provider->HasOneRef());
6190 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
6193 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
6194 // When flinging via touch, only the child should scroll (we should not
6195 // bubble).
6196 gfx::Size surface_size(10, 10);
6197 gfx::Size content_size(20, 20);
6198 scoped_ptr<LayerImpl> root_clip =
6199 LayerImpl::Create(host_impl_->active_tree(), 3);
6200 root_clip->SetHasRenderSurface(true);
6202 scoped_ptr<LayerImpl> root =
6203 CreateScrollableLayer(1, content_size, root_clip.get());
6204 root->SetIsContainerForFixedPositionLayers(true);
6205 scoped_ptr<LayerImpl> child =
6206 CreateScrollableLayer(2, content_size, root_clip.get());
6208 root->AddChild(child.Pass());
6209 int root_id = root->id();
6210 root_clip->AddChild(root.Pass());
6212 host_impl_->SetViewportSize(surface_size);
6213 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6214 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
6215 Layer::INVALID_ID);
6216 host_impl_->active_tree()->DidBecomeActive();
6217 DrawFrame();
6219 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6220 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6222 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6224 gfx::Vector2d scroll_delta(0, 100);
6225 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6226 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6228 host_impl_->ScrollEnd();
6230 scoped_ptr<ScrollAndScaleSet> scroll_info =
6231 host_impl_->ProcessScrollDeltas();
6233 // Only the child should have scrolled.
6234 ASSERT_EQ(1u, scroll_info->scrolls.size());
6235 ExpectNone(*scroll_info.get(), root_id);
6239 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
6240 // Scroll a child layer beyond its maximum scroll range and make sure the
6241 // the scroll doesn't bubble up to the parent layer.
6242 gfx::Size surface_size(10, 10);
6243 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
6244 root->SetHasRenderSurface(true);
6245 scoped_ptr<LayerImpl> root_scrolling =
6246 CreateScrollableLayer(2, surface_size, root.get());
6248 scoped_ptr<LayerImpl> grand_child =
6249 CreateScrollableLayer(4, surface_size, root.get());
6250 grand_child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6252 scoped_ptr<LayerImpl> child =
6253 CreateScrollableLayer(3, surface_size, root.get());
6254 child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6255 child->AddChild(grand_child.Pass());
6257 root_scrolling->AddChild(child.Pass());
6258 root->AddChild(root_scrolling.Pass());
6259 host_impl_->active_tree()->SetRootLayer(root.Pass());
6260 host_impl_->active_tree()->DidBecomeActive();
6261 host_impl_->SetViewportSize(surface_size);
6262 DrawFrame();
6264 scoped_ptr<ScrollAndScaleSet> scroll_info;
6265 LayerImpl* child =
6266 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6267 LayerImpl* grand_child = child->children()[0];
6269 gfx::Vector2d scroll_delta(0, -2);
6270 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6271 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6272 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6274 // The grand child should have scrolled up to its limit.
6275 scroll_info = host_impl_->ProcessScrollDeltas();
6276 ASSERT_EQ(1u, scroll_info->scrolls.size());
6277 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6278 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6280 // The child should have received the bubbled delta, but the locked
6281 // scrolling layer should remain set as the grand child.
6282 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6283 scroll_info = host_impl_->ProcessScrollDeltas();
6284 ASSERT_EQ(2u, scroll_info->scrolls.size());
6285 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6286 ExpectContains(*scroll_info, child->id(), scroll_delta);
6287 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6289 // The first |ScrollBy| after the fling should re-lock the scrolling
6290 // layer to the first layer that scrolled, which is the child.
6291 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6292 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6293 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6295 // The child should have scrolled up to its limit.
6296 scroll_info = host_impl_->ProcessScrollDeltas();
6297 ASSERT_EQ(2u, scroll_info->scrolls.size());
6298 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6299 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
6301 // As the locked layer is at it's limit, no further scrolling can occur.
6302 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6303 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6304 host_impl_->ScrollEnd();
6308 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6309 // When flinging via wheel, the root should eventually scroll (we should
6310 // bubble).
6311 gfx::Size surface_size(10, 10);
6312 gfx::Size content_size(20, 20);
6313 scoped_ptr<LayerImpl> root_clip =
6314 LayerImpl::Create(host_impl_->active_tree(), 3);
6315 root_clip->SetHasRenderSurface(true);
6316 scoped_ptr<LayerImpl> root_scroll =
6317 CreateScrollableLayer(1, content_size, root_clip.get());
6318 int root_scroll_id = root_scroll->id();
6319 scoped_ptr<LayerImpl> child =
6320 CreateScrollableLayer(2, content_size, root_clip.get());
6322 root_scroll->AddChild(child.Pass());
6323 root_clip->AddChild(root_scroll.Pass());
6325 host_impl_->SetViewportSize(surface_size);
6326 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6327 host_impl_->active_tree()->DidBecomeActive();
6328 DrawFrame();
6330 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6331 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6333 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6335 gfx::Vector2d scroll_delta(0, 100);
6336 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6337 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6339 host_impl_->ScrollEnd();
6341 scoped_ptr<ScrollAndScaleSet> scroll_info =
6342 host_impl_->ProcessScrollDeltas();
6344 // The root should have scrolled.
6345 ASSERT_EQ(2u, scroll_info->scrolls.size());
6346 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
6350 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6351 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6352 // we should return SCROLL_UNKNOWN.
6353 gfx::Size content_size(100, 100);
6354 SetupScrollAndContentsLayers(content_size);
6356 int scroll_layer_id = 2;
6357 LayerImpl* scroll_layer =
6358 host_impl_->active_tree()->LayerById(scroll_layer_id);
6359 scroll_layer->SetDrawsContent(true);
6361 int page_scale_layer_id = 5;
6362 LayerImpl* page_scale_layer =
6363 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6365 int occluder_layer_id = 6;
6366 scoped_ptr<LayerImpl> occluder_layer =
6367 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6368 occluder_layer->SetDrawsContent(true);
6369 occluder_layer->SetBounds(content_size);
6370 occluder_layer->SetContentBounds(content_size);
6371 occluder_layer->SetPosition(gfx::PointF());
6373 // The parent of the occluder is *above* the scroller.
6374 page_scale_layer->AddChild(occluder_layer.Pass());
6376 DrawFrame();
6378 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6379 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6382 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6383 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6384 // is not the first scroller we encounter when walking up from the layer, we
6385 // should also return SCROLL_UNKNOWN.
6386 gfx::Size content_size(100, 100);
6387 SetupScrollAndContentsLayers(content_size);
6389 int scroll_layer_id = 2;
6390 LayerImpl* scroll_layer =
6391 host_impl_->active_tree()->LayerById(scroll_layer_id);
6392 scroll_layer->SetDrawsContent(true);
6394 int occluder_layer_id = 6;
6395 scoped_ptr<LayerImpl> occluder_layer =
6396 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6397 occluder_layer->SetDrawsContent(true);
6398 occluder_layer->SetBounds(content_size);
6399 occluder_layer->SetContentBounds(content_size);
6400 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6402 int child_scroll_clip_layer_id = 7;
6403 scoped_ptr<LayerImpl> child_scroll_clip =
6404 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6406 int child_scroll_layer_id = 8;
6407 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6408 child_scroll_layer_id, content_size, child_scroll_clip.get());
6410 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6412 child_scroll->AddChild(occluder_layer.Pass());
6413 scroll_layer->AddChild(child_scroll.Pass());
6415 DrawFrame();
6417 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6418 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6421 TEST_F(LayerTreeHostImplTest, NotScrollInvisibleScroller) {
6422 gfx::Size content_size(100, 100);
6423 SetupScrollAndContentsLayers(content_size);
6425 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6427 int scroll_layer_id = 2;
6428 LayerImpl* scroll_layer =
6429 host_impl_->active_tree()->LayerById(scroll_layer_id);
6431 int child_scroll_layer_id = 7;
6432 scoped_ptr<LayerImpl> child_scroll =
6433 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6434 child_scroll->SetDrawsContent(false);
6436 scroll_layer->AddChild(child_scroll.Pass());
6438 DrawFrame();
6440 // We should not have scrolled |child_scroll| even though we technically "hit"
6441 // it. The reason for this is that if the scrolling the scroll would not move
6442 // any layer that is a drawn RSLL member, then we can ignore the hit.
6444 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6445 // started scrolling the inner viewport.
6446 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6447 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6449 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6452 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) {
6453 gfx::Size content_size(100, 100);
6454 SetupScrollAndContentsLayers(content_size);
6456 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6457 LayerImpl* root_scroll_layer = host_impl_->active_tree()->LayerById(2);
6459 scoped_ptr<LayerImpl> invisible_scroll_layer =
6460 CreateScrollableLayer(7, content_size, root);
6461 invisible_scroll_layer->SetDrawsContent(false);
6463 scoped_ptr<LayerImpl> child_layer =
6464 LayerImpl::Create(host_impl_->active_tree(), 8);
6465 child_layer->SetDrawsContent(false);
6467 scoped_ptr<LayerImpl> grand_child_layer =
6468 LayerImpl::Create(host_impl_->active_tree(), 9);
6469 grand_child_layer->SetDrawsContent(true);
6470 grand_child_layer->SetBounds(content_size);
6471 grand_child_layer->SetContentBounds(content_size);
6472 // Move the grand child so it's not hit by our test point.
6473 grand_child_layer->SetPosition(gfx::PointF(10.f, 10.f));
6475 child_layer->AddChild(grand_child_layer.Pass());
6476 invisible_scroll_layer->AddChild(child_layer.Pass());
6477 root_scroll_layer->AddChild(invisible_scroll_layer.Pass());
6479 DrawFrame();
6481 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6482 // a descendant which is a drawn RSLL member.
6483 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6484 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6486 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6489 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6490 // This test case is very similar to the one above with one key difference:
6491 // the invisible scroller has a scroll child that is indeed draw contents.
6492 // If we attempt to initiate a gesture scroll off of the visible scroll child
6493 // we should still start the scroll child.
6494 gfx::Size content_size(100, 100);
6495 SetupScrollAndContentsLayers(content_size);
6497 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6499 int scroll_layer_id = 2;
6500 LayerImpl* scroll_layer =
6501 host_impl_->active_tree()->LayerById(scroll_layer_id);
6503 int scroll_child_id = 6;
6504 scoped_ptr<LayerImpl> scroll_child =
6505 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6506 scroll_child->SetDrawsContent(true);
6507 scroll_child->SetBounds(content_size);
6508 scroll_child->SetContentBounds(content_size);
6509 // Move the scroll child so it's not hit by our test point.
6510 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6512 int invisible_scroll_layer_id = 7;
6513 scoped_ptr<LayerImpl> invisible_scroll =
6514 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6515 invisible_scroll->SetDrawsContent(false);
6517 int container_id = 8;
6518 scoped_ptr<LayerImpl> container =
6519 LayerImpl::Create(host_impl_->active_tree(), container_id);
6521 scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
6522 scroll_children->insert(scroll_child.get());
6523 invisible_scroll->SetScrollChildren(scroll_children.release());
6525 scroll_child->SetScrollParent(invisible_scroll.get());
6527 container->AddChild(invisible_scroll.Pass());
6528 container->AddChild(scroll_child.Pass());
6530 scroll_layer->AddChild(container.Pass());
6532 DrawFrame();
6534 // We should have scrolled |child_scroll| even though it is invisible.
6535 // The reason for this is that if the scrolling the scroll would move a layer
6536 // that is a drawn RSLL member, then we should accept this hit.
6537 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6538 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6540 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6543 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6544 // to CompositorFrameMetadata after SwapBuffers();
6545 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6546 scoped_ptr<SolidColorLayerImpl> root =
6547 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6548 root->SetPosition(gfx::PointF());
6549 root->SetBounds(gfx::Size(10, 10));
6550 root->SetContentBounds(gfx::Size(10, 10));
6551 root->SetDrawsContent(true);
6552 root->SetHasRenderSurface(true);
6554 host_impl_->active_tree()->SetRootLayer(root.Pass());
6556 FakeOutputSurface* fake_output_surface =
6557 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6559 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6560 fake_output_surface->last_sent_frame().metadata.latency_info;
6561 EXPECT_TRUE(metadata_latency_before.empty());
6563 ui::LatencyInfo latency_info;
6564 latency_info.AddLatencyNumber(
6565 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6566 scoped_ptr<SwapPromise> swap_promise(
6567 new LatencyInfoSwapPromise(latency_info));
6568 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
6569 host_impl_->SetNeedsRedraw();
6571 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6572 LayerTreeHostImpl::FrameData frame;
6573 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6574 host_impl_->DrawLayers(&frame);
6575 host_impl_->DidDrawAllLayers(frame);
6576 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6578 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6579 fake_output_surface->last_sent_frame().metadata.latency_info;
6580 EXPECT_EQ(1u, metadata_latency_after.size());
6581 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6582 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6585 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
6586 int root_layer_id = 1;
6587 scoped_ptr<SolidColorLayerImpl> root =
6588 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
6589 root->SetPosition(gfx::PointF());
6590 root->SetBounds(gfx::Size(10, 10));
6591 root->SetContentBounds(gfx::Size(10, 10));
6592 root->SetDrawsContent(true);
6593 root->SetHasRenderSurface(true);
6595 host_impl_->active_tree()->SetRootLayer(root.Pass());
6597 // Ensure the default frame selection bounds are empty.
6598 FakeOutputSurface* fake_output_surface =
6599 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6600 const ViewportSelection& selection_before =
6601 fake_output_surface->last_sent_frame().metadata.selection;
6602 EXPECT_EQ(ViewportSelectionBound(), selection_before.start);
6603 EXPECT_EQ(ViewportSelectionBound(), selection_before.end);
6605 // Plumb the layer-local selection bounds.
6606 gfx::PointF selection_top(5, 0);
6607 gfx::PointF selection_bottom(5, 5);
6608 LayerSelection selection;
6609 selection.start.type = SELECTION_BOUND_CENTER;
6610 selection.start.layer_id = root_layer_id;
6611 selection.start.edge_bottom = selection_bottom;
6612 selection.start.edge_top = selection_top;
6613 selection.end = selection.start;
6614 host_impl_->active_tree()->RegisterSelection(selection);
6616 // Trigger a draw-swap sequence.
6617 host_impl_->SetNeedsRedraw();
6619 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6620 LayerTreeHostImpl::FrameData frame;
6621 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6622 host_impl_->DrawLayers(&frame);
6623 host_impl_->DidDrawAllLayers(frame);
6624 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6626 // Ensure the selection bounds have propagated to the frame metadata.
6627 const ViewportSelection& selection_after =
6628 fake_output_surface->last_sent_frame().metadata.selection;
6629 EXPECT_EQ(selection.start.type, selection_after.start.type);
6630 EXPECT_EQ(selection.end.type, selection_after.end.type);
6631 EXPECT_EQ(selection_bottom, selection_after.start.edge_bottom);
6632 EXPECT_EQ(selection_top, selection_after.start.edge_top);
6633 EXPECT_TRUE(selection_after.start.visible);
6634 EXPECT_TRUE(selection_after.start.visible);
6637 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
6638 public:
6639 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
6640 LayerTreeHostImpl* layer_tree_host_impl,
6641 int* set_needs_commit_count,
6642 int* set_needs_redraw_count,
6643 int* forward_to_main_count)
6644 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
6645 set_needs_commit_count_(set_needs_commit_count),
6646 set_needs_redraw_count_(set_needs_redraw_count),
6647 forward_to_main_count_(forward_to_main_count) {}
6649 ~SimpleSwapPromiseMonitor() override {}
6651 void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
6653 void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; }
6655 void OnForwardScrollUpdateToMainThreadOnImpl() override {
6656 (*forward_to_main_count_)++;
6659 private:
6660 int* set_needs_commit_count_;
6661 int* set_needs_redraw_count_;
6662 int* forward_to_main_count_;
6665 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
6666 int set_needs_commit_count = 0;
6667 int set_needs_redraw_count = 0;
6668 int forward_to_main_count = 0;
6671 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6672 new SimpleSwapPromiseMonitor(NULL,
6673 host_impl_.get(),
6674 &set_needs_commit_count,
6675 &set_needs_redraw_count,
6676 &forward_to_main_count));
6677 host_impl_->SetNeedsRedraw();
6678 EXPECT_EQ(0, set_needs_commit_count);
6679 EXPECT_EQ(1, set_needs_redraw_count);
6680 EXPECT_EQ(0, forward_to_main_count);
6683 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6684 // monitored.
6685 host_impl_->SetNeedsRedraw();
6686 EXPECT_EQ(0, set_needs_commit_count);
6687 EXPECT_EQ(1, set_needs_redraw_count);
6688 EXPECT_EQ(0, forward_to_main_count);
6691 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6692 new SimpleSwapPromiseMonitor(NULL,
6693 host_impl_.get(),
6694 &set_needs_commit_count,
6695 &set_needs_redraw_count,
6696 &forward_to_main_count));
6697 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
6698 EXPECT_EQ(0, set_needs_commit_count);
6699 EXPECT_EQ(2, set_needs_redraw_count);
6700 EXPECT_EQ(0, forward_to_main_count);
6704 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6705 new SimpleSwapPromiseMonitor(NULL,
6706 host_impl_.get(),
6707 &set_needs_commit_count,
6708 &set_needs_redraw_count,
6709 &forward_to_main_count));
6710 // Empty damage rect won't signal the monitor.
6711 host_impl_->SetNeedsRedrawRect(gfx::Rect());
6712 EXPECT_EQ(0, set_needs_commit_count);
6713 EXPECT_EQ(2, set_needs_redraw_count);
6714 EXPECT_EQ(0, forward_to_main_count);
6718 set_needs_commit_count = 0;
6719 set_needs_redraw_count = 0;
6720 forward_to_main_count = 0;
6721 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6722 new SimpleSwapPromiseMonitor(NULL,
6723 host_impl_.get(),
6724 &set_needs_commit_count,
6725 &set_needs_redraw_count,
6726 &forward_to_main_count));
6727 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
6729 // Scrolling normally should not trigger any forwarding.
6730 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6731 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6732 EXPECT_TRUE(
6733 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
6734 host_impl_->ScrollEnd();
6736 EXPECT_EQ(0, set_needs_commit_count);
6737 EXPECT_EQ(1, set_needs_redraw_count);
6738 EXPECT_EQ(0, forward_to_main_count);
6740 // Scrolling with a scroll handler should defer the swap to the main
6741 // thread.
6742 scroll_layer->SetHaveScrollEventHandlers(true);
6743 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6744 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6745 EXPECT_TRUE(
6746 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
6747 host_impl_->ScrollEnd();
6749 EXPECT_EQ(0, set_needs_commit_count);
6750 EXPECT_EQ(2, set_needs_redraw_count);
6751 EXPECT_EQ(1, forward_to_main_count);
6755 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
6756 public:
6757 void SetUp() override {
6758 LayerTreeSettings settings = DefaultSettings();
6759 CreateHostImpl(settings, CreateOutputSurface());
6760 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
6761 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
6762 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
6765 protected:
6766 static const int top_controls_height_;
6769 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
6771 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
6772 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6773 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6774 host_impl_->Animate(base::TimeTicks());
6775 EXPECT_FALSE(did_request_redraw_);
6778 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsHeightIsCommitted) {
6779 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6780 EXPECT_FALSE(did_request_redraw_);
6781 host_impl_->CreatePendingTree();
6782 host_impl_->sync_tree()->set_top_controls_height(100);
6783 host_impl_->ActivateSyncTree();
6784 EXPECT_EQ(100, host_impl_->top_controls_manager()->TopControlsHeight());
6787 TEST_F(LayerTreeHostImplWithTopControlsTest,
6788 TopControlsStayFullyVisibleOnHeightChange) {
6789 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6790 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
6792 host_impl_->CreatePendingTree();
6793 host_impl_->sync_tree()->set_top_controls_height(0);
6794 host_impl_->ActivateSyncTree();
6795 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
6797 host_impl_->CreatePendingTree();
6798 host_impl_->sync_tree()->set_top_controls_height(50);
6799 host_impl_->ActivateSyncTree();
6800 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
6803 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
6804 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6805 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6806 host_impl_->DidChangeTopControlsPosition();
6807 EXPECT_TRUE(did_request_animate_);
6808 EXPECT_TRUE(did_request_redraw_);
6811 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
6812 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6813 host_impl_->SetViewportSize(gfx::Size(100, 100));
6814 host_impl_->top_controls_manager()->UpdateTopControlsState(
6815 BOTH, SHOWN, false);
6816 DrawFrame();
6818 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6819 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6820 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6821 EXPECT_EQ(gfx::Vector2dF().ToString(),
6822 scroll_layer->CurrentScrollOffset().ToString());
6824 // Scroll just the top controls and verify that the scroll succeeds.
6825 const float residue = 10;
6826 float offset = top_controls_height_ - residue;
6827 EXPECT_TRUE(
6828 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6829 EXPECT_FLOAT_EQ(-offset,
6830 host_impl_->top_controls_manager()->ControlsTopOffset());
6831 EXPECT_EQ(gfx::Vector2dF().ToString(),
6832 scroll_layer->CurrentScrollOffset().ToString());
6834 // Scroll across the boundary
6835 const float content_scroll = 20;
6836 offset = residue + content_scroll;
6837 EXPECT_TRUE(
6838 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6839 EXPECT_EQ(-top_controls_height_,
6840 host_impl_->top_controls_manager()->ControlsTopOffset());
6841 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
6842 scroll_layer->CurrentScrollOffset().ToString());
6844 // Now scroll back to the top of the content
6845 offset = -content_scroll;
6846 EXPECT_TRUE(
6847 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6848 EXPECT_EQ(-top_controls_height_,
6849 host_impl_->top_controls_manager()->ControlsTopOffset());
6850 EXPECT_EQ(gfx::Vector2dF().ToString(),
6851 scroll_layer->CurrentScrollOffset().ToString());
6853 // And scroll the top controls completely into view
6854 offset = -top_controls_height_;
6855 EXPECT_TRUE(
6856 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6857 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6858 EXPECT_EQ(gfx::Vector2dF().ToString(),
6859 scroll_layer->CurrentScrollOffset().ToString());
6861 // And attempt to scroll past the end
6862 EXPECT_FALSE(
6863 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6864 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6865 EXPECT_EQ(gfx::Vector2dF().ToString(),
6866 scroll_layer->CurrentScrollOffset().ToString());
6868 host_impl_->ScrollEnd();
6871 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
6872 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6873 host_impl_->SetViewportSize(gfx::Size(100, 200));
6874 host_impl_->top_controls_manager()->UpdateTopControlsState(
6875 BOTH, SHOWN, false);
6876 DrawFrame();
6878 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6879 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6880 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6881 EXPECT_EQ(gfx::Vector2dF().ToString(),
6882 scroll_layer->CurrentScrollOffset().ToString());
6884 // Scroll the top controls partially.
6885 const float residue = 35;
6886 float offset = top_controls_height_ - residue;
6887 EXPECT_TRUE(
6888 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6889 EXPECT_FLOAT_EQ(-offset,
6890 host_impl_->top_controls_manager()->ControlsTopOffset());
6891 EXPECT_EQ(gfx::Vector2dF().ToString(),
6892 scroll_layer->CurrentScrollOffset().ToString());
6894 did_request_redraw_ = false;
6895 did_request_animate_ = false;
6896 did_request_commit_ = false;
6898 // End the scroll while the controls are still offset from their limit.
6899 host_impl_->ScrollEnd();
6900 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
6901 EXPECT_TRUE(did_request_animate_);
6902 EXPECT_TRUE(did_request_redraw_);
6903 EXPECT_FALSE(did_request_commit_);
6905 // The top controls should properly animate until finished, despite the scroll
6906 // offset being at the origin.
6907 base::TimeTicks animation_time = base::TimeTicks::Now();
6908 while (did_request_animate_) {
6909 did_request_redraw_ = false;
6910 did_request_animate_ = false;
6911 did_request_commit_ = false;
6913 float old_offset =
6914 host_impl_->top_controls_manager()->ControlsTopOffset();
6916 animation_time += base::TimeDelta::FromMilliseconds(5);
6917 host_impl_->Animate(animation_time);
6918 EXPECT_EQ(gfx::Vector2dF().ToString(),
6919 scroll_layer->CurrentScrollOffset().ToString());
6921 float new_offset =
6922 host_impl_->top_controls_manager()->ControlsTopOffset();
6924 // No commit is needed as the controls are animating the content offset,
6925 // not the scroll offset.
6926 EXPECT_FALSE(did_request_commit_);
6928 if (new_offset != old_offset)
6929 EXPECT_TRUE(did_request_redraw_);
6931 if (new_offset != 0) {
6932 EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
6933 EXPECT_TRUE(did_request_animate_);
6936 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
6939 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
6940 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6941 host_impl_->SetViewportSize(gfx::Size(100, 100));
6942 host_impl_->top_controls_manager()->UpdateTopControlsState(
6943 BOTH, SHOWN, false);
6944 float initial_scroll_offset = 50;
6945 scroll_layer->PushScrollOffsetFromMainThread(
6946 gfx::ScrollOffset(0, initial_scroll_offset));
6947 DrawFrame();
6949 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6950 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6951 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6952 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
6953 scroll_layer->CurrentScrollOffset().ToString());
6955 // Scroll the top controls partially.
6956 const float residue = 15;
6957 float offset = top_controls_height_ - residue;
6958 EXPECT_TRUE(
6959 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6960 EXPECT_FLOAT_EQ(-offset,
6961 host_impl_->top_controls_manager()->ControlsTopOffset());
6962 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
6963 scroll_layer->CurrentScrollOffset().ToString());
6965 did_request_redraw_ = false;
6966 did_request_animate_ = false;
6967 did_request_commit_ = false;
6969 // End the scroll while the controls are still offset from the limit.
6970 host_impl_->ScrollEnd();
6971 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
6972 EXPECT_TRUE(did_request_animate_);
6973 EXPECT_TRUE(did_request_redraw_);
6974 EXPECT_FALSE(did_request_commit_);
6976 // Animate the top controls to the limit.
6977 base::TimeTicks animation_time = base::TimeTicks::Now();
6978 while (did_request_animate_) {
6979 did_request_redraw_ = false;
6980 did_request_animate_ = false;
6981 did_request_commit_ = false;
6983 float old_offset =
6984 host_impl_->top_controls_manager()->ControlsTopOffset();
6986 animation_time += base::TimeDelta::FromMilliseconds(5);
6987 host_impl_->Animate(animation_time);
6989 float new_offset =
6990 host_impl_->top_controls_manager()->ControlsTopOffset();
6992 if (new_offset != old_offset) {
6993 EXPECT_TRUE(did_request_redraw_);
6994 EXPECT_TRUE(did_request_commit_);
6997 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
6998 EXPECT_EQ(-top_controls_height_,
6999 host_impl_->top_controls_manager()->ControlsTopOffset());
7002 TEST_F(LayerTreeHostImplWithTopControlsTest,
7003 TopControlsAnimationAfterMainThreadFlingStopped) {
7004 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7005 host_impl_->SetViewportSize(gfx::Size(100, 100));
7006 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7007 false);
7008 float initial_scroll_offset = 50;
7009 scroll_layer->PushScrollOffsetFromMainThread(
7010 gfx::ScrollOffset(0, initial_scroll_offset));
7011 DrawFrame();
7013 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7014 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7015 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7016 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7017 scroll_layer->CurrentScrollOffset().ToString());
7019 // Scroll the top controls partially.
7020 const float residue = 15;
7021 float offset = top_controls_height_ - residue;
7022 EXPECT_TRUE(
7023 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7024 EXPECT_FLOAT_EQ(-offset,
7025 host_impl_->top_controls_manager()->ControlsTopOffset());
7026 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7027 scroll_layer->CurrentScrollOffset().ToString());
7029 did_request_redraw_ = false;
7030 did_request_animate_ = false;
7031 did_request_commit_ = false;
7033 // End the fling while the controls are still offset from the limit.
7034 host_impl_->MainThreadHasStoppedFlinging();
7035 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7036 EXPECT_TRUE(did_request_animate_);
7037 EXPECT_TRUE(did_request_redraw_);
7038 EXPECT_FALSE(did_request_commit_);
7040 // Animate the top controls to the limit.
7041 base::TimeTicks animation_time = base::TimeTicks::Now();
7042 while (did_request_animate_) {
7043 did_request_redraw_ = false;
7044 did_request_animate_ = false;
7045 did_request_commit_ = false;
7047 float old_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7049 animation_time += base::TimeDelta::FromMilliseconds(5);
7050 host_impl_->Animate(animation_time);
7052 float new_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7054 if (new_offset != old_offset) {
7055 EXPECT_TRUE(did_request_redraw_);
7056 EXPECT_TRUE(did_request_commit_);
7059 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7060 EXPECT_EQ(-top_controls_height_,
7061 host_impl_->top_controls_manager()->ControlsTopOffset());
7064 TEST_F(LayerTreeHostImplWithTopControlsTest,
7065 TopControlsScrollDeltaInOverScroll) {
7066 // test varifies that the overscroll delta should not have accumulated in
7067 // the top controls if we do a hide and show without releasing finger.
7069 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7070 host_impl_->SetViewportSize(gfx::Size(100, 100));
7071 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7072 false);
7073 DrawFrame();
7075 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7076 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7077 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7079 float offset = 50;
7080 EXPECT_TRUE(
7081 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7082 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7083 EXPECT_EQ(gfx::Vector2dF().ToString(),
7084 scroll_layer->CurrentScrollOffset().ToString());
7086 EXPECT_TRUE(
7087 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7088 EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
7089 scroll_layer->CurrentScrollOffset().ToString());
7091 EXPECT_TRUE(
7092 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7094 // Should have fully scrolled
7095 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer->MaxScrollOffset().y()).ToString(),
7096 scroll_layer->CurrentScrollOffset().ToString());
7098 float overscrollamount = 10;
7100 // Overscroll the content
7101 EXPECT_FALSE(
7102 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount))
7103 .did_scroll);
7104 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
7105 scroll_layer->CurrentScrollOffset().ToString());
7106 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount).ToString(),
7107 host_impl_->accumulated_root_overscroll().ToString());
7109 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset))
7110 .did_scroll);
7111 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7112 scroll_layer->CurrentScrollOffset().ToString());
7113 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7115 EXPECT_TRUE(
7116 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset)).did_scroll);
7117 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7118 scroll_layer->CurrentScrollOffset().ToString());
7120 // Top controls should be fully visible
7121 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7123 host_impl_->ScrollEnd();
7126 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
7127 public:
7128 void SetupVirtualViewportLayers(const gfx::Size& content_size,
7129 const gfx::Size& outer_viewport,
7130 const gfx::Size& inner_viewport) {
7131 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
7132 const int kOuterViewportClipLayerId = 6;
7133 const int kOuterViewportScrollLayerId = 7;
7134 const int kInnerViewportScrollLayerId = 2;
7135 const int kInnerViewportClipLayerId = 4;
7136 const int kPageScaleLayerId = 5;
7138 scoped_ptr<LayerImpl> inner_scroll =
7139 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
7140 inner_scroll->SetIsContainerForFixedPositionLayers(true);
7141 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7143 scoped_ptr<LayerImpl> inner_clip =
7144 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
7145 inner_clip->SetBounds(inner_viewport);
7147 scoped_ptr<LayerImpl> page_scale =
7148 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
7150 inner_scroll->SetScrollClipLayer(inner_clip->id());
7151 inner_scroll->SetBounds(outer_viewport);
7152 inner_scroll->SetContentBounds(outer_viewport);
7153 inner_scroll->SetPosition(gfx::PointF());
7155 scoped_ptr<LayerImpl> outer_clip =
7156 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
7157 outer_clip->SetBounds(outer_viewport);
7158 outer_clip->SetIsContainerForFixedPositionLayers(true);
7160 scoped_ptr<LayerImpl> outer_scroll =
7161 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
7162 outer_scroll->SetScrollClipLayer(outer_clip->id());
7163 outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7164 outer_scroll->SetBounds(content_size);
7165 outer_scroll->SetContentBounds(content_size);
7166 outer_scroll->SetPosition(gfx::PointF());
7168 scoped_ptr<LayerImpl> contents =
7169 LayerImpl::Create(layer_tree_impl, 8);
7170 contents->SetDrawsContent(true);
7171 contents->SetBounds(content_size);
7172 contents->SetContentBounds(content_size);
7173 contents->SetPosition(gfx::PointF());
7175 outer_scroll->AddChild(contents.Pass());
7176 outer_clip->AddChild(outer_scroll.Pass());
7177 inner_scroll->AddChild(outer_clip.Pass());
7178 page_scale->AddChild(inner_scroll.Pass());
7179 inner_clip->AddChild(page_scale.Pass());
7181 inner_clip->SetHasRenderSurface(true);
7182 layer_tree_impl->SetRootLayer(inner_clip.Pass());
7183 layer_tree_impl->SetViewportLayersFromIds(
7184 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
7185 kOuterViewportScrollLayerId);
7187 host_impl_->active_tree()->DidBecomeActive();
7191 TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) {
7192 gfx::Size content_size = gfx::Size(100, 160);
7193 gfx::Size outer_viewport = gfx::Size(50, 80);
7194 gfx::Size inner_viewport = gfx::Size(25, 40);
7196 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7198 TestScrollOffsetDelegate scroll_delegate;
7199 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
7201 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7202 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7203 DrawFrame();
7205 gfx::ScrollOffset inner_expected;
7206 gfx::ScrollOffset outer_expected;
7207 EXPECT_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7208 EXPECT_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7210 gfx::ScrollOffset current_offset(70.f, 100.f);
7212 scroll_delegate.set_getter_return_value(current_offset);
7213 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
7214 EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->MaxScrollOffset());
7215 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), outer_scroll->MaxScrollOffset());
7217 // Outer viewport scrolls first. Then the rest is applied to the inner
7218 // viewport.
7219 EXPECT_EQ(gfx::ScrollOffset(20.f, 20.f),
7220 inner_scroll->CurrentScrollOffset());
7221 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f),
7222 outer_scroll->CurrentScrollOffset());
7226 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
7227 gfx::Size content_size = gfx::Size(100, 160);
7228 gfx::Size outer_viewport = gfx::Size(50, 80);
7229 gfx::Size inner_viewport = gfx::Size(25, 40);
7231 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7233 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7234 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7235 DrawFrame();
7237 gfx::Vector2dF inner_expected;
7238 gfx::Vector2dF outer_expected;
7239 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7240 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7242 // Make sure the fling goes to the outer viewport first
7243 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7244 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7245 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7247 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7248 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7249 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7251 host_impl_->ScrollEnd();
7253 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7254 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7256 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7257 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7258 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7259 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7261 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7262 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7264 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7265 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7267 host_impl_->ScrollEnd();
7269 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7270 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7274 TEST_F(LayerTreeHostImplVirtualViewportTest,
7275 DiagonalScrollBubblesPerfectlyToInner) {
7276 gfx::Size content_size = gfx::Size(100, 160);
7277 gfx::Size outer_viewport = gfx::Size(50, 80);
7278 gfx::Size inner_viewport = gfx::Size(25, 40);
7280 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7282 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7283 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7284 DrawFrame();
7286 gfx::Vector2dF inner_expected;
7287 gfx::Vector2dF outer_expected;
7288 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7289 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7291 // Make sure the scroll goes to the outer viewport first.
7292 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7293 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7294 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7295 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7296 InputHandler::GESTURE));
7298 // Scroll near the edge of the outer viewport.
7299 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7300 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7301 outer_expected += scroll_delta;
7302 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7303 InputHandler::GESTURE));
7305 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7306 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7308 // Now diagonal scroll across the outer viewport boundary in a single event.
7309 // The entirety of the scroll should be consumed, as bubbling between inner
7310 // and outer viewport layers is perfect.
7311 host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2));
7312 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7313 InputHandler::GESTURE));
7314 outer_expected += scroll_delta;
7315 inner_expected += scroll_delta;
7316 host_impl_->ScrollEnd();
7317 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
7318 gfx::Point(), InputHandler::GESTURE));
7320 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7321 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7325 TEST_F(LayerTreeHostImplVirtualViewportTest,
7326 TouchFlingCanLockToViewportLayerAfterBubbling) {
7327 gfx::Size content_size = gfx::Size(100, 160);
7328 gfx::Size outer_viewport = gfx::Size(50, 80);
7329 gfx::Size inner_viewport = gfx::Size(25, 40);
7331 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7333 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7334 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7336 scoped_ptr<LayerImpl> child =
7337 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7338 LayerImpl* child_scroll = child.get();
7339 outer_scroll->children()[0]->AddChild(child.Pass());
7341 DrawFrame();
7343 scoped_ptr<ScrollAndScaleSet> scroll_info;
7345 gfx::Vector2d scroll_delta(0, inner_viewport.height());
7346 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7347 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7348 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7349 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7350 InputHandler::GESTURE));
7352 // The child should have scrolled up to its limit.
7353 scroll_info = host_impl_->ProcessScrollDeltas();
7354 ASSERT_EQ(1u, scroll_info->scrolls.size());
7355 ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
7356 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7358 // The first |ScrollBy| after the fling should re-lock the scrolling
7359 // layer to the first layer that scrolled, the inner viewport scroll layer.
7360 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7361 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7362 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7363 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7364 InputHandler::GESTURE));
7366 // The inner viewport should have scrolled up to its limit.
7367 scroll_info = host_impl_->ProcessScrollDeltas();
7368 ASSERT_EQ(2u, scroll_info->scrolls.size());
7369 ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
7370 ExpectContains(*scroll_info, inner_scroll->id(), scroll_delta);
7372 // As the locked layer is at its limit, no further scrolling can occur.
7373 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7374 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7375 host_impl_->ScrollEnd();
7376 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
7377 gfx::Point(), InputHandler::GESTURE));
7381 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
7382 public:
7383 void SetUp() override {
7384 LayerTreeSettings settings = DefaultSettings();
7385 settings.max_memory_for_prepaint_percentage = 50;
7386 CreateHostImpl(settings, CreateOutputSurface());
7390 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
7391 // Set up a memory policy and percentages which could cause
7392 // 32-bit integer overflows.
7393 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
7395 // Verify implicit limits are calculated correctly with no overflows
7396 host_impl_->SetMemoryPolicy(mem_policy);
7397 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
7398 300u * 1024u * 1024u);
7399 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
7400 150u * 1024u * 1024u);
7403 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
7404 const gfx::Size layer_size(100, 100);
7405 gfx::Transform external_transform;
7406 const gfx::Rect external_viewport(layer_size);
7407 const gfx::Rect external_clip(layer_size);
7408 const bool resourceless_software_draw = false;
7409 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
7411 host_impl_->SetExternalDrawConstraints(external_transform,
7412 external_viewport,
7413 external_clip,
7414 external_viewport,
7415 external_transform,
7416 resourceless_software_draw);
7417 DrawFrame();
7418 EXPECT_TRANSFORMATION_MATRIX_EQ(
7419 external_transform, layer->draw_properties().target_space_transform);
7421 external_transform.Translate(20, 20);
7422 host_impl_->SetExternalDrawConstraints(external_transform,
7423 external_viewport,
7424 external_clip,
7425 external_viewport,
7426 external_transform,
7427 resourceless_software_draw);
7428 DrawFrame();
7429 EXPECT_TRANSFORMATION_MATRIX_EQ(
7430 external_transform, layer->draw_properties().target_space_transform);
7433 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
7434 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7435 DrawFrame();
7437 base::TimeTicks start_time =
7438 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7440 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7441 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7443 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
7445 host_impl_->Animate(start_time);
7446 host_impl_->UpdateAnimationState(true);
7448 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
7450 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
7451 host_impl_->UpdateAnimationState(true);
7453 float y = scrolling_layer->CurrentScrollOffset().y();
7454 EXPECT_TRUE(y > 1 && y < 49);
7456 // Update target.
7457 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7458 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7460 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
7461 host_impl_->UpdateAnimationState(true);
7463 y = scrolling_layer->CurrentScrollOffset().y();
7464 EXPECT_TRUE(y > 50 && y < 100);
7465 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
7467 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
7468 host_impl_->UpdateAnimationState(true);
7470 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7471 scrolling_layer->CurrentScrollOffset());
7472 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
7475 TEST_F(LayerTreeHostImplTest, InvalidLayerNotAddedToRasterQueue) {
7476 host_impl_->CreatePendingTree();
7478 Region empty_invalidation;
7479 scoped_refptr<RasterSource> pile_with_tiles(
7480 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
7481 gfx::Size(10, 10)));
7483 scoped_ptr<FakePictureLayerImpl> layer =
7484 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11);
7485 layer->SetBounds(gfx::Size(10, 10));
7486 layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
7487 layer->SetDrawsContent(true);
7488 layer->tilings()->AddTiling(1.0f, pile_with_tiles);
7489 layer->UpdateRasterSource(pile_with_tiles, &empty_invalidation, nullptr);
7490 layer->tilings()->tiling_at(0)->set_resolution(
7491 TileResolution::HIGH_RESOLUTION);
7492 layer->tilings()->tiling_at(0)->CreateAllTilesForTesting();
7493 layer->tilings()->tiling_at(0)->ComputeTilePriorityRects(
7494 gfx::Rect(gfx::Size(10, 10)), 1.f, 1.0, Occlusion());
7495 host_impl_->pending_tree()->SetRootLayer(layer.Pass());
7497 FakePictureLayerImpl* root_layer = static_cast<FakePictureLayerImpl*>(
7498 host_impl_->pending_tree()->root_layer());
7500 root_layer->set_has_valid_tile_priorities(true);
7501 scoped_ptr<RasterTilePriorityQueue> non_empty_raster_priority_queue_all =
7502 host_impl_->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES,
7503 RasterTilePriorityQueue::Type::ALL);
7504 EXPECT_FALSE(non_empty_raster_priority_queue_all->IsEmpty());
7506 root_layer->set_has_valid_tile_priorities(false);
7507 scoped_ptr<RasterTilePriorityQueue> empty_raster_priority_queue_all =
7508 host_impl_->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES,
7509 RasterTilePriorityQueue::Type::ALL);
7510 EXPECT_TRUE(empty_raster_priority_queue_all->IsEmpty());
7513 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
7514 host_impl_->CreatePendingTree();
7515 host_impl_->ActivateSyncTree();
7516 host_impl_->CreatePendingTree();
7518 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
7520 scoped_ptr<FakePictureLayerImpl> pending_layer =
7521 FakePictureLayerImpl::Create(pending_tree, 10);
7522 FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
7523 pending_tree->SetRootLayer(pending_layer.Pass());
7524 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
7526 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
7527 pending_tree->DidBecomeActive();
7528 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7530 scoped_ptr<FakePictureLayerImpl> mask_layer =
7531 FakePictureLayerImpl::Create(pending_tree, 11);
7532 FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
7533 raw_pending_layer->SetMaskLayer(mask_layer.Pass());
7534 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
7536 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7537 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
7538 pending_tree->DidBecomeActive();
7539 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7540 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7542 scoped_ptr<FakePictureLayerImpl> replica_layer =
7543 FakePictureLayerImpl::Create(pending_tree, 12);
7544 scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
7545 FakePictureLayerImpl::Create(pending_tree, 13);
7546 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
7547 replica_layer->SetMaskLayer(replica_mask_layer.Pass());
7548 raw_pending_layer->SetReplicaLayer(replica_layer.Pass());
7549 ASSERT_EQ(raw_replica_mask_layer,
7550 raw_pending_layer->replica_layer()->mask_layer());
7552 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7553 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7554 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
7555 pending_tree->DidBecomeActive();
7556 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
7557 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
7558 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
7561 TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
7562 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
7563 host_impl_->SetViewportSize(gfx::Size(50, 50));
7564 DrawFrame();
7566 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
7568 float min_page_scale = 1.f, max_page_scale = 4.f;
7569 float page_scale_factor = 1.f;
7571 // The scroll deltas should have the page scale factor applied.
7573 host_impl_->active_tree()->PushPageScaleFromMainThread(
7574 page_scale_factor, min_page_scale, max_page_scale);
7575 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
7576 scroll_layer->SetScrollDelta(gfx::Vector2d());
7578 float page_scale_delta = 2.f;
7579 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
7580 host_impl_->PinchGestureBegin();
7581 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
7582 host_impl_->PinchGestureEnd();
7583 host_impl_->ScrollEnd();
7585 gfx::Vector2dF scroll_delta(0, 5);
7586 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7587 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7588 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
7590 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7591 host_impl_->ScrollEnd();
7592 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
7593 scroll_layer->CurrentScrollOffset());
7597 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
7598 public:
7599 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7600 void DidLoseOutputSurfaceOnImplThread() override { num_lost_surfaces_++; }
7602 protected:
7603 int num_lost_surfaces_;
7606 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
7607 // Really we just need at least one client notification each time
7608 // we go from having a valid output surface to not having a valid output
7609 // surface.
7610 EXPECT_EQ(0, num_lost_surfaces_);
7611 host_impl_->DidLoseOutputSurface();
7612 EXPECT_EQ(1, num_lost_surfaces_);
7613 host_impl_->DidLoseOutputSurface();
7614 EXPECT_LE(1, num_lost_surfaces_);
7617 TEST_F(LayerTreeHostImplTest, RemoveUnreferencedRenderPass) {
7618 LayerTreeHostImpl::FrameData frame;
7619 frame.render_passes.push_back(RenderPass::Create());
7620 RenderPass* pass3 = frame.render_passes.back();
7621 frame.render_passes.push_back(RenderPass::Create());
7622 RenderPass* pass2 = frame.render_passes.back();
7623 frame.render_passes.push_back(RenderPass::Create());
7624 RenderPass* pass1 = frame.render_passes.back();
7626 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7627 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7628 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7630 frame.render_passes_by_id[pass1->id] = pass1;
7631 frame.render_passes_by_id[pass2->id] = pass2;
7632 frame.render_passes_by_id[pass3->id] = pass3;
7634 // Add a quad to each pass so they aren't empty.
7635 SolidColorDrawQuad* color_quad;
7636 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7637 color_quad->material = DrawQuad::SOLID_COLOR;
7638 color_quad = pass2->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7639 color_quad->material = DrawQuad::SOLID_COLOR;
7640 color_quad = pass3->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7641 color_quad->material = DrawQuad::SOLID_COLOR;
7643 // pass3 is referenced by pass2.
7644 RenderPassDrawQuad* rpdq =
7645 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7646 rpdq->material = DrawQuad::RENDER_PASS;
7647 rpdq->render_pass_id = pass3->id;
7649 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
7650 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
7651 EXPECT_EQ(1u, frame.render_passes_by_id.size());
7652 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
7653 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
7654 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
7655 EXPECT_EQ(1u, frame.render_passes.size());
7656 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
7659 TEST_F(LayerTreeHostImplTest, RemoveEmptyRenderPass) {
7660 LayerTreeHostImpl::FrameData frame;
7661 frame.render_passes.push_back(RenderPass::Create());
7662 RenderPass* pass3 = frame.render_passes.back();
7663 frame.render_passes.push_back(RenderPass::Create());
7664 RenderPass* pass2 = frame.render_passes.back();
7665 frame.render_passes.push_back(RenderPass::Create());
7666 RenderPass* pass1 = frame.render_passes.back();
7668 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7669 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7670 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7672 frame.render_passes_by_id[pass1->id] = pass1;
7673 frame.render_passes_by_id[pass2->id] = pass2;
7674 frame.render_passes_by_id[pass3->id] = pass3;
7676 // pass1 is not empty, but pass2 and pass3 are.
7677 SolidColorDrawQuad* color_quad;
7678 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7679 color_quad->material = DrawQuad::SOLID_COLOR;
7681 // pass3 is referenced by pass2.
7682 RenderPassDrawQuad* rpdq =
7683 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7684 rpdq->material = DrawQuad::RENDER_PASS;
7685 rpdq->render_pass_id = pass3->id;
7687 // pass2 is referenced by pass1.
7688 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7689 rpdq->material = DrawQuad::RENDER_PASS;
7690 rpdq->render_pass_id = pass2->id;
7692 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7693 // should be removed.
7694 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
7695 EXPECT_EQ(1u, frame.render_passes_by_id.size());
7696 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
7697 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
7698 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
7699 EXPECT_EQ(1u, frame.render_passes.size());
7700 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
7701 // The RenderPassDrawQuad should be removed from pass1.
7702 EXPECT_EQ(1u, pass1->quad_list.size());
7703 EXPECT_EQ(DrawQuad::SOLID_COLOR, pass1->quad_list.ElementAt(0)->material);
7706 TEST_F(LayerTreeHostImplTest, DoNotRemoveEmptyRootRenderPass) {
7707 LayerTreeHostImpl::FrameData frame;
7708 frame.render_passes.push_back(RenderPass::Create());
7709 RenderPass* pass3 = frame.render_passes.back();
7710 frame.render_passes.push_back(RenderPass::Create());
7711 RenderPass* pass2 = frame.render_passes.back();
7712 frame.render_passes.push_back(RenderPass::Create());
7713 RenderPass* pass1 = frame.render_passes.back();
7715 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7716 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7717 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7719 frame.render_passes_by_id[pass1->id] = pass1;
7720 frame.render_passes_by_id[pass2->id] = pass2;
7721 frame.render_passes_by_id[pass3->id] = pass3;
7723 // pass3 is referenced by pass2.
7724 RenderPassDrawQuad* rpdq =
7725 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7726 rpdq->material = DrawQuad::RENDER_PASS;
7727 rpdq->render_pass_id = pass3->id;
7729 // pass2 is referenced by pass1.
7730 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7731 rpdq->material = DrawQuad::RENDER_PASS;
7732 rpdq->render_pass_id = pass2->id;
7734 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7735 // should be removed. Then pass1 is empty too, but it's the root so it should
7736 // not be removed.
7737 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
7738 EXPECT_EQ(1u, frame.render_passes_by_id.size());
7739 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
7740 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
7741 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
7742 EXPECT_EQ(1u, frame.render_passes.size());
7743 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
7744 // The RenderPassDrawQuad should be removed from pass1.
7745 EXPECT_EQ(0u, pass1->quad_list.size());
7748 class FakeVideoFrameController : public VideoFrameController {
7749 public:
7750 void OnBeginFrame(const BeginFrameArgs& args) override {
7751 begin_frame_args_ = args;
7754 const BeginFrameArgs& begin_frame_args() { return begin_frame_args_; }
7756 private:
7757 BeginFrameArgs begin_frame_args_;
7760 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) {
7761 BeginFrameArgs begin_frame_args =
7762 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
7763 FakeVideoFrameController controller;
7765 host_impl_->WillBeginImplFrame(begin_frame_args);
7766 EXPECT_FALSE(controller.begin_frame_args().IsValid());
7767 host_impl_->AddVideoFrameController(&controller);
7768 EXPECT_TRUE(controller.begin_frame_args().IsValid());
7769 host_impl_->DidFinishImplFrame();
7772 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerOutsideFrame) {
7773 BeginFrameArgs begin_frame_args =
7774 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
7775 FakeVideoFrameController controller;
7777 host_impl_->WillBeginImplFrame(begin_frame_args);
7778 host_impl_->DidFinishImplFrame();
7780 EXPECT_FALSE(controller.begin_frame_args().IsValid());
7781 host_impl_->AddVideoFrameController(&controller);
7782 EXPECT_FALSE(controller.begin_frame_args().IsValid());
7784 begin_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
7785 EXPECT_FALSE(controller.begin_frame_args().IsValid());
7786 host_impl_->WillBeginImplFrame(begin_frame_args);
7787 EXPECT_TRUE(controller.begin_frame_args().IsValid());
7790 TEST_F(LayerTreeHostImplTest, GpuRasterizationStatusModes) {
7791 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
7793 host_impl_->SetHasGpuRasterizationTrigger(true);
7794 host_impl_->SetContentIsSuitableForGpuRasterization(true);
7795 EXPECT_EQ(GpuRasterizationStatus::ON, host_impl_->gpu_rasterization_status());
7796 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
7798 host_impl_->SetHasGpuRasterizationTrigger(false);
7799 host_impl_->SetContentIsSuitableForGpuRasterization(true);
7800 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT,
7801 host_impl_->gpu_rasterization_status());
7802 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
7804 host_impl_->SetHasGpuRasterizationTrigger(true);
7805 host_impl_->SetContentIsSuitableForGpuRasterization(false);
7806 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT,
7807 host_impl_->gpu_rasterization_status());
7808 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
7809 EXPECT_FALSE(host_impl_->use_msaa());
7811 scoped_ptr<TestWebGraphicsContext3D> context_with_msaa =
7812 TestWebGraphicsContext3D::Create();
7813 context_with_msaa->SetMaxSamples(8);
7815 LayerTreeSettings msaaSettings = GpuRasterizationEnabledSettings();
7816 msaaSettings.gpu_rasterization_msaa_sample_count = 4;
7817 EXPECT_TRUE(CreateHostImpl(
7818 msaaSettings, FakeOutputSurface::Create3d(context_with_msaa.Pass())));
7819 host_impl_->SetHasGpuRasterizationTrigger(true);
7820 host_impl_->SetContentIsSuitableForGpuRasterization(false);
7821 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT,
7822 host_impl_->gpu_rasterization_status());
7823 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
7824 EXPECT_TRUE(host_impl_->use_msaa());
7826 LayerTreeSettings settings = DefaultSettings();
7827 settings.gpu_rasterization_enabled = false;
7828 EXPECT_TRUE(CreateHostImpl(settings, FakeOutputSurface::Create3d()));
7829 host_impl_->SetHasGpuRasterizationTrigger(true);
7830 host_impl_->SetContentIsSuitableForGpuRasterization(true);
7831 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE,
7832 host_impl_->gpu_rasterization_status());
7833 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
7835 settings.gpu_rasterization_forced = true;
7836 EXPECT_TRUE(CreateHostImpl(settings, FakeOutputSurface::Create3d()));
7838 host_impl_->SetHasGpuRasterizationTrigger(false);
7839 host_impl_->SetContentIsSuitableForGpuRasterization(false);
7840 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED,
7841 host_impl_->gpu_rasterization_status());
7842 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
7845 // A mock output surface which lets us detect calls to ForceReclaimResources.
7846 class MockReclaimResourcesOutputSurface : public FakeOutputSurface {
7847 public:
7848 static scoped_ptr<MockReclaimResourcesOutputSurface> Create3d() {
7849 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
7850 TestContextProvider::Create(), TestContextProvider::Create(), false));
7853 MOCK_METHOD0(ForceReclaimResources, void());
7855 protected:
7856 MockReclaimResourcesOutputSurface(
7857 scoped_refptr<ContextProvider> context_provider,
7858 scoped_refptr<ContextProvider> worker_context_provider,
7859 bool delegated_rendering)
7860 : FakeOutputSurface(context_provider,
7861 worker_context_provider,
7862 delegated_rendering) {}
7865 // Display::Draw (and the planned Display Scheduler) currently rely on resources
7866 // being reclaimed to block drawing between BeginCommit / Swap. This test
7867 // ensures that BeginCommit triggers ForceReclaimResources. See
7868 // crbug.com/489515.
7869 TEST_F(LayerTreeHostImplTest, BeginCommitReclaimsResources) {
7870 scoped_ptr<MockReclaimResourcesOutputSurface> output_surface(
7871 MockReclaimResourcesOutputSurface::Create3d());
7872 // Hold an unowned pointer to the output surface to use for mock expectations.
7873 MockReclaimResourcesOutputSurface* mock_output_surface = output_surface.get();
7875 CreateHostImpl(DefaultSettings(), output_surface.Pass());
7876 EXPECT_CALL(*mock_output_surface, ForceReclaimResources()).Times(1);
7877 host_impl_->BeginCommit();
7880 } // namespace
7881 } // namespace cc