1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host_impl.h"
10 #include "base/command_line.h"
11 #include "base/containers/hash_tables.h"
12 #include "base/containers/scoped_ptr_hash_map.h"
13 #include "cc/animation/scrollbar_animation_controller_thinning.h"
14 #include "cc/base/latency_info_swap_promise.h"
15 #include "cc/base/math_util.h"
16 #include "cc/input/top_controls_manager.h"
17 #include "cc/layers/append_quads_data.h"
18 #include "cc/layers/delegated_renderer_layer_impl.h"
19 #include "cc/layers/heads_up_display_layer_impl.h"
20 #include "cc/layers/io_surface_layer_impl.h"
21 #include "cc/layers/layer_impl.h"
22 #include "cc/layers/painted_scrollbar_layer_impl.h"
23 #include "cc/layers/quad_sink.h"
24 #include "cc/layers/render_surface_impl.h"
25 #include "cc/layers/solid_color_layer_impl.h"
26 #include "cc/layers/texture_layer_impl.h"
27 #include "cc/layers/tiled_layer_impl.h"
28 #include "cc/layers/video_layer_impl.h"
29 #include "cc/output/begin_frame_args.h"
30 #include "cc/output/compositor_frame_ack.h"
31 #include "cc/output/compositor_frame_metadata.h"
32 #include "cc/output/copy_output_request.h"
33 #include "cc/output/copy_output_result.h"
34 #include "cc/output/gl_renderer.h"
35 #include "cc/quads/render_pass_draw_quad.h"
36 #include "cc/quads/solid_color_draw_quad.h"
37 #include "cc/quads/texture_draw_quad.h"
38 #include "cc/quads/tile_draw_quad.h"
39 #include "cc/resources/layer_tiling_data.h"
40 #include "cc/test/animation_test_common.h"
41 #include "cc/test/fake_layer_tree_host_impl.h"
42 #include "cc/test/fake_output_surface.h"
43 #include "cc/test/fake_output_surface_client.h"
44 #include "cc/test/fake_picture_layer_impl.h"
45 #include "cc/test/fake_picture_pile_impl.h"
46 #include "cc/test/fake_proxy.h"
47 #include "cc/test/fake_rendering_stats_instrumentation.h"
48 #include "cc/test/fake_video_frame_provider.h"
49 #include "cc/test/geometry_test_utils.h"
50 #include "cc/test/layer_test_common.h"
51 #include "cc/test/render_pass_test_common.h"
52 #include "cc/test/test_shared_bitmap_manager.h"
53 #include "cc/test/test_web_graphics_context_3d.h"
54 #include "cc/trees/layer_tree_impl.h"
55 #include "cc/trees/single_thread_proxy.h"
56 #include "media/base/media.h"
57 #include "testing/gmock/include/gmock/gmock.h"
58 #include "testing/gtest/include/gtest/gtest.h"
59 #include "third_party/skia/include/core/SkMallocPixelRef.h"
60 #include "ui/gfx/frame_time.h"
61 #include "ui/gfx/rect_conversions.h"
62 #include "ui/gfx/size_conversions.h"
63 #include "ui/gfx/vector2d_conversions.h"
65 using ::testing::Mock;
66 using ::testing::Return;
67 using ::testing::AnyNumber;
68 using ::testing::AtLeast;
70 using media::VideoFrame;
75 class LayerTreeHostImplTest : public testing::Test,
76 public LayerTreeHostImplClient {
78 LayerTreeHostImplTest()
79 : proxy_(base::MessageLoopProxy::current()),
80 always_impl_thread_(&proxy_),
81 always_main_thread_blocked_(&proxy_),
82 shared_bitmap_manager_(new TestSharedBitmapManager()),
83 on_can_draw_state_changed_called_(false),
84 did_notify_ready_to_activate_(false),
85 did_request_commit_(false),
86 did_request_redraw_(false),
87 did_request_manage_tiles_(false),
88 did_upload_visible_tile_(false),
89 reduce_memory_result_(true),
90 current_limit_bytes_(0),
91 current_priority_cutoff_value_(0) {
92 media::InitializeMediaLibraryForTesting();
95 LayerTreeSettings DefaultSettings() {
96 LayerTreeSettings settings;
97 settings.minimum_occlusion_tracking_size = gfx::Size();
98 settings.impl_side_painting = true;
99 settings.texture_id_allocation_chunk_size = 1;
103 virtual void SetUp() OVERRIDE {
104 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
107 virtual void TearDown() OVERRIDE {}
109 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {}
110 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
111 virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
112 virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {}
113 virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE {}
114 virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
115 on_can_draw_state_changed_called_ = true;
117 virtual void NotifyReadyToActivate() OVERRIDE {
118 did_notify_ready_to_activate_ = true;
119 host_impl_->ActivatePendingTree();
121 virtual void SetNeedsRedrawOnImplThread() OVERRIDE {
122 did_request_redraw_ = true;
124 virtual void SetNeedsRedrawRectOnImplThread(
125 const gfx::Rect& damage_rect) OVERRIDE {
126 did_request_redraw_ = true;
128 virtual void SetNeedsManageTilesOnImplThread() OVERRIDE {
129 did_request_manage_tiles_ = true;
131 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {
132 did_upload_visible_tile_ = true;
134 virtual void SetNeedsCommitOnImplThread() OVERRIDE {
135 did_request_commit_ = true;
137 virtual void PostAnimationEventsToMainThreadOnImplThread(
138 scoped_ptr<AnimationEventsVector> events) OVERRIDE {}
139 virtual bool ReduceContentsTextureMemoryOnImplThread(
140 size_t limit_bytes, int priority_cutoff) OVERRIDE {
141 current_limit_bytes_ = limit_bytes;
142 current_priority_cutoff_value_ = priority_cutoff;
143 return reduce_memory_result_;
145 virtual void SendManagedMemoryStats() OVERRIDE {}
146 virtual bool IsInsideDraw() OVERRIDE { return false; }
147 virtual void RenewTreePriority() OVERRIDE {}
148 virtual void RequestScrollbarAnimationOnImplThread(base::TimeDelta delay)
149 OVERRIDE { requested_scrollbar_animation_delay_ = delay; }
150 virtual void DidActivatePendingTree() OVERRIDE {}
151 virtual void DidManageTiles() OVERRIDE {}
153 void set_reduce_memory_result(bool reduce_memory_result) {
154 reduce_memory_result_ = reduce_memory_result;
157 bool CreateHostImpl(const LayerTreeSettings& settings,
158 scoped_ptr<OutputSurface> output_surface) {
159 host_impl_ = LayerTreeHostImpl::Create(settings,
162 &stats_instrumentation_,
163 shared_bitmap_manager_.get(),
165 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
166 host_impl_->SetViewportSize(gfx::Size(10, 10));
170 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
171 root->SetAnchorPoint(gfx::PointF());
172 root->SetPosition(gfx::PointF());
173 root->SetBounds(gfx::Size(10, 10));
174 root->SetContentBounds(gfx::Size(10, 10));
175 root->SetDrawsContent(true);
176 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
177 host_impl_->active_tree()->SetRootLayer(root.Pass());
180 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
181 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
182 for (size_t i = 0; i < layer->children().size(); ++i)
183 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
186 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
188 const gfx::Vector2d& scroll_delta) {
189 int times_encountered = 0;
191 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
192 if (scroll_info.scrolls[i].layer_id != id)
194 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
198 ASSERT_EQ(1, times_encountered);
201 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
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)
210 ASSERT_EQ(0, times_encountered);
213 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
214 const gfx::Size& content_size) {
215 const int kInnerViewportScrollLayerId = 2;
216 const int kInnerViewportClipLayerId = 4;
217 const int kPageScaleLayerId = 5;
218 scoped_ptr<LayerImpl> root =
219 LayerImpl::Create(layer_tree_impl, 1);
220 root->SetBounds(content_size);
221 root->SetContentBounds(content_size);
222 root->SetPosition(gfx::PointF());
223 root->SetAnchorPoint(gfx::PointF());
225 scoped_ptr<LayerImpl> scroll =
226 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
227 LayerImpl* scroll_layer = scroll.get();
228 scroll->SetIsContainerForFixedPositionLayers(true);
229 scroll->SetScrollOffset(gfx::Vector2d());
231 scoped_ptr<LayerImpl> clip =
232 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
234 gfx::Size(content_size.width() / 2, content_size.height() / 2));
236 scoped_ptr<LayerImpl> page_scale =
237 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
239 scroll->SetScrollClipLayer(clip->id());
240 scroll->SetBounds(content_size);
241 scroll->SetContentBounds(content_size);
242 scroll->SetPosition(gfx::PointF());
243 scroll->SetAnchorPoint(gfx::PointF());
244 scroll->SetIsContainerForFixedPositionLayers(true);
246 scoped_ptr<LayerImpl> contents =
247 LayerImpl::Create(layer_tree_impl, 3);
248 contents->SetDrawsContent(true);
249 contents->SetBounds(content_size);
250 contents->SetContentBounds(content_size);
251 contents->SetPosition(gfx::PointF());
252 contents->SetAnchorPoint(gfx::PointF());
254 scroll->AddChild(contents.Pass());
255 page_scale->AddChild(scroll.Pass());
256 clip->AddChild(page_scale.Pass());
257 root->AddChild(clip.Pass());
259 layer_tree_impl->SetRootLayer(root.Pass());
260 layer_tree_impl->SetViewportLayersFromIds(
261 kPageScaleLayerId, kInnerViewportScrollLayerId, Layer::INVALID_ID);
266 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
267 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
268 host_impl_->active_tree(), content_size);
269 host_impl_->active_tree()->DidBecomeActive();
273 // TODO(wjmaclean) Add clip-layer pointer to parameters.
274 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
275 const gfx::Size& size,
276 LayerImpl* clip_layer) {
278 DCHECK(id != clip_layer->id());
279 scoped_ptr<LayerImpl> layer =
280 LayerImpl::Create(host_impl_->active_tree(), id);
281 layer->SetScrollClipLayer(clip_layer->id());
282 layer->SetDrawsContent(true);
283 layer->SetBounds(size);
284 layer->SetContentBounds(size);
285 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
290 LayerTreeHostImpl::FrameData frame;
291 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
292 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
293 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
294 host_impl_->DidDrawAllLayers(frame);
297 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
298 void pinch_zoom_pan_viewport_test(float device_scale_factor);
299 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
300 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
301 float device_scale_factor);
303 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
304 // Note: It is not possible to disable the renderer once it has been set,
305 // so we do not need to test that disabling the renderer notifies us
306 // that can_draw changed.
307 EXPECT_FALSE(host_impl_->CanDraw());
308 on_can_draw_state_changed_called_ = false;
310 // Set up the root layer, which allows us to draw.
311 SetupScrollAndContentsLayers(gfx::Size(100, 100));
312 EXPECT_TRUE(host_impl_->CanDraw());
313 EXPECT_TRUE(on_can_draw_state_changed_called_);
314 on_can_draw_state_changed_called_ = false;
316 // Toggle the root layer to make sure it toggles can_draw
317 host_impl_->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
318 EXPECT_FALSE(host_impl_->CanDraw());
319 EXPECT_TRUE(on_can_draw_state_changed_called_);
320 on_can_draw_state_changed_called_ = false;
322 SetupScrollAndContentsLayers(gfx::Size(100, 100));
323 EXPECT_TRUE(host_impl_->CanDraw());
324 EXPECT_TRUE(on_can_draw_state_changed_called_);
325 on_can_draw_state_changed_called_ = false;
327 // Toggle the device viewport size to make sure it toggles can_draw.
328 host_impl_->SetViewportSize(gfx::Size());
330 EXPECT_TRUE(host_impl_->CanDraw());
332 EXPECT_FALSE(host_impl_->CanDraw());
334 EXPECT_TRUE(on_can_draw_state_changed_called_);
335 on_can_draw_state_changed_called_ = false;
337 host_impl_->SetViewportSize(gfx::Size(100, 100));
338 EXPECT_TRUE(host_impl_->CanDraw());
339 EXPECT_TRUE(on_can_draw_state_changed_called_);
340 on_can_draw_state_changed_called_ = false;
342 // Toggle contents textures purged without causing any evictions,
343 // and make sure that it does not change can_draw.
344 set_reduce_memory_result(false);
345 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
346 host_impl_->memory_allocation_limit_bytes() - 1));
347 EXPECT_TRUE(host_impl_->CanDraw());
348 EXPECT_FALSE(on_can_draw_state_changed_called_);
349 on_can_draw_state_changed_called_ = false;
351 // Toggle contents textures purged to make sure it toggles can_draw.
352 set_reduce_memory_result(true);
353 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
354 host_impl_->memory_allocation_limit_bytes() - 1));
356 EXPECT_TRUE(host_impl_->CanDraw());
358 EXPECT_FALSE(host_impl_->CanDraw());
360 EXPECT_TRUE(on_can_draw_state_changed_called_);
361 on_can_draw_state_changed_called_ = false;
363 host_impl_->active_tree()->ResetContentsTexturesPurged();
364 EXPECT_TRUE(host_impl_->CanDraw());
365 EXPECT_TRUE(on_can_draw_state_changed_called_);
366 on_can_draw_state_changed_called_ = false;
369 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
372 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
373 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
376 void DrawOneFrame() {
377 LayerTreeHostImpl::FrameData frame_data;
378 host_impl_->PrepareToDraw(&frame_data, gfx::Rect());
379 host_impl_->DidDrawAllLayers(frame_data);
383 DebugScopedSetImplThread always_impl_thread_;
384 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
386 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
387 scoped_ptr<LayerTreeHostImpl> host_impl_;
388 FakeRenderingStatsInstrumentation stats_instrumentation_;
389 bool on_can_draw_state_changed_called_;
390 bool did_notify_ready_to_activate_;
391 bool did_request_commit_;
392 bool did_request_redraw_;
393 bool did_request_manage_tiles_;
394 bool did_upload_visible_tile_;
395 bool reduce_memory_result_;
396 base::TimeDelta requested_scrollbar_animation_delay_;
397 size_t current_limit_bytes_;
398 int current_priority_cutoff_value_;
401 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
402 bool always_draw = false;
403 CheckNotifyCalledIfCanDrawChanged(always_draw);
406 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
407 scoped_ptr<FakeOutputSurface> output_surface(
408 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
409 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
411 bool always_draw = true;
412 CheckNotifyCalledIfCanDrawChanged(always_draw);
415 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
416 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
418 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
419 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
422 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
424 scoped_ptr<LayerImpl> root =
425 LayerImpl::Create(host_impl_->active_tree(), 1);
426 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
427 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
428 root->children()[1]->AddChild(
429 LayerImpl::Create(host_impl_->active_tree(), 4));
430 root->children()[1]->AddChild(
431 LayerImpl::Create(host_impl_->active_tree(), 5));
432 root->children()[1]->children()[0]->AddChild(
433 LayerImpl::Create(host_impl_->active_tree(), 6));
434 host_impl_->active_tree()->SetRootLayer(root.Pass());
436 LayerImpl* root = host_impl_->active_tree()->root_layer();
438 ExpectClearedScrollDeltasRecursive(root);
440 scoped_ptr<ScrollAndScaleSet> scroll_info;
442 scroll_info = host_impl_->ProcessScrollDeltas();
443 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
444 ExpectClearedScrollDeltasRecursive(root);
446 scroll_info = host_impl_->ProcessScrollDeltas();
447 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
448 ExpectClearedScrollDeltasRecursive(root);
451 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
452 gfx::Vector2d scroll_offset(20, 30);
453 gfx::Vector2d scroll_delta(11, -15);
455 scoped_ptr<LayerImpl> root_clip =
456 LayerImpl::Create(host_impl_->active_tree(), 2);
457 scoped_ptr<LayerImpl> root =
458 LayerImpl::Create(host_impl_->active_tree(), 1);
459 root_clip->SetBounds(gfx::Size(10, 10));
460 LayerImpl* root_layer = root.get();
461 root_clip->AddChild(root.Pass());
462 root_layer->SetBounds(gfx::Size(110, 110));
463 root_layer->SetScrollClipLayer(root_clip->id());
464 root_layer->SetScrollOffset(scroll_offset);
465 root_layer->ScrollBy(scroll_delta);
466 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
468 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
470 scoped_ptr<ScrollAndScaleSet> scroll_info;
472 scroll_info = host_impl_->ProcessScrollDeltas();
473 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
474 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta);
475 ExpectContains(*scroll_info, root->id(), scroll_delta);
477 gfx::Vector2d scroll_delta2(-5, 27);
478 root->ScrollBy(scroll_delta2);
479 scroll_info = host_impl_->ProcessScrollDeltas();
480 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
481 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
482 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
484 root->ScrollBy(gfx::Vector2d());
485 scroll_info = host_impl_->ProcessScrollDeltas();
486 EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
489 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
490 SetupScrollAndContentsLayers(gfx::Size(100, 100));
491 host_impl_->SetViewportSize(gfx::Size(50, 50));
494 EXPECT_EQ(InputHandler::ScrollStarted,
495 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
496 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
497 host_impl_->ScrollEnd();
498 EXPECT_TRUE(did_request_redraw_);
499 EXPECT_TRUE(did_request_commit_);
502 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
503 // We should not crash when trying to scroll an empty layer tree.
504 EXPECT_EQ(InputHandler::ScrollIgnored,
505 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
508 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
509 scoped_ptr<TestWebGraphicsContext3D> context_owned =
510 TestWebGraphicsContext3D::Create();
511 context_owned->set_context_lost(true);
513 scoped_ptr<FakeOutputSurface> output_surface(FakeOutputSurface::Create3d(
514 context_owned.Pass()));
516 // Initialization will fail.
517 EXPECT_FALSE(CreateHostImpl(DefaultSettings(),
518 output_surface.PassAs<OutputSurface>()));
520 SetupScrollAndContentsLayers(gfx::Size(100, 100));
522 // We should not crash when trying to scroll after the renderer initialization
524 EXPECT_EQ(InputHandler::ScrollIgnored,
525 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
528 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
529 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
530 host_impl_->SetViewportSize(gfx::Size(50, 50));
533 // We should not crash if the tree is replaced while we are scrolling.
534 EXPECT_EQ(InputHandler::ScrollStarted,
535 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
536 host_impl_->active_tree()->DetachLayerTree();
538 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
540 // We should still be scrolling, because the scrolled layer also exists in the
542 gfx::Vector2d scroll_delta(0, 10);
543 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
544 host_impl_->ScrollEnd();
545 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
546 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
549 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
550 SetupScrollAndContentsLayers(gfx::Size(100, 100));
551 host_impl_->SetViewportSize(gfx::Size(50, 50));
554 // We should be able to scroll even if the root layer loses its render surface
555 // after the most recent render.
556 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
557 host_impl_->active_tree()->set_needs_update_draw_properties();
559 EXPECT_EQ(InputHandler::ScrollStarted,
560 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
563 TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
564 SetupScrollAndContentsLayers(gfx::Size(100, 100));
565 host_impl_->SetViewportSize(gfx::Size(50, 50));
567 LayerImpl* root = host_impl_->active_tree()->root_layer();
569 root->SetHaveWheelEventHandlers(true);
571 // With registered event handlers, wheel scrolls have to go to the main
573 EXPECT_EQ(InputHandler::ScrollOnMainThread,
574 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
576 // But gesture scrolls can still be handled.
577 EXPECT_EQ(InputHandler::ScrollStarted,
578 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
581 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
582 SetupScrollAndContentsLayers(gfx::Size(100, 100));
583 host_impl_->SetViewportSize(gfx::Size(50, 50));
586 // Ignore the fling since no layer is being scrolled
587 EXPECT_EQ(InputHandler::ScrollIgnored,
588 host_impl_->FlingScrollBegin());
590 // Start scrolling a layer
591 EXPECT_EQ(InputHandler::ScrollStarted,
592 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
594 // Now the fling should go ahead since we've started scrolling a layer
595 EXPECT_EQ(InputHandler::ScrollStarted,
596 host_impl_->FlingScrollBegin());
599 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
600 SetupScrollAndContentsLayers(gfx::Size(100, 100));
601 host_impl_->SetViewportSize(gfx::Size(50, 50));
604 // Ignore the fling since no layer is being scrolled
605 EXPECT_EQ(InputHandler::ScrollIgnored,
606 host_impl_->FlingScrollBegin());
608 // Start scrolling a layer
609 EXPECT_EQ(InputHandler::ScrollStarted,
610 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
612 // Now the fling should go ahead since we've started scrolling a layer
613 EXPECT_EQ(InputHandler::ScrollStarted,
614 host_impl_->FlingScrollBegin());
617 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
618 SetupScrollAndContentsLayers(gfx::Size(100, 100));
619 host_impl_->SetViewportSize(gfx::Size(50, 50));
621 LayerImpl* root = host_impl_->active_tree()->root_layer();
623 root->SetShouldScrollOnMainThread(true);
625 // Start scrolling a layer
626 EXPECT_EQ(InputHandler::ScrollOnMainThread,
627 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
629 // The fling should be ignored since there's no layer being scrolled impl-side
630 EXPECT_EQ(InputHandler::ScrollIgnored,
631 host_impl_->FlingScrollBegin());
634 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
635 SetupScrollAndContentsLayers(gfx::Size(100, 100));
636 host_impl_->SetViewportSize(gfx::Size(50, 50));
638 LayerImpl* root = host_impl_->active_tree()->root_layer();
640 root->SetShouldScrollOnMainThread(true);
642 EXPECT_EQ(InputHandler::ScrollOnMainThread,
643 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
644 EXPECT_EQ(InputHandler::ScrollOnMainThread,
645 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
648 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
649 SetupScrollAndContentsLayers(gfx::Size(200, 200));
650 host_impl_->SetViewportSize(gfx::Size(100, 100));
652 LayerImpl* root = host_impl_->active_tree()->root_layer();
653 root->SetContentsScale(2.f, 2.f);
654 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
658 // All scroll types inside the non-fast scrollable region should fail.
659 EXPECT_EQ(InputHandler::ScrollOnMainThread,
660 host_impl_->ScrollBegin(gfx::Point(25, 25),
661 InputHandler::Wheel));
662 EXPECT_EQ(InputHandler::ScrollOnMainThread,
663 host_impl_->ScrollBegin(gfx::Point(25, 25),
664 InputHandler::Gesture));
666 // All scroll types outside this region should succeed.
667 EXPECT_EQ(InputHandler::ScrollStarted,
668 host_impl_->ScrollBegin(gfx::Point(75, 75),
669 InputHandler::Wheel));
670 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
671 host_impl_->ScrollEnd();
672 EXPECT_EQ(InputHandler::ScrollStarted,
673 host_impl_->ScrollBegin(gfx::Point(75, 75),
674 InputHandler::Gesture));
675 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
676 host_impl_->ScrollEnd();
679 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
680 SetupScrollAndContentsLayers(gfx::Size(200, 200));
681 host_impl_->SetViewportSize(gfx::Size(100, 100));
683 LayerImpl* root = host_impl_->active_tree()->root_layer();
684 root->SetContentsScale(2.f, 2.f);
685 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
686 root->SetPosition(gfx::PointF(-25.f, 0.f));
690 // This point would fall into the non-fast scrollable region except that we've
691 // moved the layer down by 25 pixels.
692 EXPECT_EQ(InputHandler::ScrollStarted,
693 host_impl_->ScrollBegin(gfx::Point(40, 10),
694 InputHandler::Wheel));
695 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
696 host_impl_->ScrollEnd();
698 // This point is still inside the non-fast region.
699 EXPECT_EQ(InputHandler::ScrollOnMainThread,
700 host_impl_->ScrollBegin(gfx::Point(10, 10),
701 InputHandler::Wheel));
704 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
705 SetupScrollAndContentsLayers(gfx::Size(200, 200));
706 host_impl_->SetViewportSize(gfx::Size(100, 100));
710 EXPECT_EQ(InputHandler::ScrollStarted,
711 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
713 // Trying to scroll to the left/top will not succeed.
714 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
715 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
716 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
718 // Scrolling to the right/bottom will succeed.
719 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
720 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
721 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
723 // Scrolling to left/top will now succeed.
724 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
725 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
726 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
728 // Scrolling diagonally against an edge will succeed.
729 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
730 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
731 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
733 // Trying to scroll more than the available space will also succeed.
734 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
737 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
738 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
739 host_impl_->SetViewportSize(gfx::Size(100, 1000));
743 EXPECT_EQ(InputHandler::ScrollStarted,
744 host_impl_->ScrollBegin(gfx::Point(),
745 InputHandler::Wheel));
747 // Trying to scroll without a vertical scrollbar will fail.
748 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
749 gfx::Point(), SCROLL_FORWARD));
750 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
751 gfx::Point(), SCROLL_BACKWARD));
753 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
754 PaintedScrollbarLayerImpl::Create(
755 host_impl_->active_tree(),
758 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
759 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
760 vertical_scrollbar.get());
762 // Trying to scroll with a vertical scrollbar will succeed.
763 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
764 gfx::Point(), SCROLL_FORWARD));
765 EXPECT_FLOAT_EQ(875.f,
766 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
767 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
768 gfx::Point(), SCROLL_BACKWARD));
771 // The user-scrollability breaks for zoomed-in pages. So disable this.
772 // http://crbug.com/322223
773 TEST_F(LayerTreeHostImplTest, DISABLED_ScrollWithUserUnscrollableLayers) {
774 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
775 host_impl_->SetViewportSize(gfx::Size(100, 100));
777 gfx::Size overflow_size(400, 400);
778 ASSERT_EQ(1u, scroll_layer->children().size());
779 LayerImpl* overflow = scroll_layer->children()[0];
780 overflow->SetBounds(overflow_size);
781 overflow->SetContentBounds(overflow_size);
782 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
783 overflow->SetScrollOffset(gfx::Vector2d());
784 overflow->SetPosition(gfx::PointF());
785 overflow->SetAnchorPoint(gfx::PointF());
788 gfx::Point scroll_position(10, 10);
790 EXPECT_EQ(InputHandler::ScrollStarted,
791 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
792 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
793 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->TotalScrollOffset());
795 gfx::Vector2dF scroll_delta(10, 10);
796 host_impl_->ScrollBy(scroll_position, scroll_delta);
797 host_impl_->ScrollEnd();
798 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
799 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
801 overflow->set_user_scrollable_horizontal(false);
803 EXPECT_EQ(InputHandler::ScrollStarted,
804 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
805 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
806 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
808 host_impl_->ScrollBy(scroll_position, scroll_delta);
809 host_impl_->ScrollEnd();
810 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
811 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
813 overflow->set_user_scrollable_vertical(false);
815 EXPECT_EQ(InputHandler::ScrollStarted,
816 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
817 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
818 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
820 host_impl_->ScrollBy(scroll_position, scroll_delta);
821 host_impl_->ScrollEnd();
822 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->TotalScrollOffset());
823 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
826 TEST_F(LayerTreeHostImplTest,
827 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
828 SetupScrollAndContentsLayers(gfx::Size(100, 100));
829 host_impl_->SetViewportSize(gfx::Size(50, 50));
832 // We should be able to hit test for touch event handlers even if the root
833 // layer loses its render surface after the most recent render.
834 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
835 host_impl_->active_tree()->set_needs_update_draw_properties();
837 EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
840 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
841 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
842 host_impl_->SetViewportSize(gfx::Size(50, 50));
845 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
846 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
847 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
849 float min_page_scale = 1.f, max_page_scale = 4.f;
850 float page_scale_factor = 1.f;
852 // The impl-based pinch zoom should adjust the max scroll position.
854 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
855 page_scale_factor, min_page_scale, max_page_scale);
856 host_impl_->active_tree()->SetPageScaleDelta(1.f);
857 scroll_layer->SetScrollDelta(gfx::Vector2d());
859 float page_scale_delta = 2.f;
860 gfx::Vector2dF expected_container_size_delta(
861 container_layer->bounds().width(), container_layer->bounds().height());
862 expected_container_size_delta.Scale((1.f - page_scale_delta) /
863 (page_scale_factor * page_scale_delta));
865 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
866 host_impl_->PinchGestureBegin();
867 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
868 // While the gesture is still active, the scroll layer should have a
869 // container size delta = container->bounds() * ((1.f -
870 // page_scale_delta)/())
871 EXPECT_EQ(expected_container_size_delta,
872 scroll_layer->FixedContainerSizeDelta());
873 host_impl_->PinchGestureEnd();
874 host_impl_->ScrollEnd();
875 EXPECT_TRUE(did_request_redraw_);
876 EXPECT_TRUE(did_request_commit_);
877 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
879 scoped_ptr<ScrollAndScaleSet> scroll_info =
880 host_impl_->ProcessScrollDeltas();
881 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
883 EXPECT_EQ(gfx::Vector2d(75, 75).ToString(),
884 scroll_layer->MaxScrollOffset().ToString());
887 // Scrolling after a pinch gesture should always be in local space. The
888 // scroll deltas do not have the page scale factor applied.
890 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
891 page_scale_factor, min_page_scale, max_page_scale);
892 host_impl_->active_tree()->SetPageScaleDelta(1.f);
893 scroll_layer->SetScrollDelta(gfx::Vector2d());
895 float page_scale_delta = 2.f;
896 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
897 host_impl_->PinchGestureBegin();
898 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
899 host_impl_->PinchGestureEnd();
900 host_impl_->ScrollEnd();
902 gfx::Vector2d scroll_delta(0, 10);
903 EXPECT_EQ(InputHandler::ScrollStarted,
904 host_impl_->ScrollBegin(gfx::Point(5, 5),
905 InputHandler::Wheel));
906 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
907 host_impl_->ScrollEnd();
909 scoped_ptr<ScrollAndScaleSet> scroll_info =
910 host_impl_->ProcessScrollDeltas();
911 ExpectContains(*scroll_info.get(),
917 TEST_F(LayerTreeHostImplTest, PinchGesture) {
918 SetupScrollAndContentsLayers(gfx::Size(100, 100));
919 host_impl_->SetViewportSize(gfx::Size(50, 50));
922 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
923 DCHECK(scroll_layer);
925 float min_page_scale = 1.f;
926 float max_page_scale = 4.f;
928 // Basic pinch zoom in gesture
930 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
933 scroll_layer->SetScrollDelta(gfx::Vector2d());
935 float page_scale_delta = 2.f;
936 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
937 host_impl_->PinchGestureBegin();
938 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
939 host_impl_->PinchGestureEnd();
940 host_impl_->ScrollEnd();
941 EXPECT_TRUE(did_request_redraw_);
942 EXPECT_TRUE(did_request_commit_);
944 scoped_ptr<ScrollAndScaleSet> scroll_info =
945 host_impl_->ProcessScrollDeltas();
946 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
951 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
954 scroll_layer->SetScrollDelta(gfx::Vector2d());
955 float page_scale_delta = 10.f;
957 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
958 host_impl_->PinchGestureBegin();
959 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
960 host_impl_->PinchGestureEnd();
961 host_impl_->ScrollEnd();
963 scoped_ptr<ScrollAndScaleSet> scroll_info =
964 host_impl_->ProcessScrollDeltas();
965 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
970 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
973 scroll_layer->SetScrollDelta(gfx::Vector2d());
974 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
976 float page_scale_delta = 0.1f;
977 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
978 host_impl_->PinchGestureBegin();
979 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
980 host_impl_->PinchGestureEnd();
981 host_impl_->ScrollEnd();
983 scoped_ptr<ScrollAndScaleSet> scroll_info =
984 host_impl_->ProcessScrollDeltas();
985 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
987 EXPECT_TRUE(scroll_info->scrolls.empty());
990 // Two-finger panning should not happen based on pinch events only
992 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
995 scroll_layer->SetScrollDelta(gfx::Vector2d());
996 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
998 float page_scale_delta = 1.f;
999 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1000 host_impl_->PinchGestureBegin();
1001 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1002 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1003 host_impl_->PinchGestureEnd();
1004 host_impl_->ScrollEnd();
1006 scoped_ptr<ScrollAndScaleSet> scroll_info =
1007 host_impl_->ProcessScrollDeltas();
1008 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1009 EXPECT_TRUE(scroll_info->scrolls.empty());
1012 // Two-finger panning should work with interleaved scroll events
1014 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1017 scroll_layer->SetScrollDelta(gfx::Vector2d());
1018 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1020 float page_scale_delta = 1.f;
1021 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1022 host_impl_->PinchGestureBegin();
1023 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1024 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1025 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1026 host_impl_->PinchGestureEnd();
1027 host_impl_->ScrollEnd();
1029 scoped_ptr<ScrollAndScaleSet> scroll_info =
1030 host_impl_->ProcessScrollDeltas();
1031 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1032 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1035 // Two-finger panning should work when starting fully zoomed out.
1037 host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
1040 scroll_layer->SetScrollDelta(gfx::Vector2d());
1041 scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
1043 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
1044 host_impl_->PinchGestureBegin();
1045 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1046 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1047 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1048 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1049 host_impl_->PinchGestureEnd();
1050 host_impl_->ScrollEnd();
1052 scoped_ptr<ScrollAndScaleSet> scroll_info =
1053 host_impl_->ProcessScrollDeltas();
1054 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1055 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1059 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1060 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1061 host_impl_->SetViewportSize(gfx::Size(50, 50));
1064 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1065 DCHECK(scroll_layer);
1067 float min_page_scale = 0.5f;
1068 float max_page_scale = 4.f;
1069 base::TimeTicks start_time = base::TimeTicks() +
1070 base::TimeDelta::FromSeconds(1);
1071 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1072 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1073 base::TimeTicks end_time = start_time + duration;
1075 // Non-anchor zoom-in
1077 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1080 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1082 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), false, 2.f, duration);
1083 did_request_redraw_ = false;
1084 host_impl_->Animate(start_time);
1085 EXPECT_TRUE(did_request_redraw_);
1087 did_request_redraw_ = false;
1088 host_impl_->Animate(halfway_through_animation);
1089 EXPECT_TRUE(did_request_redraw_);
1091 did_request_redraw_ = false;
1092 did_request_commit_ = false;
1093 host_impl_->Animate(end_time);
1094 EXPECT_TRUE(did_request_commit_);
1096 scoped_ptr<ScrollAndScaleSet> scroll_info =
1097 host_impl_->ProcessScrollDeltas();
1098 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1099 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1104 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1107 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1109 host_impl_->StartPageScaleAnimation(
1110 gfx::Vector2d(25, 25), true, min_page_scale, duration);
1111 did_request_redraw_ = false;
1112 host_impl_->Animate(start_time);
1113 EXPECT_TRUE(did_request_redraw_);
1115 did_request_redraw_ = false;
1116 did_request_commit_ = false;
1117 host_impl_->Animate(end_time);
1118 EXPECT_TRUE(did_request_redraw_);
1119 EXPECT_TRUE(did_request_commit_);
1121 scoped_ptr<ScrollAndScaleSet> scroll_info =
1122 host_impl_->ProcessScrollDeltas();
1123 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1124 // Pushed to (0,0) via clamping against contents layer size.
1125 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1129 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1130 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1131 host_impl_->SetViewportSize(gfx::Size(50, 50));
1134 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1135 DCHECK(scroll_layer);
1137 float min_page_scale = 0.5f;
1138 float max_page_scale = 4.f;
1139 base::TimeTicks start_time = base::TimeTicks() +
1140 base::TimeDelta::FromSeconds(1);
1141 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1142 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1143 base::TimeTicks end_time = start_time + duration;
1145 // Anchor zoom with unchanged page scale should not change scroll or scale.
1147 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1150 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1152 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), true, 1.f, duration);
1153 host_impl_->Animate(start_time);
1154 host_impl_->Animate(halfway_through_animation);
1155 EXPECT_TRUE(did_request_redraw_);
1156 host_impl_->Animate(end_time);
1157 EXPECT_TRUE(did_request_commit_);
1159 scoped_ptr<ScrollAndScaleSet> scroll_info =
1160 host_impl_->ProcessScrollDeltas();
1161 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1162 ExpectNone(*scroll_info, scroll_layer->id());
1166 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1168 LayerTreeHostImplOverridePhysicalTime(
1169 const LayerTreeSettings& settings,
1170 LayerTreeHostImplClient* client,
1172 SharedBitmapManager* manager,
1173 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1174 : LayerTreeHostImpl(settings,
1177 rendering_stats_instrumentation,
1181 virtual base::TimeTicks CurrentFrameTimeTicks() OVERRIDE {
1182 return fake_current_physical_time_;
1185 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1186 fake_current_physical_time_ = fake_now;
1190 base::TimeTicks fake_current_physical_time_;
1193 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1194 LayerTreeSettings settings;
1195 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1196 settings.scrollbar_linear_fade_delay_ms = 20;
1197 settings.scrollbar_linear_fade_length_ms = 20;
1199 gfx::Size viewport_size(10, 10);
1200 gfx::Size content_size(100, 100);
1202 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
1203 new LayerTreeHostImplOverridePhysicalTime(settings,
1206 shared_bitmap_manager_.get(),
1207 &stats_instrumentation_);
1208 host_impl_ = make_scoped_ptr(host_impl_override_time);
1209 host_impl_->InitializeRenderer(CreateOutputSurface());
1210 host_impl_->SetViewportSize(viewport_size);
1212 scoped_ptr<LayerImpl> root =
1213 LayerImpl::Create(host_impl_->active_tree(), 1);
1214 root->SetBounds(viewport_size);
1216 scoped_ptr<LayerImpl> scroll =
1217 LayerImpl::Create(host_impl_->active_tree(), 2);
1218 scroll->SetScrollClipLayer(root->id());
1219 scroll->SetScrollOffset(gfx::Vector2d());
1220 root->SetBounds(viewport_size);
1221 scroll->SetBounds(content_size);
1222 scroll->SetContentBounds(content_size);
1223 scroll->SetIsContainerForFixedPositionLayers(true);
1225 scoped_ptr<LayerImpl> contents =
1226 LayerImpl::Create(host_impl_->active_tree(), 3);
1227 contents->SetDrawsContent(true);
1228 contents->SetBounds(content_size);
1229 contents->SetContentBounds(content_size);
1231 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1232 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 4, VERTICAL);
1233 scrollbar->SetScrollLayerById(2);
1234 scrollbar->SetClipLayerById(1);
1236 scroll->AddChild(contents.Pass());
1237 root->AddChild(scroll.Pass());
1238 root->AddChild(scrollbar.PassAs<LayerImpl>());
1240 host_impl_->active_tree()->SetRootLayer(root.Pass());
1241 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
1242 host_impl_->active_tree()->DidBecomeActive();
1245 base::TimeTicks fake_now = gfx::FrameTime::Now();
1246 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1248 // If no scroll happened recently, StartScrollbarAnimation should have no
1250 host_impl_->StartScrollbarAnimation();
1251 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1252 EXPECT_FALSE(did_request_redraw_);
1254 // If no scroll happened during a scroll gesture, StartScrollbarAnimation
1255 // should have no effect.
1256 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1257 host_impl_->ScrollEnd();
1258 host_impl_->StartScrollbarAnimation();
1259 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1260 EXPECT_FALSE(did_request_redraw_);
1262 // After a scroll, a fade animation should be scheduled about 20ms from now.
1263 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1264 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1265 host_impl_->ScrollEnd();
1266 did_request_redraw_ = false;
1267 host_impl_->StartScrollbarAnimation();
1268 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1269 requested_scrollbar_animation_delay_);
1270 EXPECT_FALSE(did_request_redraw_);
1271 requested_scrollbar_animation_delay_ = base::TimeDelta();
1273 // After the fade begins, we should start getting redraws instead of a
1274 // scheduled animation.
1275 fake_now += base::TimeDelta::FromMilliseconds(25);
1276 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1277 host_impl_->StartScrollbarAnimation();
1278 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1279 EXPECT_TRUE(did_request_redraw_);
1280 did_request_redraw_ = false;
1282 // If no scroll happened recently, StartScrollbarAnimation should have no
1284 fake_now += base::TimeDelta::FromMilliseconds(25);
1285 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1286 host_impl_->StartScrollbarAnimation();
1287 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1288 EXPECT_FALSE(did_request_redraw_);
1290 // Setting the scroll offset outside a scroll should also cause the scrollbar
1291 // to appear and to schedule a fade.
1292 host_impl_->InnerViewportScrollLayer()->SetScrollOffset(gfx::Vector2d(5, 5));
1293 host_impl_->StartScrollbarAnimation();
1294 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1295 requested_scrollbar_animation_delay_);
1296 EXPECT_FALSE(did_request_redraw_);
1297 requested_scrollbar_animation_delay_ = base::TimeDelta();
1299 // None of the above should have called CurrentFrameTimeTicks, so if we call
1300 // it now we should get the current time.
1301 fake_now += base::TimeDelta::FromMilliseconds(10);
1302 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1303 EXPECT_EQ(fake_now, host_impl_->CurrentFrameTimeTicks());
1306 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1307 float device_scale_factor) {
1308 LayerTreeSettings settings;
1309 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1311 gfx::Size viewport_size(300, 200);
1312 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1313 gfx::ScaleSize(viewport_size, device_scale_factor));
1314 gfx::Size content_size(1000, 1000);
1316 CreateHostImpl(settings, CreateOutputSurface());
1317 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1318 host_impl_->SetViewportSize(device_viewport_size);
1320 scoped_ptr<LayerImpl> root =
1321 LayerImpl::Create(host_impl_->active_tree(), 1);
1322 root->SetBounds(viewport_size);
1324 scoped_ptr<LayerImpl> scroll =
1325 LayerImpl::Create(host_impl_->active_tree(), 2);
1326 scroll->SetScrollClipLayer(root->id());
1327 scroll->SetScrollOffset(gfx::Vector2d());
1328 scroll->SetBounds(content_size);
1329 scroll->SetContentBounds(content_size);
1330 scroll->SetIsContainerForFixedPositionLayers(true);
1332 scoped_ptr<LayerImpl> contents =
1333 LayerImpl::Create(host_impl_->active_tree(), 3);
1334 contents->SetDrawsContent(true);
1335 contents->SetBounds(content_size);
1336 contents->SetContentBounds(content_size);
1338 // The scrollbar is on the right side.
1339 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1340 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1341 scrollbar->SetDrawsContent(true);
1342 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1343 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1344 scrollbar->SetPosition(gfx::Point(285, 0));
1345 scrollbar->SetScrollLayerById(2);
1347 scroll->AddChild(contents.Pass());
1348 root->AddChild(scroll.Pass());
1349 root->AddChild(scrollbar.PassAs<LayerImpl>());
1351 host_impl_->active_tree()->SetRootLayer(root.Pass());
1352 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
1353 host_impl_->active_tree()->DidBecomeActive();
1356 LayerImpl* root_scroll =
1357 host_impl_->active_tree()->InnerViewportScrollLayer();
1358 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1359 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1360 static_cast<ScrollbarAnimationControllerThinning*>(
1361 root_scroll->scrollbar_animation_controller());
1362 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1364 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1365 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1367 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1368 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1370 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1371 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1373 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1374 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1375 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1377 did_request_redraw_ = false;
1378 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1379 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1380 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1381 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1382 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1383 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1384 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1387 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1388 SetupMouseMoveAtWithDeviceScale(1.f);
1391 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1392 SetupMouseMoveAtWithDeviceScale(2.f);
1395 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1396 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1397 host_impl_->SetViewportSize(gfx::Size(50, 50));
1398 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
1401 CompositorFrameMetadata metadata =
1402 host_impl_->MakeCompositorFrameMetadata();
1403 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1404 EXPECT_EQ(1.f, metadata.page_scale_factor);
1405 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.viewport_size);
1406 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1407 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1408 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1411 // Scrolling should update metadata immediately.
1412 EXPECT_EQ(InputHandler::ScrollStarted,
1413 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1414 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1416 CompositorFrameMetadata metadata =
1417 host_impl_->MakeCompositorFrameMetadata();
1418 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1420 host_impl_->ScrollEnd();
1422 CompositorFrameMetadata metadata =
1423 host_impl_->MakeCompositorFrameMetadata();
1424 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1427 // Page scale should update metadata correctly (shrinking only the viewport).
1428 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1429 host_impl_->PinchGestureBegin();
1430 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1431 host_impl_->PinchGestureEnd();
1432 host_impl_->ScrollEnd();
1434 CompositorFrameMetadata metadata =
1435 host_impl_->MakeCompositorFrameMetadata();
1436 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1437 EXPECT_EQ(2.f, metadata.page_scale_factor);
1438 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.viewport_size);
1439 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1440 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1441 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1444 // Likewise if set from the main thread.
1445 host_impl_->ProcessScrollDeltas();
1446 host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
1447 host_impl_->active_tree()->SetPageScaleDelta(1.f);
1449 CompositorFrameMetadata metadata =
1450 host_impl_->MakeCompositorFrameMetadata();
1451 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1452 EXPECT_EQ(4.f, metadata.page_scale_factor);
1453 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.viewport_size);
1454 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1455 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1456 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1460 // TODO(enne): Convert this to PictureLayerImpl
1461 class DidDrawCheckLayer : public TiledLayerImpl {
1463 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1464 return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(tree_impl, id));
1467 virtual bool WillDraw(DrawMode draw_mode, ResourceProvider* provider)
1469 will_draw_called_ = true;
1470 if (will_draw_returns_false_)
1472 return TiledLayerImpl::WillDraw(draw_mode, provider);
1475 virtual void AppendQuads(QuadSink* quad_sink,
1476 AppendQuadsData* append_quads_data) OVERRIDE {
1477 append_quads_called_ = true;
1478 TiledLayerImpl::AppendQuads(quad_sink, append_quads_data);
1481 virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
1482 did_draw_called_ = true;
1483 TiledLayerImpl::DidDraw(provider);
1486 bool will_draw_called() const { return will_draw_called_; }
1487 bool append_quads_called() const { return append_quads_called_; }
1488 bool did_draw_called() const { return did_draw_called_; }
1490 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1492 void ClearDidDrawCheck() {
1493 will_draw_called_ = false;
1494 append_quads_called_ = false;
1495 did_draw_called_ = false;
1499 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1500 : TiledLayerImpl(tree_impl, id),
1501 will_draw_returns_false_(false),
1502 will_draw_called_(false),
1503 append_quads_called_(false),
1504 did_draw_called_(false) {
1505 SetAnchorPoint(gfx::PointF());
1506 SetBounds(gfx::Size(10, 10));
1507 SetContentBounds(gfx::Size(10, 10));
1508 SetDrawsContent(true);
1509 set_skips_draw(false);
1510 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1512 scoped_ptr<LayerTilingData> tiler =
1513 LayerTilingData::Create(gfx::Size(100, 100),
1514 LayerTilingData::HAS_BORDER_TEXELS);
1515 tiler->SetBounds(content_bounds());
1516 SetTilingData(*tiler.get());
1520 bool will_draw_returns_false_;
1521 bool will_draw_called_;
1522 bool append_quads_called_;
1523 bool did_draw_called_;
1526 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1527 // The root layer is always drawn, so run this test on a child layer that
1528 // will be masked out by the root layer's bounds.
1529 host_impl_->active_tree()->SetRootLayer(
1530 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1531 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1532 host_impl_->active_tree()->root_layer());
1534 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1535 DidDrawCheckLayer* layer =
1536 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1539 LayerTreeHostImpl::FrameData frame;
1540 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1541 host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
1542 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1543 host_impl_->DidDrawAllLayers(frame);
1545 EXPECT_TRUE(layer->will_draw_called());
1546 EXPECT_TRUE(layer->append_quads_called());
1547 EXPECT_TRUE(layer->did_draw_called());
1551 LayerTreeHostImpl::FrameData frame;
1553 layer->set_will_draw_returns_false();
1554 layer->ClearDidDrawCheck();
1556 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1557 host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
1558 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1559 host_impl_->DidDrawAllLayers(frame);
1561 EXPECT_TRUE(layer->will_draw_called());
1562 EXPECT_FALSE(layer->append_quads_called());
1563 EXPECT_FALSE(layer->did_draw_called());
1567 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1568 // The root layer is always drawn, so run this test on a child layer that
1569 // will be masked out by the root layer's bounds.
1570 host_impl_->active_tree()->SetRootLayer(
1571 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1572 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1573 host_impl_->active_tree()->root_layer());
1574 root->SetMasksToBounds(true);
1576 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1577 DidDrawCheckLayer* layer =
1578 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1579 // Ensure visible_content_rect for layer is empty.
1580 layer->SetPosition(gfx::PointF(100.f, 100.f));
1581 layer->SetBounds(gfx::Size(10, 10));
1582 layer->SetContentBounds(gfx::Size(10, 10));
1584 LayerTreeHostImpl::FrameData frame;
1586 EXPECT_FALSE(layer->will_draw_called());
1587 EXPECT_FALSE(layer->did_draw_called());
1589 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1590 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1591 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1592 host_impl_->DidDrawAllLayers(frame);
1594 EXPECT_FALSE(layer->will_draw_called());
1595 EXPECT_FALSE(layer->did_draw_called());
1597 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1599 // Ensure visible_content_rect for layer is not empty
1600 layer->SetPosition(gfx::PointF());
1602 EXPECT_FALSE(layer->will_draw_called());
1603 EXPECT_FALSE(layer->did_draw_called());
1605 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1606 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1607 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1608 host_impl_->DidDrawAllLayers(frame);
1610 EXPECT_TRUE(layer->will_draw_called());
1611 EXPECT_TRUE(layer->did_draw_called());
1613 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1616 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1617 gfx::Size big_size(1000, 1000);
1618 host_impl_->SetViewportSize(big_size);
1620 host_impl_->active_tree()->SetRootLayer(
1621 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1622 DidDrawCheckLayer* root =
1623 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1625 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1626 DidDrawCheckLayer* occluded_layer =
1627 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1629 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1630 DidDrawCheckLayer* top_layer =
1631 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1632 // This layer covers the occluded_layer above. Make this layer large so it can
1634 top_layer->SetBounds(big_size);
1635 top_layer->SetContentBounds(big_size);
1636 top_layer->SetContentsOpaque(true);
1638 LayerTreeHostImpl::FrameData frame;
1640 EXPECT_FALSE(occluded_layer->will_draw_called());
1641 EXPECT_FALSE(occluded_layer->did_draw_called());
1642 EXPECT_FALSE(top_layer->will_draw_called());
1643 EXPECT_FALSE(top_layer->did_draw_called());
1645 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1646 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1647 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1648 host_impl_->DidDrawAllLayers(frame);
1650 EXPECT_FALSE(occluded_layer->will_draw_called());
1651 EXPECT_FALSE(occluded_layer->did_draw_called());
1652 EXPECT_TRUE(top_layer->will_draw_called());
1653 EXPECT_TRUE(top_layer->did_draw_called());
1656 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1657 host_impl_->active_tree()->SetRootLayer(
1658 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1659 DidDrawCheckLayer* root =
1660 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1662 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1663 DidDrawCheckLayer* layer1 =
1664 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1666 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1667 DidDrawCheckLayer* layer2 =
1668 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1670 layer1->SetOpacity(0.3f);
1671 layer1->SetShouldFlattenTransform(true);
1673 EXPECT_FALSE(root->did_draw_called());
1674 EXPECT_FALSE(layer1->did_draw_called());
1675 EXPECT_FALSE(layer2->did_draw_called());
1677 LayerTreeHostImpl::FrameData frame;
1678 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1679 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1680 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1681 host_impl_->DidDrawAllLayers(frame);
1683 EXPECT_TRUE(root->did_draw_called());
1684 EXPECT_TRUE(layer1->did_draw_called());
1685 EXPECT_TRUE(layer2->did_draw_called());
1687 EXPECT_NE(root->render_surface(), layer1->render_surface());
1688 EXPECT_TRUE(!!layer1->render_surface());
1691 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1693 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1698 ResourceProvider* resource_provider) {
1699 return scoped_ptr<LayerImpl>(new MissingTextureAnimatingLayer(
1705 resource_provider));
1708 virtual void AppendQuads(QuadSink* quad_sink,
1709 AppendQuadsData* append_quads_data) OVERRIDE {
1710 TiledLayerImpl::AppendQuads(quad_sink, append_quads_data);
1712 append_quads_data->had_incomplete_tile = true;
1716 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1721 ResourceProvider* resource_provider)
1722 : DidDrawCheckLayer(tree_impl, id), tile_missing_(tile_missing) {
1723 scoped_ptr<LayerTilingData> tiling_data =
1724 LayerTilingData::Create(gfx::Size(10, 10),
1725 LayerTilingData::NO_BORDER_TEXELS);
1726 tiling_data->SetBounds(bounds());
1727 SetTilingData(*tiling_data.get());
1728 set_skips_draw(skips_draw);
1729 if (!tile_missing) {
1730 ResourceProvider::ResourceId resource =
1731 resource_provider->CreateResource(gfx::Size(1, 1),
1733 ResourceProvider::TextureUsageAny,
1735 resource_provider->AllocateForTesting(resource);
1736 PushTileProperties(0, 0, resource, gfx::Rect(), false);
1739 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1745 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenNoTexturesMissing) {
1746 host_impl_->active_tree()->SetRootLayer(
1747 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1748 DidDrawCheckLayer* root =
1749 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1751 bool tile_missing = false;
1752 bool skips_draw = false;
1753 bool is_animating = false;
1755 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1760 host_impl_->resource_provider()));
1762 LayerTreeHostImpl::FrameData frame;
1764 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1765 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1766 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1767 host_impl_->DidDrawAllLayers(frame);
1770 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) {
1771 host_impl_->active_tree()->SetRootLayer(
1772 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1773 DidDrawCheckLayer* root =
1774 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1775 bool tile_missing = false;
1776 bool skips_draw = false;
1777 bool is_animating = true;
1779 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1784 host_impl_->resource_provider()));
1786 LayerTreeHostImpl::FrameData frame;
1788 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1789 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1790 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1791 host_impl_->DidDrawAllLayers(frame);
1794 TEST_F(LayerTreeHostImplTest,
1795 PrepareToDrawSucceedsWithNonAnimatedMissingTexture) {
1796 // When a texture is missing and we're not animating, we draw as usual with
1798 host_impl_->active_tree()->SetRootLayer(
1799 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1800 DidDrawCheckLayer* root =
1801 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1803 bool tile_missing = true;
1804 bool skips_draw = false;
1805 bool is_animating = false;
1807 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1812 host_impl_->resource_provider()));
1813 LayerTreeHostImpl::FrameData frame;
1814 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1815 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1816 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1817 host_impl_->DidDrawAllLayers(frame);
1820 TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
1821 // When a texture is missing and we're animating, we don't want to draw
1823 host_impl_->active_tree()->SetRootLayer(
1824 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
1825 DidDrawCheckLayer* root =
1826 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1827 bool tile_missing = true;
1828 bool skips_draw = false;
1829 bool is_animating = true;
1831 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1836 host_impl_->resource_provider()));
1837 LayerTreeHostImpl::FrameData frame;
1838 EXPECT_EQ(DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS,
1839 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1840 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1841 host_impl_->DidDrawAllLayers(frame);
1844 TEST_F(LayerTreeHostImplTest,
1845 PrepareToDrawSucceedsWithMissingSkippedAnimatedLayer) {
1846 // When the layer skips draw and we're animating, we still draw the frame.
1847 host_impl_->active_tree()->SetRootLayer(
1848 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
1849 DidDrawCheckLayer* root =
1850 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1851 bool tile_missing = false;
1852 bool skips_draw = true;
1853 bool is_animating = true;
1855 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1860 host_impl_->resource_provider()));
1861 LayerTreeHostImpl::FrameData frame;
1862 EXPECT_EQ(host_impl_->PrepareToDraw(&frame, gfx::Rect()),
1863 DrawSwapReadbackResult::DRAW_SUCCESS);
1864 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1865 host_impl_->DidDrawAllLayers(frame);
1868 TEST_F(LayerTreeHostImplTest,
1869 PrepareToDrawSucceedsWhenHighResRequiredButNoMissingTextures) {
1870 // When the layer skips draw and we're animating, we still draw the frame.
1871 host_impl_->active_tree()->SetRootLayer(
1872 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
1873 DidDrawCheckLayer* root =
1874 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1875 bool tile_missing = false;
1876 bool skips_draw = false;
1877 bool is_animating = false;
1879 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1884 host_impl_->resource_provider()));
1885 host_impl_->active_tree()->SetRequiresHighResToDraw();
1886 LayerTreeHostImpl::FrameData frame;
1887 EXPECT_EQ(host_impl_->PrepareToDraw(&frame, gfx::Rect()),
1888 DrawSwapReadbackResult::DRAW_SUCCESS);
1889 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1890 host_impl_->DidDrawAllLayers(frame);
1893 TEST_F(LayerTreeHostImplTest,
1894 PrepareToDrawFailsWhenHighResRequiredAndMissingTextures) {
1895 // When the layer skips draw and we're animating, we still draw the frame.
1896 host_impl_->active_tree()->SetRootLayer(
1897 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
1898 DidDrawCheckLayer* root =
1899 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1900 bool tile_missing = true;
1901 bool skips_draw = false;
1902 bool is_animating = false;
1904 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1909 host_impl_->resource_provider()));
1910 host_impl_->active_tree()->SetRequiresHighResToDraw();
1911 LayerTreeHostImpl::FrameData frame;
1912 EXPECT_EQ(host_impl_->PrepareToDraw(&frame, gfx::Rect()),
1913 DrawSwapReadbackResult::DRAW_ABORTED_MISSING_HIGH_RES_CONTENT);
1914 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1915 host_impl_->DidDrawAllLayers(frame);
1918 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
1919 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1920 root->SetScrollClipLayer(Layer::INVALID_ID);
1921 host_impl_->active_tree()->SetRootLayer(root.Pass());
1924 // Scroll event is ignored because layer is not scrollable.
1925 EXPECT_EQ(InputHandler::ScrollIgnored,
1926 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1927 EXPECT_FALSE(did_request_redraw_);
1928 EXPECT_FALSE(did_request_commit_);
1931 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
1933 LayerTreeHostImplTopControlsTest()
1934 // Make the clip size the same as the layer (content) size so the layer is
1936 : layer_size_(10, 10),
1937 clip_size_(layer_size_) {
1938 settings_.calculate_top_controls_position = true;
1939 settings_.top_controls_height = 50;
1942 gfx::Size(clip_size_.width(),
1943 clip_size_.height() + settings_.top_controls_height);
1946 void SetupTopControlsAndScrollLayer() {
1947 CreateHostImpl(settings_, CreateOutputSurface());
1949 scoped_ptr<LayerImpl> root =
1950 LayerImpl::Create(host_impl_->active_tree(), 1);
1951 scoped_ptr<LayerImpl> root_clip =
1952 LayerImpl::Create(host_impl_->active_tree(), 2);
1953 root_clip->SetBounds(clip_size_);
1954 root->SetScrollClipLayer(root_clip->id());
1955 root->SetBounds(layer_size_);
1956 root->SetContentBounds(layer_size_);
1957 root->SetPosition(gfx::PointF());
1958 root->SetAnchorPoint(gfx::PointF());
1959 root->SetDrawsContent(false);
1960 root->SetIsContainerForFixedPositionLayers(true);
1961 int inner_viewport_scroll_layer_id = root->id();
1962 int page_scale_layer_id = root_clip->id();
1963 root_clip->AddChild(root.Pass());
1964 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
1965 host_impl_->active_tree()->SetViewportLayersFromIds(
1966 page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
1967 // Set a viewport size that is large enough to contain both the top controls
1968 // and some content.
1969 host_impl_->SetViewportSize(viewport_size_);
1970 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
1971 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
1975 gfx::Size layer_size_;
1976 gfx::Size clip_size_;
1977 gfx::Size viewport_size_;
1979 LayerTreeSettings settings_;
1980 }; // class LayerTreeHostImplTopControlsTest
1982 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
1983 SetupTopControlsAndScrollLayer();
1986 EXPECT_EQ(InputHandler::ScrollStarted,
1987 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
1989 // Make the test scroll delta a fractional amount, to verify that the
1990 // fixed container size delta is (1) non-zero, and (2) fractional, and
1991 // (3) matches the movement of the top controls.
1992 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
1993 host_impl_->top_controls_manager()->ScrollBegin();
1994 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
1995 host_impl_->top_controls_manager()->ScrollEnd();
1997 LayerImpl* inner_viewport_scroll_layer =
1998 host_impl_->active_tree()->InnerViewportScrollLayer();
1999 DCHECK(inner_viewport_scroll_layer);
2000 host_impl_->ScrollEnd();
2001 EXPECT_EQ(top_controls_scroll_delta,
2002 inner_viewport_scroll_layer->FixedContainerSizeDelta());
2005 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsWithPageScale) {
2006 SetupTopControlsAndScrollLayer();
2009 EXPECT_EQ(InputHandler::ScrollStarted,
2010 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2012 float page_scale = 1.5f;
2013 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale, 1.f, 2.f);
2015 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.f);
2016 gfx::Vector2dF expected_container_size_delta =
2017 ScaleVector2d(top_controls_scroll_delta, 1.f / page_scale);
2018 host_impl_->top_controls_manager()->ScrollBegin();
2019 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2020 host_impl_->top_controls_manager()->ScrollEnd();
2022 LayerImpl* inner_viewport_scroll_layer =
2023 host_impl_->active_tree()->InnerViewportScrollLayer();
2024 DCHECK(inner_viewport_scroll_layer);
2025 host_impl_->ScrollEnd();
2027 // Use a tolerance that requires the container size delta to be within 0.01
2029 double tolerance = 0.0001;
2031 (expected_container_size_delta -
2032 inner_viewport_scroll_layer->FixedContainerSizeDelta()).LengthSquared(),
2036 TEST_F(LayerTreeHostImplTopControlsTest,
2037 ScrollNonScrollableRootWithTopControls) {
2038 SetupTopControlsAndScrollLayer();
2041 EXPECT_EQ(InputHandler::ScrollStarted,
2042 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2044 host_impl_->top_controls_manager()->ScrollBegin();
2045 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
2046 host_impl_->top_controls_manager()->ScrollEnd();
2047 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->content_top_offset());
2048 // Now that top controls have moved, expect the clip to resize.
2049 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2050 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2052 host_impl_->ScrollEnd();
2054 EXPECT_EQ(InputHandler::ScrollStarted,
2055 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2057 float scroll_increment_y = -25.f;
2058 host_impl_->top_controls_manager()->ScrollBegin();
2059 host_impl_->top_controls_manager()->ScrollBy(
2060 gfx::Vector2dF(0.f, scroll_increment_y));
2061 EXPECT_EQ(-scroll_increment_y,
2062 host_impl_->top_controls_manager()->content_top_offset());
2063 // Now that top controls have moved, expect the clip to resize.
2064 EXPECT_EQ(gfx::Size(viewport_size_.width(),
2065 viewport_size_.height() + scroll_increment_y),
2066 root_clip_ptr->bounds());
2068 host_impl_->top_controls_manager()->ScrollBy(
2069 gfx::Vector2dF(0.f, scroll_increment_y));
2070 host_impl_->top_controls_manager()->ScrollEnd();
2071 EXPECT_EQ(-2 * scroll_increment_y,
2072 host_impl_->top_controls_manager()->content_top_offset());
2073 // Now that top controls have moved, expect the clip to resize.
2074 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2076 host_impl_->ScrollEnd();
2078 // Verify the layer is once-again non-scrollable.
2081 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
2083 EXPECT_EQ(InputHandler::ScrollStarted,
2084 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2087 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
2088 // Test the configuration where a non-composited root layer is embedded in a
2089 // scrollable outer layer.
2090 gfx::Size surface_size(10, 10);
2091 gfx::Size contents_size(20, 20);
2093 scoped_ptr<LayerImpl> content_layer =
2094 LayerImpl::Create(host_impl_->active_tree(), 1);
2095 content_layer->SetDrawsContent(true);
2096 content_layer->SetPosition(gfx::PointF());
2097 content_layer->SetAnchorPoint(gfx::PointF());
2098 content_layer->SetBounds(contents_size);
2099 content_layer->SetContentBounds(contents_size);
2100 content_layer->SetContentsScale(2.f, 2.f);
2102 scoped_ptr<LayerImpl> scroll_clip_layer =
2103 LayerImpl::Create(host_impl_->active_tree(), 3);
2104 scroll_clip_layer->SetBounds(surface_size);
2106 scoped_ptr<LayerImpl> scroll_layer =
2107 LayerImpl::Create(host_impl_->active_tree(), 2);
2108 scroll_layer->SetScrollClipLayer(3);
2109 scroll_layer->SetBounds(contents_size);
2110 scroll_layer->SetContentBounds(contents_size);
2111 scroll_layer->SetPosition(gfx::PointF());
2112 scroll_layer->SetAnchorPoint(gfx::PointF());
2113 scroll_layer->AddChild(content_layer.Pass());
2114 scroll_clip_layer->AddChild(scroll_layer.Pass());
2116 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
2117 host_impl_->SetViewportSize(surface_size);
2120 EXPECT_EQ(InputHandler::ScrollStarted,
2121 host_impl_->ScrollBegin(gfx::Point(5, 5),
2122 InputHandler::Wheel));
2123 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2124 host_impl_->ScrollEnd();
2125 EXPECT_TRUE(did_request_redraw_);
2126 EXPECT_TRUE(did_request_commit_);
2129 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
2130 gfx::Size surface_size(10, 10);
2131 gfx::Size contents_size(20, 20);
2132 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2133 root->SetBounds(surface_size);
2134 root->SetContentBounds(contents_size);
2135 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
2136 host_impl_->active_tree()->SetRootLayer(root.Pass());
2137 host_impl_->SetViewportSize(surface_size);
2140 EXPECT_EQ(InputHandler::ScrollStarted,
2141 host_impl_->ScrollBegin(gfx::Point(5, 5),
2142 InputHandler::Wheel));
2143 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2144 host_impl_->ScrollEnd();
2145 EXPECT_TRUE(did_request_redraw_);
2146 EXPECT_TRUE(did_request_commit_);
2149 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
2150 gfx::Size surface_size(10, 10);
2151 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2152 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
2153 host_impl_->active_tree()->SetRootLayer(root.Pass());
2154 host_impl_->SetViewportSize(surface_size);
2157 // Scroll event is ignored because the input coordinate is outside the layer
2159 EXPECT_EQ(InputHandler::ScrollIgnored,
2160 host_impl_->ScrollBegin(gfx::Point(15, 5),
2161 InputHandler::Wheel));
2162 EXPECT_FALSE(did_request_redraw_);
2163 EXPECT_FALSE(did_request_commit_);
2166 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
2167 gfx::Size surface_size(10, 10);
2168 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2169 scoped_ptr<LayerImpl> child =
2170 CreateScrollableLayer(2, surface_size, root.get());
2171 host_impl_->SetViewportSize(surface_size);
2173 gfx::Transform matrix;
2174 matrix.RotateAboutXAxis(180.0);
2175 child->SetTransform(matrix);
2176 child->SetDoubleSided(false);
2178 root->AddChild(child.Pass());
2179 host_impl_->active_tree()->SetRootLayer(root.Pass());
2182 // Scroll event is ignored because the scrollable layer is not facing the
2183 // viewer and there is nothing scrollable behind it.
2184 EXPECT_EQ(InputHandler::ScrollIgnored,
2185 host_impl_->ScrollBegin(gfx::Point(5, 5),
2186 InputHandler::Wheel));
2187 EXPECT_FALSE(did_request_redraw_);
2188 EXPECT_FALSE(did_request_commit_);
2191 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
2192 gfx::Size surface_size(10, 10);
2193 scoped_ptr<LayerImpl> clip_layer =
2194 LayerImpl::Create(host_impl_->active_tree(), 3);
2195 scoped_ptr<LayerImpl> content_layer =
2196 CreateScrollableLayer(1, surface_size, clip_layer.get());
2197 content_layer->SetShouldScrollOnMainThread(true);
2198 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
2200 // Note: we can use the same clip layer for both since both calls to
2201 // CreateScrollableLayer() use the same surface size.
2202 scoped_ptr<LayerImpl> scroll_layer =
2203 CreateScrollableLayer(2, surface_size, clip_layer.get());
2204 scroll_layer->AddChild(content_layer.Pass());
2205 clip_layer->AddChild(scroll_layer.Pass());
2207 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
2208 host_impl_->SetViewportSize(surface_size);
2211 // Scrolling fails because the content layer is asking to be scrolled on the
2213 EXPECT_EQ(InputHandler::ScrollOnMainThread,
2214 host_impl_->ScrollBegin(gfx::Point(5, 5),
2215 InputHandler::Wheel));
2218 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
2219 gfx::Size surface_size(20, 20);
2220 gfx::Size viewport_size(10, 10);
2221 float page_scale = 2.f;
2222 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2223 scoped_ptr<LayerImpl> root_clip =
2224 LayerImpl::Create(host_impl_->active_tree(), 2);
2225 scoped_ptr<LayerImpl> root_scrolling =
2226 CreateScrollableLayer(3, surface_size, root_clip.get());
2227 EXPECT_EQ(viewport_size, root_clip->bounds());
2228 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2229 root_clip->AddChild(root_scrolling.Pass());
2230 root->AddChild(root_clip.Pass());
2231 host_impl_->active_tree()->SetRootLayer(root.Pass());
2232 // The behaviour in this test assumes the page scale is applied at a layer
2233 // above the clip layer.
2234 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2235 host_impl_->active_tree()->DidBecomeActive();
2236 host_impl_->SetViewportSize(viewport_size);
2239 LayerImpl* root_scroll =
2240 host_impl_->active_tree()->InnerViewportScrollLayer();
2241 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2243 gfx::Vector2d scroll_delta(0, 10);
2244 gfx::Vector2d expected_scroll_delta = scroll_delta;
2245 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2246 EXPECT_EQ(InputHandler::ScrollStarted,
2247 host_impl_->ScrollBegin(gfx::Point(5, 5),
2248 InputHandler::Wheel));
2249 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2250 host_impl_->ScrollEnd();
2252 // Set new page scale from main thread.
2253 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2257 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2258 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2260 // The scroll range should also have been updated.
2261 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2263 // The page scale delta remains constant because the impl thread did not
2265 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2268 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
2269 gfx::Size surface_size(20, 20);
2270 gfx::Size viewport_size(10, 10);
2271 float page_scale = 2.f;
2272 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2273 scoped_ptr<LayerImpl> root_clip =
2274 LayerImpl::Create(host_impl_->active_tree(), 2);
2275 scoped_ptr<LayerImpl> root_scrolling =
2276 CreateScrollableLayer(3, surface_size, root_clip.get());
2277 EXPECT_EQ(viewport_size, root_clip->bounds());
2278 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2279 root_clip->AddChild(root_scrolling.Pass());
2280 root->AddChild(root_clip.Pass());
2281 host_impl_->active_tree()->SetRootLayer(root.Pass());
2282 // The behaviour in this test assumes the page scale is applied at a layer
2283 // above the clip layer.
2284 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2285 host_impl_->active_tree()->DidBecomeActive();
2286 host_impl_->SetViewportSize(viewport_size);
2287 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
2290 LayerImpl* root_scroll =
2291 host_impl_->active_tree()->InnerViewportScrollLayer();
2292 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2294 gfx::Vector2d scroll_delta(0, 10);
2295 gfx::Vector2d expected_scroll_delta = scroll_delta;
2296 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2297 EXPECT_EQ(InputHandler::ScrollStarted,
2298 host_impl_->ScrollBegin(gfx::Point(5, 5),
2299 InputHandler::Wheel));
2300 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2301 host_impl_->ScrollEnd();
2303 // Set new page scale on impl thread by pinching.
2304 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2305 host_impl_->PinchGestureBegin();
2306 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
2307 host_impl_->PinchGestureEnd();
2308 host_impl_->ScrollEnd();
2311 // The scroll delta is not scaled because the main thread did not scale.
2312 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2313 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2315 // The scroll range should also have been updated.
2316 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2318 // The page scale delta should match the new scale on the impl side.
2319 EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
2322 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
2323 gfx::Size surface_size(10, 10);
2324 float default_page_scale = 1.f;
2325 gfx::Transform default_page_scale_matrix;
2326 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
2328 float new_page_scale = 2.f;
2329 gfx::Transform new_page_scale_matrix;
2330 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
2332 // Create a normal scrollable root layer and another scrollable child layer.
2333 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
2334 LayerImpl* root = host_impl_->active_tree()->root_layer();
2335 LayerImpl* child = scroll->children()[0];
2337 scoped_ptr<LayerImpl> scrollable_child_clip =
2338 LayerImpl::Create(host_impl_->active_tree(), 6);
2339 scoped_ptr<LayerImpl> scrollable_child =
2340 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
2341 scrollable_child_clip->AddChild(scrollable_child.Pass());
2342 child->AddChild(scrollable_child_clip.Pass());
2343 LayerImpl* grand_child = child->children()[0];
2345 // Set new page scale on impl thread by pinching.
2346 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2347 host_impl_->PinchGestureBegin();
2348 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
2349 host_impl_->PinchGestureEnd();
2350 host_impl_->ScrollEnd();
2353 EXPECT_EQ(1.f, root->contents_scale_x());
2354 EXPECT_EQ(1.f, root->contents_scale_y());
2355 EXPECT_EQ(1.f, scroll->contents_scale_x());
2356 EXPECT_EQ(1.f, scroll->contents_scale_y());
2357 EXPECT_EQ(1.f, child->contents_scale_x());
2358 EXPECT_EQ(1.f, child->contents_scale_y());
2359 EXPECT_EQ(1.f, grand_child->contents_scale_x());
2360 EXPECT_EQ(1.f, grand_child->contents_scale_y());
2362 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
2363 // the page scale delta on the root layer is applied hierarchically.
2364 LayerTreeHostImpl::FrameData frame;
2365 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
2366 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2367 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2368 host_impl_->DidDrawAllLayers(frame);
2370 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
2371 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
2372 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
2373 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
2374 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
2375 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
2376 EXPECT_EQ(new_page_scale,
2377 grand_child->draw_transform().matrix().getDouble(0, 0));
2378 EXPECT_EQ(new_page_scale,
2379 grand_child->draw_transform().matrix().getDouble(1, 1));
2382 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
2383 gfx::Size surface_size(30, 30);
2384 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2385 root->SetBounds(gfx::Size(5, 5));
2386 scoped_ptr<LayerImpl> root_scrolling =
2387 LayerImpl::Create(host_impl_->active_tree(), 2);
2388 root_scrolling->SetBounds(surface_size);
2389 root_scrolling->SetContentBounds(surface_size);
2390 root_scrolling->SetScrollClipLayer(root->id());
2391 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2392 LayerImpl* root_scrolling_ptr = root_scrolling.get();
2393 root->AddChild(root_scrolling.Pass());
2394 int child_scroll_layer_id = 3;
2395 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
2396 child_scroll_layer_id, surface_size, root_scrolling_ptr);
2397 LayerImpl* child = child_scrolling.get();
2398 root_scrolling_ptr->AddChild(child_scrolling.Pass());
2399 host_impl_->active_tree()->SetRootLayer(root.Pass());
2400 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2401 host_impl_->active_tree()->DidBecomeActive();
2402 host_impl_->SetViewportSize(surface_size);
2405 gfx::Vector2d scroll_delta(0, 10);
2406 gfx::Vector2d expected_scroll_delta(scroll_delta);
2407 gfx::Vector2d expected_max_scroll(child->MaxScrollOffset());
2408 EXPECT_EQ(InputHandler::ScrollStarted,
2409 host_impl_->ScrollBegin(gfx::Point(5, 5),
2410 InputHandler::Wheel));
2411 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2412 host_impl_->ScrollEnd();
2414 float page_scale = 2.f;
2415 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2421 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2423 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
2425 // The scroll range should not have changed.
2426 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
2428 // The page scale delta remains constant because the impl thread did not
2430 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2433 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
2434 // Scroll a child layer beyond its maximum scroll range and make sure the
2435 // parent layer is scrolled on the axis on which the child was unable to
2437 gfx::Size surface_size(10, 10);
2438 gfx::Size content_size(20, 20);
2439 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2440 root->SetBounds(surface_size);
2442 scoped_ptr<LayerImpl> grand_child =
2443 CreateScrollableLayer(3, content_size, root.get());
2445 scoped_ptr<LayerImpl> child =
2446 CreateScrollableLayer(2, content_size, root.get());
2447 LayerImpl* grand_child_layer = grand_child.get();
2448 child->AddChild(grand_child.Pass());
2450 LayerImpl* child_layer = child.get();
2451 root->AddChild(child.Pass());
2452 host_impl_->active_tree()->SetRootLayer(root.Pass());
2453 host_impl_->active_tree()->DidBecomeActive();
2454 host_impl_->SetViewportSize(surface_size);
2455 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 5));
2456 child_layer->SetScrollOffset(gfx::Vector2d(3, 0));
2460 gfx::Vector2d scroll_delta(-8, -7);
2461 EXPECT_EQ(InputHandler::ScrollStarted,
2462 host_impl_->ScrollBegin(gfx::Point(),
2463 InputHandler::Wheel));
2464 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2465 host_impl_->ScrollEnd();
2467 scoped_ptr<ScrollAndScaleSet> scroll_info =
2468 host_impl_->ProcessScrollDeltas();
2470 // The grand child should have scrolled up to its limit.
2471 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2472 LayerImpl* grand_child = child->children()[0];
2473 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
2475 // The child should have only scrolled on the other axis.
2476 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
2480 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
2481 // Scroll a child layer beyond its maximum scroll range and make sure the
2482 // the scroll doesn't bubble up to the parent layer.
2483 gfx::Size surface_size(20, 20);
2484 gfx::Size viewport_size(10, 10);
2485 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2486 scoped_ptr<LayerImpl> root_scrolling =
2487 CreateScrollableLayer(2, surface_size, root.get());
2488 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2490 scoped_ptr<LayerImpl> grand_child =
2491 CreateScrollableLayer(4, surface_size, root.get());
2493 scoped_ptr<LayerImpl> child =
2494 CreateScrollableLayer(3, surface_size, root.get());
2495 LayerImpl* grand_child_layer = grand_child.get();
2496 child->AddChild(grand_child.Pass());
2498 LayerImpl* child_layer = child.get();
2499 root_scrolling->AddChild(child.Pass());
2500 root->AddChild(root_scrolling.Pass());
2501 EXPECT_EQ(viewport_size, root->bounds());
2502 host_impl_->active_tree()->SetRootLayer(root.Pass());
2503 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2504 host_impl_->active_tree()->DidBecomeActive();
2505 host_impl_->SetViewportSize(viewport_size);
2507 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
2508 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
2512 gfx::Vector2d scroll_delta(0, -10);
2513 EXPECT_EQ(InputHandler::ScrollStarted,
2514 host_impl_->ScrollBegin(gfx::Point(),
2515 InputHandler::NonBubblingGesture));
2516 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2517 host_impl_->ScrollEnd();
2519 scoped_ptr<ScrollAndScaleSet> scroll_info =
2520 host_impl_->ProcessScrollDeltas();
2522 // The grand child should have scrolled up to its limit.
2524 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
2525 LayerImpl* grand_child = child->children()[0];
2526 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2528 // The child should not have scrolled.
2529 ExpectNone(*scroll_info.get(), child->id());
2531 // The next time we scroll we should only scroll the parent.
2532 scroll_delta = gfx::Vector2d(0, -3);
2533 EXPECT_EQ(InputHandler::ScrollStarted,
2534 host_impl_->ScrollBegin(gfx::Point(5, 5),
2535 InputHandler::NonBubblingGesture));
2536 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2537 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2538 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
2539 host_impl_->ScrollEnd();
2541 scroll_info = host_impl_->ProcessScrollDeltas();
2543 // The child should have scrolled up to its limit.
2544 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2546 // The grand child should not have scrolled.
2547 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2549 // After scrolling the parent, another scroll on the opposite direction
2550 // should still scroll the child.
2551 scroll_delta = gfx::Vector2d(0, 7);
2552 EXPECT_EQ(InputHandler::ScrollStarted,
2553 host_impl_->ScrollBegin(gfx::Point(5, 5),
2554 InputHandler::NonBubblingGesture));
2555 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2556 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2557 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2558 host_impl_->ScrollEnd();
2560 scroll_info = host_impl_->ProcessScrollDeltas();
2562 // The grand child should have scrolled.
2563 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
2565 // The child should not have scrolled.
2566 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2569 // Scrolling should be adjusted from viewport space.
2570 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
2571 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2573 scroll_delta = gfx::Vector2d(0, -2);
2574 EXPECT_EQ(InputHandler::ScrollStarted,
2575 host_impl_->ScrollBegin(gfx::Point(1, 1),
2576 InputHandler::NonBubblingGesture));
2577 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
2578 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2579 host_impl_->ScrollEnd();
2581 scroll_info = host_impl_->ProcessScrollDeltas();
2583 // Should have scrolled by half the amount in layer space (5 - 2/2)
2584 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
2587 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
2588 // When we try to scroll a non-scrollable child layer, the scroll delta
2589 // should be applied to one of its ancestors if possible.
2590 gfx::Size surface_size(10, 10);
2591 gfx::Size content_size(20, 20);
2592 scoped_ptr<LayerImpl> root_clip =
2593 LayerImpl::Create(host_impl_->active_tree(), 3);
2594 scoped_ptr<LayerImpl> root =
2595 CreateScrollableLayer(1, content_size, root_clip.get());
2596 // Make 'root' the clip layer for child: since they have the same sizes the
2597 // child will have zero max_scroll_offset and scrolls will bubble.
2598 scoped_ptr<LayerImpl> child =
2599 CreateScrollableLayer(2, content_size, root.get());
2600 child->SetIsContainerForFixedPositionLayers(true);
2601 root->SetBounds(content_size);
2603 int root_scroll_id = root->id();
2604 root->AddChild(child.Pass());
2605 root_clip->AddChild(root.Pass());
2607 host_impl_->SetViewportSize(surface_size);
2608 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2609 host_impl_->active_tree()->SetViewportLayersFromIds(3, 2, Layer::INVALID_ID);
2610 host_impl_->active_tree()->DidBecomeActive();
2613 gfx::Vector2d scroll_delta(0, 4);
2614 EXPECT_EQ(InputHandler::ScrollStarted,
2615 host_impl_->ScrollBegin(gfx::Point(5, 5),
2616 InputHandler::Wheel));
2617 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2618 host_impl_->ScrollEnd();
2620 scoped_ptr<ScrollAndScaleSet> scroll_info =
2621 host_impl_->ProcessScrollDeltas();
2623 // Only the root scroll should have scrolled.
2624 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
2625 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
2629 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
2630 gfx::Size surface_size(10, 10);
2631 scoped_ptr<LayerImpl> root_clip =
2632 LayerImpl::Create(host_impl_->active_tree(), 1);
2633 scoped_ptr<LayerImpl> root_scroll =
2634 CreateScrollableLayer(2, surface_size, root_clip.get());
2635 root_scroll->SetIsContainerForFixedPositionLayers(true);
2636 root_clip->AddChild(root_scroll.Pass());
2637 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2638 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2639 host_impl_->active_tree()->DidBecomeActive();
2640 host_impl_->SetViewportSize(surface_size);
2642 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
2645 host_impl_->active_tree()->DetachLayerTree();
2646 scoped_ptr<LayerImpl> root_clip2 =
2647 LayerImpl::Create(host_impl_->active_tree(), 3);
2648 scoped_ptr<LayerImpl> root_scroll2 =
2649 CreateScrollableLayer(4, surface_size, root_clip2.get());
2650 root_scroll2->SetIsContainerForFixedPositionLayers(true);
2651 root_clip2->AddChild(root_scroll2.Pass());
2652 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
2653 host_impl_->active_tree()->SetViewportLayersFromIds(3, 4, Layer::INVALID_ID);
2654 host_impl_->active_tree()->DidBecomeActive();
2656 // Scrolling should still work even though we did not draw yet.
2657 EXPECT_EQ(InputHandler::ScrollStarted,
2658 host_impl_->ScrollBegin(gfx::Point(5, 5),
2659 InputHandler::Wheel));
2662 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
2663 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2665 // Rotate the root layer 90 degrees counter-clockwise about its center.
2666 gfx::Transform rotate_transform;
2667 rotate_transform.Rotate(-90.0);
2668 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
2670 gfx::Size surface_size(50, 50);
2671 host_impl_->SetViewportSize(surface_size);
2674 // Scroll to the right in screen coordinates with a gesture.
2675 gfx::Vector2d gesture_scroll_delta(10, 0);
2676 EXPECT_EQ(InputHandler::ScrollStarted,
2677 host_impl_->ScrollBegin(gfx::Point(),
2678 InputHandler::Gesture));
2679 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2680 host_impl_->ScrollEnd();
2682 // The layer should have scrolled down in its local coordinates.
2683 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2684 ExpectContains(*scroll_info.get(),
2686 gfx::Vector2d(0, gesture_scroll_delta.x()));
2688 // Reset and scroll down with the wheel.
2689 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2690 gfx::Vector2d wheel_scroll_delta(0, 10);
2691 EXPECT_EQ(InputHandler::ScrollStarted,
2692 host_impl_->ScrollBegin(gfx::Point(),
2693 InputHandler::Wheel));
2694 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2695 host_impl_->ScrollEnd();
2697 // The layer should have scrolled down in its local coordinates.
2698 scroll_info = host_impl_->ProcessScrollDeltas();
2699 ExpectContains(*scroll_info.get(),
2701 wheel_scroll_delta);
2704 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
2705 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2706 int child_clip_layer_id = 6;
2707 int child_layer_id = 7;
2708 float child_layer_angle = -20.f;
2710 // Create a child layer that is rotated to a non-axis-aligned angle.
2711 scoped_ptr<LayerImpl> clip_layer =
2712 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
2713 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
2714 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
2715 gfx::Transform rotate_transform;
2716 rotate_transform.Translate(-50.0, -50.0);
2717 rotate_transform.Rotate(child_layer_angle);
2718 rotate_transform.Translate(50.0, 50.0);
2719 clip_layer->SetTransform(rotate_transform);
2721 // Only allow vertical scrolling.
2722 clip_layer->SetBounds(
2723 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
2724 // The rotation depends on the layer's anchor point, and the child layer is a
2725 // different size than the clip, so make sure the clip layer's anchor lines
2726 // up over the child.
2727 clip_layer->SetAnchorPoint(gfx::PointF(0.5, 1.0));
2728 LayerImpl* child_ptr = child.get();
2729 clip_layer->AddChild(child.Pass());
2730 scroll_layer->AddChild(clip_layer.Pass());
2732 gfx::Size surface_size(50, 50);
2733 host_impl_->SetViewportSize(surface_size);
2736 // Scroll down in screen coordinates with a gesture.
2737 gfx::Vector2d gesture_scroll_delta(0, 10);
2738 EXPECT_EQ(InputHandler::ScrollStarted,
2739 host_impl_->ScrollBegin(gfx::Point(1, 1),
2740 InputHandler::Gesture));
2741 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2742 host_impl_->ScrollEnd();
2744 // The child layer should have scrolled down in its local coordinates an
2745 // amount proportional to the angle between it and the input scroll delta.
2746 gfx::Vector2d expected_scroll_delta(
2748 gesture_scroll_delta.y() *
2749 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
2750 scoped_ptr<ScrollAndScaleSet> scroll_info =
2751 host_impl_->ProcessScrollDeltas();
2752 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2754 // The root scroll layer should not have scrolled, because the input delta
2755 // was close to the layer's axis of movement.
2756 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
2759 // Now reset and scroll the same amount horizontally.
2760 child_ptr->SetScrollDelta(gfx::Vector2dF());
2761 gfx::Vector2d gesture_scroll_delta(10, 0);
2762 EXPECT_EQ(InputHandler::ScrollStarted,
2763 host_impl_->ScrollBegin(gfx::Point(1, 1),
2764 InputHandler::Gesture));
2765 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2766 host_impl_->ScrollEnd();
2768 // The child layer should have scrolled down in its local coordinates an
2769 // amount proportional to the angle between it and the input scroll delta.
2770 gfx::Vector2d expected_scroll_delta(
2772 -gesture_scroll_delta.x() *
2773 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
2774 scoped_ptr<ScrollAndScaleSet> scroll_info =
2775 host_impl_->ProcessScrollDeltas();
2776 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2778 // The root scroll layer should have scrolled more, since the input scroll
2779 // delta was mostly orthogonal to the child layer's vertical scroll axis.
2780 gfx::Vector2d expected_root_scroll_delta(
2781 gesture_scroll_delta.x() *
2782 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
2784 ExpectContains(*scroll_info.get(),
2786 expected_root_scroll_delta);
2790 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
2791 LayerImpl* scroll_layer =
2792 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2794 // Scale the layer to twice its normal size.
2796 gfx::Transform scale_transform;
2797 scale_transform.Scale(scale, scale);
2798 scroll_layer->SetTransform(scale_transform);
2800 gfx::Size surface_size(50, 50);
2801 host_impl_->SetViewportSize(surface_size);
2804 // Scroll down in screen coordinates with a gesture.
2805 gfx::Vector2d scroll_delta(0, 10);
2806 EXPECT_EQ(InputHandler::ScrollStarted,
2807 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2808 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2809 host_impl_->ScrollEnd();
2811 // The layer should have scrolled down in its local coordinates, but half the
2813 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2814 ExpectContains(*scroll_info.get(),
2816 gfx::Vector2d(0, scroll_delta.y() / scale));
2818 // Reset and scroll down with the wheel.
2819 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2820 gfx::Vector2d wheel_scroll_delta(0, 10);
2821 EXPECT_EQ(InputHandler::ScrollStarted,
2822 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2823 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2824 host_impl_->ScrollEnd();
2826 // The scale should not have been applied to the scroll delta.
2827 scroll_info = host_impl_->ProcessScrollDeltas();
2828 ExpectContains(*scroll_info.get(),
2830 wheel_scroll_delta);
2833 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
2835 TestScrollOffsetDelegate()
2836 : page_scale_factor_(0.f),
2837 min_page_scale_factor_(-1.f),
2838 max_page_scale_factor_(-1.f) {}
2840 virtual ~TestScrollOffsetDelegate() {}
2842 virtual void SetMaxScrollOffset(
2843 const gfx::Vector2dF& max_scroll_offset) OVERRIDE {
2844 max_scroll_offset_ = max_scroll_offset;
2847 virtual void SetTotalScrollOffset(const gfx::Vector2dF& new_value) OVERRIDE {
2848 last_set_scroll_offset_ = new_value;
2851 virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
2852 return getter_return_value_;
2855 virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
2857 virtual void SetTotalPageScaleFactorAndLimits(
2858 float page_scale_factor,
2859 float min_page_scale_factor,
2860 float max_page_scale_factor) OVERRIDE {
2861 page_scale_factor_ = page_scale_factor;
2862 min_page_scale_factor_ = min_page_scale_factor;
2863 max_page_scale_factor_ = max_page_scale_factor;
2866 virtual void SetScrollableSize(const gfx::SizeF& scrollable_size) OVERRIDE {
2867 scrollable_size_ = scrollable_size;
2870 gfx::Vector2dF last_set_scroll_offset() {
2871 return last_set_scroll_offset_;
2874 void set_getter_return_value(const gfx::Vector2dF& value) {
2875 getter_return_value_ = value;
2878 gfx::Vector2dF max_scroll_offset() const {
2879 return max_scroll_offset_;
2882 gfx::SizeF scrollable_size() const {
2883 return scrollable_size_;
2886 float page_scale_factor() const {
2887 return page_scale_factor_;
2890 float min_page_scale_factor() const {
2891 return min_page_scale_factor_;
2894 float max_page_scale_factor() const {
2895 return max_page_scale_factor_;
2899 gfx::Vector2dF last_set_scroll_offset_;
2900 gfx::Vector2dF getter_return_value_;
2901 gfx::Vector2dF max_scroll_offset_;
2902 gfx::SizeF scrollable_size_;
2903 float page_scale_factor_;
2904 float min_page_scale_factor_;
2905 float max_page_scale_factor_;
2908 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
2909 TestScrollOffsetDelegate scroll_delegate;
2910 host_impl_->SetViewportSize(gfx::Size(10, 20));
2911 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2912 LayerImpl* clip_layer = scroll_layer->parent()->parent();
2913 clip_layer->SetBounds(gfx::Size(10, 20));
2915 // Setting the delegate results in the current scroll offset being set.
2916 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
2917 scroll_layer->SetScrollOffset(gfx::Vector2d());
2918 scroll_layer->SetScrollDelta(initial_scroll_delta);
2919 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
2920 EXPECT_EQ(initial_scroll_delta.ToString(),
2921 scroll_delegate.last_set_scroll_offset().ToString());
2923 // Setting the delegate results in the scrollable_size, max_scroll_offset,
2924 // page_scale_factor and {min|max}_page_scale_factor being set.
2925 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
2926 EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
2927 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
2928 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
2929 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
2931 // Updating page scale immediately updates the delegate.
2932 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
2933 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
2934 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
2935 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
2936 host_impl_->active_tree()->SetPageScaleDelta(1.5f);
2937 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
2938 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
2939 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
2940 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2941 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
2942 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
2943 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
2944 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
2946 // Scrolling should be relative to the offset as returned by the delegate.
2947 gfx::Vector2dF scroll_delta(0.f, 10.f);
2948 gfx::Vector2dF current_offset(7.f, 8.f);
2950 scroll_delegate.set_getter_return_value(current_offset);
2951 EXPECT_EQ(InputHandler::ScrollStarted,
2952 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2954 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2955 EXPECT_EQ(current_offset + scroll_delta,
2956 scroll_delegate.last_set_scroll_offset());
2958 current_offset = gfx::Vector2dF(42.f, 41.f);
2959 scroll_delegate.set_getter_return_value(current_offset);
2960 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2961 EXPECT_EQ(current_offset + scroll_delta,
2962 scroll_delegate.last_set_scroll_offset());
2963 host_impl_->ScrollEnd();
2965 // Forces a full tree synchronization and ensures that the scroll delegate
2966 // sees the correct size of the new tree.
2967 gfx::Size new_size(42, 24);
2968 host_impl_->CreatePendingTree();
2969 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
2970 host_impl_->ActivatePendingTree();
2971 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
2973 // Un-setting the delegate should propagate the delegate's current offset to
2974 // the root scrollable layer.
2975 current_offset = gfx::Vector2dF(13.f, 12.f);
2976 scroll_delegate.set_getter_return_value(current_offset);
2977 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
2979 EXPECT_EQ(current_offset.ToString(),
2980 scroll_layer->TotalScrollOffset().ToString());
2983 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
2984 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2985 host_impl_->SetViewportSize(gfx::Size(50, 50));
2986 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
2988 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2989 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2991 // In-bounds scrolling does not affect overscroll.
2992 EXPECT_EQ(InputHandler::ScrollStarted,
2993 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2994 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2995 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2996 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2998 // Overscroll events are reflected immediately.
2999 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
3000 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3001 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
3003 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
3004 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
3005 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3006 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
3007 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3008 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
3009 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3010 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
3011 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
3012 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
3013 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
3014 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
3015 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3017 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
3018 // as no scroll occurs.
3019 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3020 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
3021 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3022 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
3023 // Overscroll resets on valid scroll.
3024 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3025 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3026 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3027 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3028 host_impl_->ScrollEnd();
3030 EXPECT_EQ(InputHandler::ScrollStarted,
3031 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3032 // Fling velocity is reflected immediately.
3033 host_impl_->NotifyCurrentFlingVelocity(gfx::Vector2dF(10, 0));
3034 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
3035 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3036 EXPECT_EQ(gfx::Vector2dF(0, -20), host_impl_->accumulated_root_overscroll());
3037 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
3041 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
3042 // Scroll child layers beyond their maximum scroll range and make sure root
3043 // overscroll does not accumulate.
3044 gfx::Size surface_size(10, 10);
3045 scoped_ptr<LayerImpl> root_clip =
3046 LayerImpl::Create(host_impl_->active_tree(), 4);
3047 scoped_ptr<LayerImpl> root =
3048 CreateScrollableLayer(1, surface_size, root_clip.get());
3050 scoped_ptr<LayerImpl> grand_child =
3051 CreateScrollableLayer(3, surface_size, root_clip.get());
3053 scoped_ptr<LayerImpl> child =
3054 CreateScrollableLayer(2, surface_size, root_clip.get());
3055 LayerImpl* grand_child_layer = grand_child.get();
3056 child->AddChild(grand_child.Pass());
3058 LayerImpl* child_layer = child.get();
3059 root->AddChild(child.Pass());
3060 root_clip->AddChild(root.Pass());
3061 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
3062 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
3063 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3064 host_impl_->active_tree()->DidBecomeActive();
3065 host_impl_->SetViewportSize(surface_size);
3068 gfx::Vector2d scroll_delta(0, -10);
3069 EXPECT_EQ(InputHandler::ScrollStarted,
3070 host_impl_->ScrollBegin(gfx::Point(),
3071 InputHandler::NonBubblingGesture));
3072 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3073 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3074 host_impl_->ScrollEnd();
3076 // The next time we scroll we should only scroll the parent, but overscroll
3077 // should still not reach the root layer.
3078 scroll_delta = gfx::Vector2d(0, -30);
3079 EXPECT_EQ(InputHandler::ScrollStarted,
3080 host_impl_->ScrollBegin(gfx::Point(5, 5),
3081 InputHandler::NonBubblingGesture));
3082 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3083 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3084 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3085 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
3086 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3087 host_impl_->ScrollEnd();
3089 // After scrolling the parent, another scroll on the opposite direction
3090 // should scroll the child, resetting the fling velocity.
3091 scroll_delta = gfx::Vector2d(0, 70);
3092 host_impl_->NotifyCurrentFlingVelocity(gfx::Vector2dF(10, 0));
3093 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
3094 EXPECT_EQ(InputHandler::ScrollStarted,
3095 host_impl_->ScrollBegin(gfx::Point(5, 5),
3096 InputHandler::NonBubblingGesture));
3097 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3098 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3099 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3100 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3101 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
3102 host_impl_->ScrollEnd();
3106 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
3107 // When we try to scroll a non-scrollable child layer, the scroll delta
3108 // should be applied to one of its ancestors if possible. Overscroll should
3109 // be reflected only when it has bubbled up to the root scrolling layer.
3110 gfx::Size surface_size(10, 10);
3111 gfx::Size content_size(20, 20);
3112 scoped_ptr<LayerImpl> root_clip =
3113 LayerImpl::Create(host_impl_->active_tree(), 3);
3114 scoped_ptr<LayerImpl> root =
3115 CreateScrollableLayer(1, content_size, root_clip.get());
3116 root->SetIsContainerForFixedPositionLayers(true);
3117 scoped_ptr<LayerImpl> child =
3118 CreateScrollableLayer(2, content_size, root_clip.get());
3120 child->SetScrollClipLayer(Layer::INVALID_ID);
3121 root->AddChild(child.Pass());
3122 root_clip->AddChild(root.Pass());
3124 host_impl_->SetViewportSize(surface_size);
3125 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3126 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3127 host_impl_->active_tree()->DidBecomeActive();
3130 gfx::Vector2d scroll_delta(0, 8);
3131 EXPECT_EQ(InputHandler::ScrollStarted,
3132 host_impl_->ScrollBegin(gfx::Point(5, 5),
3133 InputHandler::Wheel));
3134 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3135 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3136 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3137 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
3138 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3139 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
3140 host_impl_->ScrollEnd();
3144 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
3145 LayerTreeSettings settings;
3146 CreateHostImpl(settings, CreateOutputSurface());
3148 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
3149 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3150 clip_layer->SetBounds(gfx::Size(50, 50));
3151 host_impl_->SetViewportSize(gfx::Size(50, 50));
3152 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3154 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3155 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
3157 // Even though the layer can't scroll the overscroll still happens.
3158 EXPECT_EQ(InputHandler::ScrollStarted,
3159 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3160 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3161 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3162 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
3165 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
3166 gfx::Size surface_size(100, 100);
3167 gfx::Size content_size(200, 200);
3168 scoped_ptr<LayerImpl> root_clip =
3169 LayerImpl::Create(host_impl_->active_tree(), 3);
3170 scoped_ptr<LayerImpl> root =
3171 CreateScrollableLayer(1, content_size, root_clip.get());
3172 root->SetIsContainerForFixedPositionLayers(true);
3173 scoped_ptr<LayerImpl> child =
3174 CreateScrollableLayer(2, content_size, root_clip.get());
3176 child->SetScrollClipLayer(Layer::INVALID_ID);
3177 root->AddChild(child.Pass());
3178 root_clip->AddChild(root.Pass());
3180 host_impl_->SetViewportSize(surface_size);
3181 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3182 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3183 host_impl_->active_tree()->DidBecomeActive();
3186 // Edge glow effect should be applicable only upon reaching Edges
3187 // of the content. unnecessary glow effect calls shouldn't be
3188 // called while scrolling up without reaching the edge of the content.
3189 EXPECT_EQ(InputHandler::ScrollStarted,
3190 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3191 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
3192 EXPECT_EQ(gfx::Vector2dF().ToString(),
3193 host_impl_->accumulated_root_overscroll().ToString());
3194 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
3195 EXPECT_EQ(gfx::Vector2dF().ToString(),
3196 host_impl_->accumulated_root_overscroll().ToString());
3197 host_impl_->ScrollEnd();
3198 // unusedrootDelta should be subtracted from applied delta so that
3199 // unwanted glow effect calls are not called.
3200 EXPECT_EQ(InputHandler::ScrollStarted,
3201 host_impl_->ScrollBegin(gfx::Point(0, 0),
3202 InputHandler::NonBubblingGesture));
3203 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
3204 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
3205 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3206 host_impl_->accumulated_root_overscroll().ToString());
3208 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
3209 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3210 host_impl_->accumulated_root_overscroll().ToString());
3211 host_impl_->ScrollEnd();
3215 class BlendStateCheckLayer : public LayerImpl {
3217 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
3219 ResourceProvider* resource_provider) {
3220 return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(tree_impl,
3222 resource_provider));
3225 virtual void AppendQuads(QuadSink* quad_sink,
3226 AppendQuadsData* append_quads_data) OVERRIDE {
3227 quads_appended_ = true;
3229 gfx::Rect opaque_rect;
3230 if (contents_opaque())
3231 opaque_rect = quad_rect_;
3233 opaque_rect = opaque_content_rect_;
3234 gfx::Rect visible_quad_rect = quad_rect_;
3236 SharedQuadState* shared_quad_state =
3237 quad_sink->UseSharedQuadState(CreateSharedQuadState());
3238 scoped_ptr<TileDrawQuad> test_blending_draw_quad = TileDrawQuad::Create();
3239 test_blending_draw_quad->SetNew(shared_quad_state,
3244 gfx::RectF(0.f, 0.f, 1.f, 1.f),
3247 test_blending_draw_quad->visible_rect = quad_visible_rect_;
3248 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
3249 EXPECT_EQ(has_render_surface_, !!render_surface());
3250 quad_sink->MaybeAppend(test_blending_draw_quad.PassAs<DrawQuad>());
3253 void SetExpectation(bool blend, bool has_render_surface) {
3255 has_render_surface_ = has_render_surface;
3256 quads_appended_ = false;
3259 bool quads_appended() const { return quads_appended_; }
3261 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
3262 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
3263 void SetOpaqueContentRect(const gfx::Rect& rect) {
3264 opaque_content_rect_ = rect;
3268 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
3270 ResourceProvider* resource_provider)
3271 : LayerImpl(tree_impl, id),
3273 has_render_surface_(false),
3274 quads_appended_(false),
3275 quad_rect_(5, 5, 5, 5),
3276 quad_visible_rect_(5, 5, 5, 5),
3277 resource_id_(resource_provider->CreateResource(
3280 ResourceProvider::TextureUsageAny,
3282 resource_provider->AllocateForTesting(resource_id_);
3283 SetAnchorPoint(gfx::PointF());
3284 SetBounds(gfx::Size(10, 10));
3285 SetContentBounds(gfx::Size(10, 10));
3286 SetDrawsContent(true);
3290 bool has_render_surface_;
3291 bool quads_appended_;
3292 gfx::Rect quad_rect_;
3293 gfx::Rect opaque_content_rect_;
3294 gfx::Rect quad_visible_rect_;
3295 ResourceProvider::ResourceId resource_id_;
3298 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
3300 scoped_ptr<LayerImpl> root =
3301 LayerImpl::Create(host_impl_->active_tree(), 1);
3302 root->SetAnchorPoint(gfx::PointF());
3303 root->SetBounds(gfx::Size(10, 10));
3304 root->SetContentBounds(root->bounds());
3305 root->SetDrawsContent(false);
3306 host_impl_->active_tree()->SetRootLayer(root.Pass());
3308 LayerImpl* root = host_impl_->active_tree()->root_layer();
3311 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3313 host_impl_->resource_provider()));
3314 BlendStateCheckLayer* layer1 =
3315 static_cast<BlendStateCheckLayer*>(root->children()[0]);
3316 layer1->SetPosition(gfx::PointF(2.f, 2.f));
3318 LayerTreeHostImpl::FrameData frame;
3320 // Opaque layer, drawn without blending.
3321 layer1->SetContentsOpaque(true);
3322 layer1->SetExpectation(false, false);
3323 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3324 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3325 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3326 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3327 EXPECT_TRUE(layer1->quads_appended());
3328 host_impl_->DidDrawAllLayers(frame);
3330 // Layer with translucent content and painting, so drawn with blending.
3331 layer1->SetContentsOpaque(false);
3332 layer1->SetExpectation(true, false);
3333 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3334 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3335 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3336 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3337 EXPECT_TRUE(layer1->quads_appended());
3338 host_impl_->DidDrawAllLayers(frame);
3340 // Layer with translucent opacity, drawn with blending.
3341 layer1->SetContentsOpaque(true);
3342 layer1->SetOpacity(0.5f);
3343 layer1->SetExpectation(true, false);
3344 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3345 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3346 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3347 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3348 EXPECT_TRUE(layer1->quads_appended());
3349 host_impl_->DidDrawAllLayers(frame);
3351 // Layer with translucent opacity and painting, drawn with blending.
3352 layer1->SetContentsOpaque(true);
3353 layer1->SetOpacity(0.5f);
3354 layer1->SetExpectation(true, false);
3355 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3356 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3357 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3358 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3359 EXPECT_TRUE(layer1->quads_appended());
3360 host_impl_->DidDrawAllLayers(frame);
3363 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3365 host_impl_->resource_provider()));
3366 BlendStateCheckLayer* layer2 =
3367 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
3368 layer2->SetPosition(gfx::PointF(4.f, 4.f));
3370 // 2 opaque layers, drawn without blending.
3371 layer1->SetContentsOpaque(true);
3372 layer1->SetOpacity(1.f);
3373 layer1->SetExpectation(false, false);
3374 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3375 layer2->SetContentsOpaque(true);
3376 layer2->SetOpacity(1.f);
3377 layer2->SetExpectation(false, false);
3378 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3379 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3380 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3381 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3382 EXPECT_TRUE(layer1->quads_appended());
3383 EXPECT_TRUE(layer2->quads_appended());
3384 host_impl_->DidDrawAllLayers(frame);
3386 // Parent layer with translucent content, drawn with blending.
3387 // Child layer with opaque content, drawn without blending.
3388 layer1->SetContentsOpaque(false);
3389 layer1->SetExpectation(true, false);
3390 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3391 layer2->SetExpectation(false, false);
3392 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3393 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3394 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3395 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3396 EXPECT_TRUE(layer1->quads_appended());
3397 EXPECT_TRUE(layer2->quads_appended());
3398 host_impl_->DidDrawAllLayers(frame);
3400 // Parent layer with translucent content but opaque painting, drawn without
3402 // Child layer with opaque content, drawn without blending.
3403 layer1->SetContentsOpaque(true);
3404 layer1->SetExpectation(false, false);
3405 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3406 layer2->SetExpectation(false, false);
3407 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3408 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3409 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3410 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3411 EXPECT_TRUE(layer1->quads_appended());
3412 EXPECT_TRUE(layer2->quads_appended());
3413 host_impl_->DidDrawAllLayers(frame);
3415 // Parent layer with translucent opacity and opaque content. Since it has a
3416 // drawing child, it's drawn to a render surface which carries the opacity,
3417 // so it's itself drawn without blending.
3418 // Child layer with opaque content, drawn without blending (parent surface
3419 // carries the inherited opacity).
3420 layer1->SetContentsOpaque(true);
3421 layer1->SetOpacity(0.5f);
3422 layer1->SetExpectation(false, true);
3423 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3424 layer2->SetExpectation(false, false);
3425 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3426 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3427 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3428 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3429 EXPECT_TRUE(layer1->quads_appended());
3430 EXPECT_TRUE(layer2->quads_appended());
3431 host_impl_->DidDrawAllLayers(frame);
3433 // Draw again, but with child non-opaque, to make sure
3434 // layer1 not culled.
3435 layer1->SetContentsOpaque(true);
3436 layer1->SetOpacity(1.f);
3437 layer1->SetExpectation(false, false);
3438 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3439 layer2->SetContentsOpaque(true);
3440 layer2->SetOpacity(0.5f);
3441 layer2->SetExpectation(true, false);
3442 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3443 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3444 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3445 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3446 EXPECT_TRUE(layer1->quads_appended());
3447 EXPECT_TRUE(layer2->quads_appended());
3448 host_impl_->DidDrawAllLayers(frame);
3450 // A second way of making the child non-opaque.
3451 layer1->SetContentsOpaque(true);
3452 layer1->SetOpacity(1.f);
3453 layer1->SetExpectation(false, false);
3454 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3455 layer2->SetContentsOpaque(false);
3456 layer2->SetOpacity(1.f);
3457 layer2->SetExpectation(true, false);
3458 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3459 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3460 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3461 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3462 EXPECT_TRUE(layer1->quads_appended());
3463 EXPECT_TRUE(layer2->quads_appended());
3464 host_impl_->DidDrawAllLayers(frame);
3466 // And when the layer says its not opaque but is painted opaque, it is not
3468 layer1->SetContentsOpaque(true);
3469 layer1->SetOpacity(1.f);
3470 layer1->SetExpectation(false, false);
3471 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3472 layer2->SetContentsOpaque(true);
3473 layer2->SetOpacity(1.f);
3474 layer2->SetExpectation(false, false);
3475 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3476 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3477 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3478 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3479 EXPECT_TRUE(layer1->quads_appended());
3480 EXPECT_TRUE(layer2->quads_appended());
3481 host_impl_->DidDrawAllLayers(frame);
3483 // Layer with partially opaque contents, drawn with blending.
3484 layer1->SetContentsOpaque(false);
3485 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3486 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
3487 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3488 layer1->SetExpectation(true, false);
3489 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3490 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3491 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3492 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3493 EXPECT_TRUE(layer1->quads_appended());
3494 host_impl_->DidDrawAllLayers(frame);
3496 // Layer with partially opaque contents partially culled, drawn with blending.
3497 layer1->SetContentsOpaque(false);
3498 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3499 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
3500 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3501 layer1->SetExpectation(true, false);
3502 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3503 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3504 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3505 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3506 EXPECT_TRUE(layer1->quads_appended());
3507 host_impl_->DidDrawAllLayers(frame);
3509 // Layer with partially opaque contents culled, drawn with blending.
3510 layer1->SetContentsOpaque(false);
3511 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3512 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
3513 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3514 layer1->SetExpectation(true, false);
3515 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3516 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3517 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3518 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3519 EXPECT_TRUE(layer1->quads_appended());
3520 host_impl_->DidDrawAllLayers(frame);
3522 // Layer with partially opaque contents and translucent contents culled, drawn
3523 // without blending.
3524 layer1->SetContentsOpaque(false);
3525 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3526 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
3527 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3528 layer1->SetExpectation(false, false);
3529 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3530 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3531 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3532 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3533 EXPECT_TRUE(layer1->quads_appended());
3534 host_impl_->DidDrawAllLayers(frame);
3537 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
3539 LayerTreeHostImplViewportCoveredTest() :
3540 gutter_quad_material_(DrawQuad::SOLID_COLOR),
3542 did_activate_pending_tree_(false) {}
3544 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
3546 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
3547 .PassAs<OutputSurface>();
3549 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
3552 void SetupActiveTreeLayers() {
3553 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
3554 host_impl_->active_tree()->SetRootLayer(
3555 LayerImpl::Create(host_impl_->active_tree(), 1));
3556 host_impl_->active_tree()->root_layer()->AddChild(
3557 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3559 host_impl_->resource_provider()));
3560 child_ = static_cast<BlendStateCheckLayer*>(
3561 host_impl_->active_tree()->root_layer()->children()[0]);
3562 child_->SetExpectation(false, false);
3563 child_->SetContentsOpaque(true);
3566 // Expect no gutter rects.
3567 void TestLayerCoversFullViewport() {
3568 gfx::Rect layer_rect(viewport_size_);
3569 child_->SetPosition(layer_rect.origin());
3570 child_->SetBounds(layer_rect.size());
3571 child_->SetContentBounds(layer_rect.size());
3572 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3573 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3575 LayerTreeHostImpl::FrameData frame;
3576 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3577 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3578 ASSERT_EQ(1u, frame.render_passes.size());
3580 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3581 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3582 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3584 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3585 host_impl_->DidDrawAllLayers(frame);
3588 // Expect fullscreen gutter rect.
3589 void TestEmptyLayer() {
3590 gfx::Rect layer_rect(0, 0, 0, 0);
3591 child_->SetPosition(layer_rect.origin());
3592 child_->SetBounds(layer_rect.size());
3593 child_->SetContentBounds(layer_rect.size());
3594 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3595 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3597 LayerTreeHostImpl::FrameData frame;
3598 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3599 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3600 ASSERT_EQ(1u, frame.render_passes.size());
3602 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
3603 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3604 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3606 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3607 host_impl_->DidDrawAllLayers(frame);
3610 // Expect four surrounding gutter rects.
3611 void TestLayerInMiddleOfViewport() {
3612 gfx::Rect layer_rect(500, 500, 200, 200);
3613 child_->SetPosition(layer_rect.origin());
3614 child_->SetBounds(layer_rect.size());
3615 child_->SetContentBounds(layer_rect.size());
3616 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3617 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3619 LayerTreeHostImpl::FrameData frame;
3620 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3621 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3622 ASSERT_EQ(1u, frame.render_passes.size());
3624 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
3625 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
3626 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3628 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3629 host_impl_->DidDrawAllLayers(frame);
3632 // Expect no gutter rects.
3633 void TestLayerIsLargerThanViewport() {
3634 gfx::Rect layer_rect(viewport_size_.width() + 10,
3635 viewport_size_.height() + 10);
3636 child_->SetPosition(layer_rect.origin());
3637 child_->SetBounds(layer_rect.size());
3638 child_->SetContentBounds(layer_rect.size());
3639 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3640 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3642 LayerTreeHostImpl::FrameData frame;
3643 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3644 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3645 ASSERT_EQ(1u, frame.render_passes.size());
3647 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3648 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3649 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3651 host_impl_->DidDrawAllLayers(frame);
3654 virtual void DidActivatePendingTree() OVERRIDE {
3655 did_activate_pending_tree_ = true;
3658 void set_gutter_quad_material(DrawQuad::Material material) {
3659 gutter_quad_material_ = material;
3661 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
3662 gutter_texture_size_ = gutter_texture_size;
3666 size_t CountGutterQuads(const QuadList& quad_list) {
3667 size_t num_gutter_quads = 0;
3668 for (size_t i = 0; i < quad_list.size(); ++i) {
3669 num_gutter_quads += (quad_list[i]->material ==
3670 gutter_quad_material_) ? 1 : 0;
3672 return num_gutter_quads;
3675 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
3676 LayerTestCommon::VerifyQuadsExactlyCoverRect(
3677 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
3680 // Make sure that the texture coordinates match their expectations.
3681 void ValidateTextureDrawQuads(const QuadList& quad_list) {
3682 for (size_t i = 0; i < quad_list.size(); ++i) {
3683 if (quad_list[i]->material != DrawQuad::TEXTURE_CONTENT)
3685 const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(quad_list[i]);
3686 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
3687 gutter_texture_size_, host_impl_->device_scale_factor());
3688 EXPECT_EQ(quad->uv_top_left.x(),
3689 quad->rect.x() / gutter_texture_size_pixels.width());
3690 EXPECT_EQ(quad->uv_top_left.y(),
3691 quad->rect.y() / gutter_texture_size_pixels.height());
3692 EXPECT_EQ(quad->uv_bottom_right.x(),
3693 quad->rect.right() / gutter_texture_size_pixels.width());
3694 EXPECT_EQ(quad->uv_bottom_right.y(),
3695 quad->rect.bottom() / gutter_texture_size_pixels.height());
3699 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
3700 return gfx::ToRoundedSize(
3701 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
3704 DrawQuad::Material gutter_quad_material_;
3705 gfx::Size gutter_texture_size_;
3706 gfx::Size viewport_size_;
3707 BlendStateCheckLayer* child_;
3708 bool did_activate_pending_tree_;
3711 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
3712 viewport_size_ = gfx::Size(1000, 1000);
3714 bool always_draw = false;
3715 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3717 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3718 SetupActiveTreeLayers();
3719 TestLayerCoversFullViewport();
3721 TestLayerInMiddleOfViewport();
3722 TestLayerIsLargerThanViewport();
3725 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
3726 viewport_size_ = gfx::Size(1000, 1000);
3728 bool always_draw = false;
3729 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3731 host_impl_->SetDeviceScaleFactor(2.f);
3732 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3733 SetupActiveTreeLayers();
3734 TestLayerCoversFullViewport();
3736 TestLayerInMiddleOfViewport();
3737 TestLayerIsLargerThanViewport();
3740 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
3741 viewport_size_ = gfx::Size(1000, 1000);
3743 bool always_draw = false;
3744 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3746 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3747 SetupActiveTreeLayers();
3749 // Specify an overhang bitmap to use.
3750 bool is_opaque = false;
3751 UIResourceBitmap ui_resource_bitmap(gfx::Size(2, 2), is_opaque);
3752 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
3753 UIResourceId ui_resource_id = 12345;
3754 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
3755 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
3756 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
3757 set_gutter_texture_size(gfx::Size(32, 32));
3759 TestLayerCoversFullViewport();
3761 TestLayerInMiddleOfViewport();
3762 TestLayerIsLargerThanViewport();
3764 // Change the resource size.
3765 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
3766 set_gutter_texture_size(gfx::Size(128, 16));
3768 TestLayerCoversFullViewport();
3770 TestLayerInMiddleOfViewport();
3771 TestLayerIsLargerThanViewport();
3773 // Change the device scale factor
3774 host_impl_->SetDeviceScaleFactor(2.f);
3775 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3777 TestLayerCoversFullViewport();
3779 TestLayerInMiddleOfViewport();
3780 TestLayerIsLargerThanViewport();
3783 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
3784 viewport_size_ = gfx::Size(1000, 1000);
3786 bool always_draw = true;
3787 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3789 // Pending tree to force active_tree size invalid. Not used otherwise.
3790 host_impl_->CreatePendingTree();
3791 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3792 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3794 SetupActiveTreeLayers();
3796 TestLayerInMiddleOfViewport();
3797 TestLayerIsLargerThanViewport();
3800 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
3801 viewport_size_ = gfx::Size(1000, 1000);
3803 bool always_draw = true;
3804 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3806 // Set larger viewport and activate it to active tree.
3807 host_impl_->CreatePendingTree();
3808 gfx::Size larger_viewport(viewport_size_.width() + 100,
3809 viewport_size_.height() + 100);
3810 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
3811 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3812 host_impl_->ActivatePendingTree();
3813 EXPECT_TRUE(did_activate_pending_tree_);
3814 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
3816 // Shrink pending tree viewport without activating.
3817 host_impl_->CreatePendingTree();
3818 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3819 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3821 SetupActiveTreeLayers();
3823 TestLayerInMiddleOfViewport();
3824 TestLayerIsLargerThanViewport();
3827 class FakeDrawableLayerImpl: public LayerImpl {
3829 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
3830 return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(tree_impl, id));
3833 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
3834 : LayerImpl(tree_impl, id) {}
3837 // Only reshape when we know we are going to draw. Otherwise, the reshape
3838 // can leave the window at the wrong size if we never draw and the proper
3839 // viewport size is never set.
3840 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
3841 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
3842 scoped_ptr<OutputSurface> output_surface(
3843 FakeOutputSurface::Create3d(provider));
3844 CreateHostImpl(DefaultSettings(), output_surface.Pass());
3846 scoped_ptr<LayerImpl> root =
3847 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
3848 root->SetAnchorPoint(gfx::PointF());
3849 root->SetBounds(gfx::Size(10, 10));
3850 root->SetContentBounds(gfx::Size(10, 10));
3851 root->SetDrawsContent(true);
3852 host_impl_->active_tree()->SetRootLayer(root.Pass());
3853 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
3854 provider->TestContext3d()->clear_reshape_called();
3856 LayerTreeHostImpl::FrameData frame;
3857 host_impl_->SetViewportSize(gfx::Size(10, 10));
3858 host_impl_->SetDeviceScaleFactor(1.f);
3859 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3860 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3861 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3862 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
3863 EXPECT_EQ(provider->TestContext3d()->width(), 10);
3864 EXPECT_EQ(provider->TestContext3d()->height(), 10);
3865 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
3866 host_impl_->DidDrawAllLayers(frame);
3867 provider->TestContext3d()->clear_reshape_called();
3869 host_impl_->SetViewportSize(gfx::Size(20, 30));
3870 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3871 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3872 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3873 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
3874 EXPECT_EQ(provider->TestContext3d()->width(), 20);
3875 EXPECT_EQ(provider->TestContext3d()->height(), 30);
3876 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
3877 host_impl_->DidDrawAllLayers(frame);
3878 provider->TestContext3d()->clear_reshape_called();
3880 host_impl_->SetDeviceScaleFactor(2.f);
3881 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3882 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3883 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3884 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
3885 EXPECT_EQ(provider->TestContext3d()->width(), 20);
3886 EXPECT_EQ(provider->TestContext3d()->height(), 30);
3887 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
3888 host_impl_->DidDrawAllLayers(frame);
3889 provider->TestContext3d()->clear_reshape_called();
3892 // Make sure damage tracking propagates all the way to the graphics context,
3893 // where it should request to swap only the sub-buffer that is damaged.
3894 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
3895 scoped_refptr<TestContextProvider> context_provider(
3896 TestContextProvider::Create());
3897 context_provider->BindToCurrentThread();
3898 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
3900 scoped_ptr<OutputSurface> output_surface(
3901 FakeOutputSurface::Create3d(context_provider));
3903 // This test creates its own LayerTreeHostImpl, so
3904 // that we can force partial swap enabled.
3905 LayerTreeSettings settings;
3906 settings.partial_swap_enabled = true;
3907 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3908 new TestSharedBitmapManager());
3909 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
3910 LayerTreeHostImpl::Create(settings,
3913 &stats_instrumentation_,
3914 shared_bitmap_manager.get(),
3916 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
3917 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
3919 scoped_ptr<LayerImpl> root =
3920 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
3921 scoped_ptr<LayerImpl> child =
3922 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
3923 child->SetPosition(gfx::PointF(12.f, 13.f));
3924 child->SetAnchorPoint(gfx::PointF());
3925 child->SetBounds(gfx::Size(14, 15));
3926 child->SetContentBounds(gfx::Size(14, 15));
3927 child->SetDrawsContent(true);
3928 root->SetAnchorPoint(gfx::PointF());
3929 root->SetBounds(gfx::Size(500, 500));
3930 root->SetContentBounds(gfx::Size(500, 500));
3931 root->SetDrawsContent(true);
3932 root->AddChild(child.Pass());
3933 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
3935 LayerTreeHostImpl::FrameData frame;
3937 // First frame, the entire screen should get swapped.
3938 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3939 layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3940 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3941 layer_tree_host_impl->DidDrawAllLayers(frame);
3942 layer_tree_host_impl->SwapBuffers(frame);
3943 EXPECT_EQ(TestContextSupport::SWAP,
3944 context_provider->support()->last_swap_type());
3946 // Second frame, only the damaged area should get swapped. Damage should be
3947 // the union of old and new child rects.
3948 // expected damage rect: gfx::Rect(26, 28);
3949 // expected swap rect: vertically flipped, with origin at bottom left corner.
3950 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
3952 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3953 layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3954 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3955 host_impl_->DidDrawAllLayers(frame);
3956 layer_tree_host_impl->SwapBuffers(frame);
3958 // Make sure that partial swap is constrained to the viewport dimensions
3959 // expected damage rect: gfx::Rect(500, 500);
3960 // expected swap rect: flipped damage rect, but also clamped to viewport
3961 EXPECT_EQ(TestContextSupport::PARTIAL_SWAP,
3962 context_provider->support()->last_swap_type());
3963 gfx::Rect expected_swap_rect(0, 500-28, 26, 28);
3964 EXPECT_EQ(expected_swap_rect.ToString(),
3965 context_provider->support()->
3966 last_partial_swap_rect().ToString());
3968 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
3969 // This will damage everything.
3970 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
3972 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3973 layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3974 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3975 host_impl_->DidDrawAllLayers(frame);
3976 layer_tree_host_impl->SwapBuffers(frame);
3978 EXPECT_EQ(TestContextSupport::SWAP,
3979 context_provider->support()->last_swap_type());
3982 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
3983 scoped_ptr<LayerImpl> root =
3984 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
3985 scoped_ptr<LayerImpl> child =
3986 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
3987 child->SetAnchorPoint(gfx::PointF());
3988 child->SetBounds(gfx::Size(10, 10));
3989 child->SetContentBounds(gfx::Size(10, 10));
3990 child->SetDrawsContent(true);
3991 root->SetAnchorPoint(gfx::PointF());
3992 root->SetBounds(gfx::Size(10, 10));
3993 root->SetContentBounds(gfx::Size(10, 10));
3994 root->SetDrawsContent(true);
3995 root->SetForceRenderSurface(true);
3996 root->AddChild(child.Pass());
3998 host_impl_->active_tree()->SetRootLayer(root.Pass());
4000 LayerTreeHostImpl::FrameData frame;
4002 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4003 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4004 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
4005 EXPECT_EQ(1u, frame.render_passes.size());
4006 host_impl_->DidDrawAllLayers(frame);
4009 class FakeLayerWithQuads : public LayerImpl {
4011 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4012 return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(tree_impl, id));
4015 virtual void AppendQuads(QuadSink* quad_sink,
4016 AppendQuadsData* append_quads_data) OVERRIDE {
4017 SharedQuadState* shared_quad_state =
4018 quad_sink->UseSharedQuadState(CreateSharedQuadState());
4020 SkColor gray = SkColorSetRGB(100, 100, 100);
4021 gfx::Rect quad_rect(content_bounds());
4022 gfx::Rect visible_quad_rect(quad_rect);
4023 scoped_ptr<SolidColorDrawQuad> my_quad = SolidColorDrawQuad::Create();
4025 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
4026 quad_sink->MaybeAppend(my_quad.PassAs<DrawQuad>());
4030 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
4031 : LayerImpl(tree_impl, id) {}
4034 class MockContext : public TestWebGraphicsContext3D {
4036 MOCK_METHOD1(useProgram, void(GLuint program));
4037 MOCK_METHOD5(uniform4f, void(GLint location,
4042 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
4044 GLboolean transpose,
4045 const GLfloat* value));
4046 MOCK_METHOD4(drawElements, void(GLenum mode,
4050 MOCK_METHOD1(enable, void(GLenum cap));
4051 MOCK_METHOD1(disable, void(GLenum cap));
4052 MOCK_METHOD4(scissor, void(GLint x,
4058 class MockContextHarness {
4060 MockContext* context_;
4063 explicit MockContextHarness(MockContext* context)
4064 : context_(context) {
4065 context_->set_have_post_sub_buffer(true);
4067 // Catch "uninteresting" calls
4068 EXPECT_CALL(*context_, useProgram(_))
4071 EXPECT_CALL(*context_, drawElements(_, _, _, _))
4074 // These are not asserted
4075 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
4076 .WillRepeatedly(Return());
4078 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
4079 .WillRepeatedly(Return());
4081 // Any un-sanctioned calls to enable() are OK
4082 EXPECT_CALL(*context_, enable(_))
4083 .WillRepeatedly(Return());
4085 // Any un-sanctioned calls to disable() are OK
4086 EXPECT_CALL(*context_, disable(_))
4087 .WillRepeatedly(Return());
4090 void MustDrawSolidQuad() {
4091 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
4093 .RetiresOnSaturation();
4095 EXPECT_CALL(*context_, useProgram(_))
4097 .RetiresOnSaturation();
4100 void MustSetScissor(int x, int y, int width, int height) {
4101 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4102 .WillRepeatedly(Return());
4104 EXPECT_CALL(*context_, scissor(x, y, width, height))
4106 .WillRepeatedly(Return());
4109 void MustSetNoScissor() {
4110 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
4111 .WillRepeatedly(Return());
4113 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4116 EXPECT_CALL(*context_, scissor(_, _, _, _))
4121 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
4122 scoped_ptr<MockContext> mock_context_owned(new MockContext);
4123 MockContext* mock_context = mock_context_owned.get();
4125 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4126 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4127 MockContextHarness harness(mock_context);
4130 LayerTreeSettings settings = DefaultSettings();
4131 settings.partial_swap_enabled = false;
4132 CreateHostImpl(settings, output_surface.Pass());
4133 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4135 // Without partial swap, and no clipping, no scissor is set.
4136 harness.MustDrawSolidQuad();
4137 harness.MustSetNoScissor();
4139 LayerTreeHostImpl::FrameData frame;
4140 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4141 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4142 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4143 host_impl_->DidDrawAllLayers(frame);
4145 Mock::VerifyAndClearExpectations(&mock_context);
4147 // Without partial swap, but a layer does clip its subtree, one scissor is
4149 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
4150 harness.MustDrawSolidQuad();
4151 harness.MustSetScissor(0, 0, 10, 10);
4153 LayerTreeHostImpl::FrameData frame;
4154 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4155 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4156 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4157 host_impl_->DidDrawAllLayers(frame);
4159 Mock::VerifyAndClearExpectations(&mock_context);
4162 TEST_F(LayerTreeHostImplTest, PartialSwap) {
4163 scoped_ptr<MockContext> context_owned(new MockContext);
4164 MockContext* mock_context = context_owned.get();
4165 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4166 context_owned.PassAs<TestWebGraphicsContext3D>()));
4167 MockContextHarness harness(mock_context);
4169 LayerTreeSettings settings = DefaultSettings();
4170 settings.partial_swap_enabled = true;
4171 CreateHostImpl(settings, output_surface.Pass());
4172 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4174 // The first frame is not a partially-swapped one.
4175 harness.MustSetScissor(0, 0, 10, 10);
4176 harness.MustDrawSolidQuad();
4178 LayerTreeHostImpl::FrameData frame;
4179 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4180 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4181 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4182 host_impl_->DidDrawAllLayers(frame);
4184 Mock::VerifyAndClearExpectations(&mock_context);
4186 // Damage a portion of the frame.
4187 host_impl_->active_tree()->root_layer()->SetUpdateRect(
4188 gfx::Rect(0, 0, 2, 3));
4190 // The second frame will be partially-swapped (the y coordinates are flipped).
4191 harness.MustSetScissor(0, 7, 2, 3);
4192 harness.MustDrawSolidQuad();
4194 LayerTreeHostImpl::FrameData frame;
4195 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4196 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4197 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4198 host_impl_->DidDrawAllLayers(frame);
4200 Mock::VerifyAndClearExpectations(&mock_context);
4203 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
4205 LayerTreeHostImplClient* client,
4207 SharedBitmapManager* manager,
4208 RenderingStatsInstrumentation* stats_instrumentation) {
4209 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4210 scoped_ptr<OutputSurface> output_surface(
4211 FakeOutputSurface::Create3d(provider));
4212 provider->BindToCurrentThread();
4213 provider->TestContext3d()->set_have_post_sub_buffer(true);
4215 LayerTreeSettings settings;
4216 settings.partial_swap_enabled = partial_swap;
4217 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
4218 settings, client, proxy, stats_instrumentation, manager, 0);
4219 my_host_impl->InitializeRenderer(output_surface.Pass());
4220 my_host_impl->SetViewportSize(gfx::Size(100, 100));
4223 Layers are created as follows:
4225 +--------------------+
4229 | | +-------------------+
4231 | | +-------------------+
4236 +--------------------+
4238 Layers 1, 2 have render surfaces
4240 scoped_ptr<LayerImpl> root =
4241 LayerImpl::Create(my_host_impl->active_tree(), 1);
4242 scoped_ptr<LayerImpl> child =
4243 LayerImpl::Create(my_host_impl->active_tree(), 2);
4244 scoped_ptr<LayerImpl> grand_child =
4245 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
4247 gfx::Rect root_rect(0, 0, 100, 100);
4248 gfx::Rect child_rect(10, 10, 50, 50);
4249 gfx::Rect grand_child_rect(5, 5, 150, 150);
4251 root->CreateRenderSurface();
4252 root->SetAnchorPoint(gfx::PointF());
4253 root->SetPosition(root_rect.origin());
4254 root->SetBounds(root_rect.size());
4255 root->SetContentBounds(root->bounds());
4256 root->draw_properties().visible_content_rect = root_rect;
4257 root->SetDrawsContent(false);
4258 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
4260 child->SetAnchorPoint(gfx::PointF());
4261 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
4262 child->SetOpacity(0.5f);
4263 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
4264 child->SetContentBounds(child->bounds());
4265 child->draw_properties().visible_content_rect = child_rect;
4266 child->SetDrawsContent(false);
4267 child->SetForceRenderSurface(true);
4269 grand_child->SetAnchorPoint(gfx::PointF());
4270 grand_child->SetPosition(grand_child_rect.origin());
4271 grand_child->SetBounds(grand_child_rect.size());
4272 grand_child->SetContentBounds(grand_child->bounds());
4273 grand_child->draw_properties().visible_content_rect = grand_child_rect;
4274 grand_child->SetDrawsContent(true);
4276 child->AddChild(grand_child.Pass());
4277 root->AddChild(child.Pass());
4279 my_host_impl->active_tree()->SetRootLayer(root.Pass());
4280 return my_host_impl.Pass();
4283 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
4284 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4285 new TestSharedBitmapManager());
4286 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4287 SetupLayersForOpacity(true,
4290 shared_bitmap_manager.get(),
4291 &stats_instrumentation_);
4293 LayerTreeHostImpl::FrameData frame;
4294 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4295 my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
4297 // Verify all quads have been computed
4298 ASSERT_EQ(2U, frame.render_passes.size());
4299 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4300 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4301 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4302 frame.render_passes[0]->quad_list[0]->material);
4303 EXPECT_EQ(DrawQuad::RENDER_PASS,
4304 frame.render_passes[1]->quad_list[0]->material);
4306 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4307 my_host_impl->DidDrawAllLayers(frame);
4311 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
4312 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4313 new TestSharedBitmapManager());
4314 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4315 SetupLayersForOpacity(false,
4318 shared_bitmap_manager.get(),
4319 &stats_instrumentation_);
4321 LayerTreeHostImpl::FrameData frame;
4322 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4323 my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
4325 // Verify all quads have been computed
4326 ASSERT_EQ(2U, frame.render_passes.size());
4327 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4328 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4329 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4330 frame.render_passes[0]->quad_list[0]->material);
4331 EXPECT_EQ(DrawQuad::RENDER_PASS,
4332 frame.render_passes[1]->quad_list[0]->material);
4334 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4335 my_host_impl->DidDrawAllLayers(frame);
4339 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
4340 scoped_ptr<TestWebGraphicsContext3D> context =
4341 TestWebGraphicsContext3D::Create();
4342 TestWebGraphicsContext3D* context3d = context.get();
4343 scoped_ptr<OutputSurface> output_surface(
4344 FakeOutputSurface::Create3d(context.Pass()));
4345 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4347 scoped_ptr<LayerImpl> root_layer =
4348 LayerImpl::Create(host_impl_->active_tree(), 1);
4349 root_layer->SetBounds(gfx::Size(10, 10));
4350 root_layer->SetAnchorPoint(gfx::PointF());
4352 scoped_refptr<VideoFrame> softwareFrame =
4353 media::VideoFrame::CreateColorFrame(
4354 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
4355 FakeVideoFrameProvider provider;
4356 provider.set_frame(softwareFrame);
4357 scoped_ptr<VideoLayerImpl> video_layer =
4358 VideoLayerImpl::Create(host_impl_->active_tree(), 4, &provider);
4359 video_layer->SetBounds(gfx::Size(10, 10));
4360 video_layer->SetAnchorPoint(gfx::PointF());
4361 video_layer->SetContentBounds(gfx::Size(10, 10));
4362 video_layer->SetDrawsContent(true);
4363 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
4365 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
4366 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
4367 io_surface_layer->SetBounds(gfx::Size(10, 10));
4368 io_surface_layer->SetAnchorPoint(gfx::PointF());
4369 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
4370 io_surface_layer->SetDrawsContent(true);
4371 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
4372 root_layer->AddChild(io_surface_layer.PassAs<LayerImpl>());
4374 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
4376 EXPECT_EQ(0u, context3d->NumTextures());
4378 LayerTreeHostImpl::FrameData frame;
4379 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4380 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4381 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4382 host_impl_->DidDrawAllLayers(frame);
4383 host_impl_->SwapBuffers(frame);
4385 EXPECT_GT(context3d->NumTextures(), 0u);
4387 // Kill the layer tree.
4388 host_impl_->active_tree()->SetRootLayer(
4389 LayerImpl::Create(host_impl_->active_tree(), 100));
4390 // There should be no textures left in use after.
4391 EXPECT_EQ(0u, context3d->NumTextures());
4394 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
4396 MOCK_METHOD1(useProgram, void(GLuint program));
4397 MOCK_METHOD4(drawElements, void(GLenum mode,
4403 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
4404 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
4405 new MockDrawQuadsToFillScreenContext);
4406 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
4408 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4409 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4412 LayerTreeSettings settings = DefaultSettings();
4413 settings.partial_swap_enabled = false;
4414 CreateHostImpl(settings, output_surface.Pass());
4415 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
4416 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
4418 // Verify one quad is drawn when transparent background set is not set.
4419 host_impl_->active_tree()->set_has_transparent_background(false);
4420 EXPECT_CALL(*mock_context, useProgram(_))
4422 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
4424 LayerTreeHostImpl::FrameData frame;
4425 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4426 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4427 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4428 host_impl_->DidDrawAllLayers(frame);
4429 Mock::VerifyAndClearExpectations(&mock_context);
4431 // Verify no quads are drawn when transparent background is set.
4432 host_impl_->active_tree()->set_has_transparent_background(true);
4433 host_impl_->SetFullRootLayerDamage();
4434 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4435 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4436 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4437 host_impl_->DidDrawAllLayers(frame);
4438 Mock::VerifyAndClearExpectations(&mock_context);
4441 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
4442 set_reduce_memory_result(false);
4444 // If changing the memory limit wouldn't result in changing what was
4445 // committed, then no commit should be requested.
4446 set_reduce_memory_result(false);
4447 host_impl_->set_max_memory_needed_bytes(
4448 host_impl_->memory_allocation_limit_bytes() - 1);
4449 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4450 host_impl_->memory_allocation_limit_bytes() - 1));
4451 EXPECT_FALSE(did_request_commit_);
4452 did_request_commit_ = false;
4454 // If changing the memory limit would result in changing what was
4455 // committed, then a commit should be requested, even though nothing was
4457 set_reduce_memory_result(false);
4458 host_impl_->set_max_memory_needed_bytes(
4459 host_impl_->memory_allocation_limit_bytes());
4460 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4461 host_impl_->memory_allocation_limit_bytes() - 1));
4462 EXPECT_TRUE(did_request_commit_);
4463 did_request_commit_ = false;
4465 // Especially if changing the memory limit caused evictions, we need
4467 set_reduce_memory_result(true);
4468 host_impl_->set_max_memory_needed_bytes(1);
4469 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4470 host_impl_->memory_allocation_limit_bytes() - 1));
4471 EXPECT_TRUE(did_request_commit_);
4472 did_request_commit_ = false;
4474 // But if we set it to the same value that it was before, we shouldn't
4476 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4477 host_impl_->memory_allocation_limit_bytes()));
4478 EXPECT_FALSE(did_request_commit_);
4481 class LayerTreeHostImplTestWithDelegatingRenderer
4482 : public LayerTreeHostImplTest {
4484 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
4485 return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
4488 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
4489 bool expect_to_draw = !expected_damage.IsEmpty();
4491 LayerTreeHostImpl::FrameData frame;
4492 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4493 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4495 if (!expect_to_draw) {
4496 // With no damage, we don't draw, and no quads are created.
4497 ASSERT_EQ(0u, frame.render_passes.size());
4499 ASSERT_EQ(1u, frame.render_passes.size());
4501 // Verify the damage rect for the root render pass.
4502 const RenderPass* root_render_pass = frame.render_passes.back();
4503 EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
4505 // Verify the root and child layers' quads are generated and not being
4507 ASSERT_EQ(2u, root_render_pass->quad_list.size());
4509 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
4510 gfx::RectF expected_child_visible_rect(child->content_bounds());
4511 EXPECT_RECT_EQ(expected_child_visible_rect,
4512 root_render_pass->quad_list[0]->visible_rect);
4514 LayerImpl* root = host_impl_->active_tree()->root_layer();
4515 gfx::RectF expected_root_visible_rect(root->content_bounds());
4516 EXPECT_RECT_EQ(expected_root_visible_rect,
4517 root_render_pass->quad_list[1]->visible_rect);
4520 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4521 host_impl_->DidDrawAllLayers(frame);
4522 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
4526 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
4527 scoped_ptr<SolidColorLayerImpl> root =
4528 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4529 root->SetAnchorPoint(gfx::PointF());
4530 root->SetPosition(gfx::PointF());
4531 root->SetBounds(gfx::Size(10, 10));
4532 root->SetContentBounds(gfx::Size(10, 10));
4533 root->SetDrawsContent(true);
4535 // Child layer is in the bottom right corner.
4536 scoped_ptr<SolidColorLayerImpl> child =
4537 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
4538 child->SetAnchorPoint(gfx::PointF(0.f, 0.f));
4539 child->SetPosition(gfx::PointF(9.f, 9.f));
4540 child->SetBounds(gfx::Size(1, 1));
4541 child->SetContentBounds(gfx::Size(1, 1));
4542 child->SetDrawsContent(true);
4543 root->AddChild(child.PassAs<LayerImpl>());
4545 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
4547 // Draw a frame. In the first frame, the entire viewport should be damaged.
4548 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
4549 DrawFrameAndTestDamage(full_frame_damage);
4551 // The second frame has damage that doesn't touch the child layer. Its quads
4552 // should still be generated.
4553 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
4554 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
4555 DrawFrameAndTestDamage(small_damage);
4557 // The third frame should have no damage, so no quads should be generated.
4558 gfx::Rect no_damage;
4559 DrawFrameAndTestDamage(no_damage);
4562 // TODO(reveman): Remove this test and the ability to prevent on demand raster
4563 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
4564 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
4565 LayerTreeSettings settings;
4566 CreateHostImpl(settings, CreateOutputSurface());
4567 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
4570 class FakeMaskLayerImpl : public LayerImpl {
4572 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
4574 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
4577 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
4582 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
4583 : LayerImpl(tree_impl, id) {}
4586 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
4587 LayerTreeSettings settings;
4588 settings.layer_transforms_should_scale_layer_contents = true;
4589 CreateHostImpl(settings, CreateOutputSurface());
4593 // +-- Scaling Layer (adds a 2x scale)
4595 // +-- Content Layer
4597 scoped_ptr<LayerImpl> scoped_root =
4598 LayerImpl::Create(host_impl_->active_tree(), 1);
4599 LayerImpl* root = scoped_root.get();
4600 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4602 scoped_ptr<LayerImpl> scoped_scaling_layer =
4603 LayerImpl::Create(host_impl_->active_tree(), 2);
4604 LayerImpl* scaling_layer = scoped_scaling_layer.get();
4605 root->AddChild(scoped_scaling_layer.Pass());
4607 scoped_ptr<LayerImpl> scoped_content_layer =
4608 LayerImpl::Create(host_impl_->active_tree(), 3);
4609 LayerImpl* content_layer = scoped_content_layer.get();
4610 scaling_layer->AddChild(scoped_content_layer.Pass());
4612 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4613 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4614 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4615 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4617 gfx::Size root_size(100, 100);
4618 root->SetBounds(root_size);
4619 root->SetContentBounds(root_size);
4620 root->SetPosition(gfx::PointF());
4621 root->SetAnchorPoint(gfx::PointF());
4623 gfx::Size scaling_layer_size(50, 50);
4624 scaling_layer->SetBounds(scaling_layer_size);
4625 scaling_layer->SetContentBounds(scaling_layer_size);
4626 scaling_layer->SetPosition(gfx::PointF());
4627 scaling_layer->SetAnchorPoint(gfx::PointF());
4628 gfx::Transform scale;
4629 scale.Scale(2.f, 2.f);
4630 scaling_layer->SetTransform(scale);
4632 content_layer->SetBounds(scaling_layer_size);
4633 content_layer->SetContentBounds(scaling_layer_size);
4634 content_layer->SetPosition(gfx::PointF());
4635 content_layer->SetAnchorPoint(gfx::PointF());
4636 content_layer->SetDrawsContent(true);
4638 mask_layer->SetBounds(scaling_layer_size);
4639 mask_layer->SetContentBounds(scaling_layer_size);
4640 mask_layer->SetPosition(gfx::PointF());
4641 mask_layer->SetAnchorPoint(gfx::PointF());
4642 mask_layer->SetDrawsContent(true);
4645 // Check that the tree scaling is correctly taken into account for the mask,
4646 // that should fully map onto the quad.
4647 float device_scale_factor = 1.f;
4648 host_impl_->SetViewportSize(root_size);
4649 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4651 LayerTreeHostImpl::FrameData frame;
4652 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4653 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4655 ASSERT_EQ(1u, frame.render_passes.size());
4656 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4657 ASSERT_EQ(DrawQuad::RENDER_PASS,
4658 frame.render_passes[0]->quad_list[0]->material);
4659 const RenderPassDrawQuad* render_pass_quad =
4660 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4661 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4662 render_pass_quad->rect.ToString());
4663 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4664 render_pass_quad->mask_uv_rect.ToString());
4666 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4667 host_impl_->DidDrawAllLayers(frame);
4671 // Applying a DSF should change the render surface size, but won't affect
4672 // which part of the mask is used.
4673 device_scale_factor = 2.f;
4674 gfx::Size device_viewport =
4675 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4676 host_impl_->SetViewportSize(device_viewport);
4677 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4678 host_impl_->active_tree()->set_needs_update_draw_properties();
4680 LayerTreeHostImpl::FrameData frame;
4681 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4682 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4684 ASSERT_EQ(1u, frame.render_passes.size());
4685 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4686 ASSERT_EQ(DrawQuad::RENDER_PASS,
4687 frame.render_passes[0]->quad_list[0]->material);
4688 const RenderPassDrawQuad* render_pass_quad =
4689 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4690 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4691 render_pass_quad->rect.ToString());
4692 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4693 render_pass_quad->mask_uv_rect.ToString());
4695 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4696 host_impl_->DidDrawAllLayers(frame);
4700 // Applying an equivalent content scale on the content layer and the mask
4701 // should still result in the same part of the mask being used.
4702 gfx::Size content_bounds =
4703 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
4704 device_scale_factor));
4705 content_layer->SetContentBounds(content_bounds);
4706 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4707 mask_layer->SetContentBounds(content_bounds);
4708 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4709 host_impl_->active_tree()->set_needs_update_draw_properties();
4711 LayerTreeHostImpl::FrameData frame;
4712 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4713 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4715 ASSERT_EQ(1u, frame.render_passes.size());
4716 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4717 ASSERT_EQ(DrawQuad::RENDER_PASS,
4718 frame.render_passes[0]->quad_list[0]->material);
4719 const RenderPassDrawQuad* render_pass_quad =
4720 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4721 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4722 render_pass_quad->rect.ToString());
4723 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4724 render_pass_quad->mask_uv_rect.ToString());
4726 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4727 host_impl_->DidDrawAllLayers(frame);
4731 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
4732 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4735 scoped_ptr<LayerImpl> scoped_root =
4736 LayerImpl::Create(host_impl_->active_tree(), 1);
4737 LayerImpl* root = scoped_root.get();
4738 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4740 scoped_ptr<LayerImpl> scoped_content_layer =
4741 LayerImpl::Create(host_impl_->active_tree(), 3);
4742 LayerImpl* content_layer = scoped_content_layer.get();
4743 root->AddChild(scoped_content_layer.Pass());
4745 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4746 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4747 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4748 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4750 gfx::Size root_size(100, 100);
4751 root->SetBounds(root_size);
4752 root->SetContentBounds(root_size);
4753 root->SetPosition(gfx::PointF());
4754 root->SetAnchorPoint(gfx::PointF());
4756 gfx::Size layer_size(50, 50);
4757 content_layer->SetBounds(layer_size);
4758 content_layer->SetContentBounds(layer_size);
4759 content_layer->SetPosition(gfx::PointF());
4760 content_layer->SetAnchorPoint(gfx::PointF());
4761 content_layer->SetDrawsContent(true);
4763 gfx::Size mask_size(100, 100);
4764 mask_layer->SetBounds(mask_size);
4765 mask_layer->SetContentBounds(mask_size);
4766 mask_layer->SetPosition(gfx::PointF());
4767 mask_layer->SetAnchorPoint(gfx::PointF());
4768 mask_layer->SetDrawsContent(true);
4770 // Check that the mask fills the surface.
4771 float device_scale_factor = 1.f;
4772 host_impl_->SetViewportSize(root_size);
4773 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4775 LayerTreeHostImpl::FrameData frame;
4776 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4777 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4779 ASSERT_EQ(1u, frame.render_passes.size());
4780 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4781 ASSERT_EQ(DrawQuad::RENDER_PASS,
4782 frame.render_passes[0]->quad_list[0]->material);
4783 const RenderPassDrawQuad* render_pass_quad =
4784 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4785 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4786 render_pass_quad->rect.ToString());
4787 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4788 render_pass_quad->mask_uv_rect.ToString());
4790 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4791 host_impl_->DidDrawAllLayers(frame);
4794 // Applying a DSF should change the render surface size, but won't affect
4795 // which part of the mask is used.
4796 device_scale_factor = 2.f;
4797 gfx::Size device_viewport =
4798 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4799 host_impl_->SetViewportSize(device_viewport);
4800 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4801 host_impl_->active_tree()->set_needs_update_draw_properties();
4803 LayerTreeHostImpl::FrameData frame;
4804 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4805 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4807 ASSERT_EQ(1u, frame.render_passes.size());
4808 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4809 ASSERT_EQ(DrawQuad::RENDER_PASS,
4810 frame.render_passes[0]->quad_list[0]->material);
4811 const RenderPassDrawQuad* render_pass_quad =
4812 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4813 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4814 render_pass_quad->rect.ToString());
4815 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4816 render_pass_quad->mask_uv_rect.ToString());
4818 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4819 host_impl_->DidDrawAllLayers(frame);
4822 // Applying an equivalent content scale on the content layer and the mask
4823 // should still result in the same part of the mask being used.
4824 gfx::Size layer_size_large =
4825 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
4826 content_layer->SetContentBounds(layer_size_large);
4827 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4828 gfx::Size mask_size_large =
4829 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
4830 mask_layer->SetContentBounds(mask_size_large);
4831 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4832 host_impl_->active_tree()->set_needs_update_draw_properties();
4834 LayerTreeHostImpl::FrameData frame;
4835 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4836 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4838 ASSERT_EQ(1u, frame.render_passes.size());
4839 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4840 ASSERT_EQ(DrawQuad::RENDER_PASS,
4841 frame.render_passes[0]->quad_list[0]->material);
4842 const RenderPassDrawQuad* render_pass_quad =
4843 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4844 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4845 render_pass_quad->rect.ToString());
4846 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4847 render_pass_quad->mask_uv_rect.ToString());
4849 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4850 host_impl_->DidDrawAllLayers(frame);
4853 // Applying a different contents scale to the mask layer means it will have
4854 // a larger texture, but it should use the same tex coords to cover the
4856 mask_layer->SetContentBounds(mask_size);
4857 mask_layer->SetContentsScale(1.f, 1.f);
4858 host_impl_->active_tree()->set_needs_update_draw_properties();
4860 LayerTreeHostImpl::FrameData frame;
4861 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4862 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4864 ASSERT_EQ(1u, frame.render_passes.size());
4865 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4866 ASSERT_EQ(DrawQuad::RENDER_PASS,
4867 frame.render_passes[0]->quad_list[0]->material);
4868 const RenderPassDrawQuad* render_pass_quad =
4869 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4870 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4871 render_pass_quad->rect.ToString());
4872 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4873 render_pass_quad->mask_uv_rect.ToString());
4875 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4876 host_impl_->DidDrawAllLayers(frame);
4880 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
4881 // The replica's mask layer has bounds 100x100 but the replica is of a
4882 // layer with bounds 50x50.
4884 scoped_ptr<LayerImpl> scoped_root =
4885 LayerImpl::Create(host_impl_->active_tree(), 1);
4886 LayerImpl* root = scoped_root.get();
4887 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4889 scoped_ptr<LayerImpl> scoped_content_layer =
4890 LayerImpl::Create(host_impl_->active_tree(), 3);
4891 LayerImpl* content_layer = scoped_content_layer.get();
4892 root->AddChild(scoped_content_layer.Pass());
4894 scoped_ptr<LayerImpl> scoped_replica_layer =
4895 LayerImpl::Create(host_impl_->active_tree(), 2);
4896 LayerImpl* replica_layer = scoped_replica_layer.get();
4897 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
4899 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4900 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4901 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4902 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4904 gfx::Size root_size(100, 100);
4905 root->SetBounds(root_size);
4906 root->SetContentBounds(root_size);
4907 root->SetPosition(gfx::PointF());
4908 root->SetAnchorPoint(gfx::PointF());
4910 gfx::Size layer_size(50, 50);
4911 content_layer->SetBounds(layer_size);
4912 content_layer->SetContentBounds(layer_size);
4913 content_layer->SetPosition(gfx::PointF());
4914 content_layer->SetAnchorPoint(gfx::PointF());
4915 content_layer->SetDrawsContent(true);
4917 gfx::Size mask_size(100, 100);
4918 mask_layer->SetBounds(mask_size);
4919 mask_layer->SetContentBounds(mask_size);
4920 mask_layer->SetPosition(gfx::PointF());
4921 mask_layer->SetAnchorPoint(gfx::PointF());
4922 mask_layer->SetDrawsContent(true);
4924 // Check that the mask fills the surface.
4925 float device_scale_factor = 1.f;
4926 host_impl_->SetViewportSize(root_size);
4927 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4929 LayerTreeHostImpl::FrameData frame;
4930 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4931 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4933 ASSERT_EQ(1u, frame.render_passes.size());
4934 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4935 ASSERT_EQ(DrawQuad::RENDER_PASS,
4936 frame.render_passes[0]->quad_list[1]->material);
4937 const RenderPassDrawQuad* replica_quad =
4938 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4939 EXPECT_TRUE(replica_quad->is_replica);
4940 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4941 replica_quad->rect.ToString());
4942 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4943 replica_quad->mask_uv_rect.ToString());
4945 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4946 host_impl_->DidDrawAllLayers(frame);
4949 // Applying a DSF should change the render surface size, but won't affect
4950 // which part of the mask is used.
4951 device_scale_factor = 2.f;
4952 gfx::Size device_viewport =
4953 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4954 host_impl_->SetViewportSize(device_viewport);
4955 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4956 host_impl_->active_tree()->set_needs_update_draw_properties();
4958 LayerTreeHostImpl::FrameData frame;
4959 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4960 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4962 ASSERT_EQ(1u, frame.render_passes.size());
4963 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4964 ASSERT_EQ(DrawQuad::RENDER_PASS,
4965 frame.render_passes[0]->quad_list[1]->material);
4966 const RenderPassDrawQuad* replica_quad =
4967 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4968 EXPECT_TRUE(replica_quad->is_replica);
4969 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4970 replica_quad->rect.ToString());
4971 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4972 replica_quad->mask_uv_rect.ToString());
4974 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4975 host_impl_->DidDrawAllLayers(frame);
4978 // Applying an equivalent content scale on the content layer and the mask
4979 // should still result in the same part of the mask being used.
4980 gfx::Size layer_size_large =
4981 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
4982 content_layer->SetContentBounds(layer_size_large);
4983 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4984 gfx::Size mask_size_large =
4985 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
4986 mask_layer->SetContentBounds(mask_size_large);
4987 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4988 host_impl_->active_tree()->set_needs_update_draw_properties();
4990 LayerTreeHostImpl::FrameData frame;
4991 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4992 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4994 ASSERT_EQ(1u, frame.render_passes.size());
4995 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4996 ASSERT_EQ(DrawQuad::RENDER_PASS,
4997 frame.render_passes[0]->quad_list[1]->material);
4998 const RenderPassDrawQuad* replica_quad =
4999 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5000 EXPECT_TRUE(replica_quad->is_replica);
5001 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5002 replica_quad->rect.ToString());
5003 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5004 replica_quad->mask_uv_rect.ToString());
5006 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5007 host_impl_->DidDrawAllLayers(frame);
5010 // Applying a different contents scale to the mask layer means it will have
5011 // a larger texture, but it should use the same tex coords to cover the
5013 mask_layer->SetContentBounds(mask_size);
5014 mask_layer->SetContentsScale(1.f, 1.f);
5015 host_impl_->active_tree()->set_needs_update_draw_properties();
5017 LayerTreeHostImpl::FrameData frame;
5018 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5019 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5021 ASSERT_EQ(1u, frame.render_passes.size());
5022 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5023 ASSERT_EQ(DrawQuad::RENDER_PASS,
5024 frame.render_passes[0]->quad_list[1]->material);
5025 const RenderPassDrawQuad* replica_quad =
5026 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5027 EXPECT_TRUE(replica_quad->is_replica);
5028 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5029 replica_quad->rect.ToString());
5030 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5031 replica_quad->mask_uv_rect.ToString());
5033 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5034 host_impl_->DidDrawAllLayers(frame);
5038 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
5039 // The replica is of a layer with bounds 50x50, but it has a child that causes
5040 // the surface bounds to be larger.
5042 scoped_ptr<LayerImpl> scoped_root =
5043 LayerImpl::Create(host_impl_->active_tree(), 1);
5044 LayerImpl* root = scoped_root.get();
5045 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5047 scoped_ptr<LayerImpl> scoped_content_layer =
5048 LayerImpl::Create(host_impl_->active_tree(), 2);
5049 LayerImpl* content_layer = scoped_content_layer.get();
5050 root->AddChild(scoped_content_layer.Pass());
5052 scoped_ptr<LayerImpl> scoped_content_child_layer =
5053 LayerImpl::Create(host_impl_->active_tree(), 3);
5054 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5055 content_layer->AddChild(scoped_content_child_layer.Pass());
5057 scoped_ptr<LayerImpl> scoped_replica_layer =
5058 LayerImpl::Create(host_impl_->active_tree(), 4);
5059 LayerImpl* replica_layer = scoped_replica_layer.get();
5060 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5062 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5063 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
5064 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5065 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5067 gfx::Size root_size(100, 100);
5068 root->SetBounds(root_size);
5069 root->SetContentBounds(root_size);
5070 root->SetPosition(gfx::PointF());
5071 root->SetAnchorPoint(gfx::PointF());
5073 gfx::Size layer_size(50, 50);
5074 content_layer->SetBounds(layer_size);
5075 content_layer->SetContentBounds(layer_size);
5076 content_layer->SetPosition(gfx::PointF());
5077 content_layer->SetAnchorPoint(gfx::PointF());
5078 content_layer->SetDrawsContent(true);
5080 gfx::Size child_size(50, 50);
5081 content_child_layer->SetBounds(child_size);
5082 content_child_layer->SetContentBounds(child_size);
5083 content_child_layer->SetPosition(gfx::Point(50, 0));
5084 content_child_layer->SetAnchorPoint(gfx::PointF());
5085 content_child_layer->SetDrawsContent(true);
5087 gfx::Size mask_size(50, 50);
5088 mask_layer->SetBounds(mask_size);
5089 mask_layer->SetContentBounds(mask_size);
5090 mask_layer->SetPosition(gfx::PointF());
5091 mask_layer->SetAnchorPoint(gfx::PointF());
5092 mask_layer->SetDrawsContent(true);
5094 float device_scale_factor = 1.f;
5095 host_impl_->SetViewportSize(root_size);
5096 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5098 LayerTreeHostImpl::FrameData frame;
5099 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5100 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5102 ASSERT_EQ(1u, frame.render_passes.size());
5103 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5105 // The surface is 100x50.
5106 ASSERT_EQ(DrawQuad::RENDER_PASS,
5107 frame.render_passes[0]->quad_list[0]->material);
5108 const RenderPassDrawQuad* render_pass_quad =
5109 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5110 EXPECT_FALSE(render_pass_quad->is_replica);
5111 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5112 render_pass_quad->rect.ToString());
5114 // The mask covers the owning layer only.
5115 ASSERT_EQ(DrawQuad::RENDER_PASS,
5116 frame.render_passes[0]->quad_list[1]->material);
5117 const RenderPassDrawQuad* replica_quad =
5118 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5119 EXPECT_TRUE(replica_quad->is_replica);
5120 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5121 replica_quad->rect.ToString());
5122 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
5123 replica_quad->mask_uv_rect.ToString());
5125 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5126 host_impl_->DidDrawAllLayers(frame);
5129 // Move the child to (-50, 0) instead. Now the mask should be moved to still
5130 // cover the layer being replicated.
5131 content_child_layer->SetPosition(gfx::Point(-50, 0));
5133 LayerTreeHostImpl::FrameData frame;
5134 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5135 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5137 ASSERT_EQ(1u, frame.render_passes.size());
5138 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5140 // The surface is 100x50 with its origin at (-50, 0).
5141 ASSERT_EQ(DrawQuad::RENDER_PASS,
5142 frame.render_passes[0]->quad_list[0]->material);
5143 const RenderPassDrawQuad* render_pass_quad =
5144 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5145 EXPECT_FALSE(render_pass_quad->is_replica);
5146 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5147 render_pass_quad->rect.ToString());
5149 // The mask covers the owning layer only.
5150 ASSERT_EQ(DrawQuad::RENDER_PASS,
5151 frame.render_passes[0]->quad_list[1]->material);
5152 const RenderPassDrawQuad* replica_quad =
5153 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5154 EXPECT_TRUE(replica_quad->is_replica);
5155 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5156 replica_quad->rect.ToString());
5157 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
5158 replica_quad->mask_uv_rect.ToString());
5160 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5161 host_impl_->DidDrawAllLayers(frame);
5165 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
5166 // The masked layer has bounds 50x50, but it has a child that causes
5167 // the surface bounds to be larger. It also has a parent that clips the
5168 // masked layer and its surface.
5170 scoped_ptr<LayerImpl> scoped_root =
5171 LayerImpl::Create(host_impl_->active_tree(), 1);
5172 LayerImpl* root = scoped_root.get();
5173 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5175 scoped_ptr<LayerImpl> scoped_clipping_layer =
5176 LayerImpl::Create(host_impl_->active_tree(), 2);
5177 LayerImpl* clipping_layer = scoped_clipping_layer.get();
5178 root->AddChild(scoped_clipping_layer.Pass());
5180 scoped_ptr<LayerImpl> scoped_content_layer =
5181 LayerImpl::Create(host_impl_->active_tree(), 3);
5182 LayerImpl* content_layer = scoped_content_layer.get();
5183 clipping_layer->AddChild(scoped_content_layer.Pass());
5185 scoped_ptr<LayerImpl> scoped_content_child_layer =
5186 LayerImpl::Create(host_impl_->active_tree(), 4);
5187 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5188 content_layer->AddChild(scoped_content_child_layer.Pass());
5190 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5191 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
5192 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5193 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5195 gfx::Size root_size(100, 100);
5196 root->SetBounds(root_size);
5197 root->SetContentBounds(root_size);
5198 root->SetPosition(gfx::PointF());
5199 root->SetAnchorPoint(gfx::PointF());
5201 gfx::Rect clipping_rect(20, 10, 10, 20);
5202 clipping_layer->SetBounds(clipping_rect.size());
5203 clipping_layer->SetContentBounds(clipping_rect.size());
5204 clipping_layer->SetPosition(clipping_rect.origin());
5205 clipping_layer->SetAnchorPoint(gfx::PointF());
5206 clipping_layer->SetMasksToBounds(true);
5208 gfx::Size layer_size(50, 50);
5209 content_layer->SetBounds(layer_size);
5210 content_layer->SetContentBounds(layer_size);
5211 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
5212 content_layer->SetAnchorPoint(gfx::PointF());
5213 content_layer->SetDrawsContent(true);
5215 gfx::Size child_size(50, 50);
5216 content_child_layer->SetBounds(child_size);
5217 content_child_layer->SetContentBounds(child_size);
5218 content_child_layer->SetPosition(gfx::Point(50, 0));
5219 content_child_layer->SetAnchorPoint(gfx::PointF());
5220 content_child_layer->SetDrawsContent(true);
5222 gfx::Size mask_size(100, 100);
5223 mask_layer->SetBounds(mask_size);
5224 mask_layer->SetContentBounds(mask_size);
5225 mask_layer->SetPosition(gfx::PointF());
5226 mask_layer->SetAnchorPoint(gfx::PointF());
5227 mask_layer->SetDrawsContent(true);
5229 float device_scale_factor = 1.f;
5230 host_impl_->SetViewportSize(root_size);
5231 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5233 LayerTreeHostImpl::FrameData frame;
5234 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5235 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5237 ASSERT_EQ(1u, frame.render_passes.size());
5238 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5240 // The surface is clipped to 10x20.
5241 ASSERT_EQ(DrawQuad::RENDER_PASS,
5242 frame.render_passes[0]->quad_list[0]->material);
5243 const RenderPassDrawQuad* render_pass_quad =
5244 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5245 EXPECT_FALSE(render_pass_quad->is_replica);
5246 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
5247 render_pass_quad->rect.ToString());
5249 // The masked layer is 50x50, but the surface size is 10x20. So the texture
5250 // coords in the mask are scaled by 10/50 and 20/50.
5251 // The surface is clipped to (20,10) so the mask texture coords are offset
5252 // by 20/50 and 10/50
5253 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f),
5254 1.f / 50.f).ToString(),
5255 render_pass_quad->mask_uv_rect.ToString());
5257 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5258 host_impl_->DidDrawAllLayers(frame);
5262 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
5264 using GLRenderer::SetupQuadForAntialiasing;
5267 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
5268 // Due to precision issues (especially on Android), sometimes far
5269 // away quads can end up thinking they need AA.
5270 float device_scale_factor = 4.f / 3.f;
5271 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5272 gfx::Size root_size(2000, 1000);
5273 gfx::Size device_viewport_size =
5274 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
5275 host_impl_->SetViewportSize(device_viewport_size);
5277 host_impl_->CreatePendingTree();
5278 host_impl_->pending_tree()
5279 ->SetPageScaleFactorAndLimits(1.f, 1.f / 16.f, 16.f);
5281 scoped_ptr<LayerImpl> scoped_root =
5282 LayerImpl::Create(host_impl_->pending_tree(), 1);
5283 LayerImpl* root = scoped_root.get();
5285 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
5287 scoped_ptr<LayerImpl> scoped_scrolling_layer =
5288 LayerImpl::Create(host_impl_->pending_tree(), 2);
5289 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
5290 root->AddChild(scoped_scrolling_layer.Pass());
5292 gfx::Size content_layer_bounds(100000, 100);
5293 gfx::Size pile_tile_size(3000, 3000);
5294 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
5295 pile_tile_size, content_layer_bounds));
5297 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
5298 FakePictureLayerImpl::CreateWithPile(host_impl_->pending_tree(), 3, pile);
5299 LayerImpl* content_layer = scoped_content_layer.get();
5300 scrolling_layer->AddChild(scoped_content_layer.PassAs<LayerImpl>());
5301 content_layer->SetBounds(content_layer_bounds);
5302 content_layer->SetDrawsContent(true);
5304 root->SetBounds(root_size);
5306 gfx::Vector2d scroll_offset(100000, 0);
5307 scrolling_layer->SetScrollClipLayer(root->id());
5308 scrolling_layer->SetScrollOffset(scroll_offset);
5310 host_impl_->ActivatePendingTree();
5312 host_impl_->active_tree()->UpdateDrawProperties();
5313 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
5315 LayerTreeHostImpl::FrameData frame;
5316 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5317 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5319 ASSERT_EQ(1u, frame.render_passes.size());
5320 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
5321 const DrawQuad* quad = frame.render_passes[0]->quad_list[0];
5324 gfx::QuadF device_layer_quad;
5326 GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
5327 quad->quadTransform(), quad, &device_layer_quad, edge);
5328 EXPECT_FALSE(antialiased);
5330 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5331 host_impl_->DidDrawAllLayers(frame);
5335 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
5337 CompositorFrameMetadataTest()
5338 : swap_buffers_complete_(0) {}
5340 virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {
5341 swap_buffers_complete_++;
5344 int swap_buffers_complete_;
5347 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
5348 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5350 LayerTreeHostImpl::FrameData frame;
5351 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5352 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5353 host_impl_->DrawLayers(&frame, base::TimeTicks());
5354 host_impl_->DidDrawAllLayers(frame);
5356 CompositorFrameAck ack;
5357 host_impl_->ReclaimResources(&ack);
5358 host_impl_->OnSwapBuffersComplete();
5359 EXPECT_EQ(swap_buffers_complete_, 1);
5362 class CountingSoftwareDevice : public SoftwareOutputDevice {
5364 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5366 virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
5368 return SoftwareOutputDevice::BeginPaint(damage_rect);
5370 virtual void EndPaint(SoftwareFrameData* frame_data) OVERRIDE {
5372 SoftwareOutputDevice::EndPaint(frame_data);
5375 int frames_began_, frames_ended_;
5378 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
5379 // No main thread evictions in resourceless software mode.
5380 set_reduce_memory_result(false);
5381 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
5382 FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
5383 scoped_ptr<SoftwareOutputDevice>(software_device)).release();
5384 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5385 scoped_ptr<OutputSurface>(output_surface)));
5386 host_impl_->SetViewportSize(gfx::Size(50, 50));
5388 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5390 output_surface->set_forced_draw_to_software_device(true);
5391 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5393 EXPECT_EQ(0, software_device->frames_began_);
5394 EXPECT_EQ(0, software_device->frames_ended_);
5398 EXPECT_EQ(1, software_device->frames_began_);
5399 EXPECT_EQ(1, software_device->frames_ended_);
5401 // Call other API methods that are likely to hit NULL pointer in this mode.
5402 EXPECT_TRUE(host_impl_->AsValue());
5403 EXPECT_TRUE(host_impl_->ActivationStateAsValue());
5406 TEST_F(LayerTreeHostImplTest,
5407 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
5408 set_reduce_memory_result(false);
5409 FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
5410 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())).release();
5411 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5412 scoped_ptr<OutputSurface>(output_surface)));
5414 output_surface->set_forced_draw_to_software_device(true);
5415 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5417 // SolidColorLayerImpl will be drawn.
5418 scoped_ptr<SolidColorLayerImpl> root_layer =
5419 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5421 // VideoLayerImpl will not be drawn.
5422 FakeVideoFrameProvider provider;
5423 scoped_ptr<VideoLayerImpl> video_layer =
5424 VideoLayerImpl::Create(host_impl_->active_tree(), 2, &provider);
5425 video_layer->SetBounds(gfx::Size(10, 10));
5426 video_layer->SetContentBounds(gfx::Size(10, 10));
5427 video_layer->SetDrawsContent(true);
5428 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
5429 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5431 LayerTreeHostImpl::FrameData frame;
5432 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5433 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5434 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5435 host_impl_->DidDrawAllLayers(frame);
5437 EXPECT_EQ(1u, frame.will_draw_layers.size());
5438 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
5441 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
5443 virtual void SetUp() OVERRIDE {
5444 LayerTreeHostImplTest::SetUp();
5446 set_reduce_memory_result(false);
5448 scoped_ptr<FakeOutputSurface> output_surface(
5449 FakeOutputSurface::CreateDeferredGL(
5450 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())));
5451 output_surface_ = output_surface.get();
5453 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5454 output_surface.PassAs<OutputSurface>()));
5456 scoped_ptr<SolidColorLayerImpl> root_layer =
5457 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5458 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5460 onscreen_context_provider_ = TestContextProvider::Create();
5461 offscreen_context_provider_ = TestContextProvider::Create();
5464 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {
5465 did_update_renderer_capabilities_ = true;
5468 FakeOutputSurface* output_surface_;
5469 scoped_refptr<TestContextProvider> onscreen_context_provider_;
5470 scoped_refptr<TestContextProvider> offscreen_context_provider_;
5471 bool did_update_renderer_capabilities_;
5475 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
5479 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5480 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5482 // DeferredInitialize and hardware draw.
5483 did_update_renderer_capabilities_ = false;
5484 EXPECT_TRUE(output_surface_->InitializeAndSetContext3d(
5485 onscreen_context_provider_, offscreen_context_provider_));
5486 EXPECT_EQ(onscreen_context_provider_,
5487 host_impl_->output_surface()->context_provider());
5488 EXPECT_EQ(offscreen_context_provider_,
5489 host_impl_->offscreen_context_provider());
5490 EXPECT_TRUE(did_update_renderer_capabilities_);
5492 // Defer intialized GL draw.
5495 // Revert back to software.
5496 did_update_renderer_capabilities_ = false;
5497 output_surface_->ReleaseGL();
5498 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5499 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5500 EXPECT_TRUE(did_update_renderer_capabilities_);
5502 // Software draw again.
5506 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_0) {
5510 // Fail initialization of the onscreen context before the OutputSurface binds
5511 // it to the thread.
5512 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5514 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5515 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5517 // DeferredInitialize fails.
5518 did_update_renderer_capabilities_ = false;
5519 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5520 onscreen_context_provider_, offscreen_context_provider_));
5521 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5522 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5523 EXPECT_FALSE(did_update_renderer_capabilities_);
5525 // Software draw again.
5529 // TODO(boliu): After r239415, fails_OnscreenContext_1 and 2 are exactly the
5530 // same as 0. They were supposed to test makeCurrent failing in the
5531 // OutputSurface, LayerTreeHostImpl, and GLRenderer respectively.
5532 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_1) {
5536 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5537 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5539 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5541 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5542 // DeferredInitialize fails.
5543 did_update_renderer_capabilities_ = false;
5544 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5545 onscreen_context_provider_, offscreen_context_provider_));
5546 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5547 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5548 EXPECT_FALSE(did_update_renderer_capabilities_);
5551 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_2) {
5555 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5556 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5558 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5560 // DeferredInitialize fails.
5561 did_update_renderer_capabilities_ = false;
5562 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5563 onscreen_context_provider_, offscreen_context_provider_));
5564 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5565 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5566 EXPECT_FALSE(did_update_renderer_capabilities_);
5569 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OffscreenContext) {
5573 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5574 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5576 // Fail initialization of the offscreen context.
5577 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5579 // DeferredInitialize fails.
5580 did_update_renderer_capabilities_ = false;
5581 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5582 onscreen_context_provider_, offscreen_context_provider_));
5583 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5584 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5585 EXPECT_FALSE(did_update_renderer_capabilities_);
5588 // Checks that we have a non-0 default allocation if we pass a context that
5589 // doesn't support memory management extensions.
5590 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5591 LayerTreeSettings settings;
5592 host_impl_ = LayerTreeHostImpl::Create(settings,
5595 &stats_instrumentation_,
5596 shared_bitmap_manager_.get(),
5599 scoped_ptr<OutputSurface> output_surface(
5600 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5601 host_impl_->InitializeRenderer(output_surface.Pass());
5602 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5605 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5606 ManagedMemoryPolicy policy1(
5607 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5608 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5609 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5610 int required_only_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5611 gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY);
5612 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5613 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5615 // GPU rasterization should be disabled by default.
5616 EXPECT_EQ(LayerTreeSettings::CpuRasterization,
5617 host_impl_->settings().rasterization_site);
5619 host_impl_->SetVisible(true);
5620 host_impl_->SetMemoryPolicy(policy1);
5621 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5622 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5624 host_impl_->SetVisible(false);
5625 EXPECT_EQ(0u, current_limit_bytes_);
5626 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5628 host_impl_->SetVisible(true);
5629 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5630 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5632 // Now enable GPU rasterization and test if we get required only cutoff,
5634 LayerTreeSettings settings;
5635 settings.rasterization_site = LayerTreeSettings::GpuRasterization;
5636 host_impl_ = LayerTreeHostImpl::Create(
5637 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
5639 host_impl_->SetVisible(true);
5640 host_impl_->SetMemoryPolicy(policy1);
5641 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5642 EXPECT_EQ(required_only_cutoff_value, current_priority_cutoff_value_);
5644 host_impl_->SetVisible(false);
5645 EXPECT_EQ(0u, current_limit_bytes_);
5646 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5649 class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
5651 virtual void SetUp() OVERRIDE {
5652 LayerTreeSettings settings;
5653 settings.impl_side_painting = true;
5655 fake_host_impl_ = new FakeLayerTreeHostImpl(
5656 settings, &proxy_, shared_bitmap_manager_.get());
5657 host_impl_.reset(fake_host_impl_);
5658 host_impl_->InitializeRenderer(CreateOutputSurface());
5659 host_impl_->SetViewportSize(gfx::Size(10, 10));
5662 FakeLayerTreeHostImpl* fake_host_impl_;
5665 TEST_F(LayerTreeHostImplTestManageTiles, ManageTilesWhenInvisible) {
5666 fake_host_impl_->DidModifyTilePriorities();
5667 EXPECT_TRUE(fake_host_impl_->manage_tiles_needed());
5668 fake_host_impl_->SetVisible(false);
5669 EXPECT_FALSE(fake_host_impl_->manage_tiles_needed());
5672 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
5673 scoped_ptr<TestWebGraphicsContext3D> context =
5674 TestWebGraphicsContext3D::Create();
5675 TestWebGraphicsContext3D* context3d = context.get();
5676 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5677 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5679 EXPECT_EQ(0u, context3d->NumTextures());
5681 UIResourceId ui_resource_id = 1;
5682 bool is_opaque = false;
5683 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
5684 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5685 EXPECT_EQ(1u, context3d->NumTextures());
5686 ResourceProvider::ResourceId id1 =
5687 host_impl_->ResourceIdForUIResource(ui_resource_id);
5690 // Multiple requests with the same id is allowed. The previous texture is
5692 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5693 EXPECT_EQ(1u, context3d->NumTextures());
5694 ResourceProvider::ResourceId id2 =
5695 host_impl_->ResourceIdForUIResource(ui_resource_id);
5697 EXPECT_NE(id1, id2);
5699 // Deleting invalid UIResourceId is allowed and does not change state.
5700 host_impl_->DeleteUIResource(-1);
5701 EXPECT_EQ(1u, context3d->NumTextures());
5703 // Should return zero for invalid UIResourceId. Number of textures should
5705 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
5706 EXPECT_EQ(1u, context3d->NumTextures());
5708 host_impl_->DeleteUIResource(ui_resource_id);
5709 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
5710 EXPECT_EQ(0u, context3d->NumTextures());
5712 // Should not change state for multiple deletion on one UIResourceId
5713 host_impl_->DeleteUIResource(ui_resource_id);
5714 EXPECT_EQ(0u, context3d->NumTextures());
5717 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
5718 scoped_ptr<TestWebGraphicsContext3D> context =
5719 TestWebGraphicsContext3D::Create();
5720 TestWebGraphicsContext3D* context3d = context.get();
5721 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5722 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5724 EXPECT_EQ(0u, context3d->NumTextures());
5726 gfx::Size size(4, 4);
5727 // SkImageInfo has no support for ETC1. The |info| below contains the right
5728 // total pixel size for the bitmap but not the right height and width. The
5729 // correct width/height are passed directly to UIResourceBitmap.
5731 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
5732 skia::RefPtr<SkPixelRef> pixel_ref =
5733 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
5734 pixel_ref->setImmutable();
5735 UIResourceBitmap bitmap(pixel_ref, size);
5736 UIResourceId ui_resource_id = 1;
5737 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5738 EXPECT_EQ(1u, context3d->NumTextures());
5739 ResourceProvider::ResourceId id1 =
5740 host_impl_->ResourceIdForUIResource(ui_resource_id);
5744 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
5747 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
5748 scoped_refptr<TestContextProvider> context_provider =
5749 TestContextProvider::Create();
5753 FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>());
5755 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5757 ScopedPtrVector<CopyOutputRequest> requests;
5758 requests.push_back(CopyOutputRequest::CreateRequest(
5759 base::Bind(&ShutdownReleasesContext_Callback)));
5761 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
5763 LayerTreeHostImpl::FrameData frame;
5764 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5765 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5766 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5767 host_impl_->DidDrawAllLayers(frame);
5769 // The CopyOutputResult's callback has a ref on the ContextProvider and a
5770 // texture in a texture mailbox.
5771 EXPECT_FALSE(context_provider->HasOneRef());
5772 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
5776 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
5777 // released, and the texture deleted.
5778 EXPECT_TRUE(context_provider->HasOneRef());
5779 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
5782 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
5783 // When flinging via touch, only the child should scroll (we should not
5785 gfx::Size surface_size(10, 10);
5786 gfx::Size content_size(20, 20);
5787 scoped_ptr<LayerImpl> root_clip =
5788 LayerImpl::Create(host_impl_->active_tree(), 3);
5789 scoped_ptr<LayerImpl> root =
5790 CreateScrollableLayer(1, content_size, root_clip.get());
5791 root->SetIsContainerForFixedPositionLayers(true);
5792 scoped_ptr<LayerImpl> child =
5793 CreateScrollableLayer(2, content_size, root_clip.get());
5795 root->AddChild(child.Pass());
5796 int root_id = root->id();
5797 root_clip->AddChild(root.Pass());
5799 host_impl_->SetViewportSize(surface_size);
5800 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
5801 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
5802 host_impl_->active_tree()->DidBecomeActive();
5805 EXPECT_EQ(InputHandler::ScrollStarted,
5806 host_impl_->ScrollBegin(gfx::Point(),
5807 InputHandler::Gesture));
5809 EXPECT_EQ(InputHandler::ScrollStarted,
5810 host_impl_->FlingScrollBegin());
5812 gfx::Vector2d scroll_delta(0, 100);
5813 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5814 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5816 host_impl_->ScrollEnd();
5818 scoped_ptr<ScrollAndScaleSet> scroll_info =
5819 host_impl_->ProcessScrollDeltas();
5821 // Only the child should have scrolled.
5822 ASSERT_EQ(1u, scroll_info->scrolls.size());
5823 ExpectNone(*scroll_info.get(), root_id);
5827 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
5828 // Scroll a child layer beyond its maximum scroll range and make sure the
5829 // the scroll doesn't bubble up to the parent layer.
5830 gfx::Size surface_size(10, 10);
5831 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
5832 scoped_ptr<LayerImpl> root_scrolling =
5833 CreateScrollableLayer(2, surface_size, root.get());
5835 scoped_ptr<LayerImpl> grand_child =
5836 CreateScrollableLayer(4, surface_size, root.get());
5837 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
5839 scoped_ptr<LayerImpl> child =
5840 CreateScrollableLayer(3, surface_size, root.get());
5841 child->SetScrollOffset(gfx::Vector2d(0, 4));
5842 child->AddChild(grand_child.Pass());
5844 root_scrolling->AddChild(child.Pass());
5845 root->AddChild(root_scrolling.Pass());
5846 host_impl_->active_tree()->SetRootLayer(root.Pass());
5847 host_impl_->active_tree()->DidBecomeActive();
5848 host_impl_->SetViewportSize(surface_size);
5851 scoped_ptr<ScrollAndScaleSet> scroll_info;
5853 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
5854 LayerImpl* grand_child = child->children()[0];
5856 gfx::Vector2d scroll_delta(0, -2);
5857 EXPECT_EQ(InputHandler::ScrollStarted,
5858 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
5859 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5861 // The grand child should have scrolled up to its limit.
5862 scroll_info = host_impl_->ProcessScrollDeltas();
5863 ASSERT_EQ(1u, scroll_info->scrolls.size());
5864 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5865 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
5867 // The child should have received the bubbled delta, but the locked
5868 // scrolling layer should remain set as the grand child.
5869 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5870 scroll_info = host_impl_->ProcessScrollDeltas();
5871 ASSERT_EQ(2u, scroll_info->scrolls.size());
5872 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5873 ExpectContains(*scroll_info, child->id(), scroll_delta);
5874 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
5876 // The first |ScrollBy| after the fling should re-lock the scrolling
5877 // layer to the first layer that scrolled, which is the child.
5878 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
5879 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5880 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
5882 // The child should have scrolled up to its limit.
5883 scroll_info = host_impl_->ProcessScrollDeltas();
5884 ASSERT_EQ(2u, scroll_info->scrolls.size());
5885 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5886 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
5888 // As the locked layer is at it's limit, no further scrolling can occur.
5889 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5890 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
5891 host_impl_->ScrollEnd();
5895 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
5896 // When flinging via wheel, the root should eventually scroll (we should
5898 gfx::Size surface_size(10, 10);
5899 gfx::Size content_size(20, 20);
5900 scoped_ptr<LayerImpl> root_clip =
5901 LayerImpl::Create(host_impl_->active_tree(), 3);
5902 scoped_ptr<LayerImpl> root_scroll =
5903 CreateScrollableLayer(1, content_size, root_clip.get());
5904 int root_scroll_id = root_scroll->id();
5905 scoped_ptr<LayerImpl> child =
5906 CreateScrollableLayer(2, content_size, root_clip.get());
5908 root_scroll->AddChild(child.Pass());
5909 root_clip->AddChild(root_scroll.Pass());
5911 host_impl_->SetViewportSize(surface_size);
5912 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
5913 host_impl_->active_tree()->DidBecomeActive();
5916 EXPECT_EQ(InputHandler::ScrollStarted,
5917 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
5919 EXPECT_EQ(InputHandler::ScrollStarted,
5920 host_impl_->FlingScrollBegin());
5922 gfx::Vector2d scroll_delta(0, 100);
5923 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5924 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5926 host_impl_->ScrollEnd();
5928 scoped_ptr<ScrollAndScaleSet> scroll_info =
5929 host_impl_->ProcessScrollDeltas();
5931 // The root should have scrolled.
5932 ASSERT_EQ(2u, scroll_info->scrolls.size());
5933 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
5937 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
5938 // to CompositorFrameMetadata after SwapBuffers();
5939 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
5940 scoped_ptr<SolidColorLayerImpl> root =
5941 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5942 root->SetAnchorPoint(gfx::PointF());
5943 root->SetPosition(gfx::PointF());
5944 root->SetBounds(gfx::Size(10, 10));
5945 root->SetContentBounds(gfx::Size(10, 10));
5946 root->SetDrawsContent(true);
5948 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
5950 FakeOutputSurface* fake_output_surface =
5951 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
5953 const std::vector<ui::LatencyInfo>& metadata_latency_before =
5954 fake_output_surface->last_sent_frame().metadata.latency_info;
5955 EXPECT_TRUE(metadata_latency_before.empty());
5957 ui::LatencyInfo latency_info;
5958 latency_info.AddLatencyNumber(
5959 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
5960 scoped_ptr<SwapPromise> swap_promise(
5961 new LatencyInfoSwapPromise(latency_info));
5962 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
5963 host_impl_->SetNeedsRedraw();
5965 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
5966 LayerTreeHostImpl::FrameData frame;
5967 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5968 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5969 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5970 host_impl_->DidDrawAllLayers(frame);
5971 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
5973 const std::vector<ui::LatencyInfo>& metadata_latency_after =
5974 fake_output_surface->last_sent_frame().metadata.latency_info;
5975 EXPECT_EQ(1u, metadata_latency_after.size());
5976 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
5977 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
5980 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
5982 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
5983 LayerTreeHostImpl* layer_tree_host_impl,
5984 int* set_needs_commit_count,
5985 int* set_needs_redraw_count)
5986 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
5987 set_needs_commit_count_(set_needs_commit_count),
5988 set_needs_redraw_count_(set_needs_redraw_count) {}
5990 virtual ~SimpleSwapPromiseMonitor() {}
5992 virtual void OnSetNeedsCommitOnMain() OVERRIDE {
5993 (*set_needs_commit_count_)++;
5996 virtual void OnSetNeedsRedrawOnImpl() OVERRIDE {
5997 (*set_needs_redraw_count_)++;
6001 int* set_needs_commit_count_;
6002 int* set_needs_redraw_count_;
6005 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
6006 int set_needs_commit_count = 0;
6007 int set_needs_redraw_count = 0;
6010 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6011 new SimpleSwapPromiseMonitor(NULL,
6013 &set_needs_commit_count,
6014 &set_needs_redraw_count));
6015 host_impl_->SetNeedsRedraw();
6016 EXPECT_EQ(0, set_needs_commit_count);
6017 EXPECT_EQ(1, set_needs_redraw_count);
6020 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6022 host_impl_->SetNeedsRedraw();
6023 EXPECT_EQ(0, set_needs_commit_count);
6024 EXPECT_EQ(1, set_needs_redraw_count);
6027 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6028 new SimpleSwapPromiseMonitor(NULL,
6030 &set_needs_commit_count,
6031 &set_needs_redraw_count));
6032 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
6033 EXPECT_EQ(0, set_needs_commit_count);
6034 EXPECT_EQ(2, set_needs_redraw_count);
6038 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6039 new SimpleSwapPromiseMonitor(NULL,
6041 &set_needs_commit_count,
6042 &set_needs_redraw_count));
6043 // Empty damage rect won't signal the monitor.
6044 host_impl_->SetNeedsRedrawRect(gfx::Rect());
6045 EXPECT_EQ(0, set_needs_commit_count);
6046 EXPECT_EQ(2, set_needs_redraw_count);
6050 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
6052 virtual void SetUp() OVERRIDE {
6053 LayerTreeSettings settings = DefaultSettings();
6054 settings.calculate_top_controls_position = true;
6055 settings.top_controls_height = top_controls_height_;
6056 CreateHostImpl(settings, CreateOutputSurface());
6060 static const int top_controls_height_;
6063 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
6065 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
6066 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6067 ->SetScrollOffset(gfx::Vector2d(0, 10));
6068 host_impl_->Animate(base::TimeTicks());
6069 EXPECT_FALSE(did_request_redraw_);
6072 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
6073 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6074 host_impl_->SetViewportSize(gfx::Size(100, 100));
6077 EXPECT_EQ(InputHandler::ScrollStarted,
6078 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6079 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6080 EXPECT_EQ(gfx::Vector2dF().ToString(),
6081 scroll_layer->TotalScrollOffset().ToString());
6083 // Scroll just the top controls and verify that the scroll succeeds.
6084 const float residue = 10;
6085 float offset = top_controls_height_ - residue;
6086 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6087 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->controls_top_offset());
6088 EXPECT_EQ(gfx::Vector2dF().ToString(),
6089 scroll_layer->TotalScrollOffset().ToString());
6091 // Scroll across the boundary
6092 const float content_scroll = 20;
6093 offset = residue + content_scroll;
6094 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6095 EXPECT_EQ(-top_controls_height_,
6096 host_impl_->top_controls_manager()->controls_top_offset());
6097 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
6098 scroll_layer->TotalScrollOffset().ToString());
6100 // Now scroll back to the top of the content
6101 offset = -content_scroll;
6102 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6103 EXPECT_EQ(-top_controls_height_,
6104 host_impl_->top_controls_manager()->controls_top_offset());
6105 EXPECT_EQ(gfx::Vector2dF().ToString(),
6106 scroll_layer->TotalScrollOffset().ToString());
6108 // And scroll the top controls completely into view
6109 offset = -top_controls_height_;
6110 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6111 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6112 EXPECT_EQ(gfx::Vector2dF().ToString(),
6113 scroll_layer->TotalScrollOffset().ToString());
6115 // And attempt to scroll past the end
6116 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6117 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6118 EXPECT_EQ(gfx::Vector2dF().ToString(),
6119 scroll_layer->TotalScrollOffset().ToString());
6121 host_impl_->ScrollEnd();
6124 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
6126 void SetupVirtualViewportLayers(const gfx::Size& content_size,
6127 const gfx::Size& outer_viewport,
6128 const gfx::Size& inner_viewport) {
6129 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
6130 const int kOuterViewportClipLayerId = 6;
6131 const int kOuterViewportScrollLayerId = 7;
6132 const int kInnerViewportScrollLayerId = 2;
6133 const int kInnerViewportClipLayerId = 4;
6134 const int kPageScaleLayerId = 5;
6136 scoped_ptr<LayerImpl> inner_scroll =
6137 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
6138 inner_scroll->SetIsContainerForFixedPositionLayers(true);
6139 inner_scroll->SetScrollOffset(gfx::Vector2d());
6141 scoped_ptr<LayerImpl> inner_clip =
6142 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
6143 inner_clip->SetBounds(inner_viewport);
6145 scoped_ptr<LayerImpl> page_scale =
6146 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
6148 inner_scroll->SetScrollClipLayer(inner_clip->id());
6149 inner_scroll->SetBounds(outer_viewport);
6150 inner_scroll->SetContentBounds(outer_viewport);
6151 inner_scroll->SetPosition(gfx::PointF());
6152 inner_scroll->SetAnchorPoint(gfx::PointF());
6154 scoped_ptr<LayerImpl> outer_clip =
6155 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
6156 outer_clip->SetBounds(outer_viewport);
6157 outer_clip->SetIsContainerForFixedPositionLayers(true);
6159 scoped_ptr<LayerImpl> outer_scroll =
6160 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
6161 outer_scroll->SetScrollClipLayer(outer_clip->id());
6162 outer_scroll->SetScrollOffset(gfx::Vector2d());
6163 outer_scroll->SetBounds(content_size);
6164 outer_scroll->SetContentBounds(content_size);
6165 outer_scroll->SetPosition(gfx::PointF());
6166 outer_scroll->SetAnchorPoint(gfx::PointF());
6168 scoped_ptr<LayerImpl> contents =
6169 LayerImpl::Create(layer_tree_impl, 8);
6170 contents->SetDrawsContent(true);
6171 contents->SetBounds(content_size);
6172 contents->SetContentBounds(content_size);
6173 contents->SetPosition(gfx::PointF());
6174 contents->SetAnchorPoint(gfx::PointF());
6176 outer_scroll->AddChild(contents.Pass());
6177 outer_clip->AddChild(outer_scroll.Pass());
6178 inner_scroll->AddChild(outer_clip.Pass());
6179 page_scale->AddChild(inner_scroll.Pass());
6180 inner_clip->AddChild(page_scale.Pass());
6182 layer_tree_impl->SetRootLayer(inner_clip.Pass());
6183 layer_tree_impl->SetViewportLayersFromIds(kPageScaleLayerId,
6184 kInnerViewportScrollLayerId, kOuterViewportScrollLayerId);
6186 host_impl_->active_tree()->DidBecomeActive();
6190 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
6191 gfx::Size content_size = gfx::Size(100, 160);
6192 gfx::Size outer_viewport = gfx::Size(50, 80);
6193 gfx::Size inner_viewport = gfx::Size(25, 40);
6195 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
6197 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
6198 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
6201 gfx::Vector2dF inner_expected;
6202 gfx::Vector2dF outer_expected;
6203 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6204 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6206 // Make sure the fling goes to the outer viewport first
6207 EXPECT_EQ(InputHandler::ScrollStarted,
6208 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6209 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6211 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
6212 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6213 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6215 host_impl_->ScrollEnd();
6217 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6218 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6220 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
6221 EXPECT_EQ(InputHandler::ScrollStarted,
6222 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6223 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6225 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6226 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6228 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6229 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6231 host_impl_->ScrollEnd();
6233 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6234 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6238 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
6240 virtual void SetUp() OVERRIDE {
6241 LayerTreeSettings settings = DefaultSettings();
6242 settings.max_unused_resource_memory_percentage = 50;
6243 settings.max_memory_for_prepaint_percentage = 50;
6244 CreateHostImpl(settings, CreateOutputSurface());
6248 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
6249 // Set up a memory policy and percentages which could cause
6250 // 32-bit integer overflows.
6251 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
6253 // Verify implicit limits are calculated correctly with no overflows
6254 host_impl_->SetMemoryPolicy(mem_policy);
6255 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
6256 300u * 1024u * 1024u);
6257 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
6258 150u * 1024u * 1024u);
6259 EXPECT_EQ(host_impl_->global_tile_state().unused_memory_limit_in_bytes,
6260 75u * 1024u * 1024u);