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