Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(433)

Side by Side Diff: cc/trees/layer_tree_host_impl_unittest.cc

Issue 1057283003: Remove parts of //cc we aren't using (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/trees/layer_tree_host_impl.cc ('k') | cc/trees/layer_tree_host_perftest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "cc/trees/layer_tree_host_impl.h"
6
7 #include <algorithm>
8 #include <cmath>
9
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/containers/scoped_ptr_hash_map.h"
14 #include "cc/animation/scrollbar_animation_controller_thinning.h"
15 #include "cc/base/math_util.h"
16 #include "cc/input/page_scale_animation.h"
17 #include "cc/input/top_controls_manager.h"
18 #include "cc/layers/append_quads_data.h"
19 #include "cc/layers/delegated_renderer_layer_impl.h"
20 #include "cc/layers/heads_up_display_layer_impl.h"
21 #include "cc/layers/io_surface_layer_impl.h"
22 #include "cc/layers/layer_impl.h"
23 #include "cc/layers/painted_scrollbar_layer_impl.h"
24 #include "cc/layers/render_surface_impl.h"
25 #include "cc/layers/solid_color_layer_impl.h"
26 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
27 #include "cc/layers/texture_layer_impl.h"
28 #include "cc/layers/tiled_layer_impl.h"
29 #include "cc/output/begin_frame_args.h"
30 #include "cc/output/compositor_frame_ack.h"
31 #include "cc/output/compositor_frame_metadata.h"
32 #include "cc/output/copy_output_request.h"
33 #include "cc/output/copy_output_result.h"
34 #include "cc/output/gl_renderer.h"
35 #include "cc/output/latency_info_swap_promise.h"
36 #include "cc/quads/render_pass_draw_quad.h"
37 #include "cc/quads/solid_color_draw_quad.h"
38 #include "cc/quads/texture_draw_quad.h"
39 #include "cc/quads/tile_draw_quad.h"
40 #include "cc/resources/layer_tiling_data.h"
41 #include "cc/test/animation_test_common.h"
42 #include "cc/test/begin_frame_args_test.h"
43 #include "cc/test/fake_layer_tree_host_impl.h"
44 #include "cc/test/fake_output_surface.h"
45 #include "cc/test/fake_output_surface_client.h"
46 #include "cc/test/fake_picture_layer_impl.h"
47 #include "cc/test/fake_picture_pile_impl.h"
48 #include "cc/test/fake_proxy.h"
49 #include "cc/test/geometry_test_utils.h"
50 #include "cc/test/layer_test_common.h"
51 #include "cc/test/layer_tree_test.h"
52 #include "cc/test/render_pass_test_common.h"
53 #include "cc/test/test_gpu_memory_buffer_manager.h"
54 #include "cc/test/test_shared_bitmap_manager.h"
55 #include "cc/test/test_task_graph_runner.h"
56 #include "cc/test/test_web_graphics_context_3d.h"
57 #include "cc/trees/layer_tree_impl.h"
58 #include "cc/trees/single_thread_proxy.h"
59 #include "testing/gmock/include/gmock/gmock.h"
60 #include "testing/gtest/include/gtest/gtest.h"
61 #include "third_party/skia/include/core/SkMallocPixelRef.h"
62 #include "ui/gfx/frame_time.h"
63 #include "ui/gfx/geometry/rect_conversions.h"
64 #include "ui/gfx/geometry/size_conversions.h"
65 #include "ui/gfx/geometry/vector2d_conversions.h"
66
67 using ::testing::Mock;
68 using ::testing::Return;
69 using ::testing::AnyNumber;
70 using ::testing::AtLeast;
71 using ::testing::_;
72
73 namespace cc {
74 namespace {
75
76 class LayerTreeHostImplTest : public testing::Test,
77 public LayerTreeHostImplClient {
78 public:
79 LayerTreeHostImplTest()
80 : proxy_(base::MessageLoopProxy::current(),
81 base::MessageLoopProxy::current()),
82 always_impl_thread_(&proxy_),
83 always_main_thread_blocked_(&proxy_),
84 shared_bitmap_manager_(new TestSharedBitmapManager),
85 gpu_memory_buffer_manager_(new TestGpuMemoryBufferManager),
86 task_graph_runner_(new TestTaskGraphRunner),
87 on_can_draw_state_changed_called_(false),
88 did_notify_ready_to_activate_(false),
89 did_request_commit_(false),
90 did_request_redraw_(false),
91 did_request_animate_(false),
92 did_request_prepare_tiles_(false),
93 did_complete_page_scale_animation_(false),
94 reduce_memory_result_(true),
95 current_limit_bytes_(0),
96 current_priority_cutoff_value_(0) {
97 }
98
99 LayerTreeSettings DefaultSettings() {
100 LayerTreeSettings settings;
101 settings.minimum_occlusion_tracking_size = gfx::Size();
102 settings.impl_side_painting = true;
103 settings.renderer_settings.texture_id_allocation_chunk_size = 1;
104 settings.report_overscroll_only_for_scrollable_axes = true;
105 settings.use_pinch_virtual_viewport = true;
106 return settings;
107 }
108
109 void SetUp() override {
110 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
111 }
112
113 void TearDown() override {}
114
115 void UpdateRendererCapabilitiesOnImplThread() override {}
116 void DidLoseOutputSurfaceOnImplThread() override {}
117 void CommitVSyncParameters(base::TimeTicks timebase,
118 base::TimeDelta interval) override {}
119 void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {}
120 void SetMaxSwapsPendingOnImplThread(int max) override {}
121 void DidSwapBuffersOnImplThread() override {}
122 void DidSwapBuffersCompleteOnImplThread() override {}
123 void OnCanDrawStateChanged(bool can_draw) override {
124 on_can_draw_state_changed_called_ = true;
125 }
126 void NotifyReadyToActivate() override {
127 did_notify_ready_to_activate_ = true;
128 host_impl_->ActivateSyncTree();
129 }
130 void NotifyReadyToDraw() override {}
131 void SetNeedsRedrawOnImplThread() override { did_request_redraw_ = true; }
132 void SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) override {
133 did_request_redraw_ = true;
134 }
135 void SetNeedsAnimateOnImplThread() override { did_request_animate_ = true; }
136 void SetNeedsPrepareTilesOnImplThread() override {
137 did_request_prepare_tiles_ = true;
138 }
139 void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; }
140 void PostAnimationEventsToMainThreadOnImplThread(
141 scoped_ptr<AnimationEventsVector> events) override {}
142 bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
143 int priority_cutoff) override {
144 current_limit_bytes_ = limit_bytes;
145 current_priority_cutoff_value_ = priority_cutoff;
146 return reduce_memory_result_;
147 }
148 bool IsInsideDraw() override { return false; }
149 void RenewTreePriority() override {}
150 void PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
151 base::TimeDelta delay) override {
152 animation_task_ = task;
153 requested_animation_delay_ = delay;
154 }
155 void DidActivateSyncTree() override {}
156 void DidPrepareTiles() override {}
157 void DidCompletePageScaleAnimationOnImplThread() override {
158 did_complete_page_scale_animation_ = true;
159 }
160
161 void set_reduce_memory_result(bool reduce_memory_result) {
162 reduce_memory_result_ = reduce_memory_result;
163 }
164
165 virtual bool CreateHostImpl(const LayerTreeSettings& settings,
166 scoped_ptr<OutputSurface> output_surface) {
167 host_impl_ = LayerTreeHostImpl::Create(
168 settings, this, &proxy_, &stats_instrumentation_,
169 shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(),
170 task_graph_runner_.get(), 0);
171 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
172 host_impl_->SetViewportSize(gfx::Size(10, 10));
173 return init;
174 }
175
176 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
177 root->SetPosition(gfx::PointF());
178 root->SetBounds(gfx::Size(10, 10));
179 root->SetContentBounds(gfx::Size(10, 10));
180 root->SetDrawsContent(true);
181 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
182 root->SetHasRenderSurface(true);
183 host_impl_->active_tree()->SetRootLayer(root.Pass());
184 }
185
186 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
187 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
188 for (size_t i = 0; i < layer->children().size(); ++i)
189 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
190 }
191
192 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
193 int id,
194 const gfx::Vector2d& scroll_delta) {
195 int times_encountered = 0;
196
197 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
198 if (scroll_info.scrolls[i].layer_id != id)
199 continue;
200 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
201 times_encountered++;
202 }
203
204 ASSERT_EQ(1, times_encountered);
205 }
206
207 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
208 int times_encountered = 0;
209
210 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
211 if (scroll_info.scrolls[i].layer_id != id)
212 continue;
213 times_encountered++;
214 }
215
216 ASSERT_EQ(0, times_encountered);
217 }
218
219 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
220 const gfx::Size& content_size) {
221 const int kInnerViewportScrollLayerId = 2;
222 const int kInnerViewportClipLayerId = 4;
223 const int kPageScaleLayerId = 5;
224 scoped_ptr<LayerImpl> root =
225 LayerImpl::Create(layer_tree_impl, 1);
226 root->SetBounds(content_size);
227 root->SetContentBounds(content_size);
228 root->SetPosition(gfx::PointF());
229 root->SetHasRenderSurface(true);
230
231 scoped_ptr<LayerImpl> scroll =
232 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
233 LayerImpl* scroll_layer = scroll.get();
234 scroll->SetIsContainerForFixedPositionLayers(true);
235 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
236
237 scoped_ptr<LayerImpl> clip =
238 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
239 clip->SetBounds(
240 gfx::Size(content_size.width() / 2, content_size.height() / 2));
241
242 scoped_ptr<LayerImpl> page_scale =
243 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
244
245 scroll->SetScrollClipLayer(clip->id());
246 scroll->SetBounds(content_size);
247 scroll->SetContentBounds(content_size);
248 scroll->SetPosition(gfx::PointF());
249 scroll->SetIsContainerForFixedPositionLayers(true);
250
251 scoped_ptr<LayerImpl> contents =
252 LayerImpl::Create(layer_tree_impl, 3);
253 contents->SetDrawsContent(true);
254 contents->SetBounds(content_size);
255 contents->SetContentBounds(content_size);
256 contents->SetPosition(gfx::PointF());
257
258 scroll->AddChild(contents.Pass());
259 page_scale->AddChild(scroll.Pass());
260 clip->AddChild(page_scale.Pass());
261 root->AddChild(clip.Pass());
262
263 layer_tree_impl->SetRootLayer(root.Pass());
264 layer_tree_impl->SetViewportLayersFromIds(
265 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
266 Layer::INVALID_ID);
267
268 return scroll_layer;
269 }
270
271 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
272 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
273 host_impl_->active_tree(), content_size);
274 host_impl_->active_tree()->DidBecomeActive();
275 return scroll_layer;
276 }
277
278 // TODO(wjmaclean) Add clip-layer pointer to parameters.
279 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
280 const gfx::Size& size,
281 LayerImpl* clip_layer) {
282 DCHECK(clip_layer);
283 DCHECK(id != clip_layer->id());
284 scoped_ptr<LayerImpl> layer =
285 LayerImpl::Create(host_impl_->active_tree(), id);
286 layer->SetScrollClipLayer(clip_layer->id());
287 layer->SetDrawsContent(true);
288 layer->SetBounds(size);
289 layer->SetContentBounds(size);
290 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
291 return layer.Pass();
292 }
293
294 void DrawFrame() {
295 LayerTreeHostImpl::FrameData frame;
296 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
297 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
298 host_impl_->DidDrawAllLayers(frame);
299 }
300
301 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
302 void pinch_zoom_pan_viewport_test(float device_scale_factor);
303 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
304 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
305 float device_scale_factor);
306
307 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
308 // Note: It is not possible to disable the renderer once it has been set,
309 // so we do not need to test that disabling the renderer notifies us
310 // that can_draw changed.
311 EXPECT_FALSE(host_impl_->CanDraw());
312 on_can_draw_state_changed_called_ = false;
313
314 // Set up the root layer, which allows us to draw.
315 SetupScrollAndContentsLayers(gfx::Size(100, 100));
316 EXPECT_TRUE(host_impl_->CanDraw());
317 EXPECT_TRUE(on_can_draw_state_changed_called_);
318 on_can_draw_state_changed_called_ = false;
319
320 // Toggle the root layer to make sure it toggles can_draw
321 host_impl_->active_tree()->SetRootLayer(nullptr);
322 EXPECT_FALSE(host_impl_->CanDraw());
323 EXPECT_TRUE(on_can_draw_state_changed_called_);
324 on_can_draw_state_changed_called_ = false;
325
326 SetupScrollAndContentsLayers(gfx::Size(100, 100));
327 EXPECT_TRUE(host_impl_->CanDraw());
328 EXPECT_TRUE(on_can_draw_state_changed_called_);
329 on_can_draw_state_changed_called_ = false;
330
331 // Toggle the device viewport size to make sure it toggles can_draw.
332 host_impl_->SetViewportSize(gfx::Size());
333 if (always_draw) {
334 EXPECT_TRUE(host_impl_->CanDraw());
335 } else {
336 EXPECT_FALSE(host_impl_->CanDraw());
337 }
338 EXPECT_TRUE(on_can_draw_state_changed_called_);
339 on_can_draw_state_changed_called_ = false;
340
341 host_impl_->SetViewportSize(gfx::Size(100, 100));
342 EXPECT_TRUE(host_impl_->CanDraw());
343 EXPECT_TRUE(on_can_draw_state_changed_called_);
344 on_can_draw_state_changed_called_ = false;
345
346 // Toggle contents textures purged without causing any evictions,
347 // and make sure that it does not change can_draw.
348 set_reduce_memory_result(false);
349 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
350 host_impl_->memory_allocation_limit_bytes() - 1));
351 EXPECT_TRUE(host_impl_->CanDraw());
352 EXPECT_FALSE(on_can_draw_state_changed_called_);
353 on_can_draw_state_changed_called_ = false;
354
355 // Toggle contents textures purged to make sure it toggles can_draw.
356 set_reduce_memory_result(true);
357 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
358 host_impl_->memory_allocation_limit_bytes() - 1));
359 if (always_draw) {
360 EXPECT_TRUE(host_impl_->CanDraw());
361 } else {
362 EXPECT_FALSE(host_impl_->CanDraw());
363 }
364 EXPECT_TRUE(on_can_draw_state_changed_called_);
365 on_can_draw_state_changed_called_ = false;
366
367 host_impl_->active_tree()->ResetContentsTexturesPurged();
368 EXPECT_TRUE(host_impl_->CanDraw());
369 EXPECT_TRUE(on_can_draw_state_changed_called_);
370 on_can_draw_state_changed_called_ = false;
371 }
372
373 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
374
375 protected:
376 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
377 return FakeOutputSurface::Create3d();
378 }
379
380 void DrawOneFrame() {
381 LayerTreeHostImpl::FrameData frame_data;
382 host_impl_->PrepareToDraw(&frame_data);
383 host_impl_->DidDrawAllLayers(frame_data);
384 }
385
386 FakeProxy proxy_;
387 DebugScopedSetImplThread always_impl_thread_;
388 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
389
390 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
391 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
392 scoped_ptr<TestTaskGraphRunner> task_graph_runner_;
393 scoped_ptr<LayerTreeHostImpl> host_impl_;
394 FakeRenderingStatsInstrumentation stats_instrumentation_;
395 bool on_can_draw_state_changed_called_;
396 bool did_notify_ready_to_activate_;
397 bool did_request_commit_;
398 bool did_request_redraw_;
399 bool did_request_animate_;
400 bool did_request_prepare_tiles_;
401 bool did_complete_page_scale_animation_;
402 bool reduce_memory_result_;
403 base::Closure animation_task_;
404 base::TimeDelta requested_animation_delay_;
405 size_t current_limit_bytes_;
406 int current_priority_cutoff_value_;
407 };
408
409 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
410 bool always_draw = false;
411 CheckNotifyCalledIfCanDrawChanged(always_draw);
412 }
413
414 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
415 CreateHostImpl(DefaultSettings(),
416 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
417
418 bool always_draw = true;
419 CheckNotifyCalledIfCanDrawChanged(always_draw);
420 }
421
422 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
423 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
424
425 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
426 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
427 }
428
429 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
430 {
431 scoped_ptr<LayerImpl> root =
432 LayerImpl::Create(host_impl_->active_tree(), 1);
433 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
434 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
435 root->children()[1]->AddChild(
436 LayerImpl::Create(host_impl_->active_tree(), 4));
437 root->children()[1]->AddChild(
438 LayerImpl::Create(host_impl_->active_tree(), 5));
439 root->children()[1]->children()[0]->AddChild(
440 LayerImpl::Create(host_impl_->active_tree(), 6));
441 host_impl_->active_tree()->SetRootLayer(root.Pass());
442 }
443 LayerImpl* root = host_impl_->active_tree()->root_layer();
444
445 ExpectClearedScrollDeltasRecursive(root);
446
447 scoped_ptr<ScrollAndScaleSet> scroll_info;
448
449 scroll_info = host_impl_->ProcessScrollDeltas();
450 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
451 ExpectClearedScrollDeltasRecursive(root);
452
453 scroll_info = host_impl_->ProcessScrollDeltas();
454 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
455 ExpectClearedScrollDeltasRecursive(root);
456 }
457
458 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
459 gfx::ScrollOffset scroll_offset(20, 30);
460 gfx::Vector2d scroll_delta(11, -15);
461 {
462 scoped_ptr<LayerImpl> root_clip =
463 LayerImpl::Create(host_impl_->active_tree(), 2);
464 scoped_ptr<LayerImpl> root =
465 LayerImpl::Create(host_impl_->active_tree(), 1);
466 root_clip->SetBounds(gfx::Size(10, 10));
467 LayerImpl* root_layer = root.get();
468 root_clip->AddChild(root.Pass());
469 root_layer->SetBounds(gfx::Size(110, 110));
470 root_layer->SetScrollClipLayer(root_clip->id());
471 root_layer->PushScrollOffsetFromMainThread(scroll_offset);
472 root_layer->ScrollBy(scroll_delta);
473 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
474 }
475 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
476
477 scoped_ptr<ScrollAndScaleSet> scroll_info;
478
479 scroll_info = host_impl_->ProcessScrollDeltas();
480 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
481 ExpectContains(*scroll_info, root->id(), scroll_delta);
482
483 gfx::Vector2d scroll_delta2(-5, 27);
484 root->ScrollBy(scroll_delta2);
485 scroll_info = host_impl_->ProcessScrollDeltas();
486 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
487 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
488
489 root->ScrollBy(gfx::Vector2d());
490 scroll_info = host_impl_->ProcessScrollDeltas();
491 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
492 }
493
494 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
495 SetupScrollAndContentsLayers(gfx::Size(100, 100));
496 host_impl_->SetViewportSize(gfx::Size(50, 50));
497 DrawFrame();
498
499 EXPECT_EQ(InputHandler::SCROLL_STARTED,
500 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
501 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
502 InputHandler::WHEEL));
503 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
504 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
505 InputHandler::WHEEL));
506 host_impl_->ScrollEnd();
507 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
508 InputHandler::WHEEL));
509 EXPECT_TRUE(did_request_redraw_);
510 EXPECT_TRUE(did_request_commit_);
511 }
512
513 TEST_F(LayerTreeHostImplTest, ScrollActiveOnlyAfterScrollMovement) {
514 SetupScrollAndContentsLayers(gfx::Size(100, 100));
515 host_impl_->SetViewportSize(gfx::Size(50, 50));
516 DrawFrame();
517
518 EXPECT_EQ(InputHandler::SCROLL_STARTED,
519 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
520 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
521 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
522 EXPECT_TRUE(host_impl_->IsActivelyScrolling());
523 host_impl_->ScrollEnd();
524 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
525 }
526
527 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
528 // We should not crash when trying to scroll an empty layer tree.
529 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
530 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
531 }
532
533 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
534 scoped_ptr<TestWebGraphicsContext3D> context_owned =
535 TestWebGraphicsContext3D::Create();
536 context_owned->set_context_lost(true);
537
538 // Initialization will fail.
539 EXPECT_FALSE(CreateHostImpl(
540 DefaultSettings(), FakeOutputSurface::Create3d(context_owned.Pass())));
541
542 SetupScrollAndContentsLayers(gfx::Size(100, 100));
543
544 // We should not crash when trying to scroll after the renderer initialization
545 // fails.
546 EXPECT_EQ(InputHandler::SCROLL_STARTED,
547 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
548 }
549
550 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
551 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
552 host_impl_->SetViewportSize(gfx::Size(50, 50));
553 DrawFrame();
554
555 // We should not crash if the tree is replaced while we are scrolling.
556 EXPECT_EQ(InputHandler::SCROLL_STARTED,
557 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
558 host_impl_->active_tree()->DetachLayerTree();
559
560 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
561
562 // We should still be scrolling, because the scrolled layer also exists in the
563 // new tree.
564 gfx::Vector2d scroll_delta(0, 10);
565 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
566 host_impl_->ScrollEnd();
567 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
568 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
569 }
570
571 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
572 SetupScrollAndContentsLayers(gfx::Size(100, 100));
573 host_impl_->SetViewportSize(gfx::Size(50, 50));
574 DrawFrame();
575 LayerImpl* root = host_impl_->active_tree()->root_layer();
576
577 // With registered event handlers, wheel scrolls don't necessarily
578 // have to go to the main thread.
579 root->SetHaveWheelEventHandlers(true);
580 EXPECT_EQ(InputHandler::SCROLL_STARTED,
581 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
582 host_impl_->ScrollEnd();
583
584 // But typically the scroll-blocks-on mode will require them to.
585 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
586 SCROLL_BLOCKS_ON_START_TOUCH);
587 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
588 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
589
590 // But gesture scrolls can still be handled.
591 EXPECT_EQ(InputHandler::SCROLL_STARTED,
592 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
593 host_impl_->ScrollEnd();
594
595 // And if the handlers go away, wheel scrolls can again be processed
596 // on impl (despite the scroll-blocks-on mode).
597 root->SetHaveWheelEventHandlers(false);
598 EXPECT_EQ(InputHandler::SCROLL_STARTED,
599 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
600 host_impl_->ScrollEnd();
601 }
602
603 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
604 LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
605 host_impl_->SetViewportSize(gfx::Size(50, 50));
606 DrawFrame();
607 LayerImpl* root = host_impl_->active_tree()->root_layer();
608
609 LayerImpl* child = 0;
610 {
611 scoped_ptr<LayerImpl> child_layer =
612 LayerImpl::Create(host_impl_->active_tree(), 6);
613 child = child_layer.get();
614 child_layer->SetDrawsContent(true);
615 child_layer->SetPosition(gfx::PointF(0, 20));
616 child_layer->SetBounds(gfx::Size(50, 50));
617 child_layer->SetContentBounds(gfx::Size(50, 50));
618 scroll->AddChild(child_layer.Pass());
619 }
620
621 // Touch handler regions determine whether touch events block scroll.
622 root->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
623 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
624 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH |
625 SCROLL_BLOCKS_ON_WHEEL_EVENT);
626 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
627
628 // But they don't influence the actual handling of the scroll gestures.
629 EXPECT_EQ(InputHandler::SCROLL_STARTED,
630 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
631 host_impl_->ScrollEnd();
632
633 // It's the union of scroll-blocks-on mode bits across all layers in the
634 // scroll paret chain that matters.
635 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
636 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE);
637 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
638 child->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH);
639 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
640 }
641
642 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnScrollEventHandlers) {
643 SetupScrollAndContentsLayers(gfx::Size(100, 100));
644 host_impl_->SetViewportSize(gfx::Size(50, 50));
645 DrawFrame();
646 LayerImpl* root = host_impl_->active_tree()->root_layer();
647
648 // With registered scroll handlers, scrolls don't generally have to go
649 // to the main thread.
650 root->SetHaveScrollEventHandlers(true);
651 EXPECT_EQ(InputHandler::SCROLL_STARTED,
652 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
653 host_impl_->ScrollEnd();
654
655 // Even the default scroll blocks on mode doesn't require this.
656 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
657 SCROLL_BLOCKS_ON_START_TOUCH);
658 EXPECT_EQ(InputHandler::SCROLL_STARTED,
659 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
660 host_impl_->ScrollEnd();
661
662 // But the page can opt in to blocking on scroll event handlers.
663 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
664 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
665 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
666
667 // GESTURE and WHEEL scrolls behave identically in this regard.
668 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
669 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
670
671 // And if the handlers go away, scrolls can again be processed on impl
672 // (despite the scroll-blocks-on mode).
673 root->SetHaveScrollEventHandlers(false);
674 EXPECT_EQ(InputHandler::SCROLL_STARTED,
675 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
676 host_impl_->ScrollEnd();
677 }
678
679 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) {
680 host_impl_->SetViewportSize(gfx::Size(50, 50));
681
682 // Create a normal scrollable root layer
683 LayerImpl* root_scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
684 LayerImpl* root_child = root_scroll->children()[0];
685 LayerImpl* root = host_impl_->active_tree()->root_layer();
686 DrawFrame();
687
688 // Create two child scrollable layers
689 LayerImpl* child1 = 0;
690 {
691 scoped_ptr<LayerImpl> scrollable_child_clip_1 =
692 LayerImpl::Create(host_impl_->active_tree(), 6);
693 scoped_ptr<LayerImpl> scrollable_child_1 = CreateScrollableLayer(
694 7, gfx::Size(10, 10), scrollable_child_clip_1.get());
695 child1 = scrollable_child_1.get();
696 scrollable_child_1->SetPosition(gfx::Point(5, 5));
697 scrollable_child_1->SetHaveWheelEventHandlers(true);
698 scrollable_child_1->SetHaveScrollEventHandlers(true);
699 scrollable_child_clip_1->AddChild(scrollable_child_1.Pass());
700 root_child->AddChild(scrollable_child_clip_1.Pass());
701 }
702
703 LayerImpl* child2 = 0;
704 {
705 scoped_ptr<LayerImpl> scrollable_child_clip_2 =
706 LayerImpl::Create(host_impl_->active_tree(), 8);
707 scoped_ptr<LayerImpl> scrollable_child_2 = CreateScrollableLayer(
708 9, gfx::Size(10, 10), scrollable_child_clip_2.get());
709 child2 = scrollable_child_2.get();
710 scrollable_child_2->SetPosition(gfx::Point(5, 20));
711 scrollable_child_2->SetHaveWheelEventHandlers(true);
712 scrollable_child_2->SetHaveScrollEventHandlers(true);
713 scrollable_child_clip_2->AddChild(scrollable_child_2.Pass());
714 root_child->AddChild(scrollable_child_clip_2.Pass());
715 }
716
717 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
718 EXPECT_EQ(InputHandler::SCROLL_STARTED,
719 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
720 host_impl_->ScrollEnd();
721 child1->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
722 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
723 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
724
725 // But not those that hit only other layers.
726 EXPECT_EQ(InputHandler::SCROLL_STARTED,
727 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
728 host_impl_->ScrollEnd();
729
730 // It's the union of bits set across the scroll ancestor chain that matters.
731 EXPECT_EQ(InputHandler::SCROLL_STARTED,
732 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
733 host_impl_->ScrollEnd();
734 EXPECT_EQ(InputHandler::SCROLL_STARTED,
735 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
736 host_impl_->ScrollEnd();
737 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT);
738 EXPECT_EQ(InputHandler::SCROLL_STARTED,
739 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
740 host_impl_->ScrollEnd();
741 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
742 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
743 child2->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
744 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
745 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
746 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
747 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
748 }
749
750 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
751 SetupScrollAndContentsLayers(gfx::Size(100, 100));
752 host_impl_->SetViewportSize(gfx::Size(50, 50));
753 DrawFrame();
754
755 // Ignore the fling since no layer is being scrolled
756 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
757
758 // Start scrolling a layer
759 EXPECT_EQ(InputHandler::SCROLL_STARTED,
760 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
761
762 // Now the fling should go ahead since we've started scrolling a layer
763 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
764 }
765
766 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
767 SetupScrollAndContentsLayers(gfx::Size(100, 100));
768 host_impl_->SetViewportSize(gfx::Size(50, 50));
769 DrawFrame();
770
771 // Ignore the fling since no layer is being scrolled
772 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
773
774 // Start scrolling a layer
775 EXPECT_EQ(InputHandler::SCROLL_STARTED,
776 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
777
778 // Now the fling should go ahead since we've started scrolling a layer
779 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
780 }
781
782 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
783 SetupScrollAndContentsLayers(gfx::Size(100, 100));
784 host_impl_->SetViewportSize(gfx::Size(50, 50));
785 DrawFrame();
786 LayerImpl* root = host_impl_->active_tree()->root_layer();
787
788 root->SetShouldScrollOnMainThread(true);
789
790 // Start scrolling a layer
791 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
792 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
793
794 // The fling should be ignored since there's no layer being scrolled impl-side
795 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
796 }
797
798 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
799 SetupScrollAndContentsLayers(gfx::Size(100, 100));
800 host_impl_->SetViewportSize(gfx::Size(50, 50));
801 DrawFrame();
802 LayerImpl* root = host_impl_->active_tree()->root_layer();
803
804 root->SetShouldScrollOnMainThread(true);
805
806 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
807 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
808 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
809 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
810 }
811
812 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
813 SetupScrollAndContentsLayers(gfx::Size(200, 200));
814 host_impl_->SetViewportSize(gfx::Size(100, 100));
815
816 LayerImpl* root = host_impl_->active_tree()->root_layer();
817 root->SetContentsScale(2.f, 2.f);
818 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
819
820 DrawFrame();
821
822 // All scroll types inside the non-fast scrollable region should fail.
823 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
824 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL));
825 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
826 InputHandler::WHEEL));
827 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
828 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE));
829 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
830 InputHandler::GESTURE));
831
832 // All scroll types outside this region should succeed.
833 EXPECT_EQ(InputHandler::SCROLL_STARTED,
834 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL));
835 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
836 InputHandler::GESTURE));
837 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
838 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
839 InputHandler::GESTURE));
840 host_impl_->ScrollEnd();
841 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
842 InputHandler::GESTURE));
843 EXPECT_EQ(InputHandler::SCROLL_STARTED,
844 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE));
845 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
846 InputHandler::GESTURE));
847 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
848 host_impl_->ScrollEnd();
849 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
850 InputHandler::GESTURE));
851 }
852
853 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
854 SetupScrollAndContentsLayers(gfx::Size(200, 200));
855 host_impl_->SetViewportSize(gfx::Size(100, 100));
856
857 LayerImpl* root = host_impl_->active_tree()->root_layer();
858 root->SetContentsScale(2.f, 2.f);
859 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
860 root->SetPosition(gfx::PointF(-25.f, 0.f));
861
862 DrawFrame();
863
864 // This point would fall into the non-fast scrollable region except that we've
865 // moved the layer down by 25 pixels.
866 EXPECT_EQ(InputHandler::SCROLL_STARTED,
867 host_impl_->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL));
868 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
869 InputHandler::WHEEL));
870 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
871 host_impl_->ScrollEnd();
872
873 // This point is still inside the non-fast region.
874 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
875 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL));
876 }
877
878 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
879 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
880 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
881 host_impl_->SetViewportSize(gfx::Size(50, 50));
882 DrawFrame();
883
884 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
885 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
886 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
887 host_impl_->ScrollEnd();
888 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
889 }
890
891 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
892 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
893 scroll_layer->SetHaveScrollEventHandlers(true);
894 host_impl_->SetViewportSize(gfx::Size(50, 50));
895 DrawFrame();
896
897 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
898 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
899 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
900 host_impl_->ScrollEnd();
901 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
902 }
903
904 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
905 SetupScrollAndContentsLayers(gfx::Size(200, 200));
906 host_impl_->SetViewportSize(gfx::Size(100, 100));
907
908 DrawFrame();
909
910 EXPECT_EQ(InputHandler::SCROLL_STARTED,
911 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
912
913 // Trying to scroll to the left/top will not succeed.
914 EXPECT_FALSE(
915 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
916 EXPECT_FALSE(
917 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
918 EXPECT_FALSE(
919 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
920
921 // Scrolling to the right/bottom will succeed.
922 EXPECT_TRUE(
923 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll);
924 EXPECT_TRUE(
925 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
926 EXPECT_TRUE(
927 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll);
928
929 // Scrolling to left/top will now succeed.
930 EXPECT_TRUE(
931 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
932 EXPECT_TRUE(
933 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
934 EXPECT_TRUE(
935 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
936
937 // Scrolling diagonally against an edge will succeed.
938 EXPECT_TRUE(
939 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll);
940 EXPECT_TRUE(
941 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
942 EXPECT_TRUE(
943 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll);
944
945 // Trying to scroll more than the available space will also succeed.
946 EXPECT_TRUE(
947 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll);
948 }
949
950 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
951 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
952 host_impl_->SetViewportSize(gfx::Size(100, 1000));
953
954 DrawFrame();
955
956 EXPECT_EQ(InputHandler::SCROLL_STARTED,
957 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
958
959 // Trying to scroll without a vertical scrollbar will fail.
960 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
961 gfx::Point(), SCROLL_FORWARD));
962 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
963 gfx::Point(), SCROLL_BACKWARD));
964
965 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
966 PaintedScrollbarLayerImpl::Create(
967 host_impl_->active_tree(),
968 20,
969 VERTICAL));
970 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
971 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
972 vertical_scrollbar.get());
973
974 // Trying to scroll with a vertical scrollbar will succeed.
975 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
976 gfx::Point(), SCROLL_FORWARD));
977 EXPECT_FLOAT_EQ(875.f,
978 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
979 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
980 gfx::Point(), SCROLL_BACKWARD));
981 }
982
983 TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
984 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
985 host_impl_->SetViewportSize(gfx::Size(100, 100));
986
987 gfx::Size overflow_size(400, 400);
988 ASSERT_EQ(1u, scroll_layer->children().size());
989 LayerImpl* overflow = scroll_layer->children()[0];
990 overflow->SetBounds(overflow_size);
991 overflow->SetContentBounds(overflow_size);
992 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
993 overflow->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
994 overflow->SetPosition(gfx::PointF());
995
996 DrawFrame();
997 gfx::Point scroll_position(10, 10);
998
999 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1000 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1001 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1002 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->CurrentScrollOffset());
1003
1004 gfx::Vector2dF scroll_delta(10, 10);
1005 host_impl_->ScrollBy(scroll_position, scroll_delta);
1006 host_impl_->ScrollEnd();
1007 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1008 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1009
1010 overflow->set_user_scrollable_horizontal(false);
1011
1012 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1013 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1014 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1015 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1016
1017 host_impl_->ScrollBy(scroll_position, scroll_delta);
1018 host_impl_->ScrollEnd();
1019 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1020 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1021
1022 overflow->set_user_scrollable_vertical(false);
1023
1024 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1025 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1026 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1027 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1028
1029 host_impl_->ScrollBy(scroll_position, scroll_delta);
1030 host_impl_->ScrollEnd();
1031 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->CurrentScrollOffset());
1032 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1033 }
1034
1035 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
1036 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
1037 host_impl_->SetViewportSize(gfx::Size(50, 50));
1038 DrawFrame();
1039
1040 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
1041 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
1042 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1043
1044 float min_page_scale = 1.f, max_page_scale = 4.f;
1045 float page_scale_factor = 1.f;
1046
1047 // The impl-based pinch zoom should adjust the max scroll position.
1048 {
1049 host_impl_->active_tree()->PushPageScaleFromMainThread(
1050 page_scale_factor, min_page_scale, max_page_scale);
1051 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1052 scroll_layer->SetScrollDelta(gfx::Vector2d());
1053
1054 float page_scale_delta = 2.f;
1055
1056 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1057 host_impl_->PinchGestureBegin();
1058 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1059 host_impl_->PinchGestureEnd();
1060 host_impl_->ScrollEnd();
1061 EXPECT_FALSE(did_request_animate_);
1062 EXPECT_TRUE(did_request_redraw_);
1063 EXPECT_TRUE(did_request_commit_);
1064 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1065
1066 scoped_ptr<ScrollAndScaleSet> scroll_info =
1067 host_impl_->ProcessScrollDeltas();
1068 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1069
1070 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1071 scroll_layer->MaxScrollOffset().ToString());
1072 }
1073
1074 // Scrolling after a pinch gesture should always be in local space. The
1075 // scroll deltas have the page scale factor applied.
1076 {
1077 host_impl_->active_tree()->PushPageScaleFromMainThread(
1078 page_scale_factor, min_page_scale, max_page_scale);
1079 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1080 scroll_layer->SetScrollDelta(gfx::Vector2d());
1081
1082 float page_scale_delta = 2.f;
1083 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1084 host_impl_->PinchGestureBegin();
1085 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1086 host_impl_->PinchGestureEnd();
1087 host_impl_->ScrollEnd();
1088
1089 gfx::Vector2d scroll_delta(0, 10);
1090 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1091 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
1092 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
1093 host_impl_->ScrollEnd();
1094
1095 scoped_ptr<ScrollAndScaleSet> scroll_info =
1096 host_impl_->ProcessScrollDeltas();
1097 ExpectContains(*scroll_info.get(), scroll_layer->id(),
1098 gfx::Vector2d(0, scroll_delta.y() / page_scale_delta));
1099 }
1100 }
1101
1102 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
1103 ui::LatencyInfo latency_info;
1104 latency_info.trace_id = 1234;
1105 scoped_ptr<SwapPromise> swap_promise(
1106 new LatencyInfoSwapPromise(latency_info));
1107
1108 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1109 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1110 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
1111 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1112 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
1113 host_impl_->ScrollEnd();
1114
1115 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
1116 EXPECT_EQ(1u, scroll_info->swap_promises.size());
1117 EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId());
1118 }
1119
1120 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1121 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1122 host_impl_->SetViewportSize(gfx::Size(50, 50));
1123 DrawFrame();
1124
1125 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1126 DCHECK(scroll_layer);
1127
1128 float min_page_scale = 1.f;
1129 float max_page_scale = 4.f;
1130
1131 // Basic pinch zoom in gesture
1132 {
1133 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1134 max_page_scale);
1135 scroll_layer->SetScrollDelta(gfx::Vector2d());
1136
1137 float page_scale_delta = 2.f;
1138 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1139 host_impl_->PinchGestureBegin();
1140 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1141 host_impl_->PinchGestureEnd();
1142 host_impl_->ScrollEnd();
1143 EXPECT_FALSE(did_request_animate_);
1144 EXPECT_TRUE(did_request_redraw_);
1145 EXPECT_TRUE(did_request_commit_);
1146
1147 scoped_ptr<ScrollAndScaleSet> scroll_info =
1148 host_impl_->ProcessScrollDeltas();
1149 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1150 }
1151
1152 // Zoom-in clamping
1153 {
1154 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1155 max_page_scale);
1156 scroll_layer->SetScrollDelta(gfx::Vector2d());
1157 float page_scale_delta = 10.f;
1158
1159 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1160 host_impl_->PinchGestureBegin();
1161 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1162 host_impl_->PinchGestureEnd();
1163 host_impl_->ScrollEnd();
1164
1165 scoped_ptr<ScrollAndScaleSet> scroll_info =
1166 host_impl_->ProcessScrollDeltas();
1167 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1168 }
1169
1170 // Zoom-out clamping
1171 {
1172 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1173 max_page_scale);
1174 scroll_layer->SetScrollDelta(gfx::Vector2d());
1175 scroll_layer->PullDeltaForMainThread();
1176 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1177
1178 float page_scale_delta = 0.1f;
1179 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1180 host_impl_->PinchGestureBegin();
1181 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1182 host_impl_->PinchGestureEnd();
1183 host_impl_->ScrollEnd();
1184
1185 scoped_ptr<ScrollAndScaleSet> scroll_info =
1186 host_impl_->ProcessScrollDeltas();
1187 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1188
1189 EXPECT_TRUE(scroll_info->scrolls.empty());
1190 }
1191
1192 // Two-finger panning should not happen based on pinch events only
1193 {
1194 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1195 max_page_scale);
1196 scroll_layer->SetScrollDelta(gfx::Vector2d());
1197 scroll_layer->PullDeltaForMainThread();
1198 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1199
1200 float page_scale_delta = 1.f;
1201 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1202 host_impl_->PinchGestureBegin();
1203 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1204 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1205 host_impl_->PinchGestureEnd();
1206 host_impl_->ScrollEnd();
1207
1208 scoped_ptr<ScrollAndScaleSet> scroll_info =
1209 host_impl_->ProcessScrollDeltas();
1210 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1211 EXPECT_TRUE(scroll_info->scrolls.empty());
1212 }
1213
1214 // Two-finger panning should work with interleaved scroll events
1215 {
1216 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1217 max_page_scale);
1218 scroll_layer->SetScrollDelta(gfx::Vector2d());
1219 scroll_layer->PullDeltaForMainThread();
1220 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1221
1222 float page_scale_delta = 1.f;
1223 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1224 host_impl_->PinchGestureBegin();
1225 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1226 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1227 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1228 host_impl_->PinchGestureEnd();
1229 host_impl_->ScrollEnd();
1230
1231 scoped_ptr<ScrollAndScaleSet> scroll_info =
1232 host_impl_->ProcessScrollDeltas();
1233 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1234 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1235 }
1236
1237 // Two-finger panning should work when starting fully zoomed out.
1238 {
1239 host_impl_->active_tree()->PushPageScaleFromMainThread(0.5f, 0.5f, 4.f);
1240 scroll_layer->SetScrollDelta(gfx::Vector2d());
1241 scroll_layer->PullDeltaForMainThread();
1242 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1243
1244 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1245 host_impl_->PinchGestureBegin();
1246 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1247 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1248 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1249 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1250 host_impl_->PinchGestureEnd();
1251 host_impl_->ScrollEnd();
1252
1253 scoped_ptr<ScrollAndScaleSet> scroll_info =
1254 host_impl_->ProcessScrollDeltas();
1255 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1256 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1257 }
1258 }
1259
1260 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1261 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1262 host_impl_->SetViewportSize(gfx::Size(50, 50));
1263 DrawFrame();
1264
1265 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1266 DCHECK(scroll_layer);
1267
1268 float min_page_scale = 0.5f;
1269 float max_page_scale = 4.f;
1270 base::TimeTicks start_time = base::TimeTicks() +
1271 base::TimeDelta::FromSeconds(1);
1272 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1273 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1274 base::TimeTicks end_time = start_time + duration;
1275
1276 // Non-anchor zoom-in
1277 {
1278 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1279 max_page_scale);
1280 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1281
1282 did_request_redraw_ = false;
1283 did_request_animate_ = false;
1284 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1285 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1286 gfx::Vector2d(),
1287 false,
1288 2.f,
1289 duration)));
1290 host_impl_->ActivateSyncTree();
1291 EXPECT_FALSE(did_request_redraw_);
1292 EXPECT_TRUE(did_request_animate_);
1293
1294 did_request_redraw_ = false;
1295 did_request_animate_ = false;
1296 host_impl_->Animate(start_time);
1297 EXPECT_TRUE(did_request_redraw_);
1298 EXPECT_TRUE(did_request_animate_);
1299
1300 did_request_redraw_ = false;
1301 did_request_animate_ = false;
1302 host_impl_->Animate(halfway_through_animation);
1303 EXPECT_TRUE(did_request_redraw_);
1304 EXPECT_TRUE(did_request_animate_);
1305
1306 did_request_redraw_ = false;
1307 did_request_animate_ = false;
1308 did_request_commit_ = false;
1309 host_impl_->Animate(end_time);
1310 EXPECT_TRUE(did_request_commit_);
1311 EXPECT_FALSE(did_request_animate_);
1312
1313 scoped_ptr<ScrollAndScaleSet> scroll_info =
1314 host_impl_->ProcessScrollDeltas();
1315 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1316 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1317 }
1318
1319 // Anchor zoom-out
1320 {
1321 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1322 max_page_scale);
1323 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1324
1325 did_request_redraw_ = false;
1326 did_request_animate_ = false;
1327 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1328 scoped_ptr<PendingPageScaleAnimation> (new PendingPageScaleAnimation(
1329 gfx::Vector2d(25, 25),
1330 true,
1331 min_page_scale,
1332 duration)));
1333 host_impl_->ActivateSyncTree();
1334 EXPECT_FALSE(did_request_redraw_);
1335 EXPECT_TRUE(did_request_animate_);
1336
1337 did_request_redraw_ = false;
1338 did_request_animate_ = false;
1339 host_impl_->Animate(start_time);
1340 EXPECT_TRUE(did_request_redraw_);
1341 EXPECT_TRUE(did_request_animate_);
1342
1343 did_request_redraw_ = false;
1344 did_request_commit_ = false;
1345 did_request_animate_ = false;
1346 host_impl_->Animate(end_time);
1347 EXPECT_TRUE(did_request_redraw_);
1348 EXPECT_FALSE(did_request_animate_);
1349 EXPECT_TRUE(did_request_commit_);
1350
1351 scoped_ptr<ScrollAndScaleSet> scroll_info =
1352 host_impl_->ProcessScrollDeltas();
1353 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1354 // Pushed to (0,0) via clamping against contents layer size.
1355 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1356 }
1357 }
1358
1359 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1360 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1361 host_impl_->SetViewportSize(gfx::Size(50, 50));
1362 DrawFrame();
1363
1364 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1365 DCHECK(scroll_layer);
1366
1367 float min_page_scale = 0.5f;
1368 float max_page_scale = 4.f;
1369 base::TimeTicks start_time = base::TimeTicks() +
1370 base::TimeDelta::FromSeconds(1);
1371 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1372 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1373 base::TimeTicks end_time = start_time + duration;
1374
1375 // Anchor zoom with unchanged page scale should not change scroll or scale.
1376 {
1377 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1378 max_page_scale);
1379 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1380
1381 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1382 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1383 gfx::Vector2d(),
1384 true,
1385 1.f,
1386 duration)));
1387 host_impl_->ActivateSyncTree();
1388 host_impl_->Animate(start_time);
1389 host_impl_->Animate(halfway_through_animation);
1390 EXPECT_TRUE(did_request_redraw_);
1391 host_impl_->Animate(end_time);
1392 EXPECT_TRUE(did_request_commit_);
1393
1394 scoped_ptr<ScrollAndScaleSet> scroll_info =
1395 host_impl_->ProcessScrollDeltas();
1396 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1397 ExpectNone(*scroll_info, scroll_layer->id());
1398 }
1399 }
1400
1401 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
1402 host_impl_->CreatePendingTree();
1403 CreateScrollAndContentsLayers(
1404 host_impl_->pending_tree(),
1405 gfx::Size(100, 100));
1406 host_impl_->ActivateSyncTree();
1407 DrawFrame();
1408
1409 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1410 DCHECK(scroll_layer);
1411
1412 float min_page_scale = 0.5f;
1413 float max_page_scale = 4.f;
1414 host_impl_->sync_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1415 max_page_scale);
1416 host_impl_->ActivateSyncTree();
1417
1418 base::TimeTicks start_time = base::TimeTicks() +
1419 base::TimeDelta::FromSeconds(1);
1420 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1421 base::TimeTicks third_through_animation = start_time + duration / 3;
1422 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1423 base::TimeTicks end_time = start_time + duration;
1424 float target_scale = 2.f;
1425
1426 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1427
1428 // Make sure TakePageScaleAnimation works properly.
1429
1430 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1431 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1432 gfx::Vector2d(),
1433 false,
1434 target_scale,
1435 duration)));
1436 scoped_ptr<PendingPageScaleAnimation> psa =
1437 host_impl_->sync_tree()->TakePendingPageScaleAnimation();
1438 EXPECT_EQ(target_scale, psa->scale);
1439 EXPECT_EQ(duration, psa->duration);
1440 EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePendingPageScaleAnimation());
1441
1442 // Recreate the PSA. Nothing should happen here since the tree containing the
1443 // PSA hasn't been activated yet.
1444 did_request_redraw_ = false;
1445 did_request_animate_ = false;
1446 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1447 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1448 gfx::Vector2d(),
1449 false,
1450 target_scale,
1451 duration)));
1452 host_impl_->Animate(halfway_through_animation);
1453 EXPECT_FALSE(did_request_animate_);
1454 EXPECT_FALSE(did_request_redraw_);
1455
1456 // Activate the sync tree. This should cause the animation to become enabled.
1457 // It should also clear the pointer on the sync tree.
1458 host_impl_->ActivateSyncTree();
1459 EXPECT_EQ(nullptr,
1460 host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
1461 EXPECT_FALSE(did_request_redraw_);
1462 EXPECT_TRUE(did_request_animate_);
1463
1464 // From here on, make sure the animation runs as normal.
1465 did_request_redraw_ = false;
1466 did_request_animate_ = false;
1467 host_impl_->Animate(start_time);
1468 EXPECT_TRUE(did_request_redraw_);
1469 EXPECT_TRUE(did_request_animate_);
1470
1471 did_request_redraw_ = false;
1472 did_request_animate_ = false;
1473 host_impl_->Animate(third_through_animation);
1474 EXPECT_TRUE(did_request_redraw_);
1475 EXPECT_TRUE(did_request_animate_);
1476
1477 // Another activation shouldn't have any effect on the animation.
1478 host_impl_->ActivateSyncTree();
1479
1480 did_request_redraw_ = false;
1481 did_request_animate_ = false;
1482 host_impl_->Animate(halfway_through_animation);
1483 EXPECT_TRUE(did_request_redraw_);
1484 EXPECT_TRUE(did_request_animate_);
1485
1486 did_request_redraw_ = false;
1487 did_request_animate_ = false;
1488 did_request_commit_ = false;
1489 host_impl_->Animate(end_time);
1490 EXPECT_TRUE(did_request_commit_);
1491 EXPECT_FALSE(did_request_animate_);
1492
1493 scoped_ptr<ScrollAndScaleSet> scroll_info =
1494 host_impl_->ProcessScrollDeltas();
1495 EXPECT_EQ(scroll_info->page_scale_delta, target_scale);
1496 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1497 }
1498
1499 TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) {
1500 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1501 host_impl_->SetViewportSize(gfx::Size(50, 50));
1502 DrawFrame();
1503
1504 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1505 DCHECK(scroll_layer);
1506
1507 base::TimeTicks start_time =
1508 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
1509 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1510 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1511 base::TimeTicks end_time = start_time + duration;
1512
1513 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
1514 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1515
1516 did_complete_page_scale_animation_ = false;
1517 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1518 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1519 gfx::Vector2d(), false, 2.f, duration)));
1520 host_impl_->ActivateSyncTree();
1521 host_impl_->Animate(start_time);
1522 EXPECT_FALSE(did_complete_page_scale_animation_);
1523
1524 host_impl_->Animate(halfway_through_animation);
1525 EXPECT_FALSE(did_complete_page_scale_animation_);
1526
1527 host_impl_->Animate(end_time);
1528 EXPECT_TRUE(did_complete_page_scale_animation_);
1529 }
1530
1531 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1532 public:
1533 LayerTreeHostImplOverridePhysicalTime(
1534 const LayerTreeSettings& settings,
1535 LayerTreeHostImplClient* client,
1536 Proxy* proxy,
1537 SharedBitmapManager* manager,
1538 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1539 : LayerTreeHostImpl(settings,
1540 client,
1541 proxy,
1542 rendering_stats_instrumentation,
1543 manager,
1544 NULL,
1545 NULL,
1546 0) {}
1547
1548 BeginFrameArgs CurrentBeginFrameArgs() const override {
1549 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
1550 fake_current_physical_time_);
1551 }
1552
1553 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1554 fake_current_physical_time_ = fake_now;
1555 }
1556
1557 private:
1558 base::TimeTicks fake_current_physical_time_;
1559 };
1560
1561 class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
1562 protected:
1563 void SetupLayers(LayerTreeSettings settings) {
1564 gfx::Size viewport_size(10, 10);
1565 gfx::Size content_size(100, 100);
1566
1567 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
1568 new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_,
1569 shared_bitmap_manager_.get(),
1570 &stats_instrumentation_);
1571 host_impl_ = make_scoped_ptr(host_impl_override_time);
1572 host_impl_->InitializeRenderer(CreateOutputSurface());
1573 host_impl_->SetViewportSize(viewport_size);
1574
1575 scoped_ptr<LayerImpl> root =
1576 LayerImpl::Create(host_impl_->active_tree(), 1);
1577 root->SetBounds(viewport_size);
1578
1579 scoped_ptr<LayerImpl> scroll =
1580 LayerImpl::Create(host_impl_->active_tree(), 2);
1581 scroll->SetScrollClipLayer(root->id());
1582 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1583 root->SetBounds(viewport_size);
1584 scroll->SetBounds(content_size);
1585 scroll->SetContentBounds(content_size);
1586 scroll->SetIsContainerForFixedPositionLayers(true);
1587
1588 scoped_ptr<LayerImpl> contents =
1589 LayerImpl::Create(host_impl_->active_tree(), 3);
1590 contents->SetDrawsContent(true);
1591 contents->SetBounds(content_size);
1592 contents->SetContentBounds(content_size);
1593
1594 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
1595 SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4,
1596 VERTICAL, 10, 0, false, true);
1597 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());
1598
1599 scroll->AddChild(contents.Pass());
1600 root->AddChild(scroll.Pass());
1601 root->SetHasRenderSurface(true);
1602 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1603 root->AddChild(scrollbar.Pass());
1604
1605 host_impl_->active_tree()->SetRootLayer(root.Pass());
1606 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
1607 Layer::INVALID_ID);
1608 host_impl_->active_tree()->DidBecomeActive();
1609 DrawFrame();
1610 }
1611
1612 void RunTest(LayerTreeSettings::ScrollbarAnimator animator) {
1613 LayerTreeSettings settings;
1614 settings.scrollbar_animator = animator;
1615 settings.scrollbar_fade_delay_ms = 20;
1616 settings.scrollbar_fade_duration_ms = 20;
1617
1618 SetupLayers(settings);
1619
1620 base::TimeTicks fake_now = gfx::FrameTime::Now();
1621
1622 EXPECT_FALSE(did_request_animate_);
1623 EXPECT_FALSE(did_request_redraw_);
1624 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1625 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1626
1627 // If no scroll happened during a scroll gesture, it should have no effect.
1628 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1629 host_impl_->ScrollEnd();
1630 EXPECT_FALSE(did_request_animate_);
1631 EXPECT_FALSE(did_request_redraw_);
1632 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1633 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1634
1635 // After a scroll, a scrollbar animation should be scheduled about 20ms from
1636 // now.
1637 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1638 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1639 EXPECT_FALSE(did_request_animate_);
1640 EXPECT_TRUE(did_request_redraw_);
1641 did_request_redraw_ = false;
1642 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1643 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1644
1645 host_impl_->ScrollEnd();
1646 EXPECT_FALSE(did_request_animate_);
1647 EXPECT_FALSE(did_request_redraw_);
1648 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1649 requested_animation_delay_);
1650 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1651
1652 fake_now += requested_animation_delay_;
1653 requested_animation_delay_ = base::TimeDelta();
1654 animation_task_.Run();
1655 animation_task_ = base::Closure();
1656 EXPECT_TRUE(did_request_animate_);
1657 did_request_animate_ = false;
1658 EXPECT_FALSE(did_request_redraw_);
1659
1660 // After the scrollbar animation begins, we should start getting redraws.
1661 host_impl_->Animate(fake_now);
1662 EXPECT_TRUE(did_request_animate_);
1663 did_request_animate_ = false;
1664 EXPECT_TRUE(did_request_redraw_);
1665 did_request_redraw_ = false;
1666 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1667 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1668
1669 // Setting the scroll offset outside a scroll should also cause the
1670 // scrollbar to appear and to schedule a scrollbar animation.
1671 host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
1672 gfx::ScrollOffset(5, 5));
1673 EXPECT_FALSE(did_request_animate_);
1674 EXPECT_FALSE(did_request_redraw_);
1675 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1676 requested_animation_delay_);
1677 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1678 requested_animation_delay_ = base::TimeDelta();
1679 animation_task_ = base::Closure();
1680
1681 // Scrollbar animation is not triggered unnecessarily.
1682 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1683 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1684 EXPECT_FALSE(did_request_animate_);
1685 EXPECT_TRUE(did_request_redraw_);
1686 did_request_redraw_ = false;
1687 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1688 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1689
1690 host_impl_->ScrollEnd();
1691 EXPECT_FALSE(did_request_animate_);
1692 EXPECT_FALSE(did_request_redraw_);
1693 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1694 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1695
1696 // Changing page scale triggers scrollbar animation.
1697 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
1698 host_impl_->SetPageScaleOnActiveTree(1.1f);
1699 EXPECT_FALSE(did_request_animate_);
1700 EXPECT_FALSE(did_request_redraw_);
1701 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1702 requested_animation_delay_);
1703 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1704 requested_animation_delay_ = base::TimeDelta();
1705 animation_task_ = base::Closure();
1706 }
1707 };
1708
1709 TEST_F(LayerTreeHostImplTestScrollbarAnimation, LinearFade) {
1710 RunTest(LayerTreeSettings::LINEAR_FADE);
1711 }
1712
1713 TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) {
1714 RunTest(LayerTreeSettings::THINNING);
1715 }
1716
1717 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1718 float device_scale_factor) {
1719 LayerTreeSettings settings;
1720 settings.scrollbar_fade_delay_ms = 500;
1721 settings.scrollbar_fade_duration_ms = 300;
1722 settings.scrollbar_animator = LayerTreeSettings::THINNING;
1723
1724 gfx::Size viewport_size(300, 200);
1725 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1726 gfx::ScaleSize(viewport_size, device_scale_factor));
1727 gfx::Size content_size(1000, 1000);
1728
1729 CreateHostImpl(settings, CreateOutputSurface());
1730 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1731 host_impl_->SetViewportSize(device_viewport_size);
1732
1733 scoped_ptr<LayerImpl> root =
1734 LayerImpl::Create(host_impl_->active_tree(), 1);
1735 root->SetBounds(viewport_size);
1736 root->SetHasRenderSurface(true);
1737
1738 scoped_ptr<LayerImpl> scroll =
1739 LayerImpl::Create(host_impl_->active_tree(), 2);
1740 scroll->SetScrollClipLayer(root->id());
1741 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1742 scroll->SetBounds(content_size);
1743 scroll->SetContentBounds(content_size);
1744 scroll->SetIsContainerForFixedPositionLayers(true);
1745
1746 scoped_ptr<LayerImpl> contents =
1747 LayerImpl::Create(host_impl_->active_tree(), 3);
1748 contents->SetDrawsContent(true);
1749 contents->SetBounds(content_size);
1750 contents->SetContentBounds(content_size);
1751
1752 // The scrollbar is on the right side.
1753 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1754 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1755 scrollbar->SetDrawsContent(true);
1756 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1757 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1758 scrollbar->SetPosition(gfx::Point(285, 0));
1759
1760 scroll->AddChild(contents.Pass());
1761 root->AddChild(scroll.Pass());
1762 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1763 root->AddChild(scrollbar.Pass());
1764
1765 host_impl_->active_tree()->SetRootLayer(root.Pass());
1766 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
1767 Layer::INVALID_ID);
1768 host_impl_->active_tree()->DidBecomeActive();
1769 DrawFrame();
1770
1771 LayerImpl* root_scroll =
1772 host_impl_->active_tree()->InnerViewportScrollLayer();
1773 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1774 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1775 static_cast<ScrollbarAnimationControllerThinning*>(
1776 root_scroll->scrollbar_animation_controller());
1777 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1778
1779 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1780 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1781
1782 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1783 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1784
1785 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1786 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1787
1788 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1789 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1790 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1791
1792 did_request_redraw_ = false;
1793 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1794 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1795 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1796 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1797 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1798 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1799 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1800 }
1801
1802 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1803 SetupMouseMoveAtWithDeviceScale(1.f);
1804 }
1805
1806 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1807 SetupMouseMoveAtWithDeviceScale(2.f);
1808 }
1809
1810 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1811 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1812 host_impl_->SetViewportSize(gfx::Size(50, 50));
1813 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
1814 DrawFrame();
1815 {
1816 CompositorFrameMetadata metadata =
1817 host_impl_->MakeCompositorFrameMetadata();
1818 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1819 EXPECT_EQ(1.f, metadata.page_scale_factor);
1820 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
1821 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1822 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1823 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1824 EXPECT_FALSE(metadata.root_overflow_x_hidden);
1825 EXPECT_FALSE(metadata.root_overflow_y_hidden);
1826 }
1827
1828 // Scrolling should update metadata immediately.
1829 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1830 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
1831 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1832 {
1833 CompositorFrameMetadata metadata =
1834 host_impl_->MakeCompositorFrameMetadata();
1835 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1836 }
1837 host_impl_->ScrollEnd();
1838 {
1839 CompositorFrameMetadata metadata =
1840 host_impl_->MakeCompositorFrameMetadata();
1841 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1842 }
1843
1844 // Root "overflow: hidden" properties should be reflected.
1845 {
1846 host_impl_->active_tree()
1847 ->InnerViewportScrollLayer()
1848 ->set_user_scrollable_horizontal(false);
1849 CompositorFrameMetadata metadata =
1850 host_impl_->MakeCompositorFrameMetadata();
1851 EXPECT_TRUE(metadata.root_overflow_x_hidden);
1852 EXPECT_FALSE(metadata.root_overflow_y_hidden);
1853
1854 host_impl_->active_tree()
1855 ->InnerViewportScrollLayer()
1856 ->set_user_scrollable_vertical(false);
1857 metadata = host_impl_->MakeCompositorFrameMetadata();
1858 EXPECT_TRUE(metadata.root_overflow_x_hidden);
1859 EXPECT_TRUE(metadata.root_overflow_y_hidden);
1860 }
1861
1862 // Page scale should update metadata correctly (shrinking only the viewport).
1863 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1864 host_impl_->PinchGestureBegin();
1865 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1866 host_impl_->PinchGestureEnd();
1867 host_impl_->ScrollEnd();
1868 {
1869 CompositorFrameMetadata metadata =
1870 host_impl_->MakeCompositorFrameMetadata();
1871 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1872 EXPECT_EQ(2.f, metadata.page_scale_factor);
1873 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
1874 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1875 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1876 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1877 }
1878
1879 // Likewise if set from the main thread.
1880 host_impl_->ProcessScrollDeltas();
1881 host_impl_->active_tree()->PushPageScaleFromMainThread(4.f, 0.5f, 4.f);
1882 host_impl_->SetPageScaleOnActiveTree(4.f);
1883 {
1884 CompositorFrameMetadata metadata =
1885 host_impl_->MakeCompositorFrameMetadata();
1886 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1887 EXPECT_EQ(4.f, metadata.page_scale_factor);
1888 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
1889 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1890 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1891 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1892 }
1893 }
1894
1895 class DidDrawCheckLayer : public LayerImpl {
1896 public:
1897 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1898 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl, id));
1899 }
1900
1901 bool WillDraw(DrawMode draw_mode, ResourceProvider* provider) override {
1902 will_draw_called_ = true;
1903 if (will_draw_returns_false_)
1904 return false;
1905 return LayerImpl::WillDraw(draw_mode, provider);
1906 }
1907
1908 void AppendQuads(RenderPass* render_pass,
1909 AppendQuadsData* append_quads_data) override {
1910 append_quads_called_ = true;
1911 LayerImpl::AppendQuads(render_pass, append_quads_data);
1912 }
1913
1914 void DidDraw(ResourceProvider* provider) override {
1915 did_draw_called_ = true;
1916 LayerImpl::DidDraw(provider);
1917 }
1918
1919 bool will_draw_called() const { return will_draw_called_; }
1920 bool append_quads_called() const { return append_quads_called_; }
1921 bool did_draw_called() const { return did_draw_called_; }
1922
1923 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1924
1925 void ClearDidDrawCheck() {
1926 will_draw_called_ = false;
1927 append_quads_called_ = false;
1928 did_draw_called_ = false;
1929 }
1930
1931 static void IgnoreResult(scoped_ptr<CopyOutputResult> result) {}
1932
1933 void AddCopyRequest() {
1934 ScopedPtrVector<CopyOutputRequest> requests;
1935 requests.push_back(
1936 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult)));
1937 SetHasRenderSurface(true);
1938 PassCopyRequests(&requests);
1939 }
1940
1941 protected:
1942 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1943 : LayerImpl(tree_impl, id),
1944 will_draw_returns_false_(false),
1945 will_draw_called_(false),
1946 append_quads_called_(false),
1947 did_draw_called_(false) {
1948 SetBounds(gfx::Size(10, 10));
1949 SetContentBounds(gfx::Size(10, 10));
1950 SetDrawsContent(true);
1951 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1952 }
1953
1954 private:
1955 bool will_draw_returns_false_;
1956 bool will_draw_called_;
1957 bool append_quads_called_;
1958 bool did_draw_called_;
1959 };
1960
1961 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1962 // The root layer is always drawn, so run this test on a child layer that
1963 // will be masked out by the root layer's bounds.
1964 host_impl_->active_tree()->SetRootLayer(
1965 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1966 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1967 host_impl_->active_tree()->root_layer());
1968
1969 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1970 root->SetHasRenderSurface(true);
1971 DidDrawCheckLayer* layer =
1972 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1973
1974 {
1975 LayerTreeHostImpl::FrameData frame;
1976 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1977 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1978 host_impl_->DidDrawAllLayers(frame);
1979
1980 EXPECT_TRUE(layer->will_draw_called());
1981 EXPECT_TRUE(layer->append_quads_called());
1982 EXPECT_TRUE(layer->did_draw_called());
1983 }
1984
1985 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
1986
1987 {
1988 LayerTreeHostImpl::FrameData frame;
1989
1990 layer->set_will_draw_returns_false();
1991 layer->ClearDidDrawCheck();
1992
1993 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1994 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1995 host_impl_->DidDrawAllLayers(frame);
1996
1997 EXPECT_TRUE(layer->will_draw_called());
1998 EXPECT_FALSE(layer->append_quads_called());
1999 EXPECT_FALSE(layer->did_draw_called());
2000 }
2001 }
2002
2003 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
2004 // The root layer is always drawn, so run this test on a child layer that
2005 // will be masked out by the root layer's bounds.
2006 host_impl_->active_tree()->SetRootLayer(
2007 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2008 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2009 host_impl_->active_tree()->root_layer());
2010 root->SetMasksToBounds(true);
2011 root->SetHasRenderSurface(true);
2012 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2013 DidDrawCheckLayer* layer =
2014 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2015 // Ensure visible_content_rect for layer is empty.
2016 layer->SetPosition(gfx::PointF(100.f, 100.f));
2017 layer->SetBounds(gfx::Size(10, 10));
2018 layer->SetContentBounds(gfx::Size(10, 10));
2019
2020 LayerTreeHostImpl::FrameData frame;
2021
2022 EXPECT_FALSE(layer->will_draw_called());
2023 EXPECT_FALSE(layer->did_draw_called());
2024
2025 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2026 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2027 host_impl_->DidDrawAllLayers(frame);
2028
2029 EXPECT_FALSE(layer->will_draw_called());
2030 EXPECT_FALSE(layer->did_draw_called());
2031
2032 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
2033
2034 // Ensure visible_content_rect for layer is not empty
2035 layer->SetPosition(gfx::PointF());
2036
2037 EXPECT_FALSE(layer->will_draw_called());
2038 EXPECT_FALSE(layer->did_draw_called());
2039
2040 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2041 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2042 host_impl_->DidDrawAllLayers(frame);
2043
2044 EXPECT_TRUE(layer->will_draw_called());
2045 EXPECT_TRUE(layer->did_draw_called());
2046
2047 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
2048 }
2049
2050 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
2051 gfx::Size big_size(1000, 1000);
2052 host_impl_->SetViewportSize(big_size);
2053
2054 host_impl_->active_tree()->SetRootLayer(
2055 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2056 DidDrawCheckLayer* root =
2057 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2058
2059 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2060 DidDrawCheckLayer* occluded_layer =
2061 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2062
2063 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2064 root->SetHasRenderSurface(true);
2065 DidDrawCheckLayer* top_layer =
2066 static_cast<DidDrawCheckLayer*>(root->children()[1]);
2067 // This layer covers the occluded_layer above. Make this layer large so it can
2068 // occlude.
2069 top_layer->SetBounds(big_size);
2070 top_layer->SetContentBounds(big_size);
2071 top_layer->SetContentsOpaque(true);
2072
2073 LayerTreeHostImpl::FrameData frame;
2074
2075 EXPECT_FALSE(occluded_layer->will_draw_called());
2076 EXPECT_FALSE(occluded_layer->did_draw_called());
2077 EXPECT_FALSE(top_layer->will_draw_called());
2078 EXPECT_FALSE(top_layer->did_draw_called());
2079
2080 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2081 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2082 host_impl_->DidDrawAllLayers(frame);
2083
2084 EXPECT_FALSE(occluded_layer->will_draw_called());
2085 EXPECT_FALSE(occluded_layer->did_draw_called());
2086 EXPECT_TRUE(top_layer->will_draw_called());
2087 EXPECT_TRUE(top_layer->did_draw_called());
2088 }
2089
2090 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
2091 host_impl_->active_tree()->SetRootLayer(
2092 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2093 DidDrawCheckLayer* root =
2094 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2095
2096 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2097 root->SetHasRenderSurface(true);
2098 DidDrawCheckLayer* layer1 =
2099 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2100
2101 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2102 DidDrawCheckLayer* layer2 =
2103 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
2104
2105 layer1->SetHasRenderSurface(true);
2106 layer1->SetShouldFlattenTransform(true);
2107
2108 EXPECT_FALSE(root->did_draw_called());
2109 EXPECT_FALSE(layer1->did_draw_called());
2110 EXPECT_FALSE(layer2->did_draw_called());
2111
2112 LayerTreeHostImpl::FrameData frame;
2113 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2114 host_impl_->active_tree()->root_layer());
2115 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2116 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2117 host_impl_->DidDrawAllLayers(frame);
2118
2119 EXPECT_TRUE(root->did_draw_called());
2120 EXPECT_TRUE(layer1->did_draw_called());
2121 EXPECT_TRUE(layer2->did_draw_called());
2122
2123 EXPECT_NE(root->render_surface(), layer1->render_surface());
2124 EXPECT_TRUE(!!layer1->render_surface());
2125 }
2126
2127 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
2128 public:
2129 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
2130 int id,
2131 bool tile_missing,
2132 bool had_incomplete_tile,
2133 bool animating,
2134 ResourceProvider* resource_provider) {
2135 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl,
2136 id,
2137 tile_missing,
2138 had_incomplete_tile,
2139 animating,
2140 resource_provider));
2141 }
2142
2143 void AppendQuads(RenderPass* render_pass,
2144 AppendQuadsData* append_quads_data) override {
2145 LayerImpl::AppendQuads(render_pass, append_quads_data);
2146 if (had_incomplete_tile_)
2147 append_quads_data->num_incomplete_tiles++;
2148 if (tile_missing_)
2149 append_quads_data->num_missing_tiles++;
2150 }
2151
2152 private:
2153 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
2154 int id,
2155 bool tile_missing,
2156 bool had_incomplete_tile,
2157 bool animating,
2158 ResourceProvider* resource_provider)
2159 : DidDrawCheckLayer(tree_impl, id),
2160 tile_missing_(tile_missing),
2161 had_incomplete_tile_(had_incomplete_tile) {
2162 if (animating)
2163 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2164 }
2165
2166 bool tile_missing_;
2167 bool had_incomplete_tile_;
2168 };
2169
2170 struct PrepareToDrawSuccessTestCase {
2171 struct State {
2172 bool has_missing_tile = false;
2173 bool has_incomplete_tile = false;
2174 bool is_animating = false;
2175 bool has_copy_request = false;
2176 };
2177 bool high_res_required = false;
2178 State layer_before;
2179 State layer_between;
2180 State layer_after;
2181 DrawResult expected_result;
2182
2183 explicit PrepareToDrawSuccessTestCase(DrawResult result)
2184 : expected_result(result) {}
2185 };
2186
2187 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) {
2188 std::vector<PrepareToDrawSuccessTestCase> cases;
2189
2190 // 0. Default case.
2191 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2192 // 1. Animated layer first.
2193 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2194 cases.back().layer_before.is_animating = true;
2195 // 2. Animated layer between.
2196 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2197 cases.back().layer_between.is_animating = true;
2198 // 3. Animated layer last.
2199 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2200 cases.back().layer_after.is_animating = true;
2201 // 4. Missing tile first.
2202 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2203 cases.back().layer_before.has_missing_tile = true;
2204 // 5. Missing tile between.
2205 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2206 cases.back().layer_between.has_missing_tile = true;
2207 // 6. Missing tile last.
2208 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2209 cases.back().layer_after.has_missing_tile = true;
2210 // 7. Incomplete tile first.
2211 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2212 cases.back().layer_before.has_incomplete_tile = true;
2213 // 8. Incomplete tile between.
2214 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2215 cases.back().layer_between.has_incomplete_tile = true;
2216 // 9. Incomplete tile last.
2217 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2218 cases.back().layer_after.has_incomplete_tile = true;
2219 // 10. Animation with missing tile.
2220 cases.push_back(
2221 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS));
2222 cases.back().layer_between.has_missing_tile = true;
2223 cases.back().layer_between.is_animating = true;
2224 // 11. Animation with missing tile and copy request after. Must succeed
2225 // because the animation checkerboard means we'll get a new frame and the copy
2226 // request's layer may be destroyed.
2227 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2228 cases.back().layer_between.has_missing_tile = true;
2229 cases.back().layer_between.is_animating = true;
2230 cases.back().layer_after.has_copy_request = true;
2231 // 12. Animation with missing tile and copy request before. Must succeed
2232 // because the animation checkerboard means we'll get a new frame and the copy
2233 // request's layer may be destroyed.
2234 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2235 cases.back().layer_between.has_missing_tile = true;
2236 cases.back().layer_between.is_animating = true;
2237 cases.back().layer_before.has_copy_request = true;
2238 // 13. Animation with incomplete tile.
2239 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2240 cases.back().layer_between.has_incomplete_tile = true;
2241 cases.back().layer_between.is_animating = true;
2242
2243 // 14. High res required.
2244 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2245 cases.back().high_res_required = true;
2246 // 15. High res required with incomplete tile.
2247 cases.push_back(
2248 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2249 cases.back().high_res_required = true;
2250 cases.back().layer_between.has_incomplete_tile = true;
2251 // 16. High res required with missing tile.
2252 cases.push_back(
2253 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2254 cases.back().high_res_required = true;
2255 cases.back().layer_between.has_missing_tile = true;
2256
2257 // 17. High res required is higher priority than animating missing tiles.
2258 cases.push_back(
2259 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2260 cases.back().high_res_required = true;
2261 cases.back().layer_between.has_missing_tile = true;
2262 cases.back().layer_after.has_missing_tile = true;
2263 cases.back().layer_after.is_animating = true;
2264 // 18. High res required is higher priority than animating missing tiles.
2265 cases.push_back(
2266 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2267 cases.back().high_res_required = true;
2268 cases.back().layer_between.has_missing_tile = true;
2269 cases.back().layer_before.has_missing_tile = true;
2270 cases.back().layer_before.is_animating = true;
2271
2272 // 19. High res required is higher priority than copy requests.
2273 cases.push_back(
2274 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2275 cases.back().high_res_required = true;
2276 cases.back().layer_between.has_missing_tile = true;
2277 cases.back().layer_after.has_copy_request = true;
2278 // 20. High res required is higher priority than copy requests.
2279 cases.push_back(
2280 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2281 cases.back().high_res_required = true;
2282 cases.back().layer_between.has_missing_tile = true;
2283 cases.back().layer_before.has_copy_request = true;
2284 // 21. High res required is higher priority than copy requests.
2285 cases.push_back(
2286 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2287 cases.back().high_res_required = true;
2288 cases.back().layer_between.has_missing_tile = true;
2289 cases.back().layer_between.has_copy_request = true;
2290
2291 host_impl_->active_tree()->SetRootLayer(
2292 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2293 DidDrawCheckLayer* root =
2294 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2295 root->SetHasRenderSurface(true);
2296
2297 LayerTreeHostImpl::FrameData frame;
2298 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2299 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2300 host_impl_->DidDrawAllLayers(frame);
2301 host_impl_->SwapBuffers(frame);
2302
2303 for (size_t i = 0; i < cases.size(); ++i) {
2304 const auto& testcase = cases[i];
2305 std::vector<LayerImpl*> to_remove;
2306 for (auto* child : root->children())
2307 to_remove.push_back(child);
2308 for (auto* child : to_remove)
2309 root->RemoveChild(child);
2310
2311 std::ostringstream scope;
2312 scope << "Test case: " << i;
2313 SCOPED_TRACE(scope.str());
2314
2315 root->AddChild(MissingTextureAnimatingLayer::Create(
2316 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2317 testcase.layer_before.has_incomplete_tile,
2318 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2319 DidDrawCheckLayer* before =
2320 static_cast<DidDrawCheckLayer*>(root->children().back());
2321 if (testcase.layer_before.has_copy_request)
2322 before->AddCopyRequest();
2323
2324 root->AddChild(MissingTextureAnimatingLayer::Create(
2325 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2326 testcase.layer_between.has_incomplete_tile,
2327 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2328 DidDrawCheckLayer* between =
2329 static_cast<DidDrawCheckLayer*>(root->children().back());
2330 if (testcase.layer_between.has_copy_request)
2331 between->AddCopyRequest();
2332
2333 root->AddChild(MissingTextureAnimatingLayer::Create(
2334 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2335 testcase.layer_after.has_incomplete_tile,
2336 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2337 DidDrawCheckLayer* after =
2338 static_cast<DidDrawCheckLayer*>(root->children().back());
2339 if (testcase.layer_after.has_copy_request)
2340 after->AddCopyRequest();
2341
2342 if (testcase.high_res_required)
2343 host_impl_->SetRequiresHighResToDraw();
2344
2345 LayerTreeHostImpl::FrameData frame;
2346 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2347 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2348 host_impl_->DidDrawAllLayers(frame);
2349 host_impl_->SwapBuffers(frame);
2350 }
2351 }
2352
2353 TEST_F(LayerTreeHostImplTest,
2354 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) {
2355 CreateHostImpl(DefaultSettings(),
2356 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2357 EXPECT_TRUE(host_impl_->output_surface()
2358 ->capabilities()
2359 .draw_and_swap_full_viewport_every_frame);
2360
2361 std::vector<PrepareToDrawSuccessTestCase> cases;
2362
2363 // 0. Default case.
2364 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2365 // 1. Animation with missing tile.
2366 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2367 cases.back().layer_between.has_missing_tile = true;
2368 cases.back().layer_between.is_animating = true;
2369 // 2. High res required with incomplete tile.
2370 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2371 cases.back().high_res_required = true;
2372 cases.back().layer_between.has_incomplete_tile = true;
2373 // 3. High res required with missing tile.
2374 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2375 cases.back().high_res_required = true;
2376 cases.back().layer_between.has_missing_tile = true;
2377
2378 host_impl_->active_tree()->SetRootLayer(
2379 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2380 DidDrawCheckLayer* root =
2381 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2382 root->SetHasRenderSurface(true);
2383
2384 LayerTreeHostImpl::FrameData frame;
2385 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2386 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2387 host_impl_->DidDrawAllLayers(frame);
2388 host_impl_->SwapBuffers(frame);
2389
2390 for (size_t i = 0; i < cases.size(); ++i) {
2391 const auto& testcase = cases[i];
2392 std::vector<LayerImpl*> to_remove;
2393 for (auto* child : root->children())
2394 to_remove.push_back(child);
2395 for (auto* child : to_remove)
2396 root->RemoveChild(child);
2397
2398 std::ostringstream scope;
2399 scope << "Test case: " << i;
2400 SCOPED_TRACE(scope.str());
2401
2402 root->AddChild(MissingTextureAnimatingLayer::Create(
2403 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2404 testcase.layer_before.has_incomplete_tile,
2405 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2406 DidDrawCheckLayer* before =
2407 static_cast<DidDrawCheckLayer*>(root->children().back());
2408 if (testcase.layer_before.has_copy_request)
2409 before->AddCopyRequest();
2410
2411 root->AddChild(MissingTextureAnimatingLayer::Create(
2412 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2413 testcase.layer_between.has_incomplete_tile,
2414 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2415 DidDrawCheckLayer* between =
2416 static_cast<DidDrawCheckLayer*>(root->children().back());
2417 if (testcase.layer_between.has_copy_request)
2418 between->AddCopyRequest();
2419
2420 root->AddChild(MissingTextureAnimatingLayer::Create(
2421 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2422 testcase.layer_after.has_incomplete_tile,
2423 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2424 DidDrawCheckLayer* after =
2425 static_cast<DidDrawCheckLayer*>(root->children().back());
2426 if (testcase.layer_after.has_copy_request)
2427 after->AddCopyRequest();
2428
2429 if (testcase.high_res_required)
2430 host_impl_->SetRequiresHighResToDraw();
2431
2432 LayerTreeHostImpl::FrameData frame;
2433 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2434 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2435 host_impl_->DidDrawAllLayers(frame);
2436 host_impl_->SwapBuffers(frame);
2437 }
2438 }
2439
2440 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2441 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2442 root->SetScrollClipLayer(Layer::INVALID_ID);
2443 root->SetHasRenderSurface(true);
2444 host_impl_->active_tree()->SetRootLayer(root.Pass());
2445 DrawFrame();
2446
2447 // Scroll event is ignored because layer is not scrollable.
2448 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
2449 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
2450 EXPECT_FALSE(did_request_redraw_);
2451 EXPECT_FALSE(did_request_commit_);
2452 }
2453
2454 // TODO(bokan): Convert these tests to create inner and outer viewports.
2455 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2456 public:
2457 LayerTreeHostImplTopControlsTest()
2458 // Make the clip size the same as the layer (content) size so the layer is
2459 // non-scrollable.
2460 : layer_size_(10, 10),
2461 clip_size_(layer_size_),
2462 top_controls_height_(50) {
2463 settings_.use_pinch_virtual_viewport = true;
2464
2465 viewport_size_ = gfx::Size(clip_size_.width(),
2466 clip_size_.height() + top_controls_height_);
2467 }
2468
2469 bool CreateHostImpl(const LayerTreeSettings& settings,
2470 scoped_ptr<OutputSurface> output_surface) override {
2471 bool init =
2472 LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass());
2473 if (init) {
2474 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
2475 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
2476 }
2477 return init;
2478 }
2479
2480 void SetupTopControlsAndScrollLayer() {
2481 scoped_ptr<LayerImpl> root =
2482 LayerImpl::Create(host_impl_->active_tree(), 1);
2483 scoped_ptr<LayerImpl> root_clip =
2484 LayerImpl::Create(host_impl_->active_tree(), 2);
2485 root_clip->SetBounds(clip_size_);
2486 root->SetScrollClipLayer(root_clip->id());
2487 root->SetBounds(layer_size_);
2488 root->SetContentBounds(layer_size_);
2489 root->SetPosition(gfx::PointF());
2490 root->SetDrawsContent(false);
2491 root->SetIsContainerForFixedPositionLayers(true);
2492 int inner_viewport_scroll_layer_id = root->id();
2493 int page_scale_layer_id = root_clip->id();
2494 root_clip->SetHasRenderSurface(true);
2495 root_clip->AddChild(root.Pass());
2496 root_clip->SetHasRenderSurface(true);
2497 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2498 host_impl_->active_tree()->SetViewportLayersFromIds(
2499 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2500 Layer::INVALID_ID);
2501 // Set a viewport size that is large enough to contain both the top controls
2502 // and some content.
2503 host_impl_->SetViewportSize(viewport_size_);
2504 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2505
2506 host_impl_->DidChangeTopControlsPosition();
2507
2508 host_impl_->CreatePendingTree();
2509 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
2510 root =
2511 LayerImpl::Create(host_impl_->sync_tree(), 1);
2512 root_clip =
2513 LayerImpl::Create(host_impl_->sync_tree(), 2);
2514 root_clip->SetBounds(clip_size_);
2515 root->SetScrollClipLayer(root_clip->id());
2516 root->SetBounds(layer_size_);
2517 root->SetContentBounds(layer_size_);
2518 root->SetPosition(gfx::PointF());
2519 root->SetDrawsContent(false);
2520 root->SetIsContainerForFixedPositionLayers(true);
2521 inner_viewport_scroll_layer_id = root->id();
2522 page_scale_layer_id = root_clip->id();
2523 root_clip->AddChild(root.Pass());
2524 host_impl_->sync_tree()->SetRootLayer(root_clip.Pass());
2525 host_impl_->sync_tree()->SetViewportLayersFromIds(
2526 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2527 Layer::INVALID_ID);
2528 // Set a viewport size that is large enough to contain both the top controls
2529 // and some content.
2530 host_impl_->SetViewportSize(viewport_size_);
2531 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2532 host_impl_->DidChangeTopControlsPosition();
2533 }
2534
2535 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2536 const gfx::Size& inner_viewport_size,
2537 const gfx::Size& outer_viewport_size,
2538 const gfx::Size& scroll_layer_size) {
2539 CreateHostImpl(settings_, CreateOutputSurface());
2540 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2541 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
2542 host_impl_->DidChangeTopControlsPosition();
2543
2544 scoped_ptr<LayerImpl> root =
2545 LayerImpl::Create(host_impl_->active_tree(), 1);
2546 scoped_ptr<LayerImpl> root_clip =
2547 LayerImpl::Create(host_impl_->active_tree(), 2);
2548 scoped_ptr<LayerImpl> page_scale =
2549 LayerImpl::Create(host_impl_->active_tree(), 3);
2550
2551 scoped_ptr<LayerImpl> outer_scroll =
2552 LayerImpl::Create(host_impl_->active_tree(), 4);
2553 scoped_ptr<LayerImpl> outer_clip =
2554 LayerImpl::Create(host_impl_->active_tree(), 5);
2555
2556 root_clip->SetBounds(inner_viewport_size);
2557 root->SetScrollClipLayer(root_clip->id());
2558 root->SetBounds(outer_viewport_size);
2559 root->SetContentBounds(outer_viewport_size);
2560 root->SetPosition(gfx::PointF());
2561 root->SetDrawsContent(false);
2562 root->SetIsContainerForFixedPositionLayers(true);
2563 root_clip->SetHasRenderSurface(true);
2564 outer_clip->SetBounds(outer_viewport_size);
2565 outer_scroll->SetScrollClipLayer(outer_clip->id());
2566 outer_scroll->SetBounds(scroll_layer_size);
2567 outer_scroll->SetContentBounds(scroll_layer_size);
2568 outer_scroll->SetPosition(gfx::PointF());
2569 outer_scroll->SetDrawsContent(false);
2570 outer_scroll->SetIsContainerForFixedPositionLayers(true);
2571
2572 int inner_viewport_scroll_layer_id = root->id();
2573 int outer_viewport_scroll_layer_id = outer_scroll->id();
2574 int page_scale_layer_id = page_scale->id();
2575
2576 outer_clip->AddChild(outer_scroll.Pass());
2577 root->AddChild(outer_clip.Pass());
2578 page_scale->AddChild(root.Pass());
2579 root_clip->AddChild(page_scale.Pass());
2580
2581 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2582 host_impl_->active_tree()->SetViewportLayersFromIds(
2583 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2584 outer_viewport_scroll_layer_id);
2585
2586 host_impl_->SetViewportSize(inner_viewport_size);
2587 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2588 EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds());
2589 }
2590
2591 protected:
2592 gfx::Size layer_size_;
2593 gfx::Size clip_size_;
2594 gfx::Size viewport_size_;
2595 float top_controls_height_;
2596
2597 LayerTreeSettings settings_;
2598 }; // class LayerTreeHostImplTopControlsTest
2599
2600 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2601 SetupTopControlsAndScrollLayerWithVirtualViewport(
2602 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2603 DrawFrame();
2604
2605 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2606 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2607
2608 // Make the test scroll delta a fractional amount, to verify that the
2609 // fixed container size delta is (1) non-zero, and (2) fractional, and
2610 // (3) matches the movement of the top controls.
2611 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2612 host_impl_->top_controls_manager()->ScrollBegin();
2613 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2614 host_impl_->top_controls_manager()->ScrollEnd();
2615
2616 LayerImpl* inner_viewport_scroll_layer =
2617 host_impl_->active_tree()->InnerViewportScrollLayer();
2618 DCHECK(inner_viewport_scroll_layer);
2619 host_impl_->ScrollEnd();
2620 EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
2621 inner_viewport_scroll_layer->FixedContainerSizeDelta().y());
2622 }
2623
2624 // In this test, the outer viewport is initially unscrollable. We test that a
2625 // scroll initiated on the inner viewport, causing the top controls to show and
2626 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2627 TEST_F(LayerTreeHostImplTopControlsTest,
2628 TopControlsOuterViewportBecomesScrollable) {
2629 SetupTopControlsAndScrollLayerWithVirtualViewport(
2630 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2631 DrawFrame();
2632
2633 LayerImpl *inner_scroll =
2634 host_impl_->active_tree()->InnerViewportScrollLayer();
2635 LayerImpl *inner_container =
2636 host_impl_->active_tree()->InnerViewportContainerLayer();
2637 LayerImpl *outer_scroll =
2638 host_impl_->active_tree()->OuterViewportScrollLayer();
2639 LayerImpl *outer_container =
2640 host_impl_->active_tree()->OuterViewportContainerLayer();
2641
2642 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2643 outer_scroll->SetDrawsContent(true);
2644 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 1.f, 2.f);
2645
2646 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2647 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2648 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 50.f));
2649
2650 // The entire scroll delta should have been used to hide the top controls.
2651 // The viewport layers should be resized back to their full sizes.
2652 EXPECT_EQ(0.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2653 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
2654 EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height());
2655 EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height());
2656
2657 // The inner viewport should be scrollable by 50px * page_scale.
2658 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 100.f));
2659 EXPECT_EQ(50.f, inner_scroll->CurrentScrollOffset().y());
2660 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2661 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset());
2662
2663 host_impl_->ScrollEnd();
2664
2665 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2666 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2667 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
2668
2669 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2670
2671 // The entire scroll delta should have been used to show the top controls.
2672 // The outer viewport should be resized to accomodate and scrolled to the
2673 // bottom of the document to keep the viewport in place.
2674 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2675 EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height());
2676 EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height());
2677 EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
2678 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2679
2680 // Now when we continue scrolling, make sure the outer viewport gets scrolled
2681 // since it wasn't scrollable when the scroll began.
2682 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f));
2683 EXPECT_EQ(15.f, outer_scroll->CurrentScrollOffset().y());
2684 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2685
2686 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f));
2687 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2688 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2689
2690 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2691 host_impl_->ScrollEnd();
2692
2693 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2694 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
2695 }
2696
2697 // Test that the fixed position container delta is appropriately adjusted
2698 // by the top controls showing/hiding and page scale doesn't affect it.
2699 TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
2700 SetupTopControlsAndScrollLayerWithVirtualViewport(
2701 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
2702 DrawFrame();
2703
2704 float page_scale = 1.5f;
2705 LayerImpl* outer_viewport_scroll_layer =
2706 host_impl_->active_tree()->OuterViewportScrollLayer();
2707
2708 // Zoom in, since the fixed container is the outer viewport, the delta should
2709 // not be scaled.
2710 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
2711
2712 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2713 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2714
2715 // Scroll down, the top controls hiding should expand the viewport size so
2716 // the delta should be equal to the scroll distance.
2717 gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
2718 host_impl_->top_controls_manager()->ScrollBegin();
2719 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2720 EXPECT_FLOAT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
2721 host_impl_->top_controls_manager()->ContentTopOffset());
2722 EXPECT_VECTOR_EQ(top_controls_scroll_delta,
2723 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2724 host_impl_->ScrollEnd();
2725
2726 // Scroll past the maximum extent. The delta shouldn't be greater than the
2727 // top controls height.
2728 host_impl_->top_controls_manager()->ScrollBegin();
2729 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2730 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2731 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2732 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2733 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_),
2734 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2735 host_impl_->ScrollEnd();
2736
2737 // Scroll in the direction to make the top controls show.
2738 host_impl_->top_controls_manager()->ScrollBegin();
2739 host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta);
2740 EXPECT_EQ(top_controls_scroll_delta.y(),
2741 host_impl_->top_controls_manager()->ContentTopOffset());
2742 EXPECT_VECTOR_EQ(
2743 gfx::Vector2dF(0, top_controls_height_ - top_controls_scroll_delta.y()),
2744 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2745 host_impl_->top_controls_manager()->ScrollEnd();
2746 }
2747
2748 // Test that if a scrollable sublayer doesn't consume the scroll,
2749 // top controls should hide when scrolling down.
2750 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) {
2751 gfx::Size sub_content_size(100, 400);
2752 gfx::Size sub_content_layer_size(100, 300);
2753 SetupTopControlsAndScrollLayerWithVirtualViewport(
2754 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
2755 DrawFrame();
2756
2757 // Show top controls
2758 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2759
2760 LayerImpl* outer_viewport_scroll_layer =
2761 host_impl_->active_tree()->OuterViewportScrollLayer();
2762 int id = outer_viewport_scroll_layer->id();
2763
2764 scoped_ptr<LayerImpl> child =
2765 LayerImpl::Create(host_impl_->active_tree(), id + 2);
2766 scoped_ptr<LayerImpl> child_clip =
2767 LayerImpl::Create(host_impl_->active_tree(), id + 3);
2768
2769 child_clip->SetBounds(sub_content_layer_size);
2770 child->SetScrollClipLayer(child_clip->id());
2771 child->SetBounds(sub_content_size);
2772 child->SetContentBounds(sub_content_size);
2773 child->SetPosition(gfx::PointF());
2774 child->SetDrawsContent(true);
2775 child->SetIsContainerForFixedPositionLayers(true);
2776
2777 // scroll child to limit
2778 child->SetScrollDelta(gfx::Vector2dF(0, 100.f));
2779 child_clip->AddChild(child.Pass());
2780 outer_viewport_scroll_layer->AddChild(child_clip.Pass());
2781
2782 // Scroll 25px to hide top controls
2783 gfx::Vector2dF scroll_delta(0.f, 25.f);
2784 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2785 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2786 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2787 host_impl_->ScrollEnd();
2788
2789 // Top controls should be hidden
2790 EXPECT_EQ(scroll_delta.y(),
2791 top_controls_height_ -
2792 host_impl_->top_controls_manager()->ContentTopOffset());
2793 }
2794
2795 // Ensure setting the top controls position explicitly using the setters on the
2796 // TreeImpl correctly affects the top controls manager and viewport bounds.
2797 TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
2798 CreateHostImpl(settings_, CreateOutputSurface());
2799 SetupTopControlsAndScrollLayer();
2800 DrawFrame();
2801
2802 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2803 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2804 30.f / top_controls_height_);
2805 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2806 EXPECT_FLOAT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
2807 EXPECT_FLOAT_EQ(-20.f,
2808 host_impl_->top_controls_manager()->ControlsTopOffset());
2809
2810 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2811 EXPECT_FLOAT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2812 EXPECT_FLOAT_EQ(-50.f,
2813 host_impl_->top_controls_manager()->ControlsTopOffset());
2814
2815 host_impl_->DidChangeTopControlsPosition();
2816
2817 // Now that top controls have moved, expect the clip to resize.
2818 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2819 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2820 }
2821
2822 // Test that the top_controls delta and sent delta are appropriately
2823 // applied on sync tree activation. The total top controls offset shouldn't
2824 // change after the activation.
2825 TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
2826 CreateHostImpl(settings_, CreateOutputSurface());
2827 SetupTopControlsAndScrollLayer();
2828 DrawFrame();
2829
2830 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2831 20.f / top_controls_height_);
2832 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2833 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(
2834 15.f / top_controls_height_);
2835 host_impl_->active_tree()
2836 ->top_controls_shown_ratio()
2837 ->PullDeltaForMainThread();
2838 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2839 host_impl_->sync_tree()->PushTopControlsFromMainThread(15.f /
2840 top_controls_height_);
2841
2842 host_impl_->DidChangeTopControlsPosition();
2843 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2844 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2845 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2846
2847 host_impl_->ActivateSyncTree();
2848
2849 root_clip_ptr = host_impl_->active_tree()->root_layer();
2850 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2851 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2852
2853 EXPECT_FLOAT_EQ(
2854 -15.f, host_impl_->active_tree()->top_controls_shown_ratio()->Delta() *
2855 top_controls_height_);
2856 EXPECT_FLOAT_EQ(
2857 15.f,
2858 host_impl_->active_tree()->top_controls_shown_ratio()->ActiveBase() *
2859 top_controls_height_);
2860 }
2861
2862 // Test that changing the top controls layout height is correctly applied to
2863 // the inner viewport container bounds. That is, the top controls layout
2864 // height is the amount that the inner viewport container was shrunk outside
2865 // the compositor to accommodate the top controls.
2866 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
2867 CreateHostImpl(settings_, CreateOutputSurface());
2868 SetupTopControlsAndScrollLayer();
2869 DrawFrame();
2870
2871 host_impl_->sync_tree()->PushTopControlsFromMainThread(1.f);
2872 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2873
2874 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2875 1.f);
2876 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2877 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2878
2879 host_impl_->DidChangeTopControlsPosition();
2880 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2881 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2882 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2883
2884 host_impl_->sync_tree()->root_layer()->SetBounds(
2885 gfx::Size(root_clip_ptr->bounds().width(),
2886 root_clip_ptr->bounds().height() - 50.f));
2887
2888 host_impl_->ActivateSyncTree();
2889
2890 root_clip_ptr = host_impl_->active_tree()->root_layer();
2891 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2892
2893 // The total bounds should remain unchanged since the bounds delta should
2894 // account for the difference between the layout height and the current
2895 // top controls offset.
2896 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2897 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), root_clip_ptr->bounds_delta());
2898
2899 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
2900 host_impl_->DidChangeTopControlsPosition();
2901
2902 EXPECT_EQ(1.f, host_impl_->top_controls_manager()->TopControlsShownRatio());
2903 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->TopControlsHeight());
2904 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset());
2905 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), root_clip_ptr->bounds_delta());
2906 EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f),
2907 root_clip_ptr->bounds());
2908 }
2909
2910 // Test that showing/hiding the top controls when the viewport is fully scrolled
2911 // doesn't incorrectly change the viewport offset due to clamping from changing
2912 // viewport bounds.
2913 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) {
2914 SetupTopControlsAndScrollLayerWithVirtualViewport(
2915 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2916 DrawFrame();
2917
2918 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2919
2920 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
2921 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
2922
2923 // Scroll the viewports to max scroll offset.
2924 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
2925 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
2926
2927 gfx::ScrollOffset viewport_offset =
2928 host_impl_->active_tree()->TotalScrollOffset();
2929 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset);
2930
2931 // Hide the top controls by 25px.
2932 gfx::Vector2dF scroll_delta(0.f, 25.f);
2933 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2934 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2935 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2936
2937 // scrolling down at the max extents no longer hides the top controls
2938 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2939
2940 // forcefully hide the top controls by 25px
2941 host_impl_->top_controls_manager()->ScrollBy(scroll_delta);
2942 host_impl_->ScrollEnd();
2943
2944 EXPECT_FLOAT_EQ(scroll_delta.y(),
2945 top_controls_height_ -
2946 host_impl_->top_controls_manager()->ContentTopOffset());
2947
2948 inner_scroll->ClampScrollToMaxScrollOffset();
2949 outer_scroll->ClampScrollToMaxScrollOffset();
2950
2951 // We should still be fully scrolled.
2952 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
2953 host_impl_->active_tree()->TotalScrollOffset());
2954
2955 viewport_offset = host_impl_->active_tree()->TotalScrollOffset();
2956
2957 // Bring the top controls down by 25px.
2958 scroll_delta = gfx::Vector2dF(0.f, -25.f);
2959 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2960 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2961 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2962 host_impl_->ScrollEnd();
2963
2964 // The viewport offset shouldn't have changed.
2965 EXPECT_EQ(viewport_offset,
2966 host_impl_->active_tree()->TotalScrollOffset());
2967
2968 // Scroll the viewports to max scroll offset.
2969 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
2970 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
2971 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
2972 host_impl_->active_tree()->TotalScrollOffset());
2973 }
2974
2975 // Test that the top controls coming in and out maintains the same aspect ratio
2976 // between the inner and outer viewports.
2977 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
2978 SetupTopControlsAndScrollLayerWithVirtualViewport(
2979 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2980 DrawFrame();
2981
2982 EXPECT_FLOAT_EQ(top_controls_height_,
2983 host_impl_->top_controls_manager()->ContentTopOffset());
2984
2985 gfx::Vector2dF scroll_delta(0.f, 25.f);
2986 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2987 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2988 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2989 host_impl_->ScrollEnd();
2990
2991 EXPECT_FLOAT_EQ(scroll_delta.y(),
2992 top_controls_height_ -
2993 host_impl_->top_controls_manager()->ContentTopOffset());
2994
2995 // Top controls were hidden by 25px so the inner viewport should have expanded
2996 // by that much.
2997 LayerImpl* outer_container =
2998 host_impl_->active_tree()->OuterViewportContainerLayer();
2999 LayerImpl* inner_container =
3000 host_impl_->active_tree()->InnerViewportContainerLayer();
3001 EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling());
3002
3003 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3004 float aspect_ratio = inner_container->BoundsForScrolling().width() /
3005 inner_container->BoundsForScrolling().height();
3006 gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio));
3007 EXPECT_EQ(expected, outer_container->BoundsForScrolling());
3008 EXPECT_EQ(expected,
3009 host_impl_->InnerViewportScrollLayer()->BoundsForScrolling());
3010 }
3011
3012 // Test that scrolling the outer viewport affects the top controls.
3013 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
3014 SetupTopControlsAndScrollLayerWithVirtualViewport(
3015 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3016 DrawFrame();
3017
3018 EXPECT_EQ(top_controls_height_,
3019 host_impl_->top_controls_manager()->ContentTopOffset());
3020
3021 // Send a gesture scroll that will scroll the outer viewport, make sure the
3022 // top controls get scrolled.
3023 gfx::Vector2dF scroll_delta(0.f, 15.f);
3024 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3025 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3026 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3027 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3028 host_impl_->CurrentlyScrollingLayer());
3029 host_impl_->ScrollEnd();
3030
3031 EXPECT_FLOAT_EQ(scroll_delta.y(),
3032 top_controls_height_ -
3033 host_impl_->top_controls_manager()->ContentTopOffset());
3034
3035 scroll_delta = gfx::Vector2dF(0.f, 50.f);
3036 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3037 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3038 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3039
3040 EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset());
3041 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3042 host_impl_->CurrentlyScrollingLayer());
3043
3044 host_impl_->ScrollEnd();
3045
3046 // Position the viewports such that the inner viewport will be scrolled.
3047 gfx::Vector2dF inner_viewport_offset(0.f, 25.f);
3048 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3049 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset);
3050
3051 scroll_delta = gfx::Vector2dF(0.f, -65.f);
3052 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3053 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3054 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3055
3056 EXPECT_EQ(top_controls_height_,
3057 host_impl_->top_controls_manager()->ContentTopOffset());
3058 EXPECT_FLOAT_EQ(
3059 inner_viewport_offset.y() + (scroll_delta.y() + top_controls_height_),
3060 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
3061
3062 host_impl_->ScrollEnd();
3063 }
3064
3065 TEST_F(LayerTreeHostImplTopControlsTest,
3066 ScrollNonScrollableRootWithTopControls) {
3067 CreateHostImpl(settings_, CreateOutputSurface());
3068 SetupTopControlsAndScrollLayer();
3069 DrawFrame();
3070
3071 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3072 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3073
3074 host_impl_->top_controls_manager()->ScrollBegin();
3075 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
3076 host_impl_->top_controls_manager()->ScrollEnd();
3077 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3078 // Now that top controls have moved, expect the clip to resize.
3079 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
3080 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
3081
3082 host_impl_->ScrollEnd();
3083
3084 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3085 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3086
3087 float scroll_increment_y = -25.f;
3088 host_impl_->top_controls_manager()->ScrollBegin();
3089 host_impl_->top_controls_manager()->ScrollBy(
3090 gfx::Vector2dF(0.f, scroll_increment_y));
3091 EXPECT_FLOAT_EQ(-scroll_increment_y,
3092 host_impl_->top_controls_manager()->ContentTopOffset());
3093 // Now that top controls have moved, expect the clip to resize.
3094 EXPECT_EQ(gfx::Size(viewport_size_.width(),
3095 viewport_size_.height() + scroll_increment_y),
3096 root_clip_ptr->bounds());
3097
3098 host_impl_->top_controls_manager()->ScrollBy(
3099 gfx::Vector2dF(0.f, scroll_increment_y));
3100 host_impl_->top_controls_manager()->ScrollEnd();
3101 EXPECT_FLOAT_EQ(-2 * scroll_increment_y,
3102 host_impl_->top_controls_manager()->ContentTopOffset());
3103 // Now that top controls have moved, expect the clip to resize.
3104 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
3105
3106 host_impl_->ScrollEnd();
3107
3108 // Verify the layer is once-again non-scrollable.
3109 EXPECT_EQ(
3110 gfx::ScrollOffset(),
3111 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3112
3113 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3114 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3115 }
3116
3117 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
3118 // Test the configuration where a non-composited root layer is embedded in a
3119 // scrollable outer layer.
3120 gfx::Size surface_size(10, 10);
3121 gfx::Size contents_size(20, 20);
3122
3123 scoped_ptr<LayerImpl> content_layer =
3124 LayerImpl::Create(host_impl_->active_tree(), 1);
3125 content_layer->SetDrawsContent(true);
3126 content_layer->SetPosition(gfx::PointF());
3127 content_layer->SetBounds(contents_size);
3128 content_layer->SetContentBounds(contents_size);
3129 content_layer->SetContentsScale(2.f, 2.f);
3130
3131 scoped_ptr<LayerImpl> scroll_clip_layer =
3132 LayerImpl::Create(host_impl_->active_tree(), 3);
3133 scroll_clip_layer->SetBounds(surface_size);
3134
3135 scoped_ptr<LayerImpl> scroll_layer =
3136 LayerImpl::Create(host_impl_->active_tree(), 2);
3137 scroll_layer->SetScrollClipLayer(3);
3138 scroll_layer->SetBounds(contents_size);
3139 scroll_layer->SetContentBounds(contents_size);
3140 scroll_layer->SetPosition(gfx::PointF());
3141 scroll_layer->AddChild(content_layer.Pass());
3142 scroll_clip_layer->AddChild(scroll_layer.Pass());
3143
3144 scroll_clip_layer->SetHasRenderSurface(true);
3145 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
3146 host_impl_->SetViewportSize(surface_size);
3147 DrawFrame();
3148
3149 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3150 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3151 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3152 host_impl_->ScrollEnd();
3153 EXPECT_TRUE(did_request_redraw_);
3154 EXPECT_TRUE(did_request_commit_);
3155 }
3156
3157 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
3158 gfx::Size surface_size(10, 10);
3159 gfx::Size contents_size(20, 20);
3160 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3161 root->SetBounds(surface_size);
3162 root->SetContentBounds(contents_size);
3163 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
3164 root->SetHasRenderSurface(true);
3165 host_impl_->active_tree()->SetRootLayer(root.Pass());
3166 host_impl_->SetViewportSize(surface_size);
3167 DrawFrame();
3168
3169 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3170 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3171 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3172 host_impl_->ScrollEnd();
3173 EXPECT_TRUE(did_request_redraw_);
3174 EXPECT_TRUE(did_request_commit_);
3175 }
3176
3177 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
3178 gfx::Size surface_size(10, 10);
3179 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3180 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
3181 root->SetHasRenderSurface(true);
3182 host_impl_->active_tree()->SetRootLayer(root.Pass());
3183 host_impl_->SetViewportSize(surface_size);
3184 DrawFrame();
3185
3186 // Scroll event is ignored because the input coordinate is outside the layer
3187 // boundaries.
3188 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3189 host_impl_->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL));
3190 EXPECT_FALSE(did_request_redraw_);
3191 EXPECT_FALSE(did_request_commit_);
3192 }
3193
3194 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
3195 gfx::Size surface_size(10, 10);
3196 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3197 root->SetHasRenderSurface(true);
3198 scoped_ptr<LayerImpl> child =
3199 CreateScrollableLayer(2, surface_size, root.get());
3200 host_impl_->SetViewportSize(surface_size);
3201
3202 gfx::Transform matrix;
3203 matrix.RotateAboutXAxis(180.0);
3204 child->SetTransform(matrix);
3205 child->SetDoubleSided(false);
3206
3207 root->AddChild(child.Pass());
3208 host_impl_->active_tree()->SetRootLayer(root.Pass());
3209 DrawFrame();
3210
3211 // Scroll event is ignored because the scrollable layer is not facing the
3212 // viewer and there is nothing scrollable behind it.
3213 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3214 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3215 EXPECT_FALSE(did_request_redraw_);
3216 EXPECT_FALSE(did_request_commit_);
3217 }
3218
3219 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
3220 gfx::Size surface_size(10, 10);
3221 scoped_ptr<LayerImpl> clip_layer =
3222 LayerImpl::Create(host_impl_->active_tree(), 3);
3223 scoped_ptr<LayerImpl> content_layer =
3224 CreateScrollableLayer(1, surface_size, clip_layer.get());
3225 content_layer->SetShouldScrollOnMainThread(true);
3226 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
3227
3228 // Note: we can use the same clip layer for both since both calls to
3229 // CreateScrollableLayer() use the same surface size.
3230 scoped_ptr<LayerImpl> scroll_layer =
3231 CreateScrollableLayer(2, surface_size, clip_layer.get());
3232 scroll_layer->AddChild(content_layer.Pass());
3233 clip_layer->AddChild(scroll_layer.Pass());
3234 clip_layer->SetHasRenderSurface(true);
3235
3236 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
3237 host_impl_->SetViewportSize(surface_size);
3238 DrawFrame();
3239
3240 // Scrolling fails because the content layer is asking to be scrolled on the
3241 // main thread.
3242 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
3243 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3244 }
3245
3246 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
3247 gfx::Size surface_size(20, 20);
3248 gfx::Size viewport_size(10, 10);
3249 float page_scale = 2.f;
3250 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3251 scoped_ptr<LayerImpl> root_clip =
3252 LayerImpl::Create(host_impl_->active_tree(), 2);
3253 scoped_ptr<LayerImpl> root_scrolling =
3254 CreateScrollableLayer(3, surface_size, root_clip.get());
3255 EXPECT_EQ(viewport_size, root_clip->bounds());
3256 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3257 root_clip->AddChild(root_scrolling.Pass());
3258 root->AddChild(root_clip.Pass());
3259 root->SetHasRenderSurface(true);
3260 host_impl_->active_tree()->SetRootLayer(root.Pass());
3261 // The behaviour in this test assumes the page scale is applied at a layer
3262 // above the clip layer.
3263 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
3264 Layer::INVALID_ID);
3265 host_impl_->active_tree()->DidBecomeActive();
3266 host_impl_->SetViewportSize(viewport_size);
3267 DrawFrame();
3268
3269 LayerImpl* root_scroll =
3270 host_impl_->active_tree()->InnerViewportScrollLayer();
3271 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3272
3273 gfx::Vector2d scroll_delta(0, 10);
3274 gfx::Vector2d expected_scroll_delta = scroll_delta;
3275 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3276 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3277 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3278 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3279 host_impl_->ScrollEnd();
3280
3281 // Set new page scale from main thread.
3282 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, page_scale,
3283 page_scale);
3284
3285 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3286 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
3287
3288 // The scroll range should also have been updated.
3289 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3290
3291 // The page scale delta remains constant because the impl thread did not
3292 // scale.
3293 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3294 }
3295
3296 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
3297 gfx::Size surface_size(20, 20);
3298 gfx::Size viewport_size(10, 10);
3299 float page_scale = 2.f;
3300 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3301 scoped_ptr<LayerImpl> root_clip =
3302 LayerImpl::Create(host_impl_->active_tree(), 2);
3303 scoped_ptr<LayerImpl> root_scrolling =
3304 CreateScrollableLayer(3, surface_size, root_clip.get());
3305 EXPECT_EQ(viewport_size, root_clip->bounds());
3306 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3307 root_clip->AddChild(root_scrolling.Pass());
3308 root->AddChild(root_clip.Pass());
3309 root->SetHasRenderSurface(true);
3310 host_impl_->active_tree()->SetRootLayer(root.Pass());
3311 // The behaviour in this test assumes the page scale is applied at a layer
3312 // above the clip layer.
3313 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
3314 Layer::INVALID_ID);
3315 host_impl_->active_tree()->DidBecomeActive();
3316 host_impl_->SetViewportSize(viewport_size);
3317 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, page_scale);
3318 DrawFrame();
3319
3320 LayerImpl* root_scroll =
3321 host_impl_->active_tree()->InnerViewportScrollLayer();
3322 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3323
3324 gfx::Vector2d scroll_delta(0, 10);
3325 gfx::Vector2d expected_scroll_delta = scroll_delta;
3326 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3327 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3328 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3329 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3330 host_impl_->ScrollEnd();
3331
3332 // Set new page scale on impl thread by pinching.
3333 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3334 host_impl_->PinchGestureBegin();
3335 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
3336 host_impl_->PinchGestureEnd();
3337 host_impl_->ScrollEnd();
3338 DrawOneFrame();
3339
3340 // The scroll delta is not scaled because the main thread did not scale.
3341 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3342 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
3343
3344 // The scroll range should also have been updated.
3345 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3346
3347 // The page scale delta should match the new scale on the impl side.
3348 EXPECT_EQ(page_scale, host_impl_->active_tree()->current_page_scale_factor());
3349 }
3350
3351 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
3352 gfx::Size surface_size(10, 10);
3353 float default_page_scale = 1.f;
3354 gfx::Transform default_page_scale_matrix;
3355 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
3356
3357 float new_page_scale = 2.f;
3358 gfx::Transform new_page_scale_matrix;
3359 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
3360
3361 // Create a normal scrollable root layer and another scrollable child layer.
3362 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
3363 LayerImpl* root = host_impl_->active_tree()->root_layer();
3364 LayerImpl* child = scroll->children()[0];
3365
3366 scoped_ptr<LayerImpl> scrollable_child_clip =
3367 LayerImpl::Create(host_impl_->active_tree(), 6);
3368 scoped_ptr<LayerImpl> scrollable_child =
3369 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
3370 scrollable_child_clip->AddChild(scrollable_child.Pass());
3371 child->AddChild(scrollable_child_clip.Pass());
3372 LayerImpl* grand_child = child->children()[0];
3373
3374 // Set new page scale on impl thread by pinching.
3375 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3376 host_impl_->PinchGestureBegin();
3377 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
3378 host_impl_->PinchGestureEnd();
3379 host_impl_->ScrollEnd();
3380 DrawOneFrame();
3381
3382 EXPECT_EQ(1.f, root->contents_scale_x());
3383 EXPECT_EQ(1.f, root->contents_scale_y());
3384 EXPECT_EQ(1.f, scroll->contents_scale_x());
3385 EXPECT_EQ(1.f, scroll->contents_scale_y());
3386 EXPECT_EQ(1.f, child->contents_scale_x());
3387 EXPECT_EQ(1.f, child->contents_scale_y());
3388 EXPECT_EQ(1.f, grand_child->contents_scale_x());
3389 EXPECT_EQ(1.f, grand_child->contents_scale_y());
3390
3391 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3392 // the page scale delta on the root layer is applied hierarchically.
3393 LayerTreeHostImpl::FrameData frame;
3394 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3395 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3396 host_impl_->DidDrawAllLayers(frame);
3397
3398 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
3399 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
3400 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
3401 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
3402 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
3403 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
3404 EXPECT_EQ(new_page_scale,
3405 grand_child->draw_transform().matrix().getDouble(0, 0));
3406 EXPECT_EQ(new_page_scale,
3407 grand_child->draw_transform().matrix().getDouble(1, 1));
3408 }
3409
3410 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
3411 gfx::Size surface_size(30, 30);
3412 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3413 root->SetBounds(gfx::Size(5, 5));
3414 root->SetHasRenderSurface(true);
3415 scoped_ptr<LayerImpl> root_scrolling =
3416 LayerImpl::Create(host_impl_->active_tree(), 2);
3417 root_scrolling->SetBounds(surface_size);
3418 root_scrolling->SetContentBounds(surface_size);
3419 root_scrolling->SetScrollClipLayer(root->id());
3420 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3421 LayerImpl* root_scrolling_ptr = root_scrolling.get();
3422 root->AddChild(root_scrolling.Pass());
3423 int child_scroll_layer_id = 3;
3424 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
3425 child_scroll_layer_id, surface_size, root_scrolling_ptr);
3426 LayerImpl* child = child_scrolling.get();
3427 root_scrolling_ptr->AddChild(child_scrolling.Pass());
3428 host_impl_->active_tree()->SetRootLayer(root.Pass());
3429 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3430 Layer::INVALID_ID);
3431 host_impl_->active_tree()->DidBecomeActive();
3432 host_impl_->SetViewportSize(surface_size);
3433 DrawFrame();
3434
3435 gfx::Vector2d scroll_delta(0, 10);
3436 gfx::Vector2d expected_scroll_delta(scroll_delta);
3437 gfx::ScrollOffset expected_max_scroll(child->MaxScrollOffset());
3438 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3439 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3440 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3441 host_impl_->ScrollEnd();
3442
3443 float page_scale = 2.f;
3444 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f,
3445 page_scale);
3446
3447 DrawOneFrame();
3448
3449 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3450 ExpectContains(
3451 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
3452
3453 // The scroll range should not have changed.
3454 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
3455
3456 // The page scale delta remains constant because the impl thread did not
3457 // scale.
3458 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3459 }
3460
3461 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
3462 // Scroll a child layer beyond its maximum scroll range and make sure the
3463 // parent layer is scrolled on the axis on which the child was unable to
3464 // scroll.
3465 gfx::Size surface_size(10, 10);
3466 gfx::Size content_size(20, 20);
3467 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3468 root->SetBounds(surface_size);
3469 root->SetHasRenderSurface(true);
3470 scoped_ptr<LayerImpl> grand_child =
3471 CreateScrollableLayer(3, content_size, root.get());
3472
3473 scoped_ptr<LayerImpl> child =
3474 CreateScrollableLayer(2, content_size, root.get());
3475 LayerImpl* grand_child_layer = grand_child.get();
3476 child->AddChild(grand_child.Pass());
3477
3478 LayerImpl* child_layer = child.get();
3479 root->AddChild(child.Pass());
3480 host_impl_->active_tree()->SetRootLayer(root.Pass());
3481 host_impl_->active_tree()->DidBecomeActive();
3482 host_impl_->SetViewportSize(surface_size);
3483 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
3484 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
3485
3486 DrawFrame();
3487 {
3488 gfx::Vector2d scroll_delta(-8, -7);
3489 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3490 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3491 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3492 host_impl_->ScrollEnd();
3493
3494 scoped_ptr<ScrollAndScaleSet> scroll_info =
3495 host_impl_->ProcessScrollDeltas();
3496
3497 // The grand child should have scrolled up to its limit.
3498 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
3499 LayerImpl* grand_child = child->children()[0];
3500 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
3501
3502 // The child should have only scrolled on the other axis.
3503 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
3504 }
3505 }
3506
3507 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
3508 // Scroll a child layer beyond its maximum scroll range and make sure the
3509 // the scroll doesn't bubble up to the parent layer.
3510 gfx::Size surface_size(20, 20);
3511 gfx::Size viewport_size(10, 10);
3512 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3513 root->SetHasRenderSurface(true);
3514 scoped_ptr<LayerImpl> root_scrolling =
3515 CreateScrollableLayer(2, surface_size, root.get());
3516 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3517
3518 scoped_ptr<LayerImpl> grand_child =
3519 CreateScrollableLayer(4, surface_size, root.get());
3520
3521 scoped_ptr<LayerImpl> child =
3522 CreateScrollableLayer(3, surface_size, root.get());
3523 LayerImpl* grand_child_layer = grand_child.get();
3524 child->AddChild(grand_child.Pass());
3525
3526 LayerImpl* child_layer = child.get();
3527 root_scrolling->AddChild(child.Pass());
3528 root->AddChild(root_scrolling.Pass());
3529 EXPECT_EQ(viewport_size, root->bounds());
3530 host_impl_->active_tree()->SetRootLayer(root.Pass());
3531 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3532 Layer::INVALID_ID);
3533 host_impl_->active_tree()->DidBecomeActive();
3534 host_impl_->SetViewportSize(viewport_size);
3535
3536 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
3537 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
3538
3539 DrawFrame();
3540 {
3541 gfx::Vector2d scroll_delta(0, -10);
3542 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3543 host_impl_->ScrollBegin(gfx::Point(),
3544 InputHandler::NON_BUBBLING_GESTURE));
3545 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3546 host_impl_->ScrollEnd();
3547
3548 scoped_ptr<ScrollAndScaleSet> scroll_info =
3549 host_impl_->ProcessScrollDeltas();
3550
3551 // The grand child should have scrolled up to its limit.
3552 LayerImpl* child =
3553 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
3554 LayerImpl* grand_child = child->children()[0];
3555 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
3556
3557 // The child should not have scrolled.
3558 ExpectNone(*scroll_info.get(), child->id());
3559
3560 // The next time we scroll we should only scroll the parent.
3561 scroll_delta = gfx::Vector2d(0, -3);
3562 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3563 host_impl_->ScrollBegin(gfx::Point(5, 5),
3564 InputHandler::NON_BUBBLING_GESTURE));
3565 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3566 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3567 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
3568 host_impl_->ScrollEnd();
3569
3570 scroll_info = host_impl_->ProcessScrollDeltas();
3571
3572 // The child should have scrolled up to its limit.
3573 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
3574
3575 // The grand child should not have scrolled.
3576 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
3577
3578 // After scrolling the parent, another scroll on the opposite direction
3579 // should still scroll the child.
3580 scroll_delta = gfx::Vector2d(0, 7);
3581 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3582 host_impl_->ScrollBegin(gfx::Point(5, 5),
3583 InputHandler::NON_BUBBLING_GESTURE));
3584 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3585 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3586 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3587 host_impl_->ScrollEnd();
3588
3589 scroll_info = host_impl_->ProcessScrollDeltas();
3590
3591 // The grand child should have scrolled.
3592 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
3593
3594 // The child should not have scrolled.
3595 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
3596
3597
3598 // Scrolling should be adjusted from viewport space.
3599 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 2.f, 2.f);
3600 host_impl_->SetPageScaleOnActiveTree(2.f);
3601
3602 scroll_delta = gfx::Vector2d(0, -2);
3603 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3604 host_impl_->ScrollBegin(gfx::Point(1, 1),
3605 InputHandler::NON_BUBBLING_GESTURE));
3606 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
3607 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3608 host_impl_->ScrollEnd();
3609
3610 scroll_info = host_impl_->ProcessScrollDeltas();
3611
3612 // Should have scrolled by half the amount in layer space (5 - 2/2)
3613 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
3614 }
3615 }
3616 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
3617 // When we try to scroll a non-scrollable child layer, the scroll delta
3618 // should be applied to one of its ancestors if possible.
3619 gfx::Size surface_size(10, 10);
3620 gfx::Size content_size(20, 20);
3621 scoped_ptr<LayerImpl> root_clip =
3622 LayerImpl::Create(host_impl_->active_tree(), 3);
3623 root_clip->SetHasRenderSurface(true);
3624 scoped_ptr<LayerImpl> root =
3625 CreateScrollableLayer(1, content_size, root_clip.get());
3626 // Make 'root' the clip layer for child: since they have the same sizes the
3627 // child will have zero max_scroll_offset and scrolls will bubble.
3628 scoped_ptr<LayerImpl> child =
3629 CreateScrollableLayer(2, content_size, root.get());
3630 child->SetIsContainerForFixedPositionLayers(true);
3631 root->SetBounds(content_size);
3632
3633 int root_scroll_id = root->id();
3634 root->AddChild(child.Pass());
3635 root_clip->AddChild(root.Pass());
3636
3637 host_impl_->SetViewportSize(surface_size);
3638 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3639 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 2,
3640 Layer::INVALID_ID);
3641 host_impl_->active_tree()->DidBecomeActive();
3642 DrawFrame();
3643 {
3644 gfx::Vector2d scroll_delta(0, 4);
3645 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3646 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3647 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3648 host_impl_->ScrollEnd();
3649
3650 scoped_ptr<ScrollAndScaleSet> scroll_info =
3651 host_impl_->ProcessScrollDeltas();
3652
3653 // Only the root scroll should have scrolled.
3654 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
3655 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
3656 }
3657 }
3658
3659 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
3660 gfx::Size surface_size(10, 10);
3661 scoped_ptr<LayerImpl> root_clip =
3662 LayerImpl::Create(host_impl_->active_tree(), 1);
3663 scoped_ptr<LayerImpl> root_scroll =
3664 CreateScrollableLayer(2, surface_size, root_clip.get());
3665 root_scroll->SetIsContainerForFixedPositionLayers(true);
3666 root_clip->SetHasRenderSurface(true);
3667 root_clip->AddChild(root_scroll.Pass());
3668 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3669 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3670 Layer::INVALID_ID);
3671 host_impl_->active_tree()->DidBecomeActive();
3672 host_impl_->SetViewportSize(surface_size);
3673
3674 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3675 // synchronization.
3676 DrawFrame();
3677 host_impl_->active_tree()->DetachLayerTree();
3678 scoped_ptr<LayerImpl> root_clip2 =
3679 LayerImpl::Create(host_impl_->active_tree(), 3);
3680 scoped_ptr<LayerImpl> root_scroll2 =
3681 CreateScrollableLayer(4, surface_size, root_clip2.get());
3682 root_scroll2->SetIsContainerForFixedPositionLayers(true);
3683 root_clip2->AddChild(root_scroll2.Pass());
3684 root_clip2->SetHasRenderSurface(true);
3685 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
3686 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 4,
3687 Layer::INVALID_ID);
3688 host_impl_->active_tree()->DidBecomeActive();
3689
3690 // Scrolling should still work even though we did not draw yet.
3691 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3692 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3693 }
3694
3695 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
3696 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3697
3698 // Rotate the root layer 90 degrees counter-clockwise about its center.
3699 gfx::Transform rotate_transform;
3700 rotate_transform.Rotate(-90.0);
3701 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
3702
3703 gfx::Size surface_size(50, 50);
3704 host_impl_->SetViewportSize(surface_size);
3705 DrawFrame();
3706
3707 // Scroll to the right in screen coordinates with a gesture.
3708 gfx::Vector2d gesture_scroll_delta(10, 0);
3709 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3710 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3711 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3712 host_impl_->ScrollEnd();
3713
3714 // The layer should have scrolled down in its local coordinates.
3715 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3716 ExpectContains(*scroll_info.get(), scroll_layer->id(),
3717 gfx::Vector2d(0, gesture_scroll_delta.x()));
3718
3719 // Reset and scroll down with the wheel.
3720 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3721 gfx::Vector2d wheel_scroll_delta(0, 10);
3722 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3723 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3724 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3725 host_impl_->ScrollEnd();
3726
3727 // The layer should have scrolled down in its local coordinates.
3728 scroll_info = host_impl_->ProcessScrollDeltas();
3729 ExpectContains(*scroll_info.get(),
3730 scroll_layer->id(),
3731 wheel_scroll_delta);
3732 }
3733
3734 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
3735 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3736 int child_clip_layer_id = 6;
3737 int child_layer_id = 7;
3738 float child_layer_angle = -20.f;
3739
3740 // Create a child layer that is rotated to a non-axis-aligned angle.
3741 scoped_ptr<LayerImpl> clip_layer =
3742 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
3743 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
3744 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
3745 gfx::Transform rotate_transform;
3746 rotate_transform.Translate(-50.0, -50.0);
3747 rotate_transform.Rotate(child_layer_angle);
3748 rotate_transform.Translate(50.0, 50.0);
3749 clip_layer->SetTransform(rotate_transform);
3750
3751 // Only allow vertical scrolling.
3752 clip_layer->SetBounds(
3753 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
3754 // The rotation depends on the layer's transform origin, and the child layer
3755 // is a different size than the clip, so make sure the clip layer's origin
3756 // lines up over the child.
3757 clip_layer->SetTransformOrigin(gfx::Point3F(
3758 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
3759 LayerImpl* child_ptr = child.get();
3760 clip_layer->AddChild(child.Pass());
3761 scroll_layer->AddChild(clip_layer.Pass());
3762
3763 gfx::Size surface_size(50, 50);
3764 host_impl_->SetViewportSize(surface_size);
3765 DrawFrame();
3766 {
3767 // Scroll down in screen coordinates with a gesture.
3768 gfx::Vector2d gesture_scroll_delta(0, 10);
3769 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3770 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
3771 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3772 host_impl_->ScrollEnd();
3773
3774 // The child layer should have scrolled down in its local coordinates an
3775 // amount proportional to the angle between it and the input scroll delta.
3776 gfx::Vector2d expected_scroll_delta(
3777 0, gesture_scroll_delta.y() *
3778 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
3779 scoped_ptr<ScrollAndScaleSet> scroll_info =
3780 host_impl_->ProcessScrollDeltas();
3781 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
3782
3783 // The root scroll layer should not have scrolled, because the input delta
3784 // was close to the layer's axis of movement.
3785 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
3786 }
3787 {
3788 // Now reset and scroll the same amount horizontally.
3789 child_ptr->SetScrollDelta(gfx::Vector2dF());
3790 gfx::Vector2d gesture_scroll_delta(10, 0);
3791 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3792 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
3793 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3794 host_impl_->ScrollEnd();
3795
3796 // The child layer should have scrolled down in its local coordinates an
3797 // amount proportional to the angle between it and the input scroll delta.
3798 gfx::Vector2d expected_scroll_delta(
3799 0, -gesture_scroll_delta.x() *
3800 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
3801 scoped_ptr<ScrollAndScaleSet> scroll_info =
3802 host_impl_->ProcessScrollDeltas();
3803 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
3804
3805 // The root scroll layer should have scrolled more, since the input scroll
3806 // delta was mostly orthogonal to the child layer's vertical scroll axis.
3807 gfx::Vector2d expected_root_scroll_delta(
3808 gesture_scroll_delta.x() *
3809 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
3810 0);
3811 ExpectContains(*scroll_info.get(),
3812 scroll_layer->id(),
3813 expected_root_scroll_delta);
3814 }
3815 }
3816
3817 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
3818 LayerImpl* scroll_layer =
3819 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3820
3821 // Scale the layer to twice its normal size.
3822 int scale = 2;
3823 gfx::Transform scale_transform;
3824 scale_transform.Scale(scale, scale);
3825 scroll_layer->SetTransform(scale_transform);
3826
3827 gfx::Size surface_size(50, 50);
3828 host_impl_->SetViewportSize(surface_size);
3829 DrawFrame();
3830
3831 // Scroll down in screen coordinates with a gesture.
3832 gfx::Vector2d scroll_delta(0, 10);
3833 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3834 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3835 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3836 host_impl_->ScrollEnd();
3837
3838 // The layer should have scrolled down in its local coordinates, but half the
3839 // amount.
3840 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3841 ExpectContains(*scroll_info.get(),
3842 scroll_layer->id(),
3843 gfx::Vector2d(0, scroll_delta.y() / scale));
3844
3845 // Reset and scroll down with the wheel.
3846 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3847 gfx::Vector2d wheel_scroll_delta(0, 10);
3848 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3849 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3850 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3851 host_impl_->ScrollEnd();
3852
3853 // It should apply the scale factor to the scroll delta for the wheel event.
3854 scroll_info = host_impl_->ProcessScrollDeltas();
3855 ExpectContains(*scroll_info.get(),
3856 scroll_layer->id(),
3857 wheel_scroll_delta);
3858 }
3859
3860 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
3861 int width = 332;
3862 int height = 20;
3863 int scale = 3;
3864 SetupScrollAndContentsLayers(gfx::Size(width, height));
3865 host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
3866 gfx::Size(width * scale - 1, height * scale));
3867 host_impl_->SetDeviceScaleFactor(scale);
3868 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
3869
3870 LayerImpl* inner_viewport_scroll_layer =
3871 host_impl_->active_tree()->InnerViewportScrollLayer();
3872 EXPECT_EQ(gfx::ScrollOffset(0, 0),
3873 inner_viewport_scroll_layer->MaxScrollOffset());
3874 }
3875
3876 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
3877 public:
3878 TestScrollOffsetDelegate()
3879 : page_scale_factor_(0.f),
3880 min_page_scale_factor_(-1.f),
3881 max_page_scale_factor_(-1.f) {}
3882
3883 ~TestScrollOffsetDelegate() override {}
3884
3885 gfx::ScrollOffset GetTotalScrollOffset() override {
3886 return getter_return_value_;
3887 }
3888
3889 bool IsExternalFlingActive() const override { return false; }
3890
3891 void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
3892 const gfx::ScrollOffset& max_scroll_offset,
3893 const gfx::SizeF& scrollable_size,
3894 float page_scale_factor,
3895 float min_page_scale_factor,
3896 float max_page_scale_factor) override {
3897 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
3898 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
3899 last_set_scroll_offset_ = total_scroll_offset;
3900 max_scroll_offset_ = max_scroll_offset;
3901 scrollable_size_ = scrollable_size;
3902 page_scale_factor_ = page_scale_factor;
3903 min_page_scale_factor_ = min_page_scale_factor;
3904 max_page_scale_factor_ = max_page_scale_factor;
3905
3906 set_getter_return_value(last_set_scroll_offset_);
3907 }
3908
3909 gfx::ScrollOffset last_set_scroll_offset() {
3910 return last_set_scroll_offset_;
3911 }
3912
3913 void set_getter_return_value(const gfx::ScrollOffset& value) {
3914 getter_return_value_ = value;
3915 }
3916
3917 gfx::ScrollOffset max_scroll_offset() const {
3918 return max_scroll_offset_;
3919 }
3920
3921 gfx::SizeF scrollable_size() const {
3922 return scrollable_size_;
3923 }
3924
3925 float page_scale_factor() const {
3926 return page_scale_factor_;
3927 }
3928
3929 float min_page_scale_factor() const {
3930 return min_page_scale_factor_;
3931 }
3932
3933 float max_page_scale_factor() const {
3934 return max_page_scale_factor_;
3935 }
3936
3937 private:
3938 gfx::ScrollOffset last_set_scroll_offset_;
3939 gfx::ScrollOffset getter_return_value_;
3940 gfx::ScrollOffset max_scroll_offset_;
3941 gfx::SizeF scrollable_size_;
3942 float page_scale_factor_;
3943 float min_page_scale_factor_;
3944 float max_page_scale_factor_;
3945 };
3946
3947 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
3948 TestScrollOffsetDelegate scroll_delegate;
3949 host_impl_->SetViewportSize(gfx::Size(10, 20));
3950 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3951 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3952 clip_layer->SetBounds(gfx::Size(10, 20));
3953
3954 // Setting the delegate results in the current scroll offset being set.
3955 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
3956 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
3957 scroll_layer->SetScrollDelta(initial_scroll_delta);
3958 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3959 EXPECT_EQ(initial_scroll_delta.ToString(),
3960 scroll_delegate.last_set_scroll_offset().ToString());
3961
3962 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3963 // page_scale_factor and {min|max}_page_scale_factor being set.
3964 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
3965 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset());
3966 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3967 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
3968 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
3969
3970 // Updating page scale immediately updates the delegate.
3971 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 0.5f, 4.f);
3972 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
3973 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3974 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3975 host_impl_->SetPageScaleOnActiveTree(2.f * 1.5f);
3976 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
3977 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3978 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3979 host_impl_->SetPageScaleOnActiveTree(2.f);
3980 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
3981 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3982 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3983 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3984
3985 // The pinch gesture doesn't put the delegate into a state where the scroll
3986 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3987 // delegate).
3988 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3989 host_impl_->PinchGestureBegin();
3990 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
3991 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
3992 host_impl_->PinchGestureEnd();
3993 host_impl_->ScrollEnd();
3994
3995 // Scrolling should be relative to the offset as returned by the delegate.
3996 gfx::Vector2dF scroll_delta(0.f, 10.f);
3997 gfx::ScrollOffset current_offset(7.f, 8.f);
3998
3999 scroll_delegate.set_getter_return_value(current_offset);
4000 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4001 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4002
4003 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4004 EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
4005 scroll_delegate.last_set_scroll_offset());
4006
4007 current_offset = gfx::ScrollOffset(42.f, 41.f);
4008 scroll_delegate.set_getter_return_value(current_offset);
4009 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4010 EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
4011 scroll_delegate.last_set_scroll_offset());
4012 host_impl_->ScrollEnd();
4013 scroll_delegate.set_getter_return_value(gfx::ScrollOffset());
4014
4015 // Forces a full tree synchronization and ensures that the scroll delegate
4016 // sees the correct size of the new tree.
4017 gfx::Size new_size(42, 24);
4018 host_impl_->CreatePendingTree();
4019 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
4020 host_impl_->ActivateSyncTree();
4021 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
4022
4023 // Un-setting the delegate should propagate the delegate's current offset to
4024 // the root scrollable layer.
4025 current_offset = gfx::ScrollOffset(13.f, 12.f);
4026 scroll_delegate.set_getter_return_value(current_offset);
4027 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4028
4029 EXPECT_EQ(current_offset.ToString(),
4030 scroll_layer->CurrentScrollOffset().ToString());
4031 }
4032
4033 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
4034 const gfx::Transform target_space_transform =
4035 layer->draw_properties().target_space_transform;
4036 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
4037 gfx::Point translated_point;
4038 target_space_transform.TransformPoint(&translated_point);
4039 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
4040 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
4041 }
4042
4043 TEST_F(LayerTreeHostImplTest,
4044 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
4045 TestScrollOffsetDelegate scroll_delegate;
4046 host_impl_->SetViewportSize(gfx::Size(10, 20));
4047 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4048 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4049 clip_layer->SetBounds(gfx::Size(10, 20));
4050 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4051
4052 // Draw first frame to clear any pending draws and check scroll.
4053 DrawFrame();
4054 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
4055 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
4056
4057 // Set external scroll delta on delegate and notify LayerTreeHost.
4058 gfx::ScrollOffset scroll_offset(10.f, 10.f);
4059 scroll_delegate.set_getter_return_value(scroll_offset);
4060 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4061
4062 // Check scroll delta reflected in layer.
4063 LayerTreeHostImpl::FrameData frame;
4064 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4065 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4066 host_impl_->DidDrawAllLayers(frame);
4067 EXPECT_FALSE(frame.has_no_damage);
4068 CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset));
4069
4070 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4071 }
4072
4073 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
4074 InputHandlerScrollResult scroll_result;
4075 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4076 host_impl_->SetViewportSize(gfx::Size(50, 50));
4077 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4078 DrawFrame();
4079 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4080
4081 // In-bounds scrolling does not affect overscroll.
4082 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4083 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4084 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4085 EXPECT_TRUE(scroll_result.did_scroll);
4086 EXPECT_FALSE(scroll_result.did_overscroll_root);
4087 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4088 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4089
4090 // Overscroll events are reflected immediately.
4091 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4092 EXPECT_TRUE(scroll_result.did_scroll);
4093 EXPECT_TRUE(scroll_result.did_overscroll_root);
4094 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4095 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4096 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4097 host_impl_->accumulated_root_overscroll());
4098
4099 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4100 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4101 EXPECT_TRUE(scroll_result.did_scroll);
4102 EXPECT_FALSE(scroll_result.did_overscroll_root);
4103 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4104 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4105 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4106 host_impl_->accumulated_root_overscroll());
4107
4108 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4109 EXPECT_FALSE(scroll_result.did_scroll);
4110 EXPECT_TRUE(scroll_result.did_overscroll_root);
4111 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4112 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4113 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4114 host_impl_->accumulated_root_overscroll());
4115
4116 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4117 EXPECT_TRUE(scroll_result.did_scroll);
4118 EXPECT_FALSE(scroll_result.did_overscroll_root);
4119 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4120 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4121 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4122 host_impl_->accumulated_root_overscroll());
4123
4124 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4125 EXPECT_TRUE(scroll_result.did_scroll);
4126 EXPECT_TRUE(scroll_result.did_overscroll_root);
4127 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
4128 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
4129 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4130 host_impl_->accumulated_root_overscroll());
4131
4132 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4133 EXPECT_TRUE(scroll_result.did_scroll);
4134 EXPECT_TRUE(scroll_result.did_overscroll_root);
4135 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4136 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
4137 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4138 host_impl_->accumulated_root_overscroll());
4139
4140 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4141 EXPECT_TRUE(scroll_result.did_scroll);
4142 EXPECT_TRUE(scroll_result.did_overscroll_root);
4143 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4144 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4145 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4146 host_impl_->accumulated_root_overscroll());
4147
4148 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4149 // as no scroll occurs.
4150 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4151 EXPECT_FALSE(scroll_result.did_scroll);
4152 EXPECT_TRUE(scroll_result.did_overscroll_root);
4153 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4154 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
4155 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4156 host_impl_->accumulated_root_overscroll());
4157
4158 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4159 EXPECT_FALSE(scroll_result.did_scroll);
4160 EXPECT_TRUE(scroll_result.did_overscroll_root);
4161 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4162 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
4163 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4164 host_impl_->accumulated_root_overscroll());
4165
4166 // Overscroll resets on valid scroll.
4167 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4168 EXPECT_TRUE(scroll_result.did_scroll);
4169 EXPECT_FALSE(scroll_result.did_overscroll_root);
4170 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4171 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4172 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4173 host_impl_->accumulated_root_overscroll());
4174
4175 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4176 EXPECT_TRUE(scroll_result.did_scroll);
4177 EXPECT_TRUE(scroll_result.did_overscroll_root);
4178 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4179 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4180 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4181 host_impl_->accumulated_root_overscroll());
4182
4183 host_impl_->ScrollEnd();
4184 }
4185
4186
4187 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
4188 // Scroll child layers beyond their maximum scroll range and make sure root
4189 // overscroll does not accumulate.
4190 gfx::Size surface_size(10, 10);
4191 scoped_ptr<LayerImpl> root_clip =
4192 LayerImpl::Create(host_impl_->active_tree(), 4);
4193 root_clip->SetHasRenderSurface(true);
4194
4195 scoped_ptr<LayerImpl> root =
4196 CreateScrollableLayer(1, surface_size, root_clip.get());
4197
4198 scoped_ptr<LayerImpl> grand_child =
4199 CreateScrollableLayer(3, surface_size, root_clip.get());
4200
4201 scoped_ptr<LayerImpl> child =
4202 CreateScrollableLayer(2, surface_size, root_clip.get());
4203 LayerImpl* grand_child_layer = grand_child.get();
4204 child->AddChild(grand_child.Pass());
4205
4206 LayerImpl* child_layer = child.get();
4207 root->AddChild(child.Pass());
4208 root_clip->AddChild(root.Pass());
4209 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4210 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4211 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4212 host_impl_->active_tree()->DidBecomeActive();
4213 host_impl_->SetViewportSize(surface_size);
4214 DrawFrame();
4215 {
4216 gfx::Vector2d scroll_delta(0, -10);
4217 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4218 host_impl_->ScrollBegin(gfx::Point(),
4219 InputHandler::NON_BUBBLING_GESTURE));
4220 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4221 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4222 host_impl_->ScrollEnd();
4223
4224 // The next time we scroll we should only scroll the parent, but overscroll
4225 // should still not reach the root layer.
4226 scroll_delta = gfx::Vector2d(0, -30);
4227 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4228 host_impl_->ScrollBegin(gfx::Point(5, 5),
4229 InputHandler::NON_BUBBLING_GESTURE));
4230 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4231 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4232 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4233 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
4234 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4235 host_impl_->ScrollEnd();
4236
4237 // After scrolling the parent, another scroll on the opposite direction
4238 // should scroll the child.
4239 scroll_delta = gfx::Vector2d(0, 70);
4240 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4241 host_impl_->ScrollBegin(gfx::Point(5, 5),
4242 InputHandler::NON_BUBBLING_GESTURE));
4243 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4244 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4245 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4246 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4247 host_impl_->ScrollEnd();
4248 }
4249 }
4250
4251 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
4252 // When we try to scroll a non-scrollable child layer, the scroll delta
4253 // should be applied to one of its ancestors if possible. Overscroll should
4254 // be reflected only when it has bubbled up to the root scrolling layer.
4255 gfx::Size surface_size(10, 10);
4256 gfx::Size content_size(20, 20);
4257 scoped_ptr<LayerImpl> root_clip =
4258 LayerImpl::Create(host_impl_->active_tree(), 3);
4259 root_clip->SetHasRenderSurface(true);
4260
4261 scoped_ptr<LayerImpl> root =
4262 CreateScrollableLayer(1, content_size, root_clip.get());
4263 root->SetIsContainerForFixedPositionLayers(true);
4264 scoped_ptr<LayerImpl> child =
4265 CreateScrollableLayer(2, content_size, root_clip.get());
4266
4267 child->SetScrollClipLayer(Layer::INVALID_ID);
4268 root->AddChild(child.Pass());
4269 root_clip->AddChild(root.Pass());
4270
4271 host_impl_->SetViewportSize(surface_size);
4272 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4273 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4274 Layer::INVALID_ID);
4275 host_impl_->active_tree()->DidBecomeActive();
4276 DrawFrame();
4277 {
4278 gfx::Vector2d scroll_delta(0, 8);
4279 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4280 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4281 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4282 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4283 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4284 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
4285 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4286 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
4287 host_impl_->ScrollEnd();
4288 }
4289 }
4290
4291 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
4292 LayerTreeSettings settings;
4293 CreateHostImpl(settings, CreateOutputSurface());
4294
4295 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
4296 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4297 clip_layer->SetBounds(gfx::Size(50, 50));
4298 host_impl_->SetViewportSize(gfx::Size(50, 50));
4299 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4300 DrawFrame();
4301 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4302
4303 // Even though the layer can't scroll the overscroll still happens.
4304 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4305 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4306 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4307 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4308 }
4309
4310 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
4311 gfx::Size surface_size(980, 1439);
4312 gfx::Size content_size(980, 1438);
4313 float device_scale_factor = 1.5f;
4314 scoped_ptr<LayerImpl> root_clip =
4315 LayerImpl::Create(host_impl_->active_tree(), 3);
4316 root_clip->SetHasRenderSurface(true);
4317
4318 scoped_ptr<LayerImpl> root =
4319 CreateScrollableLayer(1, content_size, root_clip.get());
4320 root->SetIsContainerForFixedPositionLayers(true);
4321 scoped_ptr<LayerImpl> child =
4322 CreateScrollableLayer(2, content_size, root_clip.get());
4323 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
4324 host_impl_->active_tree()->PushPageScaleFromMainThread(0.326531f, 0.326531f,
4325 5.f);
4326 host_impl_->SetPageScaleOnActiveTree(0.326531f);
4327 child->SetScrollClipLayer(Layer::INVALID_ID);
4328 root->AddChild(child.Pass());
4329 root_clip->AddChild(root.Pass());
4330
4331 host_impl_->SetViewportSize(surface_size);
4332 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4333 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4334 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4335 Layer::INVALID_ID);
4336 host_impl_->active_tree()->DidBecomeActive();
4337 DrawFrame();
4338 {
4339 // Horizontal & Vertical GlowEffect should not be applied when
4340 // content size is less then view port size. For Example Horizontal &
4341 // vertical GlowEffect should not be applied in about:blank page.
4342 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4343 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4344 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
4345 EXPECT_EQ(gfx::Vector2dF().ToString(),
4346 host_impl_->accumulated_root_overscroll().ToString());
4347
4348 host_impl_->ScrollEnd();
4349 }
4350 }
4351
4352 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
4353 gfx::Size surface_size(100, 100);
4354 gfx::Size content_size(200, 200);
4355 scoped_ptr<LayerImpl> root_clip =
4356 LayerImpl::Create(host_impl_->active_tree(), 3);
4357 root_clip->SetHasRenderSurface(true);
4358
4359 scoped_ptr<LayerImpl> root =
4360 CreateScrollableLayer(1, content_size, root_clip.get());
4361 root->SetIsContainerForFixedPositionLayers(true);
4362 scoped_ptr<LayerImpl> child =
4363 CreateScrollableLayer(2, content_size, root_clip.get());
4364
4365 child->SetScrollClipLayer(Layer::INVALID_ID);
4366 root->AddChild(child.Pass());
4367 root_clip->AddChild(root.Pass());
4368
4369 host_impl_->SetViewportSize(surface_size);
4370 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4371 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4372 Layer::INVALID_ID);
4373 host_impl_->active_tree()->DidBecomeActive();
4374 DrawFrame();
4375 {
4376 // Edge glow effect should be applicable only upon reaching Edges
4377 // of the content. unnecessary glow effect calls shouldn't be
4378 // called while scrolling up without reaching the edge of the content.
4379 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4380 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4381 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4382 EXPECT_EQ(gfx::Vector2dF().ToString(),
4383 host_impl_->accumulated_root_overscroll().ToString());
4384 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
4385 EXPECT_EQ(gfx::Vector2dF().ToString(),
4386 host_impl_->accumulated_root_overscroll().ToString());
4387 host_impl_->ScrollEnd();
4388 // unusedrootDelta should be subtracted from applied delta so that
4389 // unwanted glow effect calls are not called.
4390 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4391 host_impl_->ScrollBegin(gfx::Point(0, 0),
4392 InputHandler::NON_BUBBLING_GESTURE));
4393 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
4394 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4395 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4396 host_impl_->accumulated_root_overscroll().ToString());
4397
4398 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
4399 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4400 host_impl_->accumulated_root_overscroll().ToString());
4401 host_impl_->ScrollEnd();
4402 // TestCase to check kEpsilon, which prevents minute values to trigger
4403 // gloweffect without reaching edge.
4404 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4405 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4406 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
4407 EXPECT_EQ(gfx::Vector2dF().ToString(),
4408 host_impl_->accumulated_root_overscroll().ToString());
4409 host_impl_->ScrollEnd();
4410 }
4411 }
4412
4413 class BlendStateCheckLayer : public LayerImpl {
4414 public:
4415 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
4416 int id,
4417 ResourceProvider* resource_provider) {
4418 return make_scoped_ptr(
4419 new BlendStateCheckLayer(tree_impl, id, resource_provider));
4420 }
4421
4422 void AppendQuads(RenderPass* render_pass,
4423 AppendQuadsData* append_quads_data) override {
4424 quads_appended_ = true;
4425
4426 gfx::Rect opaque_rect;
4427 if (contents_opaque())
4428 opaque_rect = quad_rect_;
4429 else
4430 opaque_rect = opaque_content_rect_;
4431 gfx::Rect visible_quad_rect = quad_rect_;
4432
4433 SharedQuadState* shared_quad_state =
4434 render_pass->CreateAndAppendSharedQuadState();
4435 PopulateSharedQuadState(shared_quad_state);
4436
4437 TileDrawQuad* test_blending_draw_quad =
4438 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
4439 test_blending_draw_quad->SetNew(shared_quad_state,
4440 quad_rect_,
4441 opaque_rect,
4442 visible_quad_rect,
4443 resource_id_,
4444 gfx::RectF(0.f, 0.f, 1.f, 1.f),
4445 gfx::Size(1, 1),
4446 false,
4447 false);
4448 test_blending_draw_quad->visible_rect = quad_visible_rect_;
4449 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
4450 EXPECT_EQ(has_render_surface_, !!render_surface());
4451 }
4452
4453 void SetExpectation(bool blend, bool has_render_surface) {
4454 blend_ = blend;
4455 has_render_surface_ = has_render_surface;
4456 quads_appended_ = false;
4457 }
4458
4459 bool quads_appended() const { return quads_appended_; }
4460
4461 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
4462 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
4463 void SetOpaqueContentRect(const gfx::Rect& rect) {
4464 opaque_content_rect_ = rect;
4465 }
4466
4467 private:
4468 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
4469 int id,
4470 ResourceProvider* resource_provider)
4471 : LayerImpl(tree_impl, id),
4472 blend_(false),
4473 has_render_surface_(false),
4474 quads_appended_(false),
4475 quad_rect_(5, 5, 5, 5),
4476 quad_visible_rect_(5, 5, 5, 5),
4477 resource_id_(resource_provider->CreateResource(
4478 gfx::Size(1, 1),
4479 GL_CLAMP_TO_EDGE,
4480 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
4481 RGBA_8888)) {
4482 resource_provider->AllocateForTesting(resource_id_);
4483 SetBounds(gfx::Size(10, 10));
4484 SetContentBounds(gfx::Size(10, 10));
4485 SetDrawsContent(true);
4486 }
4487
4488 bool blend_;
4489 bool has_render_surface_;
4490 bool quads_appended_;
4491 gfx::Rect quad_rect_;
4492 gfx::Rect opaque_content_rect_;
4493 gfx::Rect quad_visible_rect_;
4494 ResourceProvider::ResourceId resource_id_;
4495 };
4496
4497 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
4498 {
4499 scoped_ptr<LayerImpl> root =
4500 LayerImpl::Create(host_impl_->active_tree(), 1);
4501 root->SetBounds(gfx::Size(10, 10));
4502 root->SetContentBounds(root->bounds());
4503 root->SetDrawsContent(false);
4504 root->SetHasRenderSurface(true);
4505 host_impl_->active_tree()->SetRootLayer(root.Pass());
4506 }
4507 LayerImpl* root = host_impl_->active_tree()->root_layer();
4508
4509 root->AddChild(
4510 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4511 2,
4512 host_impl_->resource_provider()));
4513 BlendStateCheckLayer* layer1 =
4514 static_cast<BlendStateCheckLayer*>(root->children()[0]);
4515 layer1->SetPosition(gfx::PointF(2.f, 2.f));
4516
4517 LayerTreeHostImpl::FrameData frame;
4518
4519 // Opaque layer, drawn without blending.
4520 layer1->SetContentsOpaque(true);
4521 layer1->SetExpectation(false, false);
4522 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4523 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4524 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4525 EXPECT_TRUE(layer1->quads_appended());
4526 host_impl_->DidDrawAllLayers(frame);
4527
4528 // Layer with translucent content and painting, so drawn with blending.
4529 layer1->SetContentsOpaque(false);
4530 layer1->SetExpectation(true, false);
4531 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4532 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4533 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4534 EXPECT_TRUE(layer1->quads_appended());
4535 host_impl_->DidDrawAllLayers(frame);
4536
4537 // Layer with translucent opacity, drawn with blending.
4538 layer1->SetContentsOpaque(true);
4539 layer1->SetOpacity(0.5f);
4540 layer1->SetExpectation(true, false);
4541 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4542 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4543 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4544 EXPECT_TRUE(layer1->quads_appended());
4545 host_impl_->DidDrawAllLayers(frame);
4546
4547 // Layer with translucent opacity and painting, drawn with blending.
4548 layer1->SetContentsOpaque(true);
4549 layer1->SetOpacity(0.5f);
4550 layer1->SetExpectation(true, false);
4551 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4552 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4553 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4554 EXPECT_TRUE(layer1->quads_appended());
4555 host_impl_->DidDrawAllLayers(frame);
4556
4557 layer1->AddChild(
4558 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4559 3,
4560 host_impl_->resource_provider()));
4561 BlendStateCheckLayer* layer2 =
4562 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
4563 layer2->SetPosition(gfx::PointF(4.f, 4.f));
4564
4565 // 2 opaque layers, drawn without blending.
4566 layer1->SetContentsOpaque(true);
4567 layer1->SetOpacity(1.f);
4568 layer1->SetExpectation(false, false);
4569 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4570 layer2->SetContentsOpaque(true);
4571 layer2->SetOpacity(1.f);
4572 layer2->SetExpectation(false, false);
4573 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4574 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4575 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4576 EXPECT_TRUE(layer1->quads_appended());
4577 EXPECT_TRUE(layer2->quads_appended());
4578 host_impl_->DidDrawAllLayers(frame);
4579
4580 // Parent layer with translucent content, drawn with blending.
4581 // Child layer with opaque content, drawn without blending.
4582 layer1->SetContentsOpaque(false);
4583 layer1->SetExpectation(true, false);
4584 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4585 layer2->SetExpectation(false, false);
4586 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4587 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4588 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4589 EXPECT_TRUE(layer1->quads_appended());
4590 EXPECT_TRUE(layer2->quads_appended());
4591 host_impl_->DidDrawAllLayers(frame);
4592
4593 // Parent layer with translucent content but opaque painting, drawn without
4594 // blending.
4595 // Child layer with opaque content, drawn without blending.
4596 layer1->SetContentsOpaque(true);
4597 layer1->SetExpectation(false, false);
4598 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4599 layer2->SetExpectation(false, false);
4600 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4601 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4602 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4603 EXPECT_TRUE(layer1->quads_appended());
4604 EXPECT_TRUE(layer2->quads_appended());
4605 host_impl_->DidDrawAllLayers(frame);
4606
4607 // Parent layer with translucent opacity and opaque content. Since it has a
4608 // drawing child, it's drawn to a render surface which carries the opacity,
4609 // so it's itself drawn without blending.
4610 // Child layer with opaque content, drawn without blending (parent surface
4611 // carries the inherited opacity).
4612 layer1->SetContentsOpaque(true);
4613 layer1->SetOpacity(0.5f);
4614 layer1->SetHasRenderSurface(true);
4615 layer1->SetExpectation(false, true);
4616 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4617 layer2->SetExpectation(false, false);
4618 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4619 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
4620 host_impl_->active_tree()->root_layer());
4621 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4622 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4623 EXPECT_TRUE(layer1->quads_appended());
4624 EXPECT_TRUE(layer2->quads_appended());
4625 host_impl_->DidDrawAllLayers(frame);
4626 layer1->SetHasRenderSurface(false);
4627
4628 // Draw again, but with child non-opaque, to make sure
4629 // layer1 not culled.
4630 layer1->SetContentsOpaque(true);
4631 layer1->SetOpacity(1.f);
4632 layer1->SetExpectation(false, false);
4633 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4634 layer2->SetContentsOpaque(true);
4635 layer2->SetOpacity(0.5f);
4636 layer2->SetExpectation(true, false);
4637 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4638 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4639 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4640 EXPECT_TRUE(layer1->quads_appended());
4641 EXPECT_TRUE(layer2->quads_appended());
4642 host_impl_->DidDrawAllLayers(frame);
4643
4644 // A second way of making the child non-opaque.
4645 layer1->SetContentsOpaque(true);
4646 layer1->SetOpacity(1.f);
4647 layer1->SetExpectation(false, false);
4648 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4649 layer2->SetContentsOpaque(false);
4650 layer2->SetOpacity(1.f);
4651 layer2->SetExpectation(true, false);
4652 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4653 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4654 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4655 EXPECT_TRUE(layer1->quads_appended());
4656 EXPECT_TRUE(layer2->quads_appended());
4657 host_impl_->DidDrawAllLayers(frame);
4658
4659 // And when the layer says its not opaque but is painted opaque, it is not
4660 // blended.
4661 layer1->SetContentsOpaque(true);
4662 layer1->SetOpacity(1.f);
4663 layer1->SetExpectation(false, false);
4664 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4665 layer2->SetContentsOpaque(true);
4666 layer2->SetOpacity(1.f);
4667 layer2->SetExpectation(false, false);
4668 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4669 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4670 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4671 EXPECT_TRUE(layer1->quads_appended());
4672 EXPECT_TRUE(layer2->quads_appended());
4673 host_impl_->DidDrawAllLayers(frame);
4674
4675 // Layer with partially opaque contents, drawn with blending.
4676 layer1->SetContentsOpaque(false);
4677 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4678 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
4679 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4680 layer1->SetExpectation(true, false);
4681 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4682 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4683 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4684 EXPECT_TRUE(layer1->quads_appended());
4685 host_impl_->DidDrawAllLayers(frame);
4686
4687 // Layer with partially opaque contents partially culled, drawn with blending.
4688 layer1->SetContentsOpaque(false);
4689 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4690 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
4691 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4692 layer1->SetExpectation(true, false);
4693 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4694 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4695 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4696 EXPECT_TRUE(layer1->quads_appended());
4697 host_impl_->DidDrawAllLayers(frame);
4698
4699 // Layer with partially opaque contents culled, drawn with blending.
4700 layer1->SetContentsOpaque(false);
4701 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4702 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
4703 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4704 layer1->SetExpectation(true, false);
4705 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4706 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4707 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4708 EXPECT_TRUE(layer1->quads_appended());
4709 host_impl_->DidDrawAllLayers(frame);
4710
4711 // Layer with partially opaque contents and translucent contents culled, drawn
4712 // without blending.
4713 layer1->SetContentsOpaque(false);
4714 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4715 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
4716 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4717 layer1->SetExpectation(false, false);
4718 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4719 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4720 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4721 EXPECT_TRUE(layer1->quads_appended());
4722 host_impl_->DidDrawAllLayers(frame);
4723 }
4724
4725 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
4726 protected:
4727 LayerTreeHostImplViewportCoveredTest() :
4728 gutter_quad_material_(DrawQuad::SOLID_COLOR),
4729 child_(NULL),
4730 did_activate_pending_tree_(false) {}
4731
4732 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
4733 if (always_draw) {
4734 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
4735 }
4736 return FakeOutputSurface::Create3d();
4737 }
4738
4739 void SetupActiveTreeLayers() {
4740 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
4741 host_impl_->active_tree()->SetRootLayer(
4742 LayerImpl::Create(host_impl_->active_tree(), 1));
4743 host_impl_->active_tree()->root_layer()->SetHasRenderSurface(true);
4744 host_impl_->active_tree()->root_layer()->AddChild(
4745 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4746 2,
4747 host_impl_->resource_provider()));
4748 child_ = static_cast<BlendStateCheckLayer*>(
4749 host_impl_->active_tree()->root_layer()->children()[0]);
4750 child_->SetExpectation(false, false);
4751 child_->SetContentsOpaque(true);
4752 }
4753
4754 // Expect no gutter rects.
4755 void TestLayerCoversFullViewport() {
4756 gfx::Rect layer_rect(viewport_size_);
4757 child_->SetPosition(layer_rect.origin());
4758 child_->SetBounds(layer_rect.size());
4759 child_->SetContentBounds(layer_rect.size());
4760 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4761 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4762
4763 LayerTreeHostImpl::FrameData frame;
4764 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4765 ASSERT_EQ(1u, frame.render_passes.size());
4766
4767 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
4768 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4769 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4770
4771 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4772 host_impl_->DidDrawAllLayers(frame);
4773 }
4774
4775 // Expect fullscreen gutter rect.
4776 void TestEmptyLayer() {
4777 gfx::Rect layer_rect(0, 0, 0, 0);
4778 child_->SetPosition(layer_rect.origin());
4779 child_->SetBounds(layer_rect.size());
4780 child_->SetContentBounds(layer_rect.size());
4781 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4782 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4783
4784 LayerTreeHostImpl::FrameData frame;
4785 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4786 ASSERT_EQ(1u, frame.render_passes.size());
4787
4788 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
4789 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4790 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4791
4792 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4793 host_impl_->DidDrawAllLayers(frame);
4794 }
4795
4796 // Expect four surrounding gutter rects.
4797 void TestLayerInMiddleOfViewport() {
4798 gfx::Rect layer_rect(500, 500, 200, 200);
4799 child_->SetPosition(layer_rect.origin());
4800 child_->SetBounds(layer_rect.size());
4801 child_->SetContentBounds(layer_rect.size());
4802 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4803 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4804
4805 LayerTreeHostImpl::FrameData frame;
4806 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4807 ASSERT_EQ(1u, frame.render_passes.size());
4808
4809 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
4810 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
4811 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4812
4813 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4814 host_impl_->DidDrawAllLayers(frame);
4815 }
4816
4817 // Expect no gutter rects.
4818 void TestLayerIsLargerThanViewport() {
4819 gfx::Rect layer_rect(viewport_size_.width() + 10,
4820 viewport_size_.height() + 10);
4821 child_->SetPosition(layer_rect.origin());
4822 child_->SetBounds(layer_rect.size());
4823 child_->SetContentBounds(layer_rect.size());
4824 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4825 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4826
4827 LayerTreeHostImpl::FrameData frame;
4828 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4829 ASSERT_EQ(1u, frame.render_passes.size());
4830
4831 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
4832 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4833 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4834
4835 host_impl_->DidDrawAllLayers(frame);
4836 }
4837
4838 void DidActivateSyncTree() override { did_activate_pending_tree_ = true; }
4839
4840 void set_gutter_quad_material(DrawQuad::Material material) {
4841 gutter_quad_material_ = material;
4842 }
4843 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
4844 gutter_texture_size_ = gutter_texture_size;
4845 }
4846
4847 protected:
4848 size_t CountGutterQuads(const QuadList& quad_list) {
4849 size_t num_gutter_quads = 0;
4850 for (const auto& quad : quad_list) {
4851 num_gutter_quads += (quad->material == gutter_quad_material_) ? 1 : 0;
4852 }
4853 return num_gutter_quads;
4854 }
4855
4856 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
4857 LayerTestCommon::VerifyQuadsExactlyCoverRect(
4858 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
4859 }
4860
4861 // Make sure that the texture coordinates match their expectations.
4862 void ValidateTextureDrawQuads(const QuadList& quad_list) {
4863 for (const auto& quad : quad_list) {
4864 if (quad->material != DrawQuad::TEXTURE_CONTENT)
4865 continue;
4866 const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
4867 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
4868 gutter_texture_size_, host_impl_->device_scale_factor());
4869 EXPECT_EQ(texture_quad->uv_top_left.x(),
4870 texture_quad->rect.x() / gutter_texture_size_pixels.width());
4871 EXPECT_EQ(texture_quad->uv_top_left.y(),
4872 texture_quad->rect.y() / gutter_texture_size_pixels.height());
4873 EXPECT_EQ(
4874 texture_quad->uv_bottom_right.x(),
4875 texture_quad->rect.right() / gutter_texture_size_pixels.width());
4876 EXPECT_EQ(
4877 texture_quad->uv_bottom_right.y(),
4878 texture_quad->rect.bottom() / gutter_texture_size_pixels.height());
4879 }
4880 }
4881
4882 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
4883 return gfx::ToRoundedSize(
4884 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
4885 }
4886
4887 DrawQuad::Material gutter_quad_material_;
4888 gfx::Size gutter_texture_size_;
4889 gfx::Size viewport_size_;
4890 BlendStateCheckLayer* child_;
4891 bool did_activate_pending_tree_;
4892 };
4893
4894 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
4895 viewport_size_ = gfx::Size(1000, 1000);
4896
4897 bool always_draw = false;
4898 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4899
4900 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4901 SetupActiveTreeLayers();
4902 TestLayerCoversFullViewport();
4903 TestEmptyLayer();
4904 TestLayerInMiddleOfViewport();
4905 TestLayerIsLargerThanViewport();
4906 }
4907
4908 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
4909 viewport_size_ = gfx::Size(1000, 1000);
4910
4911 bool always_draw = false;
4912 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4913
4914 host_impl_->SetDeviceScaleFactor(2.f);
4915 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4916 SetupActiveTreeLayers();
4917 TestLayerCoversFullViewport();
4918 TestEmptyLayer();
4919 TestLayerInMiddleOfViewport();
4920 TestLayerIsLargerThanViewport();
4921 }
4922
4923 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
4924 viewport_size_ = gfx::Size(1000, 1000);
4925
4926 bool always_draw = true;
4927 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4928
4929 // Pending tree to force active_tree size invalid. Not used otherwise.
4930 host_impl_->CreatePendingTree();
4931 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4932 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4933
4934 SetupActiveTreeLayers();
4935 TestEmptyLayer();
4936 TestLayerInMiddleOfViewport();
4937 TestLayerIsLargerThanViewport();
4938 }
4939
4940 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
4941 viewport_size_ = gfx::Size(1000, 1000);
4942
4943 bool always_draw = true;
4944 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4945
4946 // Set larger viewport and activate it to active tree.
4947 host_impl_->CreatePendingTree();
4948 gfx::Size larger_viewport(viewport_size_.width() + 100,
4949 viewport_size_.height() + 100);
4950 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
4951 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4952 host_impl_->ActivateSyncTree();
4953 EXPECT_TRUE(did_activate_pending_tree_);
4954 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
4955
4956 // Shrink pending tree viewport without activating.
4957 host_impl_->CreatePendingTree();
4958 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4959 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4960
4961 SetupActiveTreeLayers();
4962 TestEmptyLayer();
4963 TestLayerInMiddleOfViewport();
4964 TestLayerIsLargerThanViewport();
4965 }
4966
4967 class FakeDrawableLayerImpl: public LayerImpl {
4968 public:
4969 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4970 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl, id));
4971 }
4972 protected:
4973 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
4974 : LayerImpl(tree_impl, id) {}
4975 };
4976
4977 // Only reshape when we know we are going to draw. Otherwise, the reshape
4978 // can leave the window at the wrong size if we never draw and the proper
4979 // viewport size is never set.
4980 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
4981 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4982 scoped_ptr<OutputSurface> output_surface(
4983 FakeOutputSurface::Create3d(provider));
4984 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4985
4986 scoped_ptr<LayerImpl> root =
4987 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4988 root->SetBounds(gfx::Size(10, 10));
4989 root->SetContentBounds(gfx::Size(10, 10));
4990 root->SetDrawsContent(true);
4991 root->SetHasRenderSurface(true);
4992 host_impl_->active_tree()->SetRootLayer(root.Pass());
4993 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
4994 provider->TestContext3d()->clear_reshape_called();
4995
4996 LayerTreeHostImpl::FrameData frame;
4997 host_impl_->SetViewportSize(gfx::Size(10, 10));
4998 host_impl_->SetDeviceScaleFactor(1.f);
4999 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5000 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5001 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5002 EXPECT_EQ(provider->TestContext3d()->width(), 10);
5003 EXPECT_EQ(provider->TestContext3d()->height(), 10);
5004 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5005 host_impl_->DidDrawAllLayers(frame);
5006 provider->TestContext3d()->clear_reshape_called();
5007
5008 host_impl_->SetViewportSize(gfx::Size(20, 30));
5009 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5010 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5011 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5012 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5013 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5014 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5015 host_impl_->DidDrawAllLayers(frame);
5016 provider->TestContext3d()->clear_reshape_called();
5017
5018 host_impl_->SetDeviceScaleFactor(2.f);
5019 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5020 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5021 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5022 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5023 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5024 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
5025 host_impl_->DidDrawAllLayers(frame);
5026 provider->TestContext3d()->clear_reshape_called();
5027 }
5028
5029 // Make sure damage tracking propagates all the way to the graphics context,
5030 // where it should request to swap only the sub-buffer that is damaged.
5031 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
5032 scoped_refptr<TestContextProvider> context_provider(
5033 TestContextProvider::Create());
5034 context_provider->BindToCurrentThread();
5035 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
5036
5037 scoped_ptr<FakeOutputSurface> output_surface(
5038 FakeOutputSurface::Create3d(context_provider));
5039 FakeOutputSurface* fake_output_surface = output_surface.get();
5040
5041 // This test creates its own LayerTreeHostImpl, so
5042 // that we can force partial swap enabled.
5043 LayerTreeSettings settings;
5044 settings.renderer_settings.partial_swap_enabled = true;
5045 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
5046 LayerTreeHostImpl::Create(
5047 settings, this, &proxy_, &stats_instrumentation_,
5048 shared_bitmap_manager_.get(), NULL, task_graph_runner_.get(), 0);
5049 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
5050 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
5051
5052 scoped_ptr<LayerImpl> root =
5053 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
5054 root->SetHasRenderSurface(true);
5055 scoped_ptr<LayerImpl> child =
5056 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
5057 child->SetPosition(gfx::PointF(12.f, 13.f));
5058 child->SetBounds(gfx::Size(14, 15));
5059 child->SetContentBounds(gfx::Size(14, 15));
5060 child->SetDrawsContent(true);
5061 root->SetBounds(gfx::Size(500, 500));
5062 root->SetContentBounds(gfx::Size(500, 500));
5063 root->SetDrawsContent(true);
5064 root->AddChild(child.Pass());
5065 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
5066
5067 LayerTreeHostImpl::FrameData frame;
5068
5069 // First frame, the entire screen should get swapped.
5070 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5071 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5072 layer_tree_host_impl->DidDrawAllLayers(frame);
5073 layer_tree_host_impl->SwapBuffers(frame);
5074 gfx::Rect expected_swap_rect(0, 0, 500, 500);
5075 EXPECT_EQ(expected_swap_rect.ToString(),
5076 fake_output_surface->last_swap_rect().ToString());
5077
5078 // Second frame, only the damaged area should get swapped. Damage should be
5079 // the union of old and new child rects.
5080 // expected damage rect: gfx::Rect(26, 28);
5081 // expected swap rect: vertically flipped, with origin at bottom left corner.
5082 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
5083 gfx::PointF());
5084 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5085 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5086 host_impl_->DidDrawAllLayers(frame);
5087 layer_tree_host_impl->SwapBuffers(frame);
5088
5089 // Make sure that partial swap is constrained to the viewport dimensions
5090 // expected damage rect: gfx::Rect(500, 500);
5091 // expected swap rect: flipped damage rect, but also clamped to viewport
5092 expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
5093 EXPECT_EQ(expected_swap_rect.ToString(),
5094 fake_output_surface->last_swap_rect().ToString());
5095
5096 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
5097 // This will damage everything.
5098 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
5099 SK_ColorBLACK);
5100 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5101 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5102 host_impl_->DidDrawAllLayers(frame);
5103 layer_tree_host_impl->SwapBuffers(frame);
5104
5105 expected_swap_rect = gfx::Rect(0, 0, 10, 10);
5106 EXPECT_EQ(expected_swap_rect.ToString(),
5107 fake_output_surface->last_swap_rect().ToString());
5108 }
5109
5110 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
5111 scoped_ptr<LayerImpl> root =
5112 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5113 scoped_ptr<LayerImpl> child =
5114 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
5115 child->SetBounds(gfx::Size(10, 10));
5116 child->SetContentBounds(gfx::Size(10, 10));
5117 child->SetDrawsContent(true);
5118 root->SetBounds(gfx::Size(10, 10));
5119 root->SetContentBounds(gfx::Size(10, 10));
5120 root->SetDrawsContent(true);
5121 root->SetHasRenderSurface(true);
5122 root->AddChild(child.Pass());
5123
5124 host_impl_->active_tree()->SetRootLayer(root.Pass());
5125
5126 LayerTreeHostImpl::FrameData frame;
5127
5128 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5129 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
5130 EXPECT_EQ(1u, frame.render_passes.size());
5131 host_impl_->DidDrawAllLayers(frame);
5132 }
5133
5134 class FakeLayerWithQuads : public LayerImpl {
5135 public:
5136 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5137 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl, id));
5138 }
5139
5140 void AppendQuads(RenderPass* render_pass,
5141 AppendQuadsData* append_quads_data) override {
5142 SharedQuadState* shared_quad_state =
5143 render_pass->CreateAndAppendSharedQuadState();
5144 PopulateSharedQuadState(shared_quad_state);
5145
5146 SkColor gray = SkColorSetRGB(100, 100, 100);
5147 gfx::Rect quad_rect(content_bounds());
5148 gfx::Rect visible_quad_rect(quad_rect);
5149 SolidColorDrawQuad* my_quad =
5150 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
5151 my_quad->SetNew(
5152 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
5153 }
5154
5155 private:
5156 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
5157 : LayerImpl(tree_impl, id) {}
5158 };
5159
5160 class MockContext : public TestWebGraphicsContext3D {
5161 public:
5162 MOCK_METHOD1(useProgram, void(GLuint program));
5163 MOCK_METHOD5(uniform4f, void(GLint location,
5164 GLfloat x,
5165 GLfloat y,
5166 GLfloat z,
5167 GLfloat w));
5168 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
5169 GLsizei count,
5170 GLboolean transpose,
5171 const GLfloat* value));
5172 MOCK_METHOD4(drawElements, void(GLenum mode,
5173 GLsizei count,
5174 GLenum type,
5175 GLintptr offset));
5176 MOCK_METHOD1(enable, void(GLenum cap));
5177 MOCK_METHOD1(disable, void(GLenum cap));
5178 MOCK_METHOD4(scissor, void(GLint x,
5179 GLint y,
5180 GLsizei width,
5181 GLsizei height));
5182 };
5183
5184 class MockContextHarness {
5185 private:
5186 MockContext* context_;
5187
5188 public:
5189 explicit MockContextHarness(MockContext* context)
5190 : context_(context) {
5191 context_->set_have_post_sub_buffer(true);
5192
5193 // Catch "uninteresting" calls
5194 EXPECT_CALL(*context_, useProgram(_))
5195 .Times(0);
5196
5197 EXPECT_CALL(*context_, drawElements(_, _, _, _))
5198 .Times(0);
5199
5200 // These are not asserted
5201 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
5202 .WillRepeatedly(Return());
5203
5204 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
5205 .WillRepeatedly(Return());
5206
5207 // Any un-sanctioned calls to enable() are OK
5208 EXPECT_CALL(*context_, enable(_))
5209 .WillRepeatedly(Return());
5210
5211 // Any un-sanctioned calls to disable() are OK
5212 EXPECT_CALL(*context_, disable(_))
5213 .WillRepeatedly(Return());
5214 }
5215
5216 void MustDrawSolidQuad() {
5217 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
5218 .WillOnce(Return())
5219 .RetiresOnSaturation();
5220
5221 EXPECT_CALL(*context_, useProgram(_))
5222 .WillOnce(Return())
5223 .RetiresOnSaturation();
5224 }
5225
5226 void MustSetScissor(int x, int y, int width, int height) {
5227 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5228 .WillRepeatedly(Return());
5229
5230 EXPECT_CALL(*context_, scissor(x, y, width, height))
5231 .Times(AtLeast(1))
5232 .WillRepeatedly(Return());
5233 }
5234
5235 void MustSetNoScissor() {
5236 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
5237 .WillRepeatedly(Return());
5238
5239 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5240 .Times(0);
5241
5242 EXPECT_CALL(*context_, scissor(_, _, _, _))
5243 .Times(0);
5244 }
5245 };
5246
5247 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
5248 scoped_ptr<MockContext> mock_context_owned(new MockContext);
5249 MockContext* mock_context = mock_context_owned.get();
5250 MockContextHarness harness(mock_context);
5251
5252 // Run test case
5253 LayerTreeSettings settings = DefaultSettings();
5254 settings.renderer_settings.partial_swap_enabled = false;
5255 CreateHostImpl(settings,
5256 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5257 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5258
5259 // Without partial swap, and no clipping, no scissor is set.
5260 harness.MustDrawSolidQuad();
5261 harness.MustSetNoScissor();
5262 {
5263 LayerTreeHostImpl::FrameData frame;
5264 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5265 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5266 host_impl_->DidDrawAllLayers(frame);
5267 }
5268 Mock::VerifyAndClearExpectations(&mock_context);
5269
5270 // Without partial swap, but a layer does clip its subtree, one scissor is
5271 // set.
5272 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
5273 harness.MustDrawSolidQuad();
5274 harness.MustSetScissor(0, 0, 10, 10);
5275 {
5276 LayerTreeHostImpl::FrameData frame;
5277 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5278 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5279 host_impl_->DidDrawAllLayers(frame);
5280 }
5281 Mock::VerifyAndClearExpectations(&mock_context);
5282 }
5283
5284 TEST_F(LayerTreeHostImplTest, PartialSwap) {
5285 scoped_ptr<MockContext> context_owned(new MockContext);
5286 MockContext* mock_context = context_owned.get();
5287 MockContextHarness harness(mock_context);
5288
5289 LayerTreeSettings settings = DefaultSettings();
5290 settings.renderer_settings.partial_swap_enabled = true;
5291 CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass()));
5292 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5293
5294 // The first frame is not a partially-swapped one. No scissor should be set.
5295 harness.MustSetNoScissor();
5296 harness.MustDrawSolidQuad();
5297 {
5298 LayerTreeHostImpl::FrameData frame;
5299 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5300 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5301 host_impl_->DidDrawAllLayers(frame);
5302 }
5303 Mock::VerifyAndClearExpectations(&mock_context);
5304
5305 // Damage a portion of the frame.
5306 host_impl_->active_tree()->root_layer()->SetUpdateRect(
5307 gfx::Rect(0, 0, 2, 3));
5308
5309 // The second frame will be partially-swapped (the y coordinates are flipped).
5310 harness.MustSetScissor(0, 7, 2, 3);
5311 harness.MustDrawSolidQuad();
5312 {
5313 LayerTreeHostImpl::FrameData frame;
5314 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5315 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5316 host_impl_->DidDrawAllLayers(frame);
5317 }
5318 Mock::VerifyAndClearExpectations(&mock_context);
5319 }
5320
5321 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
5322 bool partial_swap,
5323 LayerTreeHostImplClient* client,
5324 Proxy* proxy,
5325 SharedBitmapManager* manager,
5326 RenderingStatsInstrumentation* stats_instrumentation) {
5327 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5328 scoped_ptr<OutputSurface> output_surface(
5329 FakeOutputSurface::Create3d(provider));
5330 provider->BindToCurrentThread();
5331 provider->TestContext3d()->set_have_post_sub_buffer(true);
5332
5333 LayerTreeSettings settings;
5334 settings.renderer_settings.partial_swap_enabled = partial_swap;
5335 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
5336 settings, client, proxy, stats_instrumentation, manager, NULL, NULL, 0);
5337 my_host_impl->InitializeRenderer(output_surface.Pass());
5338 my_host_impl->SetViewportSize(gfx::Size(100, 100));
5339
5340 /*
5341 Layers are created as follows:
5342
5343 +--------------------+
5344 | 1 |
5345 | +-----------+ |
5346 | | 2 | |
5347 | | +-------------------+
5348 | | | 3 |
5349 | | +-------------------+
5350 | | | |
5351 | +-----------+ |
5352 | |
5353 | |
5354 +--------------------+
5355
5356 Layers 1, 2 have render surfaces
5357 */
5358 scoped_ptr<LayerImpl> root =
5359 LayerImpl::Create(my_host_impl->active_tree(), 1);
5360 scoped_ptr<LayerImpl> child =
5361 LayerImpl::Create(my_host_impl->active_tree(), 2);
5362 scoped_ptr<LayerImpl> grand_child =
5363 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
5364
5365 gfx::Rect root_rect(0, 0, 100, 100);
5366 gfx::Rect child_rect(10, 10, 50, 50);
5367 gfx::Rect grand_child_rect(5, 5, 150, 150);
5368
5369 root->SetHasRenderSurface(true);
5370 root->SetPosition(root_rect.origin());
5371 root->SetBounds(root_rect.size());
5372 root->SetContentBounds(root->bounds());
5373 root->draw_properties().visible_content_rect = root_rect;
5374 root->SetDrawsContent(false);
5375 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
5376
5377 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
5378 child->SetOpacity(0.5f);
5379 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
5380 child->SetContentBounds(child->bounds());
5381 child->draw_properties().visible_content_rect = child_rect;
5382 child->SetDrawsContent(false);
5383 child->SetHasRenderSurface(true);
5384
5385 grand_child->SetPosition(grand_child_rect.origin());
5386 grand_child->SetBounds(grand_child_rect.size());
5387 grand_child->SetContentBounds(grand_child->bounds());
5388 grand_child->draw_properties().visible_content_rect = grand_child_rect;
5389 grand_child->SetDrawsContent(true);
5390
5391 child->AddChild(grand_child.Pass());
5392 root->AddChild(child.Pass());
5393
5394 my_host_impl->active_tree()->SetRootLayer(root.Pass());
5395 return my_host_impl.Pass();
5396 }
5397
5398 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
5399 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
5400 new TestSharedBitmapManager());
5401 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5402 SetupLayersForOpacity(true,
5403 this,
5404 &proxy_,
5405 shared_bitmap_manager.get(),
5406 &stats_instrumentation_);
5407 {
5408 LayerTreeHostImpl::FrameData frame;
5409 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5410
5411 // Verify all quads have been computed
5412 ASSERT_EQ(2U, frame.render_passes.size());
5413 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5414 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5415 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5416 frame.render_passes[0]->quad_list.front()->material);
5417 EXPECT_EQ(DrawQuad::RENDER_PASS,
5418 frame.render_passes[1]->quad_list.front()->material);
5419
5420 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5421 my_host_impl->DidDrawAllLayers(frame);
5422 }
5423 }
5424
5425 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
5426 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
5427 new TestSharedBitmapManager());
5428 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5429 SetupLayersForOpacity(false,
5430 this,
5431 &proxy_,
5432 shared_bitmap_manager.get(),
5433 &stats_instrumentation_);
5434 {
5435 LayerTreeHostImpl::FrameData frame;
5436 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5437
5438 // Verify all quads have been computed
5439 ASSERT_EQ(2U, frame.render_passes.size());
5440 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5441 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5442 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5443 frame.render_passes[0]->quad_list.front()->material);
5444 EXPECT_EQ(DrawQuad::RENDER_PASS,
5445 frame.render_passes[1]->quad_list.front()->material);
5446
5447 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5448 my_host_impl->DidDrawAllLayers(frame);
5449 }
5450 }
5451
5452 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
5453 scoped_ptr<TestWebGraphicsContext3D> context =
5454 TestWebGraphicsContext3D::Create();
5455 TestWebGraphicsContext3D* context3d = context.get();
5456 scoped_ptr<OutputSurface> output_surface(
5457 FakeOutputSurface::Create3d(context.Pass()));
5458 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5459
5460 scoped_ptr<LayerImpl> root_layer =
5461 LayerImpl::Create(host_impl_->active_tree(), 1);
5462 root_layer->SetBounds(gfx::Size(10, 10));
5463 root_layer->SetHasRenderSurface(true);
5464
5465 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
5466 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
5467 io_surface_layer->SetBounds(gfx::Size(10, 10));
5468 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
5469 io_surface_layer->SetDrawsContent(true);
5470 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5471 root_layer->AddChild(io_surface_layer.Pass());
5472
5473 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
5474
5475 EXPECT_EQ(0u, context3d->NumTextures());
5476
5477 LayerTreeHostImpl::FrameData frame;
5478 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5479 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5480 host_impl_->DidDrawAllLayers(frame);
5481 host_impl_->SwapBuffers(frame);
5482
5483 EXPECT_GT(context3d->NumTextures(), 0u);
5484
5485 // Kill the layer tree.
5486 host_impl_->active_tree()->SetRootLayer(
5487 LayerImpl::Create(host_impl_->active_tree(), 100));
5488 // There should be no textures left in use after.
5489 EXPECT_EQ(0u, context3d->NumTextures());
5490 }
5491
5492 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
5493 public:
5494 MOCK_METHOD1(useProgram, void(GLuint program));
5495 MOCK_METHOD4(drawElements, void(GLenum mode,
5496 GLsizei count,
5497 GLenum type,
5498 GLintptr offset));
5499 };
5500
5501 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
5502 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
5503 new MockDrawQuadsToFillScreenContext);
5504 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
5505
5506 // Run test case
5507 LayerTreeSettings settings = DefaultSettings();
5508 settings.renderer_settings.partial_swap_enabled = false;
5509 CreateHostImpl(settings,
5510 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5511 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5512 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
5513
5514 // Verify one quad is drawn when transparent background set is not set.
5515 host_impl_->active_tree()->set_has_transparent_background(false);
5516 EXPECT_CALL(*mock_context, useProgram(_))
5517 .Times(1);
5518 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
5519 .Times(1);
5520 LayerTreeHostImpl::FrameData frame;
5521 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5522 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5523 host_impl_->DidDrawAllLayers(frame);
5524 Mock::VerifyAndClearExpectations(&mock_context);
5525
5526 // Verify no quads are drawn when transparent background is set.
5527 host_impl_->active_tree()->set_has_transparent_background(true);
5528 host_impl_->SetFullRootLayerDamage();
5529 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5530 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5531 host_impl_->DidDrawAllLayers(frame);
5532 Mock::VerifyAndClearExpectations(&mock_context);
5533 }
5534
5535 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
5536 set_reduce_memory_result(false);
5537
5538 // If changing the memory limit wouldn't result in changing what was
5539 // committed, then no commit should be requested.
5540 set_reduce_memory_result(false);
5541 host_impl_->set_max_memory_needed_bytes(
5542 host_impl_->memory_allocation_limit_bytes() - 1);
5543 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5544 host_impl_->memory_allocation_limit_bytes() - 1));
5545 EXPECT_FALSE(did_request_commit_);
5546 did_request_commit_ = false;
5547
5548 // If changing the memory limit would result in changing what was
5549 // committed, then a commit should be requested, even though nothing was
5550 // evicted.
5551 set_reduce_memory_result(false);
5552 host_impl_->set_max_memory_needed_bytes(
5553 host_impl_->memory_allocation_limit_bytes());
5554 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5555 host_impl_->memory_allocation_limit_bytes() - 1));
5556 EXPECT_TRUE(did_request_commit_);
5557 did_request_commit_ = false;
5558
5559 // Especially if changing the memory limit caused evictions, we need
5560 // to re-commit.
5561 set_reduce_memory_result(true);
5562 host_impl_->set_max_memory_needed_bytes(1);
5563 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5564 host_impl_->memory_allocation_limit_bytes() - 1));
5565 EXPECT_TRUE(did_request_commit_);
5566 did_request_commit_ = false;
5567
5568 // But if we set it to the same value that it was before, we shouldn't
5569 // re-commit.
5570 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5571 host_impl_->memory_allocation_limit_bytes()));
5572 EXPECT_FALSE(did_request_commit_);
5573 }
5574
5575 class LayerTreeHostImplTestWithDelegatingRenderer
5576 : public LayerTreeHostImplTest {
5577 protected:
5578 scoped_ptr<OutputSurface> CreateOutputSurface() override {
5579 return FakeOutputSurface::CreateDelegating3d();
5580 }
5581
5582 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
5583 bool expect_to_draw = !expected_damage.IsEmpty();
5584
5585 LayerTreeHostImpl::FrameData frame;
5586 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5587
5588 if (!expect_to_draw) {
5589 // With no damage, we don't draw, and no quads are created.
5590 ASSERT_EQ(0u, frame.render_passes.size());
5591 } else {
5592 ASSERT_EQ(1u, frame.render_passes.size());
5593
5594 // Verify the damage rect for the root render pass.
5595 const RenderPass* root_render_pass = frame.render_passes.back();
5596 EXPECT_EQ(expected_damage, root_render_pass->damage_rect);
5597
5598 // Verify the root and child layers' quads are generated and not being
5599 // culled.
5600 ASSERT_EQ(2u, root_render_pass->quad_list.size());
5601
5602 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
5603 gfx::RectF expected_child_visible_rect(child->content_bounds());
5604 EXPECT_EQ(expected_child_visible_rect,
5605 root_render_pass->quad_list.front()->visible_rect);
5606
5607 LayerImpl* root = host_impl_->active_tree()->root_layer();
5608 gfx::RectF expected_root_visible_rect(root->content_bounds());
5609 EXPECT_EQ(expected_root_visible_rect,
5610 root_render_pass->quad_list.ElementAt(1)->visible_rect);
5611 }
5612
5613 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5614 host_impl_->DidDrawAllLayers(frame);
5615 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
5616 }
5617 };
5618
5619 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
5620 scoped_ptr<SolidColorLayerImpl> root =
5621 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5622 root->SetPosition(gfx::PointF());
5623 root->SetBounds(gfx::Size(10, 10));
5624 root->SetContentBounds(gfx::Size(10, 10));
5625 root->SetDrawsContent(true);
5626 root->SetHasRenderSurface(true);
5627
5628 // Child layer is in the bottom right corner.
5629 scoped_ptr<SolidColorLayerImpl> child =
5630 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
5631 child->SetPosition(gfx::PointF(9.f, 9.f));
5632 child->SetBounds(gfx::Size(1, 1));
5633 child->SetContentBounds(gfx::Size(1, 1));
5634 child->SetDrawsContent(true);
5635 root->AddChild(child.Pass());
5636
5637 host_impl_->active_tree()->SetRootLayer(root.Pass());
5638
5639 // Draw a frame. In the first frame, the entire viewport should be damaged.
5640 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
5641 DrawFrameAndTestDamage(full_frame_damage);
5642
5643 // The second frame has damage that doesn't touch the child layer. Its quads
5644 // should still be generated.
5645 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
5646 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
5647 DrawFrameAndTestDamage(small_damage);
5648
5649 // The third frame should have no damage, so no quads should be generated.
5650 gfx::Rect no_damage;
5651 DrawFrameAndTestDamage(no_damage);
5652 }
5653
5654 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5655 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5656 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
5657 LayerTreeSettings settings;
5658 CreateHostImpl(settings, CreateOutputSurface());
5659 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
5660 }
5661
5662 class FakeMaskLayerImpl : public LayerImpl {
5663 public:
5664 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
5665 int id) {
5666 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
5667 }
5668
5669 void GetContentsResourceId(ResourceProvider::ResourceId* resource_id,
5670 gfx::Size* resource_size) const override {
5671 *resource_id = 0;
5672 }
5673
5674 private:
5675 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
5676 : LayerImpl(tree_impl, id) {}
5677 };
5678
5679 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
5680 LayerTreeSettings settings;
5681 settings.layer_transforms_should_scale_layer_contents = true;
5682 CreateHostImpl(settings, CreateOutputSurface());
5683
5684 // Root
5685 // |
5686 // +-- Scaling Layer (adds a 2x scale)
5687 // |
5688 // +-- Content Layer
5689 // +--Mask
5690 scoped_ptr<LayerImpl> scoped_root =
5691 LayerImpl::Create(host_impl_->active_tree(), 1);
5692 LayerImpl* root = scoped_root.get();
5693 root->SetHasRenderSurface(true);
5694 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5695
5696 scoped_ptr<LayerImpl> scoped_scaling_layer =
5697 LayerImpl::Create(host_impl_->active_tree(), 2);
5698 LayerImpl* scaling_layer = scoped_scaling_layer.get();
5699 root->AddChild(scoped_scaling_layer.Pass());
5700
5701 scoped_ptr<LayerImpl> scoped_content_layer =
5702 LayerImpl::Create(host_impl_->active_tree(), 3);
5703 LayerImpl* content_layer = scoped_content_layer.get();
5704 scaling_layer->AddChild(scoped_content_layer.Pass());
5705
5706 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5707 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5708 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5709 content_layer->SetHasRenderSurface(true);
5710 content_layer->SetMaskLayer(scoped_mask_layer.Pass());
5711
5712 gfx::Size root_size(100, 100);
5713 root->SetBounds(root_size);
5714 root->SetContentBounds(root_size);
5715 root->SetPosition(gfx::PointF());
5716
5717 gfx::Size scaling_layer_size(50, 50);
5718 scaling_layer->SetBounds(scaling_layer_size);
5719 scaling_layer->SetContentBounds(scaling_layer_size);
5720 scaling_layer->SetPosition(gfx::PointF());
5721 gfx::Transform scale;
5722 scale.Scale(2.f, 2.f);
5723 scaling_layer->SetTransform(scale);
5724
5725 content_layer->SetBounds(scaling_layer_size);
5726 content_layer->SetContentBounds(scaling_layer_size);
5727 content_layer->SetPosition(gfx::PointF());
5728 content_layer->SetDrawsContent(true);
5729
5730 mask_layer->SetBounds(scaling_layer_size);
5731 mask_layer->SetContentBounds(scaling_layer_size);
5732 mask_layer->SetPosition(gfx::PointF());
5733 mask_layer->SetDrawsContent(true);
5734
5735
5736 // Check that the tree scaling is correctly taken into account for the mask,
5737 // that should fully map onto the quad.
5738 float device_scale_factor = 1.f;
5739 host_impl_->SetViewportSize(root_size);
5740 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5741 {
5742 LayerTreeHostImpl::FrameData frame;
5743 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5744
5745 ASSERT_EQ(1u, frame.render_passes.size());
5746 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5747 ASSERT_EQ(DrawQuad::RENDER_PASS,
5748 frame.render_passes[0]->quad_list.front()->material);
5749 const RenderPassDrawQuad* render_pass_quad =
5750 RenderPassDrawQuad::MaterialCast(
5751 frame.render_passes[0]->quad_list.front());
5752 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5753 render_pass_quad->rect.ToString());
5754 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5755 render_pass_quad->MaskUVRect().ToString());
5756 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5757 render_pass_quad->mask_uv_scale.ToString());
5758
5759 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5760 host_impl_->DidDrawAllLayers(frame);
5761 }
5762
5763
5764 // Applying a DSF should change the render surface size, but won't affect
5765 // which part of the mask is used.
5766 device_scale_factor = 2.f;
5767 gfx::Size device_viewport =
5768 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5769 host_impl_->SetViewportSize(device_viewport);
5770 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5771 host_impl_->active_tree()->set_needs_update_draw_properties();
5772 {
5773 LayerTreeHostImpl::FrameData frame;
5774 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5775
5776 ASSERT_EQ(1u, frame.render_passes.size());
5777 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5778 ASSERT_EQ(DrawQuad::RENDER_PASS,
5779 frame.render_passes[0]->quad_list.front()->material);
5780 const RenderPassDrawQuad* render_pass_quad =
5781 RenderPassDrawQuad::MaterialCast(
5782 frame.render_passes[0]->quad_list.front());
5783 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
5784 render_pass_quad->rect.ToString());
5785 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5786 render_pass_quad->MaskUVRect().ToString());
5787 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5788 render_pass_quad->mask_uv_scale.ToString());
5789
5790 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5791 host_impl_->DidDrawAllLayers(frame);
5792 }
5793
5794
5795 // Applying an equivalent content scale on the content layer and the mask
5796 // should still result in the same part of the mask being used.
5797 gfx::Size content_bounds =
5798 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
5799 device_scale_factor));
5800 content_layer->SetContentBounds(content_bounds);
5801 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5802 mask_layer->SetContentBounds(content_bounds);
5803 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5804 host_impl_->active_tree()->set_needs_update_draw_properties();
5805 {
5806 LayerTreeHostImpl::FrameData frame;
5807 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5808
5809 ASSERT_EQ(1u, frame.render_passes.size());
5810 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5811 ASSERT_EQ(DrawQuad::RENDER_PASS,
5812 frame.render_passes[0]->quad_list.front()->material);
5813 const RenderPassDrawQuad* render_pass_quad =
5814 RenderPassDrawQuad::MaterialCast(
5815 frame.render_passes[0]->quad_list.front());
5816 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
5817 render_pass_quad->rect.ToString());
5818 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5819 render_pass_quad->MaskUVRect().ToString());
5820 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5821 render_pass_quad->mask_uv_scale.ToString());
5822
5823 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5824 host_impl_->DidDrawAllLayers(frame);
5825 }
5826 }
5827
5828 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
5829 // The mask layer has bounds 100x100 but is attached to a layer with bounds
5830 // 50x50.
5831
5832 scoped_ptr<LayerImpl> scoped_root =
5833 LayerImpl::Create(host_impl_->active_tree(), 1);
5834 LayerImpl* root = scoped_root.get();
5835 root->SetHasRenderSurface(true);
5836
5837 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5838
5839 scoped_ptr<LayerImpl> scoped_content_layer =
5840 LayerImpl::Create(host_impl_->active_tree(), 3);
5841 LayerImpl* content_layer = scoped_content_layer.get();
5842 root->AddChild(scoped_content_layer.Pass());
5843
5844 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5845 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5846 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5847 content_layer->SetMaskLayer(scoped_mask_layer.Pass());
5848 content_layer->SetHasRenderSurface(true);
5849
5850 gfx::Size root_size(100, 100);
5851 root->SetBounds(root_size);
5852 root->SetContentBounds(root_size);
5853 root->SetPosition(gfx::PointF());
5854
5855 gfx::Size layer_size(50, 50);
5856 content_layer->SetBounds(layer_size);
5857 content_layer->SetContentBounds(layer_size);
5858 content_layer->SetPosition(gfx::PointF());
5859 content_layer->SetDrawsContent(true);
5860
5861 gfx::Size mask_size(100, 100);
5862 mask_layer->SetBounds(mask_size);
5863 mask_layer->SetContentBounds(mask_size);
5864 mask_layer->SetPosition(gfx::PointF());
5865 mask_layer->SetDrawsContent(true);
5866
5867 // Check that the mask fills the surface.
5868 float device_scale_factor = 1.f;
5869 host_impl_->SetViewportSize(root_size);
5870 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5871 {
5872 LayerTreeHostImpl::FrameData frame;
5873 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5874
5875 ASSERT_EQ(1u, frame.render_passes.size());
5876 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5877 ASSERT_EQ(DrawQuad::RENDER_PASS,
5878 frame.render_passes[0]->quad_list.front()->material);
5879 const RenderPassDrawQuad* render_pass_quad =
5880 RenderPassDrawQuad::MaterialCast(
5881 frame.render_passes[0]->quad_list.front());
5882 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5883 render_pass_quad->rect.ToString());
5884 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5885 render_pass_quad->MaskUVRect().ToString());
5886 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5887 render_pass_quad->mask_uv_scale.ToString());
5888
5889 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5890 host_impl_->DidDrawAllLayers(frame);
5891 }
5892
5893 // Applying a DSF should change the render surface size, but won't affect
5894 // which part of the mask is used.
5895 device_scale_factor = 2.f;
5896 gfx::Size device_viewport =
5897 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5898 host_impl_->SetViewportSize(device_viewport);
5899 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5900 host_impl_->active_tree()->set_needs_update_draw_properties();
5901 {
5902 LayerTreeHostImpl::FrameData frame;
5903 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5904
5905 ASSERT_EQ(1u, frame.render_passes.size());
5906 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5907 ASSERT_EQ(DrawQuad::RENDER_PASS,
5908 frame.render_passes[0]->quad_list.front()->material);
5909 const RenderPassDrawQuad* render_pass_quad =
5910 RenderPassDrawQuad::MaterialCast(
5911 frame.render_passes[0]->quad_list.front());
5912 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5913 render_pass_quad->rect.ToString());
5914 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5915 render_pass_quad->MaskUVRect().ToString());
5916 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5917 render_pass_quad->mask_uv_scale.ToString());
5918
5919 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5920 host_impl_->DidDrawAllLayers(frame);
5921 }
5922
5923 // Applying an equivalent content scale on the content layer and the mask
5924 // should still result in the same part of the mask being used.
5925 gfx::Size layer_size_large =
5926 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5927 content_layer->SetContentBounds(layer_size_large);
5928 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5929 gfx::Size mask_size_large =
5930 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5931 mask_layer->SetContentBounds(mask_size_large);
5932 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5933 host_impl_->active_tree()->set_needs_update_draw_properties();
5934 {
5935 LayerTreeHostImpl::FrameData frame;
5936 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5937
5938 ASSERT_EQ(1u, frame.render_passes.size());
5939 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5940 ASSERT_EQ(DrawQuad::RENDER_PASS,
5941 frame.render_passes[0]->quad_list.front()->material);
5942 const RenderPassDrawQuad* render_pass_quad =
5943 RenderPassDrawQuad::MaterialCast(
5944 frame.render_passes[0]->quad_list.front());
5945 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5946 render_pass_quad->rect.ToString());
5947 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5948 render_pass_quad->MaskUVRect().ToString());
5949 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5950 render_pass_quad->mask_uv_scale.ToString());
5951
5952 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5953 host_impl_->DidDrawAllLayers(frame);
5954 }
5955
5956 // Applying a different contents scale to the mask layer means it will have
5957 // a larger texture, but it should use the same tex coords to cover the
5958 // layer it masks.
5959 mask_layer->SetContentBounds(mask_size);
5960 mask_layer->SetContentsScale(1.f, 1.f);
5961 host_impl_->active_tree()->set_needs_update_draw_properties();
5962 {
5963 LayerTreeHostImpl::FrameData frame;
5964 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5965
5966 ASSERT_EQ(1u, frame.render_passes.size());
5967 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5968 ASSERT_EQ(DrawQuad::RENDER_PASS,
5969 frame.render_passes[0]->quad_list.front()->material);
5970 const RenderPassDrawQuad* render_pass_quad =
5971 RenderPassDrawQuad::MaterialCast(
5972 frame.render_passes[0]->quad_list.front());
5973 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5974 render_pass_quad->rect.ToString());
5975 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5976 render_pass_quad->MaskUVRect().ToString());
5977 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5978 render_pass_quad->mask_uv_scale.ToString());
5979
5980 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5981 host_impl_->DidDrawAllLayers(frame);
5982 }
5983 }
5984
5985 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
5986 // The replica's mask layer has bounds 100x100 but the replica is of a
5987 // layer with bounds 50x50.
5988
5989 scoped_ptr<LayerImpl> scoped_root =
5990 LayerImpl::Create(host_impl_->active_tree(), 1);
5991 LayerImpl* root = scoped_root.get();
5992 root->SetHasRenderSurface(true);
5993
5994 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5995
5996 scoped_ptr<LayerImpl> scoped_content_layer =
5997 LayerImpl::Create(host_impl_->active_tree(), 3);
5998 LayerImpl* content_layer = scoped_content_layer.get();
5999 root->AddChild(scoped_content_layer.Pass());
6000
6001 scoped_ptr<LayerImpl> scoped_replica_layer =
6002 LayerImpl::Create(host_impl_->active_tree(), 2);
6003 LayerImpl* replica_layer = scoped_replica_layer.get();
6004 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
6005 content_layer->SetHasRenderSurface(true);
6006
6007 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
6008 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
6009 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
6010 replica_layer->SetMaskLayer(scoped_mask_layer.Pass());
6011 replica_layer->SetHasRenderSurface(true);
6012
6013 gfx::Size root_size(100, 100);
6014 root->SetBounds(root_size);
6015 root->SetContentBounds(root_size);
6016 root->SetPosition(gfx::PointF());
6017
6018 gfx::Size layer_size(50, 50);
6019 content_layer->SetBounds(layer_size);
6020 content_layer->SetContentBounds(layer_size);
6021 content_layer->SetPosition(gfx::PointF());
6022 content_layer->SetDrawsContent(true);
6023
6024 gfx::Size mask_size(100, 100);
6025 mask_layer->SetBounds(mask_size);
6026 mask_layer->SetContentBounds(mask_size);
6027 mask_layer->SetPosition(gfx::PointF());
6028 mask_layer->SetDrawsContent(true);
6029
6030 // Check that the mask fills the surface.
6031 float device_scale_factor = 1.f;
6032 host_impl_->SetViewportSize(root_size);
6033 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6034 {
6035 LayerTreeHostImpl::FrameData frame;
6036 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6037
6038 ASSERT_EQ(1u, frame.render_passes.size());
6039 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
6040 ASSERT_EQ(DrawQuad::RENDER_PASS,
6041 frame.render_passes[0]->quad_list.ElementAt(1)->material);
6042 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
6043 frame.render_passes[0]->quad_list.ElementAt(1));
6044 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
6045 replica_quad->rect.ToString());
6046 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
6047 replica_quad->MaskUVRect().ToString());
6048 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
6049 replica_quad->mask_uv_scale.ToString());
6050
6051 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6052 host_impl_->DidDrawAllLayers(frame);
6053 }
6054
6055 // Applying a DSF should change the render surface size, but won't affect
6056 // which part of the mask is used.
6057 device_scale_factor = 2.f;
6058 gfx::Size device_viewport =
6059 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
6060 host_impl_->SetViewportSize(device_viewport);
6061 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6062 host_impl_->active_tree()->set_needs_update_draw_properties();
6063 {
6064 LayerTreeHostImpl::FrameData frame;
6065 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6066
6067 ASSERT_EQ(1u, frame.render_passes.size());
6068 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
6069 ASSERT_EQ(DrawQuad::RENDER_PASS,
6070 frame.render_passes[0]->quad_list.ElementAt(1)->material);
6071 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
6072 frame.render_passes[0]->quad_list.ElementAt(1));
6073 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
6074 replica_quad->rect.ToString());
6075 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
6076 replica_quad->MaskUVRect().ToString());
6077 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
6078 replica_quad->mask_uv_scale.ToString());
6079
6080 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6081 host_impl_->DidDrawAllLayers(frame);
6082 }
6083
6084 // Applying an equivalent content scale on the content layer and the mask
6085 // should still result in the same part of the mask being used.
6086 gfx::Size layer_size_large =
6087 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
6088 content_layer->SetContentBounds(layer_size_large);
6089 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
6090 gfx::Size mask_size_large =
6091 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
6092 mask_layer->SetContentBounds(mask_size_large);
6093 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
6094 host_impl_->active_tree()->set_needs_update_draw_properties();
6095 {
6096 LayerTreeHostImpl::FrameData frame;
6097 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6098
6099 ASSERT_EQ(1u, frame.render_passes.size());
6100 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
6101 ASSERT_EQ(DrawQuad::RENDER_PASS,
6102 frame.render_passes[0]->quad_list.ElementAt(1)->material);
6103 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
6104 frame.render_passes[0]->quad_list.ElementAt(1));
6105 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
6106 replica_quad->rect.ToString());
6107 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
6108 replica_quad->MaskUVRect().ToString());
6109 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
6110 replica_quad->mask_uv_scale.ToString());
6111
6112 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6113 host_impl_->DidDrawAllLayers(frame);
6114 }
6115
6116 // Applying a different contents scale to the mask layer means it will have
6117 // a larger texture, but it should use the same tex coords to cover the
6118 // layer it masks.
6119 mask_layer->SetContentBounds(mask_size);
6120 mask_layer->SetContentsScale(1.f, 1.f);
6121 host_impl_->active_tree()->set_needs_update_draw_properties();
6122 {
6123 LayerTreeHostImpl::FrameData frame;
6124 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6125
6126 ASSERT_EQ(1u, frame.render_passes.size());
6127 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
6128 ASSERT_EQ(DrawQuad::RENDER_PASS,
6129 frame.render_passes[0]->quad_list.ElementAt(1)->material);
6130 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
6131 frame.render_passes[0]->quad_list.ElementAt(1));
6132 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
6133 replica_quad->rect.ToString());
6134 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
6135 replica_quad->MaskUVRect().ToString());
6136 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
6137 replica_quad->mask_uv_scale.ToString());
6138
6139 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6140 host_impl_->DidDrawAllLayers(frame);
6141 }
6142 }
6143
6144 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
6145 // The replica is of a layer with bounds 50x50, but it has a child that causes
6146 // the surface bounds to be larger.
6147
6148 scoped_ptr<LayerImpl> scoped_root =
6149 LayerImpl::Create(host_impl_->active_tree(), 1);
6150 LayerImpl* root = scoped_root.get();
6151 root->SetHasRenderSurface(true);
6152 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
6153
6154 scoped_ptr<LayerImpl> scoped_content_layer =
6155 LayerImpl::Create(host_impl_->active_tree(), 2);
6156 LayerImpl* content_layer = scoped_content_layer.get();
6157 root->AddChild(scoped_content_layer.Pass());
6158
6159 scoped_ptr<LayerImpl> scoped_content_child_layer =
6160 LayerImpl::Create(host_impl_->active_tree(), 3);
6161 LayerImpl* content_child_layer = scoped_content_child_layer.get();
6162 content_layer->AddChild(scoped_content_child_layer.Pass());
6163
6164 scoped_ptr<LayerImpl> scoped_replica_layer =
6165 LayerImpl::Create(host_impl_->active_tree(), 4);
6166 LayerImpl* replica_layer = scoped_replica_layer.get();
6167 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
6168 content_layer->SetHasRenderSurface(true);
6169
6170 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
6171 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
6172 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
6173 replica_layer->SetMaskLayer(scoped_mask_layer.Pass());
6174 replica_layer->SetHasRenderSurface(true);
6175
6176 gfx::Size root_size(100, 100);
6177 root->SetBounds(root_size);
6178 root->SetContentBounds(root_size);
6179 root->SetPosition(gfx::PointF());
6180
6181 gfx::Size layer_size(50, 50);
6182 content_layer->SetBounds(layer_size);
6183 content_layer->SetContentBounds(layer_size);
6184 content_layer->SetPosition(gfx::PointF());
6185 content_layer->SetDrawsContent(true);
6186
6187 gfx::Size child_size(50, 50);
6188 content_child_layer->SetBounds(child_size);
6189 content_child_layer->SetContentBounds(child_size);
6190 content_child_layer->SetPosition(gfx::Point(50, 0));
6191 content_child_layer->SetDrawsContent(true);
6192
6193 gfx::Size mask_size(50, 50);
6194 mask_layer->SetBounds(mask_size);
6195 mask_layer->SetContentBounds(mask_size);
6196 mask_layer->SetPosition(gfx::PointF());
6197 mask_layer->SetDrawsContent(true);
6198
6199 float device_scale_factor = 1.f;
6200 host_impl_->SetViewportSize(root_size);
6201 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6202 {
6203 LayerTreeHostImpl::FrameData frame;
6204 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6205
6206 ASSERT_EQ(1u, frame.render_passes.size());
6207 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
6208
6209 // The surface is 100x50.
6210 ASSERT_EQ(DrawQuad::RENDER_PASS,
6211 frame.render_passes[0]->quad_list.front()->material);
6212 const RenderPassDrawQuad* render_pass_quad =
6213 RenderPassDrawQuad::MaterialCast(
6214 frame.render_passes[0]->quad_list.front());
6215 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
6216 render_pass_quad->rect.ToString());
6217
6218 // The mask covers the owning layer only.
6219 ASSERT_EQ(DrawQuad::RENDER_PASS,
6220 frame.render_passes[0]->quad_list.ElementAt(1)->material);
6221 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
6222 frame.render_passes[0]->quad_list.ElementAt(1));
6223 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
6224 replica_quad->rect.ToString());
6225 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
6226 replica_quad->MaskUVRect().ToString());
6227 EXPECT_EQ(gfx::Vector2dF(2.f, 1.f).ToString(),
6228 replica_quad->mask_uv_scale.ToString());
6229
6230 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6231 host_impl_->DidDrawAllLayers(frame);
6232 }
6233
6234 // Move the child to (-50, 0) instead. Now the mask should be moved to still
6235 // cover the layer being replicated.
6236 content_child_layer->SetPosition(gfx::Point(-50, 0));
6237 {
6238 LayerTreeHostImpl::FrameData frame;
6239 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6240
6241 ASSERT_EQ(1u, frame.render_passes.size());
6242 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
6243
6244 // The surface is 100x50 with its origin at (-50, 0).
6245 ASSERT_EQ(DrawQuad::RENDER_PASS,
6246 frame.render_passes[0]->quad_list.front()->material);
6247 const RenderPassDrawQuad* render_pass_quad =
6248 RenderPassDrawQuad::MaterialCast(
6249 frame.render_passes[0]->quad_list.front());
6250 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
6251 render_pass_quad->rect.ToString());
6252
6253 // The mask covers the owning layer only.
6254 ASSERT_EQ(DrawQuad::RENDER_PASS,
6255 frame.render_passes[0]->quad_list.ElementAt(1)->material);
6256 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
6257 frame.render_passes[0]->quad_list.ElementAt(1));
6258 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
6259 replica_quad->rect.ToString());
6260 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
6261 replica_quad->MaskUVRect().ToString());
6262 EXPECT_EQ(gfx::Vector2dF(2.f, 1.f).ToString(),
6263 replica_quad->mask_uv_scale.ToString());
6264
6265 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6266 host_impl_->DidDrawAllLayers(frame);
6267 }
6268 }
6269
6270 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
6271 // The masked layer has bounds 50x50, but it has a child that causes
6272 // the surface bounds to be larger. It also has a parent that clips the
6273 // masked layer and its surface.
6274
6275 scoped_ptr<LayerImpl> scoped_root =
6276 LayerImpl::Create(host_impl_->active_tree(), 1);
6277 LayerImpl* root = scoped_root.get();
6278 root->SetHasRenderSurface(true);
6279
6280 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
6281
6282 scoped_ptr<LayerImpl> scoped_clipping_layer =
6283 LayerImpl::Create(host_impl_->active_tree(), 2);
6284 LayerImpl* clipping_layer = scoped_clipping_layer.get();
6285 root->AddChild(scoped_clipping_layer.Pass());
6286
6287 scoped_ptr<LayerImpl> scoped_content_layer =
6288 LayerImpl::Create(host_impl_->active_tree(), 3);
6289 LayerImpl* content_layer = scoped_content_layer.get();
6290 clipping_layer->AddChild(scoped_content_layer.Pass());
6291
6292 scoped_ptr<LayerImpl> scoped_content_child_layer =
6293 LayerImpl::Create(host_impl_->active_tree(), 4);
6294 LayerImpl* content_child_layer = scoped_content_child_layer.get();
6295 content_layer->AddChild(scoped_content_child_layer.Pass());
6296
6297 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
6298 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
6299 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
6300 content_layer->SetMaskLayer(scoped_mask_layer.Pass());
6301 content_layer->SetHasRenderSurface(true);
6302
6303 gfx::Size root_size(100, 100);
6304 root->SetBounds(root_size);
6305 root->SetContentBounds(root_size);
6306 root->SetPosition(gfx::PointF());
6307
6308 gfx::Rect clipping_rect(20, 10, 10, 20);
6309 clipping_layer->SetBounds(clipping_rect.size());
6310 clipping_layer->SetContentBounds(clipping_rect.size());
6311 clipping_layer->SetPosition(clipping_rect.origin());
6312 clipping_layer->SetMasksToBounds(true);
6313
6314 gfx::Size layer_size(50, 50);
6315 content_layer->SetBounds(layer_size);
6316 content_layer->SetContentBounds(layer_size);
6317 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
6318 content_layer->SetDrawsContent(true);
6319
6320 gfx::Size child_size(50, 50);
6321 content_child_layer->SetBounds(child_size);
6322 content_child_layer->SetContentBounds(child_size);
6323 content_child_layer->SetPosition(gfx::Point(50, 0));
6324 content_child_layer->SetDrawsContent(true);
6325
6326 gfx::Size mask_size(100, 100);
6327 mask_layer->SetBounds(mask_size);
6328 mask_layer->SetContentBounds(mask_size);
6329 mask_layer->SetPosition(gfx::PointF());
6330 mask_layer->SetDrawsContent(true);
6331
6332 float device_scale_factor = 1.f;
6333 host_impl_->SetViewportSize(root_size);
6334 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6335 {
6336 LayerTreeHostImpl::FrameData frame;
6337 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6338
6339 ASSERT_EQ(1u, frame.render_passes.size());
6340 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
6341
6342 // The surface is clipped to 10x20.
6343 ASSERT_EQ(DrawQuad::RENDER_PASS,
6344 frame.render_passes[0]->quad_list.front()->material);
6345 const RenderPassDrawQuad* render_pass_quad =
6346 RenderPassDrawQuad::MaterialCast(
6347 frame.render_passes[0]->quad_list.front());
6348 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
6349 render_pass_quad->rect.ToString());
6350 // The masked layer is 50x50, but the surface size is 10x20. So the texture
6351 // coords in the mask are scaled by 10/50 and 20/50.
6352 // The surface is clipped to (20,10) so the mask texture coords are offset
6353 // by 20/50 and 10/50
6354 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f)
6355 .ToString(),
6356 render_pass_quad->MaskUVRect().ToString());
6357 EXPECT_EQ(gfx::Vector2dF(10.f / 50.f, 20.f / 50.f).ToString(),
6358 render_pass_quad->mask_uv_scale.ToString());
6359
6360 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6361 host_impl_->DidDrawAllLayers(frame);
6362 }
6363 }
6364
6365 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
6366 public:
6367 using GLRenderer::ShouldAntialiasQuad;
6368 };
6369
6370 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
6371 // Due to precision issues (especially on Android), sometimes far
6372 // away quads can end up thinking they need AA.
6373 float device_scale_factor = 4.f / 3.f;
6374 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6375 gfx::Size root_size(2000, 1000);
6376 gfx::Size device_viewport_size =
6377 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
6378 host_impl_->SetViewportSize(device_viewport_size);
6379
6380 host_impl_->CreatePendingTree();
6381 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f,
6382 16.f);
6383
6384 scoped_ptr<LayerImpl> scoped_root =
6385 LayerImpl::Create(host_impl_->pending_tree(), 1);
6386 LayerImpl* root = scoped_root.get();
6387 root->SetHasRenderSurface(true);
6388
6389 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
6390
6391 scoped_ptr<LayerImpl> scoped_scrolling_layer =
6392 LayerImpl::Create(host_impl_->pending_tree(), 2);
6393 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
6394 root->AddChild(scoped_scrolling_layer.Pass());
6395
6396 gfx::Size content_layer_bounds(100000, 100);
6397 gfx::Size pile_tile_size(3000, 3000);
6398 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
6399 pile_tile_size, content_layer_bounds));
6400
6401 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
6402 FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(),
6403 3, pile);
6404 LayerImpl* content_layer = scoped_content_layer.get();
6405 scrolling_layer->AddChild(scoped_content_layer.Pass());
6406 content_layer->SetBounds(content_layer_bounds);
6407 content_layer->SetDrawsContent(true);
6408
6409 root->SetBounds(root_size);
6410
6411 gfx::ScrollOffset scroll_offset(100000, 0);
6412 scrolling_layer->SetScrollClipLayer(root->id());
6413 scrolling_layer->PushScrollOffsetFromMainThread(scroll_offset);
6414
6415 host_impl_->ActivateSyncTree();
6416
6417 bool update_lcd_text = false;
6418 host_impl_->active_tree()->UpdateDrawProperties(update_lcd_text);
6419 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
6420
6421 LayerTreeHostImpl::FrameData frame;
6422 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6423
6424 ASSERT_EQ(1u, frame.render_passes.size());
6425 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
6426 const DrawQuad* quad = frame.render_passes[0]->quad_list.front();
6427
6428 bool antialiased =
6429 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6430 quad->quadTransform(), quad, false);
6431 EXPECT_FALSE(antialiased);
6432
6433 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6434 host_impl_->DidDrawAllLayers(frame);
6435 }
6436
6437
6438 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
6439 public:
6440 CompositorFrameMetadataTest()
6441 : swap_buffers_complete_(0) {}
6442
6443 void DidSwapBuffersCompleteOnImplThread() override {
6444 swap_buffers_complete_++;
6445 }
6446
6447 int swap_buffers_complete_;
6448 };
6449
6450 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
6451 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
6452 {
6453 LayerTreeHostImpl::FrameData frame;
6454 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6455 host_impl_->DrawLayers(&frame, base::TimeTicks());
6456 host_impl_->DidDrawAllLayers(frame);
6457 }
6458 CompositorFrameAck ack;
6459 host_impl_->ReclaimResources(&ack);
6460 host_impl_->DidSwapBuffersComplete();
6461 EXPECT_EQ(swap_buffers_complete_, 1);
6462 }
6463
6464 class CountingSoftwareDevice : public SoftwareOutputDevice {
6465 public:
6466 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6467
6468 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
6469 ++frames_began_;
6470 return SoftwareOutputDevice::BeginPaint(damage_rect);
6471 }
6472 void EndPaint(SoftwareFrameData* frame_data) override {
6473 ++frames_ended_;
6474 SoftwareOutputDevice::EndPaint(frame_data);
6475 }
6476
6477 int frames_began_, frames_ended_;
6478 };
6479
6480 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
6481 // No main thread evictions in resourceless software mode.
6482 set_reduce_memory_result(false);
6483 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
6484 bool delegated_rendering = false;
6485 FakeOutputSurface* output_surface =
6486 FakeOutputSurface::CreateDeferredGL(
6487 scoped_ptr<SoftwareOutputDevice>(software_device),
6488 delegated_rendering).release();
6489 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6490 scoped_ptr<OutputSurface>(output_surface)));
6491 host_impl_->SetViewportSize(gfx::Size(50, 50));
6492
6493 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6494
6495 const gfx::Transform external_transform;
6496 const gfx::Rect external_viewport;
6497 const gfx::Rect external_clip;
6498 const bool resourceless_software_draw = true;
6499 host_impl_->SetExternalDrawConstraints(external_transform,
6500 external_viewport,
6501 external_clip,
6502 external_viewport,
6503 external_transform,
6504 resourceless_software_draw);
6505
6506 EXPECT_EQ(0, software_device->frames_began_);
6507 EXPECT_EQ(0, software_device->frames_ended_);
6508
6509 DrawFrame();
6510
6511 EXPECT_EQ(1, software_device->frames_began_);
6512 EXPECT_EQ(1, software_device->frames_ended_);
6513
6514 // Call another API method that is likely to hit nullptr in this mode.
6515 scoped_refptr<base::trace_event::TracedValue> state =
6516 make_scoped_refptr(new base::trace_event::TracedValue());
6517 host_impl_->ActivationStateAsValueInto(state.get());
6518 }
6519
6520 TEST_F(LayerTreeHostImplTest,
6521 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
6522 set_reduce_memory_result(false);
6523 bool delegated_rendering = false;
6524 FakeOutputSurface* output_surface =
6525 FakeOutputSurface::CreateDeferredGL(
6526 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
6527 delegated_rendering).release();
6528 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6529 scoped_ptr<OutputSurface>(output_surface)));
6530
6531 const gfx::Transform external_transform;
6532 const gfx::Rect external_viewport;
6533 const gfx::Rect external_clip;
6534 const bool resourceless_software_draw = true;
6535 host_impl_->SetExternalDrawConstraints(external_transform,
6536 external_viewport,
6537 external_clip,
6538 external_viewport,
6539 external_transform,
6540 resourceless_software_draw);
6541
6542 // SolidColorLayerImpl will be drawn.
6543 scoped_ptr<SolidColorLayerImpl> root_layer =
6544 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6545
6546 LayerTreeHostImpl::FrameData frame;
6547 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6548 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6549 host_impl_->DidDrawAllLayers(frame);
6550
6551 EXPECT_EQ(1u, frame.will_draw_layers.size());
6552 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
6553 }
6554
6555 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
6556 protected:
6557 void SetUp() override {
6558 LayerTreeHostImplTest::SetUp();
6559
6560 set_reduce_memory_result(false);
6561
6562 bool delegated_rendering = false;
6563 scoped_ptr<FakeOutputSurface> output_surface(
6564 FakeOutputSurface::CreateDeferredGL(
6565 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
6566 delegated_rendering));
6567 output_surface_ = output_surface.get();
6568
6569 EXPECT_TRUE(CreateHostImpl(DefaultSettings(), output_surface.Pass()));
6570
6571 scoped_ptr<SolidColorLayerImpl> root_layer =
6572 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6573 SetupRootLayerImpl(root_layer.Pass());
6574
6575 onscreen_context_provider_ = TestContextProvider::Create();
6576 }
6577
6578 void UpdateRendererCapabilitiesOnImplThread() override {
6579 did_update_renderer_capabilities_ = true;
6580 }
6581
6582 FakeOutputSurface* output_surface_;
6583 scoped_refptr<TestContextProvider> onscreen_context_provider_;
6584 bool did_update_renderer_capabilities_;
6585 };
6586
6587
6588 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
6589 // Software draw.
6590 DrawFrame();
6591
6592 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6593
6594 // DeferredInitialize and hardware draw.
6595 did_update_renderer_capabilities_ = false;
6596 EXPECT_TRUE(output_surface_->InitializeAndSetContext3d(
6597 onscreen_context_provider_, nullptr));
6598 EXPECT_EQ(onscreen_context_provider_.get(),
6599 host_impl_->output_surface()->context_provider());
6600 EXPECT_TRUE(did_update_renderer_capabilities_);
6601
6602 // Defer intialized GL draw.
6603 DrawFrame();
6604
6605 // Revert back to software.
6606 did_update_renderer_capabilities_ = false;
6607 output_surface_->ReleaseGL();
6608 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6609 EXPECT_TRUE(did_update_renderer_capabilities_);
6610
6611 // Software draw again.
6612 DrawFrame();
6613 }
6614
6615 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails) {
6616 // Software draw.
6617 DrawFrame();
6618
6619 // Fail initialization of the onscreen context before the OutputSurface binds
6620 // it to the thread.
6621 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
6622
6623 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6624
6625 // DeferredInitialize fails.
6626 did_update_renderer_capabilities_ = false;
6627 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
6628 onscreen_context_provider_, nullptr));
6629 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6630 EXPECT_FALSE(did_update_renderer_capabilities_);
6631
6632 // Software draw again.
6633 DrawFrame();
6634 }
6635
6636 // Checks that we have a non-0 default allocation if we pass a context that
6637 // doesn't support memory management extensions.
6638 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
6639 LayerTreeSettings settings;
6640 host_impl_ = LayerTreeHostImpl::Create(
6641 settings, this, &proxy_, &stats_instrumentation_,
6642 shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(),
6643 task_graph_runner_.get(), 0);
6644
6645 scoped_ptr<OutputSurface> output_surface(
6646 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6647 host_impl_->InitializeRenderer(output_surface.Pass());
6648 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
6649 }
6650
6651 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
6652 ManagedMemoryPolicy policy1(
6653 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
6654 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
6655 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
6656 int allow_nice_to_have_cutoff_value =
6657 ManagedMemoryPolicy::PriorityCutoffToValue(
6658 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
6659 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
6660 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
6661
6662 // GPU rasterization should be disabled by default on the tree(s)
6663 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
6664 EXPECT_TRUE(host_impl_->pending_tree() == NULL);
6665
6666 host_impl_->SetVisible(true);
6667 host_impl_->SetMemoryPolicy(policy1);
6668 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
6669 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
6670
6671 host_impl_->SetVisible(false);
6672 EXPECT_EQ(0u, current_limit_bytes_);
6673 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
6674
6675 host_impl_->SetVisible(true);
6676 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
6677 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
6678
6679 // Now enable GPU rasterization and test if we get nice to have cutoff,
6680 // when visible.
6681 LayerTreeSettings settings;
6682 settings.gpu_rasterization_enabled = true;
6683 host_impl_ = LayerTreeHostImpl::Create(
6684 settings, this, &proxy_, &stats_instrumentation_, NULL, NULL, NULL, 0);
6685 host_impl_->SetUseGpuRasterization(true);
6686 host_impl_->SetVisible(true);
6687 host_impl_->SetMemoryPolicy(policy1);
6688 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
6689 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
6690
6691 host_impl_->SetVisible(false);
6692 EXPECT_EQ(0u, current_limit_bytes_);
6693 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
6694 }
6695
6696 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
6697 ASSERT_TRUE(host_impl_->active_tree());
6698
6699 // RequiresHighResToDraw is set when new output surface is used.
6700 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6701
6702 host_impl_->ResetRequiresHighResToDraw();
6703
6704 host_impl_->SetVisible(false);
6705 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6706 host_impl_->SetVisible(true);
6707 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6708 host_impl_->SetVisible(false);
6709 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6710
6711 host_impl_->ResetRequiresHighResToDraw();
6712
6713 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6714 host_impl_->SetVisible(true);
6715 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6716 }
6717
6718 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
6719 ASSERT_TRUE(host_impl_->active_tree());
6720 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
6721
6722 // RequiresHighResToDraw is set when new output surface is used.
6723 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6724
6725 host_impl_->ResetRequiresHighResToDraw();
6726
6727 host_impl_->SetUseGpuRasterization(false);
6728 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6729 host_impl_->SetUseGpuRasterization(true);
6730 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6731 host_impl_->SetUseGpuRasterization(false);
6732 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6733
6734 host_impl_->ResetRequiresHighResToDraw();
6735
6736 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6737 host_impl_->SetUseGpuRasterization(true);
6738 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6739 }
6740
6741 class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest {
6742 public:
6743 void SetUp() override {
6744 LayerTreeSettings settings;
6745 settings.impl_side_painting = true;
6746
6747 fake_host_impl_ = new FakeLayerTreeHostImpl(settings, &proxy_,
6748 shared_bitmap_manager_.get(),
6749 task_graph_runner_.get());
6750 host_impl_.reset(fake_host_impl_);
6751 host_impl_->InitializeRenderer(CreateOutputSurface());
6752 host_impl_->SetViewportSize(gfx::Size(10, 10));
6753 }
6754
6755 FakeLayerTreeHostImpl* fake_host_impl_;
6756 };
6757
6758 TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) {
6759 fake_host_impl_->DidModifyTilePriorities();
6760 EXPECT_TRUE(fake_host_impl_->prepare_tiles_needed());
6761 fake_host_impl_->SetVisible(false);
6762 EXPECT_FALSE(fake_host_impl_->prepare_tiles_needed());
6763 }
6764
6765 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
6766 scoped_ptr<TestWebGraphicsContext3D> context =
6767 TestWebGraphicsContext3D::Create();
6768 TestWebGraphicsContext3D* context3d = context.get();
6769 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
6770 CreateHostImpl(DefaultSettings(), output_surface.Pass());
6771
6772 EXPECT_EQ(0u, context3d->NumTextures());
6773
6774 UIResourceId ui_resource_id = 1;
6775 bool is_opaque = false;
6776 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
6777 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6778 EXPECT_EQ(1u, context3d->NumTextures());
6779 ResourceProvider::ResourceId id1 =
6780 host_impl_->ResourceIdForUIResource(ui_resource_id);
6781 EXPECT_NE(0u, id1);
6782
6783 // Multiple requests with the same id is allowed. The previous texture is
6784 // deleted.
6785 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6786 EXPECT_EQ(1u, context3d->NumTextures());
6787 ResourceProvider::ResourceId id2 =
6788 host_impl_->ResourceIdForUIResource(ui_resource_id);
6789 EXPECT_NE(0u, id2);
6790 EXPECT_NE(id1, id2);
6791
6792 // Deleting invalid UIResourceId is allowed and does not change state.
6793 host_impl_->DeleteUIResource(-1);
6794 EXPECT_EQ(1u, context3d->NumTextures());
6795
6796 // Should return zero for invalid UIResourceId. Number of textures should
6797 // not change.
6798 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
6799 EXPECT_EQ(1u, context3d->NumTextures());
6800
6801 host_impl_->DeleteUIResource(ui_resource_id);
6802 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
6803 EXPECT_EQ(0u, context3d->NumTextures());
6804
6805 // Should not change state for multiple deletion on one UIResourceId
6806 host_impl_->DeleteUIResource(ui_resource_id);
6807 EXPECT_EQ(0u, context3d->NumTextures());
6808 }
6809
6810 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
6811 scoped_ptr<TestWebGraphicsContext3D> context =
6812 TestWebGraphicsContext3D::Create();
6813 TestWebGraphicsContext3D* context3d = context.get();
6814 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6815
6816 EXPECT_EQ(0u, context3d->NumTextures());
6817
6818 gfx::Size size(4, 4);
6819 // SkImageInfo has no support for ETC1. The |info| below contains the right
6820 // total pixel size for the bitmap but not the right height and width. The
6821 // correct width/height are passed directly to UIResourceBitmap.
6822 SkImageInfo info =
6823 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
6824 skia::RefPtr<SkPixelRef> pixel_ref =
6825 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
6826 pixel_ref->setImmutable();
6827 UIResourceBitmap bitmap(pixel_ref, size);
6828 UIResourceId ui_resource_id = 1;
6829 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6830 EXPECT_EQ(1u, context3d->NumTextures());
6831 ResourceProvider::ResourceId id1 =
6832 host_impl_->ResourceIdForUIResource(ui_resource_id);
6833 EXPECT_NE(0u, id1);
6834 }
6835
6836 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
6837 }
6838
6839 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
6840 scoped_refptr<TestContextProvider> context_provider =
6841 TestContextProvider::Create();
6842
6843 CreateHostImpl(DefaultSettings(),
6844 FakeOutputSurface::Create3d(context_provider));
6845
6846 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
6847
6848 ScopedPtrVector<CopyOutputRequest> requests;
6849 requests.push_back(CopyOutputRequest::CreateRequest(
6850 base::Bind(&ShutdownReleasesContext_Callback)));
6851
6852 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
6853
6854 LayerTreeHostImpl::FrameData frame;
6855 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6856 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6857 host_impl_->DidDrawAllLayers(frame);
6858
6859 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6860 // texture in a texture mailbox.
6861 EXPECT_FALSE(context_provider->HasOneRef());
6862 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
6863
6864 host_impl_ = nullptr;
6865
6866 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6867 // released, and the texture deleted.
6868 EXPECT_TRUE(context_provider->HasOneRef());
6869 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
6870 }
6871
6872 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
6873 // When flinging via touch, only the child should scroll (we should not
6874 // bubble).
6875 gfx::Size surface_size(10, 10);
6876 gfx::Size content_size(20, 20);
6877 scoped_ptr<LayerImpl> root_clip =
6878 LayerImpl::Create(host_impl_->active_tree(), 3);
6879 root_clip->SetHasRenderSurface(true);
6880
6881 scoped_ptr<LayerImpl> root =
6882 CreateScrollableLayer(1, content_size, root_clip.get());
6883 root->SetIsContainerForFixedPositionLayers(true);
6884 scoped_ptr<LayerImpl> child =
6885 CreateScrollableLayer(2, content_size, root_clip.get());
6886
6887 root->AddChild(child.Pass());
6888 int root_id = root->id();
6889 root_clip->AddChild(root.Pass());
6890
6891 host_impl_->SetViewportSize(surface_size);
6892 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6893 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
6894 Layer::INVALID_ID);
6895 host_impl_->active_tree()->DidBecomeActive();
6896 DrawFrame();
6897 {
6898 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6899 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6900
6901 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6902
6903 gfx::Vector2d scroll_delta(0, 100);
6904 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6905 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6906
6907 host_impl_->ScrollEnd();
6908
6909 scoped_ptr<ScrollAndScaleSet> scroll_info =
6910 host_impl_->ProcessScrollDeltas();
6911
6912 // Only the child should have scrolled.
6913 ASSERT_EQ(1u, scroll_info->scrolls.size());
6914 ExpectNone(*scroll_info.get(), root_id);
6915 }
6916 }
6917
6918 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
6919 // Scroll a child layer beyond its maximum scroll range and make sure the
6920 // the scroll doesn't bubble up to the parent layer.
6921 gfx::Size surface_size(10, 10);
6922 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
6923 root->SetHasRenderSurface(true);
6924 scoped_ptr<LayerImpl> root_scrolling =
6925 CreateScrollableLayer(2, surface_size, root.get());
6926
6927 scoped_ptr<LayerImpl> grand_child =
6928 CreateScrollableLayer(4, surface_size, root.get());
6929 grand_child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6930
6931 scoped_ptr<LayerImpl> child =
6932 CreateScrollableLayer(3, surface_size, root.get());
6933 child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6934 child->AddChild(grand_child.Pass());
6935
6936 root_scrolling->AddChild(child.Pass());
6937 root->AddChild(root_scrolling.Pass());
6938 host_impl_->active_tree()->SetRootLayer(root.Pass());
6939 host_impl_->active_tree()->DidBecomeActive();
6940 host_impl_->SetViewportSize(surface_size);
6941 DrawFrame();
6942 {
6943 scoped_ptr<ScrollAndScaleSet> scroll_info;
6944 LayerImpl* child =
6945 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6946 LayerImpl* grand_child = child->children()[0];
6947
6948 gfx::Vector2d scroll_delta(0, -2);
6949 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6950 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6951 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6952
6953 // The grand child should have scrolled up to its limit.
6954 scroll_info = host_impl_->ProcessScrollDeltas();
6955 ASSERT_EQ(1u, scroll_info->scrolls.size());
6956 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6957 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6958
6959 // The child should have received the bubbled delta, but the locked
6960 // scrolling layer should remain set as the grand child.
6961 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6962 scroll_info = host_impl_->ProcessScrollDeltas();
6963 ASSERT_EQ(2u, scroll_info->scrolls.size());
6964 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6965 ExpectContains(*scroll_info, child->id(), scroll_delta);
6966 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6967
6968 // The first |ScrollBy| after the fling should re-lock the scrolling
6969 // layer to the first layer that scrolled, which is the child.
6970 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6971 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6972 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6973
6974 // The child should have scrolled up to its limit.
6975 scroll_info = host_impl_->ProcessScrollDeltas();
6976 ASSERT_EQ(2u, scroll_info->scrolls.size());
6977 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6978 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
6979
6980 // As the locked layer is at it's limit, no further scrolling can occur.
6981 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6982 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6983 host_impl_->ScrollEnd();
6984 }
6985 }
6986
6987 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6988 // When flinging via wheel, the root should eventually scroll (we should
6989 // bubble).
6990 gfx::Size surface_size(10, 10);
6991 gfx::Size content_size(20, 20);
6992 scoped_ptr<LayerImpl> root_clip =
6993 LayerImpl::Create(host_impl_->active_tree(), 3);
6994 root_clip->SetHasRenderSurface(true);
6995 scoped_ptr<LayerImpl> root_scroll =
6996 CreateScrollableLayer(1, content_size, root_clip.get());
6997 int root_scroll_id = root_scroll->id();
6998 scoped_ptr<LayerImpl> child =
6999 CreateScrollableLayer(2, content_size, root_clip.get());
7000
7001 root_scroll->AddChild(child.Pass());
7002 root_clip->AddChild(root_scroll.Pass());
7003
7004 host_impl_->SetViewportSize(surface_size);
7005 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
7006 host_impl_->active_tree()->DidBecomeActive();
7007 DrawFrame();
7008 {
7009 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7010 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7011
7012 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7013
7014 gfx::Vector2d scroll_delta(0, 100);
7015 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7016 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7017
7018 host_impl_->ScrollEnd();
7019
7020 scoped_ptr<ScrollAndScaleSet> scroll_info =
7021 host_impl_->ProcessScrollDeltas();
7022
7023 // The root should have scrolled.
7024 ASSERT_EQ(2u, scroll_info->scrolls.size());
7025 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
7026 }
7027 }
7028
7029 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
7030 // If we ray cast a scroller that is not on the first layer's ancestor chain,
7031 // we should return SCROLL_UNKNOWN.
7032 gfx::Size content_size(100, 100);
7033 SetupScrollAndContentsLayers(content_size);
7034
7035 int scroll_layer_id = 2;
7036 LayerImpl* scroll_layer =
7037 host_impl_->active_tree()->LayerById(scroll_layer_id);
7038 scroll_layer->SetDrawsContent(true);
7039
7040 int page_scale_layer_id = 5;
7041 LayerImpl* page_scale_layer =
7042 host_impl_->active_tree()->LayerById(page_scale_layer_id);
7043
7044 int occluder_layer_id = 6;
7045 scoped_ptr<LayerImpl> occluder_layer =
7046 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
7047 occluder_layer->SetDrawsContent(true);
7048 occluder_layer->SetBounds(content_size);
7049 occluder_layer->SetContentBounds(content_size);
7050 occluder_layer->SetPosition(gfx::PointF());
7051
7052 // The parent of the occluder is *above* the scroller.
7053 page_scale_layer->AddChild(occluder_layer.Pass());
7054
7055 DrawFrame();
7056
7057 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
7058 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7059 }
7060
7061 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
7062 // If we ray cast a scroller this is on the first layer's ancestor chain, but
7063 // is not the first scroller we encounter when walking up from the layer, we
7064 // should also return SCROLL_UNKNOWN.
7065 gfx::Size content_size(100, 100);
7066 SetupScrollAndContentsLayers(content_size);
7067
7068 int scroll_layer_id = 2;
7069 LayerImpl* scroll_layer =
7070 host_impl_->active_tree()->LayerById(scroll_layer_id);
7071 scroll_layer->SetDrawsContent(true);
7072
7073 int occluder_layer_id = 6;
7074 scoped_ptr<LayerImpl> occluder_layer =
7075 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
7076 occluder_layer->SetDrawsContent(true);
7077 occluder_layer->SetBounds(content_size);
7078 occluder_layer->SetContentBounds(content_size);
7079 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
7080
7081 int child_scroll_clip_layer_id = 7;
7082 scoped_ptr<LayerImpl> child_scroll_clip =
7083 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
7084
7085 int child_scroll_layer_id = 8;
7086 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
7087 child_scroll_layer_id, content_size, child_scroll_clip.get());
7088
7089 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
7090
7091 child_scroll->AddChild(occluder_layer.Pass());
7092 scroll_layer->AddChild(child_scroll.Pass());
7093
7094 DrawFrame();
7095
7096 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
7097 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7098 }
7099
7100 TEST_F(LayerTreeHostImplTest, NotScrollInvisibleScroller) {
7101 gfx::Size content_size(100, 100);
7102 SetupScrollAndContentsLayers(content_size);
7103
7104 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
7105
7106 int scroll_layer_id = 2;
7107 LayerImpl* scroll_layer =
7108 host_impl_->active_tree()->LayerById(scroll_layer_id);
7109
7110 int child_scroll_layer_id = 7;
7111 scoped_ptr<LayerImpl> child_scroll =
7112 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
7113 child_scroll->SetDrawsContent(false);
7114
7115 scroll_layer->AddChild(child_scroll.Pass());
7116
7117 DrawFrame();
7118
7119 // We should not have scrolled |child_scroll| even though we technically "hit"
7120 // it. The reason for this is that if the scrolling the scroll would not move
7121 // any layer that is a drawn RSLL member, then we can ignore the hit.
7122 //
7123 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
7124 // started scrolling the inner viewport.
7125 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7126 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7127
7128 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
7129 }
7130
7131 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) {
7132 gfx::Size content_size(100, 100);
7133 SetupScrollAndContentsLayers(content_size);
7134
7135 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
7136 LayerImpl* root_scroll_layer = host_impl_->active_tree()->LayerById(2);
7137
7138 scoped_ptr<LayerImpl> invisible_scroll_layer =
7139 CreateScrollableLayer(7, content_size, root);
7140 invisible_scroll_layer->SetDrawsContent(false);
7141
7142 scoped_ptr<LayerImpl> child_layer =
7143 LayerImpl::Create(host_impl_->active_tree(), 8);
7144 child_layer->SetDrawsContent(false);
7145
7146 scoped_ptr<LayerImpl> grand_child_layer =
7147 LayerImpl::Create(host_impl_->active_tree(), 9);
7148 grand_child_layer->SetDrawsContent(true);
7149 grand_child_layer->SetBounds(content_size);
7150 grand_child_layer->SetContentBounds(content_size);
7151 // Move the grand child so it's not hit by our test point.
7152 grand_child_layer->SetPosition(gfx::PointF(10.f, 10.f));
7153
7154 child_layer->AddChild(grand_child_layer.Pass());
7155 invisible_scroll_layer->AddChild(child_layer.Pass());
7156 root_scroll_layer->AddChild(invisible_scroll_layer.Pass());
7157
7158 DrawFrame();
7159
7160 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
7161 // a descendant which is a drawn RSLL member.
7162 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7163 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7164
7165 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
7166 }
7167
7168 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
7169 // This test case is very similar to the one above with one key difference:
7170 // the invisible scroller has a scroll child that is indeed draw contents.
7171 // If we attempt to initiate a gesture scroll off of the visible scroll child
7172 // we should still start the scroll child.
7173 gfx::Size content_size(100, 100);
7174 SetupScrollAndContentsLayers(content_size);
7175
7176 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
7177
7178 int scroll_layer_id = 2;
7179 LayerImpl* scroll_layer =
7180 host_impl_->active_tree()->LayerById(scroll_layer_id);
7181
7182 int scroll_child_id = 6;
7183 scoped_ptr<LayerImpl> scroll_child =
7184 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
7185 scroll_child->SetDrawsContent(true);
7186 scroll_child->SetBounds(content_size);
7187 scroll_child->SetContentBounds(content_size);
7188 // Move the scroll child so it's not hit by our test point.
7189 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
7190
7191 int invisible_scroll_layer_id = 7;
7192 scoped_ptr<LayerImpl> invisible_scroll =
7193 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
7194 invisible_scroll->SetDrawsContent(false);
7195
7196 int container_id = 8;
7197 scoped_ptr<LayerImpl> container =
7198 LayerImpl::Create(host_impl_->active_tree(), container_id);
7199
7200 scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
7201 scroll_children->insert(scroll_child.get());
7202 invisible_scroll->SetScrollChildren(scroll_children.release());
7203
7204 scroll_child->SetScrollParent(invisible_scroll.get());
7205
7206 container->AddChild(invisible_scroll.Pass());
7207 container->AddChild(scroll_child.Pass());
7208
7209 scroll_layer->AddChild(container.Pass());
7210
7211 DrawFrame();
7212
7213 // We should have scrolled |child_scroll| even though it is invisible.
7214 // The reason for this is that if the scrolling the scroll would move a layer
7215 // that is a drawn RSLL member, then we should accept this hit.
7216 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7217 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7218
7219 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
7220 }
7221
7222 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
7223 // to CompositorFrameMetadata after SwapBuffers();
7224 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
7225 scoped_ptr<SolidColorLayerImpl> root =
7226 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
7227 root->SetPosition(gfx::PointF());
7228 root->SetBounds(gfx::Size(10, 10));
7229 root->SetContentBounds(gfx::Size(10, 10));
7230 root->SetDrawsContent(true);
7231 root->SetHasRenderSurface(true);
7232
7233 host_impl_->active_tree()->SetRootLayer(root.Pass());
7234
7235 FakeOutputSurface* fake_output_surface =
7236 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
7237
7238 const std::vector<ui::LatencyInfo>& metadata_latency_before =
7239 fake_output_surface->last_sent_frame().metadata.latency_info;
7240 EXPECT_TRUE(metadata_latency_before.empty());
7241
7242 ui::LatencyInfo latency_info;
7243 latency_info.AddLatencyNumber(
7244 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
7245 scoped_ptr<SwapPromise> swap_promise(
7246 new LatencyInfoSwapPromise(latency_info));
7247 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
7248 host_impl_->SetNeedsRedraw();
7249
7250 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
7251 LayerTreeHostImpl::FrameData frame;
7252 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
7253 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
7254 host_impl_->DidDrawAllLayers(frame);
7255 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
7256
7257 const std::vector<ui::LatencyInfo>& metadata_latency_after =
7258 fake_output_surface->last_sent_frame().metadata.latency_info;
7259 EXPECT_EQ(1u, metadata_latency_after.size());
7260 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
7261 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
7262 }
7263
7264 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
7265 int root_layer_id = 1;
7266 scoped_ptr<SolidColorLayerImpl> root =
7267 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
7268 root->SetPosition(gfx::PointF());
7269 root->SetBounds(gfx::Size(10, 10));
7270 root->SetContentBounds(gfx::Size(10, 10));
7271 root->SetDrawsContent(true);
7272 root->SetHasRenderSurface(true);
7273
7274 host_impl_->active_tree()->SetRootLayer(root.Pass());
7275
7276 // Ensure the default frame selection bounds are empty.
7277 FakeOutputSurface* fake_output_surface =
7278 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
7279 const ViewportSelectionBound& selection_start_before =
7280 fake_output_surface->last_sent_frame().metadata.selection_start;
7281 const ViewportSelectionBound& selection_end_before =
7282 fake_output_surface->last_sent_frame().metadata.selection_end;
7283 EXPECT_EQ(ViewportSelectionBound(), selection_start_before);
7284 EXPECT_EQ(ViewportSelectionBound(), selection_end_before);
7285
7286 // Plumb the layer-local selection bounds.
7287 gfx::PointF selection_top(5, 0);
7288 gfx::PointF selection_bottom(5, 5);
7289 LayerSelectionBound start, end;
7290 start.type = SELECTION_BOUND_CENTER;
7291 start.layer_id = root_layer_id;
7292 start.edge_bottom = selection_bottom;
7293 start.edge_top = selection_top;
7294 end = start;
7295 host_impl_->active_tree()->RegisterSelection(start, end);
7296
7297 // Trigger a draw-swap sequence.
7298 host_impl_->SetNeedsRedraw();
7299
7300 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
7301 LayerTreeHostImpl::FrameData frame;
7302 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
7303 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
7304 host_impl_->DidDrawAllLayers(frame);
7305 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
7306
7307 // Ensure the selection bounds have propagated to the frame metadata.
7308 const ViewportSelectionBound& selection_start_after =
7309 fake_output_surface->last_sent_frame().metadata.selection_start;
7310 const ViewportSelectionBound& selection_end_after =
7311 fake_output_surface->last_sent_frame().metadata.selection_end;
7312 EXPECT_EQ(start.type, selection_start_after.type);
7313 EXPECT_EQ(end.type, selection_end_after.type);
7314 EXPECT_EQ(selection_bottom, selection_start_after.edge_bottom);
7315 EXPECT_EQ(selection_top, selection_start_after.edge_top);
7316 EXPECT_TRUE(selection_start_after.visible);
7317 EXPECT_TRUE(selection_start_after.visible);
7318 }
7319
7320 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
7321 public:
7322 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
7323 LayerTreeHostImpl* layer_tree_host_impl,
7324 int* set_needs_commit_count,
7325 int* set_needs_redraw_count,
7326 int* forward_to_main_count)
7327 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
7328 set_needs_commit_count_(set_needs_commit_count),
7329 set_needs_redraw_count_(set_needs_redraw_count),
7330 forward_to_main_count_(forward_to_main_count) {}
7331
7332 ~SimpleSwapPromiseMonitor() override {}
7333
7334 void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
7335
7336 void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; }
7337
7338 void OnForwardScrollUpdateToMainThreadOnImpl() override {
7339 (*forward_to_main_count_)++;
7340 }
7341
7342 private:
7343 int* set_needs_commit_count_;
7344 int* set_needs_redraw_count_;
7345 int* forward_to_main_count_;
7346 };
7347
7348 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
7349 int set_needs_commit_count = 0;
7350 int set_needs_redraw_count = 0;
7351 int forward_to_main_count = 0;
7352
7353 {
7354 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7355 new SimpleSwapPromiseMonitor(NULL,
7356 host_impl_.get(),
7357 &set_needs_commit_count,
7358 &set_needs_redraw_count,
7359 &forward_to_main_count));
7360 host_impl_->SetNeedsRedraw();
7361 EXPECT_EQ(0, set_needs_commit_count);
7362 EXPECT_EQ(1, set_needs_redraw_count);
7363 EXPECT_EQ(0, forward_to_main_count);
7364 }
7365
7366 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
7367 // monitored.
7368 host_impl_->SetNeedsRedraw();
7369 EXPECT_EQ(0, set_needs_commit_count);
7370 EXPECT_EQ(1, set_needs_redraw_count);
7371 EXPECT_EQ(0, forward_to_main_count);
7372
7373 {
7374 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7375 new SimpleSwapPromiseMonitor(NULL,
7376 host_impl_.get(),
7377 &set_needs_commit_count,
7378 &set_needs_redraw_count,
7379 &forward_to_main_count));
7380 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
7381 EXPECT_EQ(0, set_needs_commit_count);
7382 EXPECT_EQ(2, set_needs_redraw_count);
7383 EXPECT_EQ(0, forward_to_main_count);
7384 }
7385
7386 {
7387 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7388 new SimpleSwapPromiseMonitor(NULL,
7389 host_impl_.get(),
7390 &set_needs_commit_count,
7391 &set_needs_redraw_count,
7392 &forward_to_main_count));
7393 // Empty damage rect won't signal the monitor.
7394 host_impl_->SetNeedsRedrawRect(gfx::Rect());
7395 EXPECT_EQ(0, set_needs_commit_count);
7396 EXPECT_EQ(2, set_needs_redraw_count);
7397 EXPECT_EQ(0, forward_to_main_count);
7398 }
7399
7400 {
7401 set_needs_commit_count = 0;
7402 set_needs_redraw_count = 0;
7403 forward_to_main_count = 0;
7404 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7405 new SimpleSwapPromiseMonitor(NULL,
7406 host_impl_.get(),
7407 &set_needs_commit_count,
7408 &set_needs_redraw_count,
7409 &forward_to_main_count));
7410 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
7411
7412 // Scrolling normally should not trigger any forwarding.
7413 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7414 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7415 EXPECT_TRUE(
7416 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
7417 host_impl_->ScrollEnd();
7418
7419 EXPECT_EQ(0, set_needs_commit_count);
7420 EXPECT_EQ(1, set_needs_redraw_count);
7421 EXPECT_EQ(0, forward_to_main_count);
7422
7423 // Scrolling with a scroll handler should defer the swap to the main
7424 // thread.
7425 scroll_layer->SetHaveScrollEventHandlers(true);
7426 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7427 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7428 EXPECT_TRUE(
7429 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
7430 host_impl_->ScrollEnd();
7431
7432 EXPECT_EQ(0, set_needs_commit_count);
7433 EXPECT_EQ(2, set_needs_redraw_count);
7434 EXPECT_EQ(1, forward_to_main_count);
7435 }
7436 }
7437
7438 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
7439 public:
7440 void SetUp() override {
7441 LayerTreeSettings settings = DefaultSettings();
7442 CreateHostImpl(settings, CreateOutputSurface());
7443 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
7444 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
7445 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
7446 }
7447
7448 protected:
7449 static const int top_controls_height_;
7450 };
7451
7452 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
7453
7454 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
7455 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7456 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7457 host_impl_->Animate(base::TimeTicks());
7458 EXPECT_FALSE(did_request_redraw_);
7459 }
7460
7461 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsHeightIsCommitted) {
7462 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7463 EXPECT_FALSE(did_request_redraw_);
7464 host_impl_->CreatePendingTree();
7465 host_impl_->sync_tree()->set_top_controls_height(100);
7466 host_impl_->ActivateSyncTree();
7467 EXPECT_EQ(100, host_impl_->top_controls_manager()->TopControlsHeight());
7468 }
7469
7470 TEST_F(LayerTreeHostImplWithTopControlsTest,
7471 TopControlsStayFullyVisibleOnHeightChange) {
7472 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7473 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7474
7475 host_impl_->CreatePendingTree();
7476 host_impl_->sync_tree()->set_top_controls_height(0);
7477 host_impl_->ActivateSyncTree();
7478 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7479
7480 host_impl_->CreatePendingTree();
7481 host_impl_->sync_tree()->set_top_controls_height(50);
7482 host_impl_->ActivateSyncTree();
7483 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7484 }
7485
7486 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
7487 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7488 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7489 host_impl_->DidChangeTopControlsPosition();
7490 EXPECT_TRUE(did_request_animate_);
7491 EXPECT_TRUE(did_request_redraw_);
7492 }
7493
7494 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
7495 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7496 host_impl_->SetViewportSize(gfx::Size(100, 100));
7497 host_impl_->top_controls_manager()->UpdateTopControlsState(
7498 BOTH, SHOWN, false);
7499 DrawFrame();
7500
7501 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7502 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7503 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7504 EXPECT_EQ(gfx::Vector2dF().ToString(),
7505 scroll_layer->CurrentScrollOffset().ToString());
7506
7507 // Scroll just the top controls and verify that the scroll succeeds.
7508 const float residue = 10;
7509 float offset = top_controls_height_ - residue;
7510 EXPECT_TRUE(
7511 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7512 EXPECT_FLOAT_EQ(-offset,
7513 host_impl_->top_controls_manager()->ControlsTopOffset());
7514 EXPECT_EQ(gfx::Vector2dF().ToString(),
7515 scroll_layer->CurrentScrollOffset().ToString());
7516
7517 // Scroll across the boundary
7518 const float content_scroll = 20;
7519 offset = residue + content_scroll;
7520 EXPECT_TRUE(
7521 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7522 EXPECT_EQ(-top_controls_height_,
7523 host_impl_->top_controls_manager()->ControlsTopOffset());
7524 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
7525 scroll_layer->CurrentScrollOffset().ToString());
7526
7527 // Now scroll back to the top of the content
7528 offset = -content_scroll;
7529 EXPECT_TRUE(
7530 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7531 EXPECT_EQ(-top_controls_height_,
7532 host_impl_->top_controls_manager()->ControlsTopOffset());
7533 EXPECT_EQ(gfx::Vector2dF().ToString(),
7534 scroll_layer->CurrentScrollOffset().ToString());
7535
7536 // And scroll the top controls completely into view
7537 offset = -top_controls_height_;
7538 EXPECT_TRUE(
7539 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7540 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7541 EXPECT_EQ(gfx::Vector2dF().ToString(),
7542 scroll_layer->CurrentScrollOffset().ToString());
7543
7544 // And attempt to scroll past the end
7545 EXPECT_FALSE(
7546 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7547 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7548 EXPECT_EQ(gfx::Vector2dF().ToString(),
7549 scroll_layer->CurrentScrollOffset().ToString());
7550
7551 host_impl_->ScrollEnd();
7552 }
7553
7554 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
7555 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7556 host_impl_->SetViewportSize(gfx::Size(100, 200));
7557 host_impl_->top_controls_manager()->UpdateTopControlsState(
7558 BOTH, SHOWN, false);
7559 DrawFrame();
7560
7561 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7562 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7563 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7564 EXPECT_EQ(gfx::Vector2dF().ToString(),
7565 scroll_layer->CurrentScrollOffset().ToString());
7566
7567 // Scroll the top controls partially.
7568 const float residue = 35;
7569 float offset = top_controls_height_ - residue;
7570 EXPECT_TRUE(
7571 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7572 EXPECT_FLOAT_EQ(-offset,
7573 host_impl_->top_controls_manager()->ControlsTopOffset());
7574 EXPECT_EQ(gfx::Vector2dF().ToString(),
7575 scroll_layer->CurrentScrollOffset().ToString());
7576
7577 did_request_redraw_ = false;
7578 did_request_animate_ = false;
7579 did_request_commit_ = false;
7580
7581 // End the scroll while the controls are still offset from their limit.
7582 host_impl_->ScrollEnd();
7583 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7584 EXPECT_TRUE(did_request_animate_);
7585 EXPECT_TRUE(did_request_redraw_);
7586 EXPECT_FALSE(did_request_commit_);
7587
7588 // The top controls should properly animate until finished, despite the scroll
7589 // offset being at the origin.
7590 base::TimeTicks animation_time = gfx::FrameTime::Now();
7591 while (did_request_animate_) {
7592 did_request_redraw_ = false;
7593 did_request_animate_ = false;
7594 did_request_commit_ = false;
7595
7596 float old_offset =
7597 host_impl_->top_controls_manager()->ControlsTopOffset();
7598
7599 animation_time += base::TimeDelta::FromMilliseconds(5);
7600 host_impl_->Animate(animation_time);
7601 EXPECT_EQ(gfx::Vector2dF().ToString(),
7602 scroll_layer->CurrentScrollOffset().ToString());
7603
7604 float new_offset =
7605 host_impl_->top_controls_manager()->ControlsTopOffset();
7606
7607 // No commit is needed as the controls are animating the content offset,
7608 // not the scroll offset.
7609 EXPECT_FALSE(did_request_commit_);
7610
7611 if (new_offset != old_offset)
7612 EXPECT_TRUE(did_request_redraw_);
7613
7614 if (new_offset != 0) {
7615 EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
7616 EXPECT_TRUE(did_request_animate_);
7617 }
7618 }
7619 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7620 }
7621
7622 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
7623 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7624 host_impl_->SetViewportSize(gfx::Size(100, 100));
7625 host_impl_->top_controls_manager()->UpdateTopControlsState(
7626 BOTH, SHOWN, false);
7627 float initial_scroll_offset = 50;
7628 scroll_layer->PushScrollOffsetFromMainThread(
7629 gfx::ScrollOffset(0, initial_scroll_offset));
7630 DrawFrame();
7631
7632 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7633 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7634 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7635 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7636 scroll_layer->CurrentScrollOffset().ToString());
7637
7638 // Scroll the top controls partially.
7639 const float residue = 15;
7640 float offset = top_controls_height_ - residue;
7641 EXPECT_TRUE(
7642 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7643 EXPECT_FLOAT_EQ(-offset,
7644 host_impl_->top_controls_manager()->ControlsTopOffset());
7645 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7646 scroll_layer->CurrentScrollOffset().ToString());
7647
7648 did_request_redraw_ = false;
7649 did_request_animate_ = false;
7650 did_request_commit_ = false;
7651
7652 // End the scroll while the controls are still offset from the limit.
7653 host_impl_->ScrollEnd();
7654 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7655 EXPECT_TRUE(did_request_animate_);
7656 EXPECT_TRUE(did_request_redraw_);
7657 EXPECT_FALSE(did_request_commit_);
7658
7659 // Animate the top controls to the limit.
7660 base::TimeTicks animation_time = gfx::FrameTime::Now();
7661 while (did_request_animate_) {
7662 did_request_redraw_ = false;
7663 did_request_animate_ = false;
7664 did_request_commit_ = false;
7665
7666 float old_offset =
7667 host_impl_->top_controls_manager()->ControlsTopOffset();
7668
7669 animation_time += base::TimeDelta::FromMilliseconds(5);
7670 host_impl_->Animate(animation_time);
7671
7672 float new_offset =
7673 host_impl_->top_controls_manager()->ControlsTopOffset();
7674
7675 if (new_offset != old_offset) {
7676 EXPECT_TRUE(did_request_redraw_);
7677 EXPECT_TRUE(did_request_commit_);
7678 }
7679 }
7680 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7681 EXPECT_EQ(-top_controls_height_,
7682 host_impl_->top_controls_manager()->ControlsTopOffset());
7683 }
7684
7685 TEST_F(LayerTreeHostImplWithTopControlsTest,
7686 TopControlsAnimationAfterMainThreadFlingStopped) {
7687 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7688 host_impl_->SetViewportSize(gfx::Size(100, 100));
7689 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7690 false);
7691 float initial_scroll_offset = 50;
7692 scroll_layer->PushScrollOffsetFromMainThread(
7693 gfx::ScrollOffset(0, initial_scroll_offset));
7694 DrawFrame();
7695
7696 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7697 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7698 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7699 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7700 scroll_layer->CurrentScrollOffset().ToString());
7701
7702 // Scroll the top controls partially.
7703 const float residue = 15;
7704 float offset = top_controls_height_ - residue;
7705 EXPECT_TRUE(
7706 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7707 EXPECT_FLOAT_EQ(-offset,
7708 host_impl_->top_controls_manager()->ControlsTopOffset());
7709 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7710 scroll_layer->CurrentScrollOffset().ToString());
7711
7712 did_request_redraw_ = false;
7713 did_request_animate_ = false;
7714 did_request_commit_ = false;
7715
7716 // End the fling while the controls are still offset from the limit.
7717 host_impl_->MainThreadHasStoppedFlinging();
7718 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7719 EXPECT_TRUE(did_request_animate_);
7720 EXPECT_TRUE(did_request_redraw_);
7721 EXPECT_FALSE(did_request_commit_);
7722
7723 // Animate the top controls to the limit.
7724 base::TimeTicks animation_time = gfx::FrameTime::Now();
7725 while (did_request_animate_) {
7726 did_request_redraw_ = false;
7727 did_request_animate_ = false;
7728 did_request_commit_ = false;
7729
7730 float old_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7731
7732 animation_time += base::TimeDelta::FromMilliseconds(5);
7733 host_impl_->Animate(animation_time);
7734
7735 float new_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7736
7737 if (new_offset != old_offset) {
7738 EXPECT_TRUE(did_request_redraw_);
7739 EXPECT_TRUE(did_request_commit_);
7740 }
7741 }
7742 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7743 EXPECT_EQ(-top_controls_height_,
7744 host_impl_->top_controls_manager()->ControlsTopOffset());
7745 }
7746
7747 TEST_F(LayerTreeHostImplWithTopControlsTest,
7748 TopControlsScrollDeltaInOverScroll) {
7749 // test varifies that the overscroll delta should not have accumulated in
7750 // the top controls if we do a hide and show without releasing finger.
7751
7752 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7753 host_impl_->SetViewportSize(gfx::Size(100, 100));
7754 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7755 false);
7756 DrawFrame();
7757
7758 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7759 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7760 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7761
7762 float offset = 50;
7763 EXPECT_TRUE(
7764 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7765 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7766 EXPECT_EQ(gfx::Vector2dF().ToString(),
7767 scroll_layer->CurrentScrollOffset().ToString());
7768
7769 EXPECT_TRUE(
7770 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7771 EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
7772 scroll_layer->CurrentScrollOffset().ToString());
7773
7774 EXPECT_TRUE(
7775 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7776
7777 // Should have fully scrolled
7778 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer->MaxScrollOffset().y()).ToString(),
7779 scroll_layer->CurrentScrollOffset().ToString());
7780
7781 float overscrollamount = 10;
7782
7783 // Overscroll the content
7784 EXPECT_FALSE(
7785 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount))
7786 .did_scroll);
7787 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
7788 scroll_layer->CurrentScrollOffset().ToString());
7789 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount).ToString(),
7790 host_impl_->accumulated_root_overscroll().ToString());
7791
7792 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset))
7793 .did_scroll);
7794 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7795 scroll_layer->CurrentScrollOffset().ToString());
7796 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7797
7798 EXPECT_TRUE(
7799 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset)).did_scroll);
7800 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7801 scroll_layer->CurrentScrollOffset().ToString());
7802
7803 // Top controls should be fully visible
7804 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7805
7806 host_impl_->ScrollEnd();
7807 }
7808
7809 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
7810 public:
7811 void SetupVirtualViewportLayers(const gfx::Size& content_size,
7812 const gfx::Size& outer_viewport,
7813 const gfx::Size& inner_viewport) {
7814 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
7815 const int kOuterViewportClipLayerId = 6;
7816 const int kOuterViewportScrollLayerId = 7;
7817 const int kInnerViewportScrollLayerId = 2;
7818 const int kInnerViewportClipLayerId = 4;
7819 const int kPageScaleLayerId = 5;
7820
7821 scoped_ptr<LayerImpl> inner_scroll =
7822 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
7823 inner_scroll->SetIsContainerForFixedPositionLayers(true);
7824 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7825
7826 scoped_ptr<LayerImpl> inner_clip =
7827 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
7828 inner_clip->SetBounds(inner_viewport);
7829
7830 scoped_ptr<LayerImpl> page_scale =
7831 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
7832
7833 inner_scroll->SetScrollClipLayer(inner_clip->id());
7834 inner_scroll->SetBounds(outer_viewport);
7835 inner_scroll->SetContentBounds(outer_viewport);
7836 inner_scroll->SetPosition(gfx::PointF());
7837
7838 scoped_ptr<LayerImpl> outer_clip =
7839 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
7840 outer_clip->SetBounds(outer_viewport);
7841 outer_clip->SetIsContainerForFixedPositionLayers(true);
7842
7843 scoped_ptr<LayerImpl> outer_scroll =
7844 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
7845 outer_scroll->SetScrollClipLayer(outer_clip->id());
7846 outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7847 outer_scroll->SetBounds(content_size);
7848 outer_scroll->SetContentBounds(content_size);
7849 outer_scroll->SetPosition(gfx::PointF());
7850
7851 scoped_ptr<LayerImpl> contents =
7852 LayerImpl::Create(layer_tree_impl, 8);
7853 contents->SetDrawsContent(true);
7854 contents->SetBounds(content_size);
7855 contents->SetContentBounds(content_size);
7856 contents->SetPosition(gfx::PointF());
7857
7858 outer_scroll->AddChild(contents.Pass());
7859 outer_clip->AddChild(outer_scroll.Pass());
7860 inner_scroll->AddChild(outer_clip.Pass());
7861 page_scale->AddChild(inner_scroll.Pass());
7862 inner_clip->AddChild(page_scale.Pass());
7863
7864 inner_clip->SetHasRenderSurface(true);
7865 layer_tree_impl->SetRootLayer(inner_clip.Pass());
7866 layer_tree_impl->SetViewportLayersFromIds(
7867 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
7868 kOuterViewportScrollLayerId);
7869
7870 host_impl_->active_tree()->DidBecomeActive();
7871 }
7872 };
7873
7874 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
7875 gfx::Size content_size = gfx::Size(100, 160);
7876 gfx::Size outer_viewport = gfx::Size(50, 80);
7877 gfx::Size inner_viewport = gfx::Size(25, 40);
7878
7879 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7880
7881 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7882 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7883 DrawFrame();
7884 {
7885 gfx::Vector2dF inner_expected;
7886 gfx::Vector2dF outer_expected;
7887 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7888 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7889
7890 // Make sure the fling goes to the outer viewport first
7891 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7892 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7893 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7894
7895 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7896 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7897 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7898
7899 host_impl_->ScrollEnd();
7900
7901 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7902 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7903
7904 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7905 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7906 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7907 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7908
7909 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7910 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7911
7912 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7913 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7914
7915 host_impl_->ScrollEnd();
7916
7917 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7918 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7919 }
7920 }
7921
7922 TEST_F(LayerTreeHostImplVirtualViewportTest,
7923 DiagonalScrollBubblesPerfectlyToInner) {
7924 gfx::Size content_size = gfx::Size(100, 160);
7925 gfx::Size outer_viewport = gfx::Size(50, 80);
7926 gfx::Size inner_viewport = gfx::Size(25, 40);
7927
7928 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7929
7930 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7931 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7932 DrawFrame();
7933 {
7934 gfx::Vector2dF inner_expected;
7935 gfx::Vector2dF outer_expected;
7936 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7937 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7938
7939 // Make sure the scroll goes to the outer viewport first.
7940 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7941 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7942 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7943
7944 // Scroll near the edge of the outer viewport.
7945 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7946 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7947 outer_expected += scroll_delta;
7948
7949 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7950 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7951
7952 // Now diagonal scroll across the outer viewport boundary in a single event.
7953 // The entirety of the scroll should be consumed, as bubbling between inner
7954 // and outer viewport layers is perfect.
7955 host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2));
7956 outer_expected += scroll_delta;
7957 inner_expected += scroll_delta;
7958 host_impl_->ScrollEnd();
7959
7960 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7961 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7962 }
7963 }
7964
7965 TEST_F(LayerTreeHostImplVirtualViewportTest,
7966 TouchFlingCanLockToViewportLayerAfterBubbling) {
7967 gfx::Size content_size = gfx::Size(100, 160);
7968 gfx::Size outer_viewport = gfx::Size(50, 80);
7969 gfx::Size inner_viewport = gfx::Size(25, 40);
7970
7971 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7972
7973 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7974 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7975
7976 scoped_ptr<LayerImpl> child =
7977 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7978 LayerImpl* child_scroll = child.get();
7979 outer_scroll->children()[0]->AddChild(child.Pass());
7980
7981 DrawFrame();
7982 {
7983 scoped_ptr<ScrollAndScaleSet> scroll_info;
7984
7985 gfx::Vector2d scroll_delta(0, inner_viewport.height());
7986 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7987 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7988 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7989
7990 // The child should have scrolled up to its limit.
7991 scroll_info = host_impl_->ProcessScrollDeltas();
7992 ASSERT_EQ(1u, scroll_info->scrolls.size());
7993 ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
7994 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7995
7996 // The first |ScrollBy| after the fling should re-lock the scrolling
7997 // layer to the first layer that scrolled, the inner viewport scroll layer.
7998 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7999 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
8000 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
8001
8002 // The inner viewport should have scrolled up to its limit.
8003 scroll_info = host_impl_->ProcessScrollDeltas();
8004 ASSERT_EQ(2u, scroll_info->scrolls.size());
8005 ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
8006 ExpectContains(*scroll_info, inner_scroll->id(), scroll_delta);
8007
8008 // As the locked layer is at its limit, no further scrolling can occur.
8009 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
8010 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
8011 host_impl_->ScrollEnd();
8012 }
8013 }
8014
8015 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
8016 public:
8017 void SetUp() override {
8018 LayerTreeSettings settings = DefaultSettings();
8019 settings.max_memory_for_prepaint_percentage = 50;
8020 CreateHostImpl(settings, CreateOutputSurface());
8021 }
8022 };
8023
8024 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
8025 // Set up a memory policy and percentages which could cause
8026 // 32-bit integer overflows.
8027 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
8028
8029 // Verify implicit limits are calculated correctly with no overflows
8030 host_impl_->SetMemoryPolicy(mem_policy);
8031 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
8032 300u * 1024u * 1024u);
8033 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
8034 150u * 1024u * 1024u);
8035 }
8036
8037 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
8038 const gfx::Size layer_size(100, 100);
8039 gfx::Transform external_transform;
8040 const gfx::Rect external_viewport(layer_size);
8041 const gfx::Rect external_clip(layer_size);
8042 const bool resourceless_software_draw = false;
8043 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
8044
8045 host_impl_->SetExternalDrawConstraints(external_transform,
8046 external_viewport,
8047 external_clip,
8048 external_viewport,
8049 external_transform,
8050 resourceless_software_draw);
8051 DrawFrame();
8052 EXPECT_TRANSFORMATION_MATRIX_EQ(
8053 external_transform, layer->draw_properties().target_space_transform);
8054
8055 external_transform.Translate(20, 20);
8056 host_impl_->SetExternalDrawConstraints(external_transform,
8057 external_viewport,
8058 external_clip,
8059 external_viewport,
8060 external_transform,
8061 resourceless_software_draw);
8062 DrawFrame();
8063 EXPECT_TRANSFORMATION_MATRIX_EQ(
8064 external_transform, layer->draw_properties().target_space_transform);
8065 }
8066
8067 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
8068 SetupScrollAndContentsLayers(gfx::Size(100, 200));
8069 DrawFrame();
8070
8071 base::TimeTicks start_time =
8072 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
8073
8074 EXPECT_EQ(InputHandler::SCROLL_STARTED,
8075 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8076
8077 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
8078
8079 host_impl_->Animate(start_time);
8080 host_impl_->UpdateAnimationState(true);
8081
8082 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
8083
8084 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
8085 host_impl_->UpdateAnimationState(true);
8086
8087 float y = scrolling_layer->CurrentScrollOffset().y();
8088 EXPECT_TRUE(y > 1 && y < 49);
8089
8090 // Update target.
8091 EXPECT_EQ(InputHandler::SCROLL_STARTED,
8092 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8093
8094 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
8095 host_impl_->UpdateAnimationState(true);
8096
8097 y = scrolling_layer->CurrentScrollOffset().y();
8098 EXPECT_TRUE(y > 50 && y < 100);
8099 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
8100
8101 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
8102 host_impl_->UpdateAnimationState(true);
8103
8104 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8105 scrolling_layer->CurrentScrollOffset());
8106 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
8107 }
8108
8109 TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairs) {
8110 host_impl_->CreatePendingTree();
8111
8112 scoped_ptr<PictureLayerImpl> layer =
8113 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 10);
8114 layer->SetBounds(gfx::Size(10, 10));
8115 scoped_ptr<FakePictureLayerImpl> nondraw_layer =
8116 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 12);
8117 nondraw_layer->SetBounds(gfx::Size(10, 10));
8118
8119 scoped_refptr<RasterSource> pile(FakePicturePileImpl::CreateEmptyPile(
8120 gfx::Size(10, 10), gfx::Size(10, 10)));
8121 Region empty_invalidation;
8122 const PictureLayerTilingSet* null_tiling_set = nullptr;
8123 layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
8124 layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
8125 nondraw_layer->set_gpu_raster_max_texture_size(
8126 host_impl_->device_viewport_size());
8127 nondraw_layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
8128
8129 layer->AddChild(nondraw_layer.Pass());
8130 host_impl_->pending_tree()->SetRootLayer(layer.Pass());
8131
8132 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
8133 LayerImpl* pending_layer = pending_tree->root_layer();
8134 FakePictureLayerImpl* pending_nondraw_layer =
8135 static_cast<FakePictureLayerImpl*>(pending_layer->children()[0]);
8136
8137 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
8138
8139 std::vector<PictureLayerImpl::Pair> layer_pairs;
8140 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
8141 EXPECT_EQ(1u, layer_pairs.size());
8142 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
8143 EXPECT_EQ(nullptr, layer_pairs[0].active);
8144
8145 host_impl_->ActivateSyncTree();
8146
8147 LayerTreeImpl* active_tree = host_impl_->active_tree();
8148 LayerImpl* active_layer = active_tree->root_layer();
8149 FakePictureLayerImpl* active_nondraw_layer =
8150 static_cast<FakePictureLayerImpl*>(active_layer->children()[0]);
8151 EXPECT_NE(active_tree, pending_tree);
8152 EXPECT_NE(active_layer, pending_layer);
8153 EXPECT_NE(active_nondraw_layer, pending_nondraw_layer);
8154 EXPECT_NE(nullptr, active_tree);
8155 EXPECT_NE(nullptr, active_layer);
8156 EXPECT_NE(nullptr, active_nondraw_layer);
8157
8158 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
8159
8160 host_impl_->CreatePendingTree();
8161
8162 layer_pairs.clear();
8163 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
8164 EXPECT_EQ(1u, layer_pairs.size());
8165 EXPECT_EQ(active_layer, layer_pairs[0].active);
8166 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
8167
8168 // Activate, the active layer has no twin now.
8169 host_impl_->ActivateSyncTree();
8170
8171 layer_pairs.clear();
8172 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
8173 EXPECT_EQ(1u, layer_pairs.size());
8174 EXPECT_EQ(active_layer, layer_pairs[0].active);
8175 EXPECT_EQ(nullptr, layer_pairs[0].pending);
8176
8177 // Create another layer in the pending tree that's not in the active tree. We
8178 // should get two pairs.
8179 host_impl_->CreatePendingTree();
8180 host_impl_->pending_tree()->root_layer()->AddChild(
8181 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11));
8182
8183 LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[1];
8184
8185 layer_pairs.clear();
8186 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
8187 EXPECT_EQ(2u, layer_pairs.size());
8188 // The pair ordering is flaky, so make it consistent.
8189 if (layer_pairs[0].active != active_layer)
8190 std::swap(layer_pairs[0], layer_pairs[1]);
8191 EXPECT_EQ(active_layer, layer_pairs[0].active);
8192 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
8193 EXPECT_EQ(new_pending_layer, layer_pairs[1].pending);
8194 EXPECT_EQ(nullptr, layer_pairs[1].active);
8195
8196 host_impl_->pending_tree()->root_layer()->RemoveChild(new_pending_layer);
8197
8198 // Have the pending layer be part of the RSLL now. It should appear in the
8199 // list without an active twin.
8200 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
8201
8202 layer_pairs.clear();
8203 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
8204 EXPECT_EQ(2u, layer_pairs.size());
8205 // The pair ordering is flaky, so make it consistent.
8206 if (layer_pairs[0].active != active_layer)
8207 std::swap(layer_pairs[0], layer_pairs[1]);
8208 EXPECT_EQ(active_layer, layer_pairs[0].active);
8209 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
8210 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
8211 EXPECT_EQ(nullptr, layer_pairs[1].active);
8212
8213 // Have the active layer be part of the RSLL now instead. It should appear in
8214 // the list without a pending twin.
8215 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
8216 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
8217
8218 layer_pairs.clear();
8219 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
8220 EXPECT_EQ(2u, layer_pairs.size());
8221 // The pair ordering is flaky, so make it consistent.
8222 if (layer_pairs[0].active != active_layer)
8223 std::swap(layer_pairs[0], layer_pairs[1]);
8224 EXPECT_EQ(active_layer, layer_pairs[0].active);
8225 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
8226 EXPECT_EQ(nullptr, layer_pairs[1].pending);
8227 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
8228 }
8229
8230 TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairsWithNonRSLLMembers) {
8231 host_impl_->CreatePendingTree();
8232
8233 scoped_ptr<PictureLayerImpl> layer =
8234 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 10);
8235 layer->SetBounds(gfx::Size(10, 10));
8236 scoped_ptr<FakePictureLayerImpl> nondraw_layer =
8237 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 12);
8238 nondraw_layer->SetBounds(gfx::Size(10, 10));
8239
8240 scoped_refptr<RasterSource> pile(FakePicturePileImpl::CreateEmptyPile(
8241 gfx::Size(10, 10), gfx::Size(10, 10)));
8242 Region empty_invalidation;
8243 const PictureLayerTilingSet* null_tiling_set = nullptr;
8244 layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
8245 layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
8246 nondraw_layer->set_gpu_raster_max_texture_size(
8247 host_impl_->device_viewport_size());
8248 nondraw_layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
8249
8250 layer->AddChild(nondraw_layer.Pass());
8251 host_impl_->pending_tree()->SetRootLayer(layer.Pass());
8252
8253 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
8254 LayerImpl* pending_layer = pending_tree->root_layer();
8255 FakePictureLayerImpl* pending_nondraw_layer =
8256 static_cast<FakePictureLayerImpl*>(pending_layer->children()[0]);
8257
8258 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
8259
8260 std::vector<PictureLayerImpl::Pair> layer_pairs;
8261 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
8262 EXPECT_EQ(2u, layer_pairs.size());
8263 // The pair ordering is flaky, so make it consistent.
8264 if (layer_pairs[0].pending != pending_layer)
8265 std::swap(layer_pairs[0], layer_pairs[1]);
8266 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
8267 EXPECT_EQ(nullptr, layer_pairs[0].active);
8268 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
8269 EXPECT_EQ(nullptr, layer_pairs[1].active);
8270
8271 host_impl_->ActivateSyncTree();
8272
8273 LayerTreeImpl* active_tree = host_impl_->active_tree();
8274 LayerImpl* active_layer = active_tree->root_layer();
8275 FakePictureLayerImpl* active_nondraw_layer =
8276 static_cast<FakePictureLayerImpl*>(active_layer->children()[0]);
8277 EXPECT_NE(active_tree, pending_tree);
8278 EXPECT_NE(active_layer, pending_layer);
8279 EXPECT_NE(active_nondraw_layer, pending_nondraw_layer);
8280 EXPECT_NE(nullptr, active_tree);
8281 EXPECT_NE(nullptr, active_layer);
8282 EXPECT_NE(nullptr, active_nondraw_layer);
8283
8284 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
8285
8286 host_impl_->CreatePendingTree();
8287
8288 layer_pairs.clear();
8289 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
8290 EXPECT_EQ(2u, layer_pairs.size());
8291 // The pair ordering is flaky, so make it consistent.
8292 if (layer_pairs[0].active != active_layer)
8293 std::swap(layer_pairs[0], layer_pairs[1]);
8294 EXPECT_EQ(active_layer, layer_pairs[0].active);
8295 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
8296 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
8297 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
8298
8299 // Activate, the active layer has no twin now.
8300 host_impl_->ActivateSyncTree();
8301
8302 layer_pairs.clear();
8303 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
8304 EXPECT_EQ(2u, layer_pairs.size());
8305 // The pair ordering is flaky, so make it consistent.
8306 if (layer_pairs[0].active != active_layer)
8307 std::swap(layer_pairs[0], layer_pairs[1]);
8308 EXPECT_EQ(active_layer, layer_pairs[0].active);
8309 EXPECT_EQ(nullptr, layer_pairs[0].pending);
8310 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
8311 EXPECT_EQ(nullptr, layer_pairs[1].pending);
8312
8313 // Create another layer in the pending tree that's not in the active tree. We
8314 // should get three pairs including the nondraw layers.
8315 host_impl_->CreatePendingTree();
8316 host_impl_->pending_tree()->root_layer()->AddChild(
8317 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11));
8318
8319 LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[1];
8320
8321 layer_pairs.clear();
8322 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
8323 EXPECT_EQ(3u, layer_pairs.size());
8324 // The pair ordering is flaky, so make it consistent.
8325 if (layer_pairs[0].active != active_layer)
8326 std::swap(layer_pairs[0], layer_pairs[1]);
8327 if (layer_pairs[0].active != active_layer)
8328 std::swap(layer_pairs[0], layer_pairs[2]);
8329 if (layer_pairs[1].pending != new_pending_layer)
8330 std::swap(layer_pairs[1], layer_pairs[2]);
8331 EXPECT_EQ(active_layer, layer_pairs[0].active);
8332 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
8333 EXPECT_EQ(new_pending_layer, layer_pairs[1].pending);
8334 EXPECT_EQ(nullptr, layer_pairs[1].active);
8335 EXPECT_EQ(active_nondraw_layer, layer_pairs[2].active);
8336 EXPECT_EQ(pending_nondraw_layer, layer_pairs[2].pending);
8337
8338 host_impl_->pending_tree()->root_layer()->RemoveChild(new_pending_layer);
8339
8340 // Have the pending layer be part of the RSLL now. It should appear in the
8341 // list, as should its active twin since we don't request only layers with
8342 // valid draw properties.
8343 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
8344
8345 layer_pairs.clear();
8346 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
8347 EXPECT_EQ(2u, layer_pairs.size());
8348 // The pair ordering is flaky, so make it consistent.
8349 if (layer_pairs[0].active != active_layer)
8350 std::swap(layer_pairs[0], layer_pairs[1]);
8351 EXPECT_EQ(active_layer, layer_pairs[0].active);
8352 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
8353 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
8354 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
8355
8356 // Have the active layer be part of the RSLL now instead. It should appear in
8357 // the list, as should its pending twin since we don't request only layers
8358 // with valid draw properties.
8359 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
8360 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
8361
8362 layer_pairs.clear();
8363 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
8364 EXPECT_EQ(2u, layer_pairs.size());
8365 // The pair ordering is flaky, so make it consistent.
8366 if (layer_pairs[0].active != active_layer)
8367 std::swap(layer_pairs[0], layer_pairs[1]);
8368 EXPECT_EQ(active_layer, layer_pairs[0].active);
8369 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
8370 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
8371 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
8372 }
8373
8374 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
8375 host_impl_->CreatePendingTree();
8376 host_impl_->ActivateSyncTree();
8377 host_impl_->CreatePendingTree();
8378
8379 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
8380
8381 scoped_ptr<FakePictureLayerImpl> pending_layer =
8382 FakePictureLayerImpl::Create(pending_tree, 10);
8383 FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
8384 pending_tree->SetRootLayer(pending_layer.Pass());
8385 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
8386
8387 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
8388 pending_tree->DidBecomeActive();
8389 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
8390
8391 scoped_ptr<FakePictureLayerImpl> mask_layer =
8392 FakePictureLayerImpl::Create(pending_tree, 11);
8393 FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
8394 raw_pending_layer->SetMaskLayer(mask_layer.Pass());
8395 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
8396
8397 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
8398 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
8399 pending_tree->DidBecomeActive();
8400 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
8401 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
8402
8403 scoped_ptr<FakePictureLayerImpl> replica_layer =
8404 FakePictureLayerImpl::Create(pending_tree, 12);
8405 scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
8406 FakePictureLayerImpl::Create(pending_tree, 13);
8407 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
8408 replica_layer->SetMaskLayer(replica_mask_layer.Pass());
8409 raw_pending_layer->SetReplicaLayer(replica_layer.Pass());
8410 ASSERT_EQ(raw_replica_mask_layer,
8411 raw_pending_layer->replica_layer()->mask_layer());
8412
8413 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
8414 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
8415 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
8416 pending_tree->DidBecomeActive();
8417 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
8418 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
8419 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
8420 }
8421
8422 TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
8423 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
8424 host_impl_->SetViewportSize(gfx::Size(50, 50));
8425 DrawFrame();
8426
8427 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
8428
8429 float min_page_scale = 1.f, max_page_scale = 4.f;
8430 float page_scale_factor = 1.f;
8431
8432 // The scroll deltas should have the page scale factor applied.
8433 {
8434 host_impl_->active_tree()->PushPageScaleFromMainThread(
8435 page_scale_factor, min_page_scale, max_page_scale);
8436 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
8437 scroll_layer->SetScrollDelta(gfx::Vector2d());
8438
8439 float page_scale_delta = 2.f;
8440 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
8441 host_impl_->PinchGestureBegin();
8442 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
8443 host_impl_->PinchGestureEnd();
8444 host_impl_->ScrollEnd();
8445
8446 gfx::Vector2dF scroll_delta(0, 5);
8447 EXPECT_EQ(InputHandler::SCROLL_STARTED,
8448 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
8449 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
8450
8451 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
8452 host_impl_->ScrollEnd();
8453 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
8454 scroll_layer->CurrentScrollOffset());
8455 }
8456 }
8457
8458 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
8459 public:
8460 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
8461 void DidLoseOutputSurfaceOnImplThread() override { num_lost_surfaces_++; }
8462
8463 protected:
8464 int num_lost_surfaces_;
8465 };
8466
8467 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
8468 // Really we just need at least one client notification each time
8469 // we go from having a valid output surface to not having a valid output
8470 // surface.
8471 EXPECT_EQ(0, num_lost_surfaces_);
8472 host_impl_->DidLoseOutputSurface();
8473 EXPECT_EQ(1, num_lost_surfaces_);
8474 host_impl_->DidLoseOutputSurface();
8475 EXPECT_LE(1, num_lost_surfaces_);
8476 }
8477
8478 } // namespace
8479 } // namespace cc
OLDNEW
« no previous file with comments | « cc/trees/layer_tree_host_impl.cc ('k') | cc/trees/layer_tree_host_perftest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698