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_web_graphics_context_3d.h"
53 #include "cc/trees/layer_tree_impl.h"
54 #include "cc/trees/single_thread_proxy.h"
55 #include "media/base/media.h"
56 #include "testing/gmock/include/gmock/gmock.h"
57 #include "testing/gtest/include/gtest/gtest.h"
58 #include "third_party/skia/include/core/SkMallocPixelRef.h"
59 #include "ui/gfx/frame_time.h"
60 #include "ui/gfx/rect_conversions.h"
61 #include "ui/gfx/size_conversions.h"
62 #include "ui/gfx/vector2d_conversions.h"
64 using ::testing::Mock;
65 using ::testing::Return;
66 using ::testing::AnyNumber;
67 using ::testing::AtLeast;
69 using media::VideoFrame;
74 class LayerTreeHostImplTest : public testing::Test,
75 public LayerTreeHostImplClient {
77 LayerTreeHostImplTest()
79 always_impl_thread_(&proxy_),
80 always_main_thread_blocked_(&proxy_),
81 on_can_draw_state_changed_called_(false),
82 did_notify_ready_to_activate_(false),
83 did_request_commit_(false),
84 did_request_redraw_(false),
85 did_request_manage_tiles_(false),
86 did_upload_visible_tile_(false),
87 reduce_memory_result_(true),
88 current_limit_bytes_(0),
89 current_priority_cutoff_value_(0) {
90 media::InitializeMediaLibraryForTesting();
93 LayerTreeSettings DefaultSettings() {
94 LayerTreeSettings settings;
95 settings.minimum_occlusion_tracking_size = gfx::Size();
96 settings.impl_side_painting = true;
97 settings.texture_id_allocation_chunk_size = 1;
101 virtual void SetUp() OVERRIDE {
102 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
105 virtual void TearDown() OVERRIDE {}
107 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {}
108 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
109 virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
110 virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {}
111 virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE {}
112 virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
113 on_can_draw_state_changed_called_ = true;
115 virtual void NotifyReadyToActivate() OVERRIDE {
116 did_notify_ready_to_activate_ = true;
117 host_impl_->ActivatePendingTree();
119 virtual void SetNeedsRedrawOnImplThread() OVERRIDE {
120 did_request_redraw_ = true;
122 virtual void SetNeedsRedrawRectOnImplThread(
123 const gfx::Rect& damage_rect) OVERRIDE {
124 did_request_redraw_ = true;
126 virtual void SetNeedsManageTilesOnImplThread() OVERRIDE {
127 did_request_manage_tiles_ = true;
129 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {
130 did_upload_visible_tile_ = true;
132 virtual void SetNeedsCommitOnImplThread() OVERRIDE {
133 did_request_commit_ = true;
135 virtual void PostAnimationEventsToMainThreadOnImplThread(
136 scoped_ptr<AnimationEventsVector> events,
137 base::Time wall_clock_time) OVERRIDE {}
138 virtual bool ReduceContentsTextureMemoryOnImplThread(
139 size_t limit_bytes, int priority_cutoff) OVERRIDE {
140 current_limit_bytes_ = limit_bytes;
141 current_priority_cutoff_value_ = priority_cutoff;
142 return reduce_memory_result_;
144 virtual void SendManagedMemoryStats() OVERRIDE {}
145 virtual bool IsInsideDraw() OVERRIDE { return false; }
146 virtual void RenewTreePriority() OVERRIDE {}
147 virtual void RequestScrollbarAnimationOnImplThread(base::TimeDelta delay)
148 OVERRIDE { requested_scrollbar_animation_delay_ = delay; }
149 virtual void DidActivatePendingTree() OVERRIDE {}
150 virtual void DidManageTiles() OVERRIDE {}
152 void set_reduce_memory_result(bool reduce_memory_result) {
153 reduce_memory_result_ = reduce_memory_result;
156 bool CreateHostImpl(const LayerTreeSettings& settings,
157 scoped_ptr<OutputSurface> output_surface) {
158 host_impl_ = LayerTreeHostImpl::Create(
159 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
160 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
161 host_impl_->SetViewportSize(gfx::Size(10, 10));
165 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
166 root->SetAnchorPoint(gfx::PointF());
167 root->SetPosition(gfx::PointF());
168 root->SetBounds(gfx::Size(10, 10));
169 root->SetContentBounds(gfx::Size(10, 10));
170 root->SetDrawsContent(true);
171 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
172 host_impl_->active_tree()->SetRootLayer(root.Pass());
175 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
176 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
177 for (size_t i = 0; i < layer->children().size(); ++i)
178 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
181 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
183 const gfx::Vector2d& scroll_delta) {
184 int times_encountered = 0;
186 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
187 if (scroll_info.scrolls[i].layer_id != id)
189 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
193 ASSERT_EQ(1, times_encountered);
196 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
197 int times_encountered = 0;
199 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
200 if (scroll_info.scrolls[i].layer_id != id)
205 ASSERT_EQ(0, times_encountered);
208 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
209 const gfx::Size& content_size) {
210 const int kInnerViewportScrollLayerId = 2;
211 const int kInnerViewportClipLayerId = 4;
212 const int kPageScaleLayerId = 5;
213 scoped_ptr<LayerImpl> root =
214 LayerImpl::Create(layer_tree_impl, 1);
215 root->SetBounds(content_size);
216 root->SetContentBounds(content_size);
217 root->SetPosition(gfx::PointF());
218 root->SetAnchorPoint(gfx::PointF());
220 scoped_ptr<LayerImpl> scroll =
221 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
222 LayerImpl* scroll_layer = scroll.get();
223 scroll->SetIsContainerForFixedPositionLayers(true);
224 scroll->SetScrollOffset(gfx::Vector2d());
226 scoped_ptr<LayerImpl> clip =
227 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
229 gfx::Size(content_size.width() / 2, content_size.height() / 2));
231 scoped_ptr<LayerImpl> page_scale =
232 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
234 scroll->SetScrollClipLayer(clip->id());
235 scroll->SetBounds(content_size);
236 scroll->SetContentBounds(content_size);
237 scroll->SetPosition(gfx::PointF());
238 scroll->SetAnchorPoint(gfx::PointF());
239 scroll->SetIsContainerForFixedPositionLayers(true);
241 scoped_ptr<LayerImpl> contents =
242 LayerImpl::Create(layer_tree_impl, 3);
243 contents->SetDrawsContent(true);
244 contents->SetBounds(content_size);
245 contents->SetContentBounds(content_size);
246 contents->SetPosition(gfx::PointF());
247 contents->SetAnchorPoint(gfx::PointF());
249 scroll->AddChild(contents.Pass());
250 page_scale->AddChild(scroll.Pass());
251 clip->AddChild(page_scale.Pass());
252 root->AddChild(clip.Pass());
254 layer_tree_impl->SetRootLayer(root.Pass());
255 layer_tree_impl->SetViewportLayersFromIds(
256 kPageScaleLayerId, kInnerViewportScrollLayerId, Layer::INVALID_ID);
261 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
262 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
263 host_impl_->active_tree(), content_size);
264 host_impl_->active_tree()->DidBecomeActive();
268 // TODO(wjmaclean) Add clip-layer pointer to parameters.
269 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
270 const gfx::Size& size,
271 LayerImpl* clip_layer) {
273 DCHECK(id != clip_layer->id());
274 scoped_ptr<LayerImpl> layer =
275 LayerImpl::Create(host_impl_->active_tree(), id);
276 layer->SetScrollClipLayer(clip_layer->id());
277 layer->SetDrawsContent(true);
278 layer->SetBounds(size);
279 layer->SetContentBounds(size);
280 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
285 LayerTreeHostImpl::FrameData frame;
286 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
287 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
288 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
289 host_impl_->DidDrawAllLayers(frame);
292 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
293 void pinch_zoom_pan_viewport_test(float device_scale_factor);
294 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
295 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
296 float device_scale_factor);
298 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
299 // Note: It is not possible to disable the renderer once it has been set,
300 // so we do not need to test that disabling the renderer notifies us
301 // that can_draw changed.
302 EXPECT_FALSE(host_impl_->CanDraw());
303 on_can_draw_state_changed_called_ = false;
305 // Set up the root layer, which allows us to draw.
306 SetupScrollAndContentsLayers(gfx::Size(100, 100));
307 EXPECT_TRUE(host_impl_->CanDraw());
308 EXPECT_TRUE(on_can_draw_state_changed_called_);
309 on_can_draw_state_changed_called_ = false;
311 // Toggle the root layer to make sure it toggles can_draw
312 host_impl_->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
313 EXPECT_FALSE(host_impl_->CanDraw());
314 EXPECT_TRUE(on_can_draw_state_changed_called_);
315 on_can_draw_state_changed_called_ = false;
317 SetupScrollAndContentsLayers(gfx::Size(100, 100));
318 EXPECT_TRUE(host_impl_->CanDraw());
319 EXPECT_TRUE(on_can_draw_state_changed_called_);
320 on_can_draw_state_changed_called_ = false;
322 // Toggle the device viewport size to make sure it toggles can_draw.
323 host_impl_->SetViewportSize(gfx::Size());
325 EXPECT_TRUE(host_impl_->CanDraw());
327 EXPECT_FALSE(host_impl_->CanDraw());
329 EXPECT_TRUE(on_can_draw_state_changed_called_);
330 on_can_draw_state_changed_called_ = false;
332 host_impl_->SetViewportSize(gfx::Size(100, 100));
333 EXPECT_TRUE(host_impl_->CanDraw());
334 EXPECT_TRUE(on_can_draw_state_changed_called_);
335 on_can_draw_state_changed_called_ = false;
337 // Toggle contents textures purged without causing any evictions,
338 // and make sure that it does not change can_draw.
339 set_reduce_memory_result(false);
340 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
341 host_impl_->memory_allocation_limit_bytes() - 1));
342 EXPECT_TRUE(host_impl_->CanDraw());
343 EXPECT_FALSE(on_can_draw_state_changed_called_);
344 on_can_draw_state_changed_called_ = false;
346 // Toggle contents textures purged to make sure it toggles can_draw.
347 set_reduce_memory_result(true);
348 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
349 host_impl_->memory_allocation_limit_bytes() - 1));
351 EXPECT_TRUE(host_impl_->CanDraw());
353 EXPECT_FALSE(host_impl_->CanDraw());
355 EXPECT_TRUE(on_can_draw_state_changed_called_);
356 on_can_draw_state_changed_called_ = false;
358 host_impl_->active_tree()->ResetContentsTexturesPurged();
359 EXPECT_TRUE(host_impl_->CanDraw());
360 EXPECT_TRUE(on_can_draw_state_changed_called_);
361 on_can_draw_state_changed_called_ = false;
364 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
367 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
368 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
371 void DrawOneFrame() {
372 LayerTreeHostImpl::FrameData frame_data;
373 host_impl_->PrepareToDraw(&frame_data, gfx::Rect());
374 host_impl_->DidDrawAllLayers(frame_data);
378 DebugScopedSetImplThread always_impl_thread_;
379 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
381 scoped_ptr<LayerTreeHostImpl> host_impl_;
382 FakeRenderingStatsInstrumentation stats_instrumentation_;
383 bool on_can_draw_state_changed_called_;
384 bool did_notify_ready_to_activate_;
385 bool did_request_commit_;
386 bool did_request_redraw_;
387 bool did_request_manage_tiles_;
388 bool did_upload_visible_tile_;
389 bool reduce_memory_result_;
390 base::TimeDelta requested_scrollbar_animation_delay_;
391 size_t current_limit_bytes_;
392 int current_priority_cutoff_value_;
395 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
396 bool always_draw = false;
397 CheckNotifyCalledIfCanDrawChanged(always_draw);
400 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
401 scoped_ptr<FakeOutputSurface> output_surface(
402 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
403 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
405 bool always_draw = true;
406 CheckNotifyCalledIfCanDrawChanged(always_draw);
409 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
410 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
412 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
413 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
416 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
418 scoped_ptr<LayerImpl> root =
419 LayerImpl::Create(host_impl_->active_tree(), 1);
420 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
421 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
422 root->children()[1]->AddChild(
423 LayerImpl::Create(host_impl_->active_tree(), 4));
424 root->children()[1]->AddChild(
425 LayerImpl::Create(host_impl_->active_tree(), 5));
426 root->children()[1]->children()[0]->AddChild(
427 LayerImpl::Create(host_impl_->active_tree(), 6));
428 host_impl_->active_tree()->SetRootLayer(root.Pass());
430 LayerImpl* root = host_impl_->active_tree()->root_layer();
432 ExpectClearedScrollDeltasRecursive(root);
434 scoped_ptr<ScrollAndScaleSet> scroll_info;
436 scroll_info = host_impl_->ProcessScrollDeltas();
437 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
438 ExpectClearedScrollDeltasRecursive(root);
440 scroll_info = host_impl_->ProcessScrollDeltas();
441 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
442 ExpectClearedScrollDeltasRecursive(root);
445 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
446 gfx::Vector2d scroll_offset(20, 30);
447 gfx::Vector2d scroll_delta(11, -15);
449 scoped_ptr<LayerImpl> root_clip =
450 LayerImpl::Create(host_impl_->active_tree(), 2);
451 scoped_ptr<LayerImpl> root =
452 LayerImpl::Create(host_impl_->active_tree(), 1);
453 root_clip->SetBounds(gfx::Size(10, 10));
454 LayerImpl* root_layer = root.get();
455 root_clip->AddChild(root.Pass());
456 root_layer->SetBounds(gfx::Size(110, 110));
457 root_layer->SetScrollClipLayer(root_clip->id());
458 root_layer->SetScrollOffset(scroll_offset);
459 root_layer->ScrollBy(scroll_delta);
460 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
462 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
464 scoped_ptr<ScrollAndScaleSet> scroll_info;
466 scroll_info = host_impl_->ProcessScrollDeltas();
467 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
468 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta);
469 ExpectContains(*scroll_info, root->id(), scroll_delta);
471 gfx::Vector2d scroll_delta2(-5, 27);
472 root->ScrollBy(scroll_delta2);
473 scroll_info = host_impl_->ProcessScrollDeltas();
474 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
475 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
476 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
478 root->ScrollBy(gfx::Vector2d());
479 scroll_info = host_impl_->ProcessScrollDeltas();
480 EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
483 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
484 SetupScrollAndContentsLayers(gfx::Size(100, 100));
485 host_impl_->SetViewportSize(gfx::Size(50, 50));
488 EXPECT_EQ(InputHandler::ScrollStarted,
489 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
490 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
491 host_impl_->ScrollEnd();
492 EXPECT_TRUE(did_request_redraw_);
493 EXPECT_TRUE(did_request_commit_);
496 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
497 // We should not crash when trying to scroll an empty layer tree.
498 EXPECT_EQ(InputHandler::ScrollIgnored,
499 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
502 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
503 scoped_ptr<TestWebGraphicsContext3D> context_owned =
504 TestWebGraphicsContext3D::Create();
505 context_owned->set_context_lost(true);
507 scoped_ptr<FakeOutputSurface> output_surface(FakeOutputSurface::Create3d(
508 context_owned.Pass()));
510 // Initialization will fail.
511 EXPECT_FALSE(CreateHostImpl(DefaultSettings(),
512 output_surface.PassAs<OutputSurface>()));
514 SetupScrollAndContentsLayers(gfx::Size(100, 100));
516 // We should not crash when trying to scroll after the renderer initialization
518 EXPECT_EQ(InputHandler::ScrollIgnored,
519 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
522 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
523 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
524 host_impl_->SetViewportSize(gfx::Size(50, 50));
527 // We should not crash if the tree is replaced while we are scrolling.
528 EXPECT_EQ(InputHandler::ScrollStarted,
529 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
530 host_impl_->active_tree()->DetachLayerTree();
532 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
534 // We should still be scrolling, because the scrolled layer also exists in the
536 gfx::Vector2d scroll_delta(0, 10);
537 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
538 host_impl_->ScrollEnd();
539 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
540 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
543 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
544 SetupScrollAndContentsLayers(gfx::Size(100, 100));
545 host_impl_->SetViewportSize(gfx::Size(50, 50));
548 // We should be able to scroll even if the root layer loses its render surface
549 // after the most recent render.
550 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
551 host_impl_->active_tree()->set_needs_update_draw_properties();
553 EXPECT_EQ(InputHandler::ScrollStarted,
554 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
557 TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
558 SetupScrollAndContentsLayers(gfx::Size(100, 100));
559 host_impl_->SetViewportSize(gfx::Size(50, 50));
561 LayerImpl* root = host_impl_->active_tree()->root_layer();
563 root->SetHaveWheelEventHandlers(true);
565 // With registered event handlers, wheel scrolls have to go to the main
567 EXPECT_EQ(InputHandler::ScrollOnMainThread,
568 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
570 // But gesture scrolls can still be handled.
571 EXPECT_EQ(InputHandler::ScrollStarted,
572 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
575 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
576 SetupScrollAndContentsLayers(gfx::Size(100, 100));
577 host_impl_->SetViewportSize(gfx::Size(50, 50));
580 // Ignore the fling since no layer is being scrolled
581 EXPECT_EQ(InputHandler::ScrollIgnored,
582 host_impl_->FlingScrollBegin());
584 // Start scrolling a layer
585 EXPECT_EQ(InputHandler::ScrollStarted,
586 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
588 // Now the fling should go ahead since we've started scrolling a layer
589 EXPECT_EQ(InputHandler::ScrollStarted,
590 host_impl_->FlingScrollBegin());
593 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
594 SetupScrollAndContentsLayers(gfx::Size(100, 100));
595 host_impl_->SetViewportSize(gfx::Size(50, 50));
598 // Ignore the fling since no layer is being scrolled
599 EXPECT_EQ(InputHandler::ScrollIgnored,
600 host_impl_->FlingScrollBegin());
602 // Start scrolling a layer
603 EXPECT_EQ(InputHandler::ScrollStarted,
604 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
606 // Now the fling should go ahead since we've started scrolling a layer
607 EXPECT_EQ(InputHandler::ScrollStarted,
608 host_impl_->FlingScrollBegin());
611 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
612 SetupScrollAndContentsLayers(gfx::Size(100, 100));
613 host_impl_->SetViewportSize(gfx::Size(50, 50));
615 LayerImpl* root = host_impl_->active_tree()->root_layer();
617 root->SetShouldScrollOnMainThread(true);
619 // Start scrolling a layer
620 EXPECT_EQ(InputHandler::ScrollOnMainThread,
621 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
623 // The fling should be ignored since there's no layer being scrolled impl-side
624 EXPECT_EQ(InputHandler::ScrollIgnored,
625 host_impl_->FlingScrollBegin());
628 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
629 SetupScrollAndContentsLayers(gfx::Size(100, 100));
630 host_impl_->SetViewportSize(gfx::Size(50, 50));
632 LayerImpl* root = host_impl_->active_tree()->root_layer();
634 root->SetShouldScrollOnMainThread(true);
636 EXPECT_EQ(InputHandler::ScrollOnMainThread,
637 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
638 EXPECT_EQ(InputHandler::ScrollOnMainThread,
639 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
642 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
643 SetupScrollAndContentsLayers(gfx::Size(200, 200));
644 host_impl_->SetViewportSize(gfx::Size(100, 100));
646 LayerImpl* root = host_impl_->active_tree()->root_layer();
647 root->SetContentsScale(2.f, 2.f);
648 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
652 // All scroll types inside the non-fast scrollable region should fail.
653 EXPECT_EQ(InputHandler::ScrollOnMainThread,
654 host_impl_->ScrollBegin(gfx::Point(25, 25),
655 InputHandler::Wheel));
656 EXPECT_EQ(InputHandler::ScrollOnMainThread,
657 host_impl_->ScrollBegin(gfx::Point(25, 25),
658 InputHandler::Gesture));
660 // All scroll types outside this region should succeed.
661 EXPECT_EQ(InputHandler::ScrollStarted,
662 host_impl_->ScrollBegin(gfx::Point(75, 75),
663 InputHandler::Wheel));
664 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
665 host_impl_->ScrollEnd();
666 EXPECT_EQ(InputHandler::ScrollStarted,
667 host_impl_->ScrollBegin(gfx::Point(75, 75),
668 InputHandler::Gesture));
669 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
670 host_impl_->ScrollEnd();
673 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
674 SetupScrollAndContentsLayers(gfx::Size(200, 200));
675 host_impl_->SetViewportSize(gfx::Size(100, 100));
677 LayerImpl* root = host_impl_->active_tree()->root_layer();
678 root->SetContentsScale(2.f, 2.f);
679 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
680 root->SetPosition(gfx::PointF(-25.f, 0.f));
684 // This point would fall into the non-fast scrollable region except that we've
685 // moved the layer down by 25 pixels.
686 EXPECT_EQ(InputHandler::ScrollStarted,
687 host_impl_->ScrollBegin(gfx::Point(40, 10),
688 InputHandler::Wheel));
689 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
690 host_impl_->ScrollEnd();
692 // This point is still inside the non-fast region.
693 EXPECT_EQ(InputHandler::ScrollOnMainThread,
694 host_impl_->ScrollBegin(gfx::Point(10, 10),
695 InputHandler::Wheel));
698 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
699 SetupScrollAndContentsLayers(gfx::Size(200, 200));
700 host_impl_->SetViewportSize(gfx::Size(100, 100));
704 EXPECT_EQ(InputHandler::ScrollStarted,
705 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
707 // Trying to scroll to the left/top will not succeed.
708 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
709 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
710 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
712 // Scrolling to the right/bottom will succeed.
713 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
714 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
715 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
717 // Scrolling to left/top will now succeed.
718 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
719 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
720 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
722 // Scrolling diagonally against an edge will succeed.
723 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
724 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
725 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
727 // Trying to scroll more than the available space will also succeed.
728 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
731 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
732 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
733 host_impl_->SetViewportSize(gfx::Size(100, 1000));
737 EXPECT_EQ(InputHandler::ScrollStarted,
738 host_impl_->ScrollBegin(gfx::Point(),
739 InputHandler::Wheel));
741 // Trying to scroll without a vertical scrollbar will fail.
742 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
743 gfx::Point(), SCROLL_FORWARD));
744 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
745 gfx::Point(), SCROLL_BACKWARD));
747 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
748 PaintedScrollbarLayerImpl::Create(
749 host_impl_->active_tree(),
752 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
753 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
754 vertical_scrollbar.get());
756 // Trying to scroll with a vertical scrollbar will succeed.
757 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
758 gfx::Point(), SCROLL_FORWARD));
759 EXPECT_FLOAT_EQ(875.f,
760 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
761 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
762 gfx::Point(), SCROLL_BACKWARD));
765 // The user-scrollability breaks for zoomed-in pages. So disable this.
766 // http://crbug.com/322223
767 TEST_F(LayerTreeHostImplTest, DISABLED_ScrollWithUserUnscrollableLayers) {
768 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
769 host_impl_->SetViewportSize(gfx::Size(100, 100));
771 gfx::Size overflow_size(400, 400);
772 ASSERT_EQ(1u, scroll_layer->children().size());
773 LayerImpl* overflow = scroll_layer->children()[0];
774 overflow->SetBounds(overflow_size);
775 overflow->SetContentBounds(overflow_size);
776 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
777 overflow->SetScrollOffset(gfx::Vector2d());
778 overflow->SetPosition(gfx::PointF());
779 overflow->SetAnchorPoint(gfx::PointF());
782 gfx::Point scroll_position(10, 10);
784 EXPECT_EQ(InputHandler::ScrollStarted,
785 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
786 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
787 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->TotalScrollOffset());
789 gfx::Vector2dF scroll_delta(10, 10);
790 host_impl_->ScrollBy(scroll_position, scroll_delta);
791 host_impl_->ScrollEnd();
792 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
793 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
795 overflow->set_user_scrollable_horizontal(false);
797 EXPECT_EQ(InputHandler::ScrollStarted,
798 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
799 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
800 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
802 host_impl_->ScrollBy(scroll_position, scroll_delta);
803 host_impl_->ScrollEnd();
804 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
805 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
807 overflow->set_user_scrollable_vertical(false);
809 EXPECT_EQ(InputHandler::ScrollStarted,
810 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
811 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
812 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
814 host_impl_->ScrollBy(scroll_position, scroll_delta);
815 host_impl_->ScrollEnd();
816 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->TotalScrollOffset());
817 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
820 TEST_F(LayerTreeHostImplTest,
821 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
822 SetupScrollAndContentsLayers(gfx::Size(100, 100));
823 host_impl_->SetViewportSize(gfx::Size(50, 50));
826 // We should be able to hit test for touch event handlers even if the root
827 // layer loses its render surface after the most recent render.
828 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
829 host_impl_->active_tree()->set_needs_update_draw_properties();
831 EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
834 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
835 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
836 host_impl_->SetViewportSize(gfx::Size(50, 50));
839 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
840 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
841 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
843 float min_page_scale = 1.f, max_page_scale = 4.f;
844 float page_scale_factor = 1.f;
846 // The impl-based pinch zoom should adjust the max scroll position.
848 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
849 page_scale_factor, min_page_scale, max_page_scale);
850 host_impl_->active_tree()->SetPageScaleDelta(1.f);
851 scroll_layer->SetScrollDelta(gfx::Vector2d());
853 float page_scale_delta = 2.f;
854 gfx::Vector2dF expected_container_size_delta(
855 container_layer->bounds().width(), container_layer->bounds().height());
856 expected_container_size_delta.Scale((1.f - page_scale_delta) /
857 (page_scale_factor * page_scale_delta));
859 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
860 host_impl_->PinchGestureBegin();
861 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
862 // While the gesture is still active, the scroll layer should have a
863 // container size delta = container->bounds() * ((1.f -
864 // page_scale_delta)/())
865 EXPECT_EQ(expected_container_size_delta,
866 scroll_layer->FixedContainerSizeDelta());
867 host_impl_->PinchGestureEnd();
868 host_impl_->ScrollEnd();
869 EXPECT_TRUE(did_request_redraw_);
870 EXPECT_TRUE(did_request_commit_);
871 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
873 scoped_ptr<ScrollAndScaleSet> scroll_info =
874 host_impl_->ProcessScrollDeltas();
875 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
877 EXPECT_EQ(gfx::Vector2d(75, 75).ToString(),
878 scroll_layer->MaxScrollOffset().ToString());
881 // Scrolling after a pinch gesture should always be in local space. The
882 // scroll deltas do not have the page scale factor applied.
884 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
885 page_scale_factor, min_page_scale, max_page_scale);
886 host_impl_->active_tree()->SetPageScaleDelta(1.f);
887 scroll_layer->SetScrollDelta(gfx::Vector2d());
889 float page_scale_delta = 2.f;
890 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
891 host_impl_->PinchGestureBegin();
892 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
893 host_impl_->PinchGestureEnd();
894 host_impl_->ScrollEnd();
896 gfx::Vector2d scroll_delta(0, 10);
897 EXPECT_EQ(InputHandler::ScrollStarted,
898 host_impl_->ScrollBegin(gfx::Point(5, 5),
899 InputHandler::Wheel));
900 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
901 host_impl_->ScrollEnd();
903 scoped_ptr<ScrollAndScaleSet> scroll_info =
904 host_impl_->ProcessScrollDeltas();
905 ExpectContains(*scroll_info.get(),
911 TEST_F(LayerTreeHostImplTest, PinchGesture) {
912 SetupScrollAndContentsLayers(gfx::Size(100, 100));
913 host_impl_->SetViewportSize(gfx::Size(50, 50));
916 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
917 DCHECK(scroll_layer);
919 float min_page_scale = 1.f;
920 float max_page_scale = 4.f;
922 // Basic pinch zoom in gesture
924 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
927 scroll_layer->SetScrollDelta(gfx::Vector2d());
929 float page_scale_delta = 2.f;
930 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
931 host_impl_->PinchGestureBegin();
932 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
933 host_impl_->PinchGestureEnd();
934 host_impl_->ScrollEnd();
935 EXPECT_TRUE(did_request_redraw_);
936 EXPECT_TRUE(did_request_commit_);
938 scoped_ptr<ScrollAndScaleSet> scroll_info =
939 host_impl_->ProcessScrollDeltas();
940 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
945 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
948 scroll_layer->SetScrollDelta(gfx::Vector2d());
949 float page_scale_delta = 10.f;
951 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
952 host_impl_->PinchGestureBegin();
953 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
954 host_impl_->PinchGestureEnd();
955 host_impl_->ScrollEnd();
957 scoped_ptr<ScrollAndScaleSet> scroll_info =
958 host_impl_->ProcessScrollDeltas();
959 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
964 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
967 scroll_layer->SetScrollDelta(gfx::Vector2d());
968 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
970 float page_scale_delta = 0.1f;
971 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
972 host_impl_->PinchGestureBegin();
973 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
974 host_impl_->PinchGestureEnd();
975 host_impl_->ScrollEnd();
977 scoped_ptr<ScrollAndScaleSet> scroll_info =
978 host_impl_->ProcessScrollDeltas();
979 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
981 EXPECT_TRUE(scroll_info->scrolls.empty());
984 // Two-finger panning should not happen based on pinch events only
986 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
989 scroll_layer->SetScrollDelta(gfx::Vector2d());
990 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
992 float page_scale_delta = 1.f;
993 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
994 host_impl_->PinchGestureBegin();
995 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
996 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
997 host_impl_->PinchGestureEnd();
998 host_impl_->ScrollEnd();
1000 scoped_ptr<ScrollAndScaleSet> scroll_info =
1001 host_impl_->ProcessScrollDeltas();
1002 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1003 EXPECT_TRUE(scroll_info->scrolls.empty());
1006 // Two-finger panning should work with interleaved scroll events
1008 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1011 scroll_layer->SetScrollDelta(gfx::Vector2d());
1012 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1014 float page_scale_delta = 1.f;
1015 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1016 host_impl_->PinchGestureBegin();
1017 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1018 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1019 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1020 host_impl_->PinchGestureEnd();
1021 host_impl_->ScrollEnd();
1023 scoped_ptr<ScrollAndScaleSet> scroll_info =
1024 host_impl_->ProcessScrollDeltas();
1025 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1026 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1029 // Two-finger panning should work when starting fully zoomed out.
1031 host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
1034 scroll_layer->SetScrollDelta(gfx::Vector2d());
1035 scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
1037 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
1038 host_impl_->PinchGestureBegin();
1039 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1040 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1041 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1042 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1043 host_impl_->PinchGestureEnd();
1044 host_impl_->ScrollEnd();
1046 scoped_ptr<ScrollAndScaleSet> scroll_info =
1047 host_impl_->ProcessScrollDeltas();
1048 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1049 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1053 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1054 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1055 host_impl_->SetViewportSize(gfx::Size(50, 50));
1058 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1059 DCHECK(scroll_layer);
1061 float min_page_scale = 0.5f;
1062 float max_page_scale = 4.f;
1063 base::TimeTicks start_time = base::TimeTicks() +
1064 base::TimeDelta::FromSeconds(1);
1065 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1066 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1067 base::TimeTicks end_time = start_time + duration;
1069 // Non-anchor zoom-in
1071 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1074 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1076 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), false, 2.f, duration);
1077 did_request_redraw_ = false;
1078 host_impl_->Animate(start_time, base::Time());
1079 EXPECT_TRUE(did_request_redraw_);
1081 did_request_redraw_ = false;
1082 host_impl_->Animate(halfway_through_animation, base::Time());
1083 EXPECT_TRUE(did_request_redraw_);
1085 did_request_redraw_ = false;
1086 did_request_commit_ = false;
1087 host_impl_->Animate(end_time, base::Time());
1088 EXPECT_TRUE(did_request_commit_);
1090 scoped_ptr<ScrollAndScaleSet> scroll_info =
1091 host_impl_->ProcessScrollDeltas();
1092 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1093 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1098 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1101 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1103 host_impl_->StartPageScaleAnimation(
1104 gfx::Vector2d(25, 25), true, min_page_scale, duration);
1105 did_request_redraw_ = false;
1106 host_impl_->Animate(start_time, base::Time());
1107 EXPECT_TRUE(did_request_redraw_);
1109 did_request_redraw_ = false;
1110 did_request_commit_ = false;
1111 host_impl_->Animate(end_time, base::Time());
1112 EXPECT_TRUE(did_request_redraw_);
1113 EXPECT_TRUE(did_request_commit_);
1115 scoped_ptr<ScrollAndScaleSet> scroll_info =
1116 host_impl_->ProcessScrollDeltas();
1117 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1118 // Pushed to (0,0) via clamping against contents layer size.
1119 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1123 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1124 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1125 host_impl_->SetViewportSize(gfx::Size(50, 50));
1128 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1129 DCHECK(scroll_layer);
1131 float min_page_scale = 0.5f;
1132 float max_page_scale = 4.f;
1133 base::TimeTicks start_time = base::TimeTicks() +
1134 base::TimeDelta::FromSeconds(1);
1135 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1136 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1137 base::TimeTicks end_time = start_time + duration;
1139 // Anchor zoom with unchanged page scale should not change scroll or scale.
1141 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1144 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1146 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), true, 1.f, duration);
1147 host_impl_->Animate(start_time, base::Time());
1148 host_impl_->Animate(halfway_through_animation, base::Time());
1149 EXPECT_TRUE(did_request_redraw_);
1150 host_impl_->Animate(end_time, base::Time());
1151 EXPECT_TRUE(did_request_commit_);
1153 scoped_ptr<ScrollAndScaleSet> scroll_info =
1154 host_impl_->ProcessScrollDeltas();
1155 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1156 ExpectNone(*scroll_info, scroll_layer->id());
1160 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1162 LayerTreeHostImplOverridePhysicalTime(
1163 const LayerTreeSettings& settings,
1164 LayerTreeHostImplClient* client,
1166 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1167 : LayerTreeHostImpl(settings,
1170 rendering_stats_instrumentation,
1174 virtual base::TimeTicks CurrentPhysicalTimeTicks() const OVERRIDE {
1175 return fake_current_physical_time_;
1178 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1179 fake_current_physical_time_ = fake_now;
1183 base::TimeTicks fake_current_physical_time_;
1186 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1187 LayerTreeSettings settings;
1188 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1189 settings.scrollbar_linear_fade_delay_ms = 20;
1190 settings.scrollbar_linear_fade_length_ms = 20;
1192 gfx::Size viewport_size(10, 10);
1193 gfx::Size content_size(100, 100);
1195 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
1196 new LayerTreeHostImplOverridePhysicalTime(
1197 settings, this, &proxy_, &stats_instrumentation_);
1198 host_impl_ = make_scoped_ptr(host_impl_override_time);
1199 host_impl_->InitializeRenderer(CreateOutputSurface());
1200 host_impl_->SetViewportSize(viewport_size);
1202 scoped_ptr<LayerImpl> root =
1203 LayerImpl::Create(host_impl_->active_tree(), 1);
1204 root->SetBounds(viewport_size);
1206 scoped_ptr<LayerImpl> scroll =
1207 LayerImpl::Create(host_impl_->active_tree(), 2);
1208 scroll->SetScrollClipLayer(root->id());
1209 scroll->SetScrollOffset(gfx::Vector2d());
1210 root->SetBounds(viewport_size);
1211 scroll->SetBounds(content_size);
1212 scroll->SetContentBounds(content_size);
1213 scroll->SetIsContainerForFixedPositionLayers(true);
1215 scoped_ptr<LayerImpl> contents =
1216 LayerImpl::Create(host_impl_->active_tree(), 3);
1217 contents->SetDrawsContent(true);
1218 contents->SetBounds(content_size);
1219 contents->SetContentBounds(content_size);
1221 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1222 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 4, VERTICAL);
1223 scrollbar->SetScrollLayerById(2);
1224 scrollbar->SetClipLayerById(1);
1226 scroll->AddChild(contents.Pass());
1227 root->AddChild(scroll.Pass());
1228 root->AddChild(scrollbar.PassAs<LayerImpl>());
1230 host_impl_->active_tree()->SetRootLayer(root.Pass());
1231 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
1232 host_impl_->active_tree()->DidBecomeActive();
1235 base::TimeTicks fake_now = gfx::FrameTime::Now();
1236 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1238 // If no scroll happened recently, StartScrollbarAnimation should have no
1240 host_impl_->StartScrollbarAnimation();
1241 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1242 EXPECT_FALSE(did_request_redraw_);
1244 // If no scroll happened during a scroll gesture, StartScrollbarAnimation
1245 // should have no effect.
1246 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1247 host_impl_->ScrollEnd();
1248 host_impl_->StartScrollbarAnimation();
1249 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1250 EXPECT_FALSE(did_request_redraw_);
1252 // After a scroll, a fade animation should be scheduled about 20ms from now.
1253 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1254 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1255 host_impl_->ScrollEnd();
1256 did_request_redraw_ = false;
1257 host_impl_->StartScrollbarAnimation();
1258 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1259 requested_scrollbar_animation_delay_);
1260 EXPECT_FALSE(did_request_redraw_);
1261 requested_scrollbar_animation_delay_ = base::TimeDelta();
1263 // After the fade begins, we should start getting redraws instead of a
1264 // scheduled animation.
1265 fake_now += base::TimeDelta::FromMilliseconds(25);
1266 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1267 host_impl_->StartScrollbarAnimation();
1268 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1269 EXPECT_TRUE(did_request_redraw_);
1270 did_request_redraw_ = false;
1272 // If no scroll happened recently, StartScrollbarAnimation should have no
1274 fake_now += base::TimeDelta::FromMilliseconds(25);
1275 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1276 host_impl_->StartScrollbarAnimation();
1277 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1278 EXPECT_FALSE(did_request_redraw_);
1280 // Setting the scroll offset outside a scroll should also cause the scrollbar
1281 // to appear and to schedule a fade.
1282 host_impl_->InnerViewportScrollLayer()->SetScrollOffset(gfx::Vector2d(5, 5));
1283 host_impl_->StartScrollbarAnimation();
1284 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1285 requested_scrollbar_animation_delay_);
1286 EXPECT_FALSE(did_request_redraw_);
1287 requested_scrollbar_animation_delay_ = base::TimeDelta();
1289 // None of the above should have called CurrentFrameTimeTicks, so if we call
1290 // it now we should get the current time.
1291 fake_now += base::TimeDelta::FromMilliseconds(10);
1292 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1293 EXPECT_EQ(fake_now, host_impl_->CurrentFrameTimeTicks());
1296 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1297 float device_scale_factor) {
1298 LayerTreeSettings settings;
1299 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1301 gfx::Size viewport_size(300, 200);
1302 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1303 gfx::ScaleSize(viewport_size, device_scale_factor));
1304 gfx::Size content_size(1000, 1000);
1306 CreateHostImpl(settings, CreateOutputSurface());
1307 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1308 host_impl_->SetViewportSize(device_viewport_size);
1310 scoped_ptr<LayerImpl> root =
1311 LayerImpl::Create(host_impl_->active_tree(), 1);
1312 root->SetBounds(viewport_size);
1314 scoped_ptr<LayerImpl> scroll =
1315 LayerImpl::Create(host_impl_->active_tree(), 2);
1316 scroll->SetScrollClipLayer(root->id());
1317 scroll->SetScrollOffset(gfx::Vector2d());
1318 scroll->SetBounds(content_size);
1319 scroll->SetContentBounds(content_size);
1320 scroll->SetIsContainerForFixedPositionLayers(true);
1322 scoped_ptr<LayerImpl> contents =
1323 LayerImpl::Create(host_impl_->active_tree(), 3);
1324 contents->SetDrawsContent(true);
1325 contents->SetBounds(content_size);
1326 contents->SetContentBounds(content_size);
1328 // The scrollbar is on the right side.
1329 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1330 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1331 scrollbar->SetDrawsContent(true);
1332 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1333 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1334 scrollbar->SetPosition(gfx::Point(285, 0));
1335 scrollbar->SetScrollLayerById(2);
1337 scroll->AddChild(contents.Pass());
1338 root->AddChild(scroll.Pass());
1339 root->AddChild(scrollbar.PassAs<LayerImpl>());
1341 host_impl_->active_tree()->SetRootLayer(root.Pass());
1342 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
1343 host_impl_->active_tree()->DidBecomeActive();
1346 LayerImpl* root_scroll =
1347 host_impl_->active_tree()->InnerViewportScrollLayer();
1348 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1349 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1350 static_cast<ScrollbarAnimationControllerThinning*>(
1351 root_scroll->scrollbar_animation_controller());
1352 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1354 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1355 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1357 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1358 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1360 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1361 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1363 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1364 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1365 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1367 did_request_redraw_ = false;
1368 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1369 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1370 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1371 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1372 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1373 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1374 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1377 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1378 SetupMouseMoveAtWithDeviceScale(1.f);
1381 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1382 SetupMouseMoveAtWithDeviceScale(2.f);
1385 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1386 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1387 host_impl_->SetViewportSize(gfx::Size(50, 50));
1388 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
1391 CompositorFrameMetadata metadata =
1392 host_impl_->MakeCompositorFrameMetadata();
1393 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1394 EXPECT_EQ(1.f, metadata.page_scale_factor);
1395 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.viewport_size);
1396 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1397 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1398 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1401 // Scrolling should update metadata immediately.
1402 EXPECT_EQ(InputHandler::ScrollStarted,
1403 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1404 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1406 CompositorFrameMetadata metadata =
1407 host_impl_->MakeCompositorFrameMetadata();
1408 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1410 host_impl_->ScrollEnd();
1412 CompositorFrameMetadata metadata =
1413 host_impl_->MakeCompositorFrameMetadata();
1414 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1417 // Page scale should update metadata correctly (shrinking only the viewport).
1418 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1419 host_impl_->PinchGestureBegin();
1420 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1421 host_impl_->PinchGestureEnd();
1422 host_impl_->ScrollEnd();
1424 CompositorFrameMetadata metadata =
1425 host_impl_->MakeCompositorFrameMetadata();
1426 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1427 EXPECT_EQ(2.f, metadata.page_scale_factor);
1428 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.viewport_size);
1429 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1430 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1431 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1434 // Likewise if set from the main thread.
1435 host_impl_->ProcessScrollDeltas();
1436 host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
1437 host_impl_->active_tree()->SetPageScaleDelta(1.f);
1439 CompositorFrameMetadata metadata =
1440 host_impl_->MakeCompositorFrameMetadata();
1441 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1442 EXPECT_EQ(4.f, metadata.page_scale_factor);
1443 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.viewport_size);
1444 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1445 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1446 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1450 // TODO(enne): Convert this to PictureLayerImpl
1451 class DidDrawCheckLayer : public TiledLayerImpl {
1453 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1454 return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(tree_impl, id));
1457 virtual bool WillDraw(DrawMode draw_mode, ResourceProvider* provider)
1459 will_draw_called_ = true;
1460 if (will_draw_returns_false_)
1462 return TiledLayerImpl::WillDraw(draw_mode, provider);
1465 virtual void AppendQuads(QuadSink* quad_sink,
1466 AppendQuadsData* append_quads_data) OVERRIDE {
1467 append_quads_called_ = true;
1468 TiledLayerImpl::AppendQuads(quad_sink, append_quads_data);
1471 virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
1472 did_draw_called_ = true;
1473 TiledLayerImpl::DidDraw(provider);
1476 bool will_draw_called() const { return will_draw_called_; }
1477 bool append_quads_called() const { return append_quads_called_; }
1478 bool did_draw_called() const { return did_draw_called_; }
1480 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1482 void ClearDidDrawCheck() {
1483 will_draw_called_ = false;
1484 append_quads_called_ = false;
1485 did_draw_called_ = false;
1489 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1490 : TiledLayerImpl(tree_impl, id),
1491 will_draw_returns_false_(false),
1492 will_draw_called_(false),
1493 append_quads_called_(false),
1494 did_draw_called_(false) {
1495 SetAnchorPoint(gfx::PointF());
1496 SetBounds(gfx::Size(10, 10));
1497 SetContentBounds(gfx::Size(10, 10));
1498 SetDrawsContent(true);
1499 set_skips_draw(false);
1500 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1502 scoped_ptr<LayerTilingData> tiler =
1503 LayerTilingData::Create(gfx::Size(100, 100),
1504 LayerTilingData::HAS_BORDER_TEXELS);
1505 tiler->SetBounds(content_bounds());
1506 SetTilingData(*tiler.get());
1510 bool will_draw_returns_false_;
1511 bool will_draw_called_;
1512 bool append_quads_called_;
1513 bool did_draw_called_;
1516 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1517 // The root layer is always drawn, so run this test on a child layer that
1518 // will be masked out by the root layer's bounds.
1519 host_impl_->active_tree()->SetRootLayer(
1520 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1521 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1522 host_impl_->active_tree()->root_layer());
1524 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1525 DidDrawCheckLayer* layer =
1526 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1529 LayerTreeHostImpl::FrameData frame;
1530 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1531 host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
1532 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1533 host_impl_->DidDrawAllLayers(frame);
1535 EXPECT_TRUE(layer->will_draw_called());
1536 EXPECT_TRUE(layer->append_quads_called());
1537 EXPECT_TRUE(layer->did_draw_called());
1541 LayerTreeHostImpl::FrameData frame;
1543 layer->set_will_draw_returns_false();
1544 layer->ClearDidDrawCheck();
1546 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1547 host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
1548 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1549 host_impl_->DidDrawAllLayers(frame);
1551 EXPECT_TRUE(layer->will_draw_called());
1552 EXPECT_FALSE(layer->append_quads_called());
1553 EXPECT_FALSE(layer->did_draw_called());
1557 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1558 // The root layer is always drawn, so run this test on a child layer that
1559 // will be masked out by the root layer's bounds.
1560 host_impl_->active_tree()->SetRootLayer(
1561 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1562 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1563 host_impl_->active_tree()->root_layer());
1564 root->SetMasksToBounds(true);
1566 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1567 DidDrawCheckLayer* layer =
1568 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1569 // Ensure visible_content_rect for layer is empty.
1570 layer->SetPosition(gfx::PointF(100.f, 100.f));
1571 layer->SetBounds(gfx::Size(10, 10));
1572 layer->SetContentBounds(gfx::Size(10, 10));
1574 LayerTreeHostImpl::FrameData frame;
1576 EXPECT_FALSE(layer->will_draw_called());
1577 EXPECT_FALSE(layer->did_draw_called());
1579 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1580 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1581 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1582 host_impl_->DidDrawAllLayers(frame);
1584 EXPECT_FALSE(layer->will_draw_called());
1585 EXPECT_FALSE(layer->did_draw_called());
1587 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1589 // Ensure visible_content_rect for layer is not empty
1590 layer->SetPosition(gfx::PointF());
1592 EXPECT_FALSE(layer->will_draw_called());
1593 EXPECT_FALSE(layer->did_draw_called());
1595 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1596 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1597 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1598 host_impl_->DidDrawAllLayers(frame);
1600 EXPECT_TRUE(layer->will_draw_called());
1601 EXPECT_TRUE(layer->did_draw_called());
1603 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1606 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1607 gfx::Size big_size(1000, 1000);
1608 host_impl_->SetViewportSize(big_size);
1610 host_impl_->active_tree()->SetRootLayer(
1611 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1612 DidDrawCheckLayer* root =
1613 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1615 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1616 DidDrawCheckLayer* occluded_layer =
1617 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1619 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1620 DidDrawCheckLayer* top_layer =
1621 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1622 // This layer covers the occluded_layer above. Make this layer large so it can
1624 top_layer->SetBounds(big_size);
1625 top_layer->SetContentBounds(big_size);
1626 top_layer->SetContentsOpaque(true);
1628 LayerTreeHostImpl::FrameData frame;
1630 EXPECT_FALSE(occluded_layer->will_draw_called());
1631 EXPECT_FALSE(occluded_layer->did_draw_called());
1632 EXPECT_FALSE(top_layer->will_draw_called());
1633 EXPECT_FALSE(top_layer->did_draw_called());
1635 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1636 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1637 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1638 host_impl_->DidDrawAllLayers(frame);
1640 EXPECT_FALSE(occluded_layer->will_draw_called());
1641 EXPECT_FALSE(occluded_layer->did_draw_called());
1642 EXPECT_TRUE(top_layer->will_draw_called());
1643 EXPECT_TRUE(top_layer->did_draw_called());
1646 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1647 host_impl_->active_tree()->SetRootLayer(
1648 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1649 DidDrawCheckLayer* root =
1650 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1652 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1653 DidDrawCheckLayer* layer1 =
1654 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1656 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1657 DidDrawCheckLayer* layer2 =
1658 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1660 layer1->SetOpacity(0.3f);
1661 layer1->SetShouldFlattenTransform(true);
1663 EXPECT_FALSE(root->did_draw_called());
1664 EXPECT_FALSE(layer1->did_draw_called());
1665 EXPECT_FALSE(layer2->did_draw_called());
1667 LayerTreeHostImpl::FrameData frame;
1668 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1669 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1670 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1671 host_impl_->DidDrawAllLayers(frame);
1673 EXPECT_TRUE(root->did_draw_called());
1674 EXPECT_TRUE(layer1->did_draw_called());
1675 EXPECT_TRUE(layer2->did_draw_called());
1677 EXPECT_NE(root->render_surface(), layer1->render_surface());
1678 EXPECT_TRUE(!!layer1->render_surface());
1681 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1683 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1688 ResourceProvider* resource_provider) {
1689 return scoped_ptr<LayerImpl>(new MissingTextureAnimatingLayer(
1695 resource_provider));
1698 virtual void AppendQuads(QuadSink* quad_sink,
1699 AppendQuadsData* append_quads_data) OVERRIDE {
1700 TiledLayerImpl::AppendQuads(quad_sink, append_quads_data);
1702 append_quads_data->had_incomplete_tile = true;
1706 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1711 ResourceProvider* resource_provider)
1712 : DidDrawCheckLayer(tree_impl, id), tile_missing_(tile_missing) {
1713 scoped_ptr<LayerTilingData> tiling_data =
1714 LayerTilingData::Create(gfx::Size(10, 10),
1715 LayerTilingData::NO_BORDER_TEXELS);
1716 tiling_data->SetBounds(bounds());
1717 SetTilingData(*tiling_data.get());
1718 set_skips_draw(skips_draw);
1719 if (!tile_missing) {
1720 ResourceProvider::ResourceId resource =
1721 resource_provider->CreateResource(gfx::Size(1, 1),
1723 ResourceProvider::TextureUsageAny,
1725 resource_provider->AllocateForTesting(resource);
1726 PushTileProperties(0, 0, resource, gfx::Rect(), false);
1729 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1735 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenNoTexturesMissing) {
1736 host_impl_->active_tree()->SetRootLayer(
1737 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1738 DidDrawCheckLayer* root =
1739 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1741 bool tile_missing = false;
1742 bool skips_draw = false;
1743 bool is_animating = false;
1745 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1750 host_impl_->resource_provider()));
1752 LayerTreeHostImpl::FrameData frame;
1754 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1755 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1756 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1757 host_impl_->DidDrawAllLayers(frame);
1760 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) {
1761 host_impl_->active_tree()->SetRootLayer(
1762 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1763 DidDrawCheckLayer* root =
1764 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1765 bool tile_missing = false;
1766 bool skips_draw = false;
1767 bool is_animating = true;
1769 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1774 host_impl_->resource_provider()));
1776 LayerTreeHostImpl::FrameData frame;
1778 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1779 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1780 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1781 host_impl_->DidDrawAllLayers(frame);
1784 TEST_F(LayerTreeHostImplTest,
1785 PrepareToDrawSucceedsWithNonAnimatedMissingTexture) {
1786 // When a texture is missing and we're not animating, we draw as usual with
1788 host_impl_->active_tree()->SetRootLayer(
1789 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1790 DidDrawCheckLayer* root =
1791 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1793 bool tile_missing = true;
1794 bool skips_draw = false;
1795 bool is_animating = false;
1797 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1802 host_impl_->resource_provider()));
1803 LayerTreeHostImpl::FrameData frame;
1804 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
1805 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1806 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1807 host_impl_->DidDrawAllLayers(frame);
1810 TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
1811 // When a texture is missing and we're animating, we don't want to draw
1813 host_impl_->active_tree()->SetRootLayer(
1814 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
1815 DidDrawCheckLayer* root =
1816 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1817 bool tile_missing = true;
1818 bool skips_draw = false;
1819 bool is_animating = true;
1821 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1826 host_impl_->resource_provider()));
1827 LayerTreeHostImpl::FrameData frame;
1828 EXPECT_EQ(DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS,
1829 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1830 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1831 host_impl_->DidDrawAllLayers(frame);
1834 TEST_F(LayerTreeHostImplTest,
1835 PrepareToDrawSucceedsWithMissingSkippedAnimatedLayer) {
1836 // When the layer skips draw and we're animating, we still draw the frame.
1837 host_impl_->active_tree()->SetRootLayer(
1838 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
1839 DidDrawCheckLayer* root =
1840 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1841 bool tile_missing = false;
1842 bool skips_draw = true;
1843 bool is_animating = true;
1845 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1850 host_impl_->resource_provider()));
1851 LayerTreeHostImpl::FrameData frame;
1852 EXPECT_EQ(host_impl_->PrepareToDraw(&frame, gfx::Rect()),
1853 DrawSwapReadbackResult::DRAW_SUCCESS);
1854 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1855 host_impl_->DidDrawAllLayers(frame);
1858 TEST_F(LayerTreeHostImplTest,
1859 PrepareToDrawSucceedsWhenHighResRequiredButNoMissingTextures) {
1860 // When the layer skips draw and we're animating, we still draw the frame.
1861 host_impl_->active_tree()->SetRootLayer(
1862 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
1863 DidDrawCheckLayer* root =
1864 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1865 bool tile_missing = false;
1866 bool skips_draw = false;
1867 bool is_animating = false;
1869 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1874 host_impl_->resource_provider()));
1875 host_impl_->active_tree()->SetRequiresHighResToDraw();
1876 LayerTreeHostImpl::FrameData frame;
1877 EXPECT_EQ(host_impl_->PrepareToDraw(&frame, gfx::Rect()),
1878 DrawSwapReadbackResult::DRAW_SUCCESS);
1879 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1880 host_impl_->DidDrawAllLayers(frame);
1883 TEST_F(LayerTreeHostImplTest,
1884 PrepareToDrawFailsWhenHighResRequiredAndMissingTextures) {
1885 // When the layer skips draw and we're animating, we still draw the frame.
1886 host_impl_->active_tree()->SetRootLayer(
1887 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
1888 DidDrawCheckLayer* root =
1889 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1890 bool tile_missing = true;
1891 bool skips_draw = false;
1892 bool is_animating = false;
1894 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1899 host_impl_->resource_provider()));
1900 host_impl_->active_tree()->SetRequiresHighResToDraw();
1901 LayerTreeHostImpl::FrameData frame;
1902 EXPECT_EQ(host_impl_->PrepareToDraw(&frame, gfx::Rect()),
1903 DrawSwapReadbackResult::DRAW_ABORTED_MISSING_HIGH_RES_CONTENT);
1904 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1905 host_impl_->DidDrawAllLayers(frame);
1908 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
1909 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1910 root->SetScrollClipLayer(Layer::INVALID_ID);
1911 host_impl_->active_tree()->SetRootLayer(root.Pass());
1914 // Scroll event is ignored because layer is not scrollable.
1915 EXPECT_EQ(InputHandler::ScrollIgnored,
1916 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1917 EXPECT_FALSE(did_request_redraw_);
1918 EXPECT_FALSE(did_request_commit_);
1921 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
1923 LayerTreeHostImplTopControlsTest()
1924 // Make the clip size the same as the layer (content) size so the layer is
1926 : layer_size_(10, 10),
1927 clip_size_(layer_size_) {
1928 settings_.calculate_top_controls_position = true;
1929 settings_.top_controls_height = 50;
1932 gfx::Size(clip_size_.width(),
1933 clip_size_.height() + settings_.top_controls_height);
1936 void SetupTopControlsAndScrollLayer() {
1937 CreateHostImpl(settings_, CreateOutputSurface());
1939 scoped_ptr<LayerImpl> root =
1940 LayerImpl::Create(host_impl_->active_tree(), 1);
1941 scoped_ptr<LayerImpl> root_clip =
1942 LayerImpl::Create(host_impl_->active_tree(), 2);
1943 root_clip->SetBounds(clip_size_);
1944 root->SetScrollClipLayer(root_clip->id());
1945 root->SetBounds(layer_size_);
1946 root->SetContentBounds(layer_size_);
1947 root->SetPosition(gfx::PointF());
1948 root->SetAnchorPoint(gfx::PointF());
1949 root->SetDrawsContent(false);
1950 root->SetIsContainerForFixedPositionLayers(true);
1951 int inner_viewport_scroll_layer_id = root->id();
1952 int page_scale_layer_id = root_clip->id();
1953 root_clip->AddChild(root.Pass());
1954 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
1955 host_impl_->active_tree()->SetViewportLayersFromIds(
1956 page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
1957 // Set a viewport size that is large enough to contain both the top controls
1958 // and some content.
1959 host_impl_->SetViewportSize(viewport_size_);
1960 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
1961 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
1965 gfx::Size layer_size_;
1966 gfx::Size clip_size_;
1967 gfx::Size viewport_size_;
1969 LayerTreeSettings settings_;
1970 }; // class LayerTreeHostImplTopControlsTest
1972 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
1973 SetupTopControlsAndScrollLayer();
1976 EXPECT_EQ(InputHandler::ScrollStarted,
1977 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
1979 // Make the test scroll delta a fractional amount, to verify that the
1980 // fixed container size delta is (1) non-zero, and (2) fractional, and
1981 // (3) matches the movement of the top controls.
1982 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
1983 host_impl_->top_controls_manager()->ScrollBegin();
1984 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
1985 host_impl_->top_controls_manager()->ScrollEnd();
1987 LayerImpl* inner_viewport_scroll_layer =
1988 host_impl_->active_tree()->InnerViewportScrollLayer();
1989 DCHECK(inner_viewport_scroll_layer);
1990 host_impl_->ScrollEnd();
1991 EXPECT_EQ(top_controls_scroll_delta,
1992 inner_viewport_scroll_layer->FixedContainerSizeDelta());
1995 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsWithPageScale) {
1996 SetupTopControlsAndScrollLayer();
1999 EXPECT_EQ(InputHandler::ScrollStarted,
2000 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2002 float page_scale = 1.5f;
2003 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale, 1.f, 2.f);
2005 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.f);
2006 gfx::Vector2dF expected_container_size_delta =
2007 ScaleVector2d(top_controls_scroll_delta, 1.f / page_scale);
2008 host_impl_->top_controls_manager()->ScrollBegin();
2009 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2010 host_impl_->top_controls_manager()->ScrollEnd();
2012 LayerImpl* inner_viewport_scroll_layer =
2013 host_impl_->active_tree()->InnerViewportScrollLayer();
2014 DCHECK(inner_viewport_scroll_layer);
2015 host_impl_->ScrollEnd();
2017 // Use a tolerance that requires the container size delta to be within 0.01
2019 double tolerance = 0.0001;
2021 (expected_container_size_delta -
2022 inner_viewport_scroll_layer->FixedContainerSizeDelta()).LengthSquared(),
2026 TEST_F(LayerTreeHostImplTopControlsTest,
2027 ScrollNonScrollableRootWithTopControls) {
2028 SetupTopControlsAndScrollLayer();
2031 EXPECT_EQ(InputHandler::ScrollStarted,
2032 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2034 host_impl_->top_controls_manager()->ScrollBegin();
2035 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
2036 host_impl_->top_controls_manager()->ScrollEnd();
2037 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->content_top_offset());
2038 // Now that top controls have moved, expect the clip to resize.
2039 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2040 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2042 host_impl_->ScrollEnd();
2044 EXPECT_EQ(InputHandler::ScrollStarted,
2045 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2047 float scroll_increment_y = -25.f;
2048 host_impl_->top_controls_manager()->ScrollBegin();
2049 host_impl_->top_controls_manager()->ScrollBy(
2050 gfx::Vector2dF(0.f, scroll_increment_y));
2051 EXPECT_EQ(-scroll_increment_y,
2052 host_impl_->top_controls_manager()->content_top_offset());
2053 // Now that top controls have moved, expect the clip to resize.
2054 EXPECT_EQ(gfx::Size(viewport_size_.width(),
2055 viewport_size_.height() + scroll_increment_y),
2056 root_clip_ptr->bounds());
2058 host_impl_->top_controls_manager()->ScrollBy(
2059 gfx::Vector2dF(0.f, scroll_increment_y));
2060 host_impl_->top_controls_manager()->ScrollEnd();
2061 EXPECT_EQ(-2 * 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(clip_size_, root_clip_ptr->bounds());
2066 host_impl_->ScrollEnd();
2068 // Verify the layer is once-again non-scrollable.
2071 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
2073 EXPECT_EQ(InputHandler::ScrollStarted,
2074 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2077 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
2078 // Test the configuration where a non-composited root layer is embedded in a
2079 // scrollable outer layer.
2080 gfx::Size surface_size(10, 10);
2081 gfx::Size contents_size(20, 20);
2083 scoped_ptr<LayerImpl> content_layer =
2084 LayerImpl::Create(host_impl_->active_tree(), 1);
2085 content_layer->SetDrawsContent(true);
2086 content_layer->SetPosition(gfx::PointF());
2087 content_layer->SetAnchorPoint(gfx::PointF());
2088 content_layer->SetBounds(contents_size);
2089 content_layer->SetContentBounds(contents_size);
2090 content_layer->SetContentsScale(2.f, 2.f);
2092 scoped_ptr<LayerImpl> scroll_clip_layer =
2093 LayerImpl::Create(host_impl_->active_tree(), 3);
2094 scroll_clip_layer->SetBounds(surface_size);
2096 scoped_ptr<LayerImpl> scroll_layer =
2097 LayerImpl::Create(host_impl_->active_tree(), 2);
2098 scroll_layer->SetScrollClipLayer(3);
2099 scroll_layer->SetBounds(contents_size);
2100 scroll_layer->SetContentBounds(contents_size);
2101 scroll_layer->SetPosition(gfx::PointF());
2102 scroll_layer->SetAnchorPoint(gfx::PointF());
2103 scroll_layer->AddChild(content_layer.Pass());
2104 scroll_clip_layer->AddChild(scroll_layer.Pass());
2106 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
2107 host_impl_->SetViewportSize(surface_size);
2110 EXPECT_EQ(InputHandler::ScrollStarted,
2111 host_impl_->ScrollBegin(gfx::Point(5, 5),
2112 InputHandler::Wheel));
2113 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2114 host_impl_->ScrollEnd();
2115 EXPECT_TRUE(did_request_redraw_);
2116 EXPECT_TRUE(did_request_commit_);
2119 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
2120 gfx::Size surface_size(10, 10);
2121 gfx::Size contents_size(20, 20);
2122 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2123 root->SetBounds(surface_size);
2124 root->SetContentBounds(contents_size);
2125 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
2126 host_impl_->active_tree()->SetRootLayer(root.Pass());
2127 host_impl_->SetViewportSize(surface_size);
2130 EXPECT_EQ(InputHandler::ScrollStarted,
2131 host_impl_->ScrollBegin(gfx::Point(5, 5),
2132 InputHandler::Wheel));
2133 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2134 host_impl_->ScrollEnd();
2135 EXPECT_TRUE(did_request_redraw_);
2136 EXPECT_TRUE(did_request_commit_);
2139 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
2140 gfx::Size surface_size(10, 10);
2141 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2142 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
2143 host_impl_->active_tree()->SetRootLayer(root.Pass());
2144 host_impl_->SetViewportSize(surface_size);
2147 // Scroll event is ignored because the input coordinate is outside the layer
2149 EXPECT_EQ(InputHandler::ScrollIgnored,
2150 host_impl_->ScrollBegin(gfx::Point(15, 5),
2151 InputHandler::Wheel));
2152 EXPECT_FALSE(did_request_redraw_);
2153 EXPECT_FALSE(did_request_commit_);
2156 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
2157 gfx::Size surface_size(10, 10);
2158 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2159 scoped_ptr<LayerImpl> child =
2160 CreateScrollableLayer(2, surface_size, root.get());
2161 host_impl_->SetViewportSize(surface_size);
2163 gfx::Transform matrix;
2164 matrix.RotateAboutXAxis(180.0);
2165 child->SetTransform(matrix);
2166 child->SetDoubleSided(false);
2168 root->AddChild(child.Pass());
2169 host_impl_->active_tree()->SetRootLayer(root.Pass());
2172 // Scroll event is ignored because the scrollable layer is not facing the
2173 // viewer and there is nothing scrollable behind it.
2174 EXPECT_EQ(InputHandler::ScrollIgnored,
2175 host_impl_->ScrollBegin(gfx::Point(5, 5),
2176 InputHandler::Wheel));
2177 EXPECT_FALSE(did_request_redraw_);
2178 EXPECT_FALSE(did_request_commit_);
2181 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
2182 gfx::Size surface_size(10, 10);
2183 scoped_ptr<LayerImpl> clip_layer =
2184 LayerImpl::Create(host_impl_->active_tree(), 3);
2185 scoped_ptr<LayerImpl> content_layer =
2186 CreateScrollableLayer(1, surface_size, clip_layer.get());
2187 content_layer->SetShouldScrollOnMainThread(true);
2188 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
2190 // Note: we can use the same clip layer for both since both calls to
2191 // CreateScrollableLayer() use the same surface size.
2192 scoped_ptr<LayerImpl> scroll_layer =
2193 CreateScrollableLayer(2, surface_size, clip_layer.get());
2194 scroll_layer->AddChild(content_layer.Pass());
2195 clip_layer->AddChild(scroll_layer.Pass());
2197 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
2198 host_impl_->SetViewportSize(surface_size);
2201 // Scrolling fails because the content layer is asking to be scrolled on the
2203 EXPECT_EQ(InputHandler::ScrollOnMainThread,
2204 host_impl_->ScrollBegin(gfx::Point(5, 5),
2205 InputHandler::Wheel));
2208 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
2209 gfx::Size surface_size(20, 20);
2210 gfx::Size viewport_size(10, 10);
2211 float page_scale = 2.f;
2212 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2213 scoped_ptr<LayerImpl> root_clip =
2214 LayerImpl::Create(host_impl_->active_tree(), 2);
2215 scoped_ptr<LayerImpl> root_scrolling =
2216 CreateScrollableLayer(3, surface_size, root_clip.get());
2217 EXPECT_EQ(viewport_size, root_clip->bounds());
2218 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2219 root_clip->AddChild(root_scrolling.Pass());
2220 root->AddChild(root_clip.Pass());
2221 host_impl_->active_tree()->SetRootLayer(root.Pass());
2222 // The behaviour in this test assumes the page scale is applied at a layer
2223 // above the clip layer.
2224 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2225 host_impl_->active_tree()->DidBecomeActive();
2226 host_impl_->SetViewportSize(viewport_size);
2229 LayerImpl* root_scroll =
2230 host_impl_->active_tree()->InnerViewportScrollLayer();
2231 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2233 gfx::Vector2d scroll_delta(0, 10);
2234 gfx::Vector2d expected_scroll_delta = scroll_delta;
2235 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2236 EXPECT_EQ(InputHandler::ScrollStarted,
2237 host_impl_->ScrollBegin(gfx::Point(5, 5),
2238 InputHandler::Wheel));
2239 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2240 host_impl_->ScrollEnd();
2242 // Set new page scale from main thread.
2243 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2247 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2248 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2250 // The scroll range should also have been updated.
2251 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2253 // The page scale delta remains constant because the impl thread did not
2255 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2258 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
2259 gfx::Size surface_size(20, 20);
2260 gfx::Size viewport_size(10, 10);
2261 float page_scale = 2.f;
2262 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2263 scoped_ptr<LayerImpl> root_clip =
2264 LayerImpl::Create(host_impl_->active_tree(), 2);
2265 scoped_ptr<LayerImpl> root_scrolling =
2266 CreateScrollableLayer(3, surface_size, root_clip.get());
2267 EXPECT_EQ(viewport_size, root_clip->bounds());
2268 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2269 root_clip->AddChild(root_scrolling.Pass());
2270 root->AddChild(root_clip.Pass());
2271 host_impl_->active_tree()->SetRootLayer(root.Pass());
2272 // The behaviour in this test assumes the page scale is applied at a layer
2273 // above the clip layer.
2274 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2275 host_impl_->active_tree()->DidBecomeActive();
2276 host_impl_->SetViewportSize(viewport_size);
2277 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
2280 LayerImpl* root_scroll =
2281 host_impl_->active_tree()->InnerViewportScrollLayer();
2282 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2284 gfx::Vector2d scroll_delta(0, 10);
2285 gfx::Vector2d expected_scroll_delta = scroll_delta;
2286 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2287 EXPECT_EQ(InputHandler::ScrollStarted,
2288 host_impl_->ScrollBegin(gfx::Point(5, 5),
2289 InputHandler::Wheel));
2290 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2291 host_impl_->ScrollEnd();
2293 // Set new page scale on impl thread by pinching.
2294 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2295 host_impl_->PinchGestureBegin();
2296 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
2297 host_impl_->PinchGestureEnd();
2298 host_impl_->ScrollEnd();
2301 // The scroll delta is not scaled because the main thread did not scale.
2302 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2303 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2305 // The scroll range should also have been updated.
2306 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2308 // The page scale delta should match the new scale on the impl side.
2309 EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
2312 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
2313 gfx::Size surface_size(10, 10);
2314 float default_page_scale = 1.f;
2315 gfx::Transform default_page_scale_matrix;
2316 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
2318 float new_page_scale = 2.f;
2319 gfx::Transform new_page_scale_matrix;
2320 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
2322 // Create a normal scrollable root layer and another scrollable child layer.
2323 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
2324 LayerImpl* root = host_impl_->active_tree()->root_layer();
2325 LayerImpl* child = scroll->children()[0];
2327 scoped_ptr<LayerImpl> scrollable_child_clip =
2328 LayerImpl::Create(host_impl_->active_tree(), 6);
2329 scoped_ptr<LayerImpl> scrollable_child =
2330 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
2331 scrollable_child_clip->AddChild(scrollable_child.Pass());
2332 child->AddChild(scrollable_child_clip.Pass());
2333 LayerImpl* grand_child = child->children()[0];
2335 // Set new page scale on impl thread by pinching.
2336 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2337 host_impl_->PinchGestureBegin();
2338 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
2339 host_impl_->PinchGestureEnd();
2340 host_impl_->ScrollEnd();
2343 EXPECT_EQ(1.f, root->contents_scale_x());
2344 EXPECT_EQ(1.f, root->contents_scale_y());
2345 EXPECT_EQ(1.f, scroll->contents_scale_x());
2346 EXPECT_EQ(1.f, scroll->contents_scale_y());
2347 EXPECT_EQ(1.f, child->contents_scale_x());
2348 EXPECT_EQ(1.f, child->contents_scale_y());
2349 EXPECT_EQ(1.f, grand_child->contents_scale_x());
2350 EXPECT_EQ(1.f, grand_child->contents_scale_y());
2352 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
2353 // the page scale delta on the root layer is applied hierarchically.
2354 LayerTreeHostImpl::FrameData frame;
2355 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
2356 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2357 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2358 host_impl_->DidDrawAllLayers(frame);
2360 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
2361 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
2362 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
2363 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
2364 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
2365 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
2366 EXPECT_EQ(new_page_scale,
2367 grand_child->draw_transform().matrix().getDouble(0, 0));
2368 EXPECT_EQ(new_page_scale,
2369 grand_child->draw_transform().matrix().getDouble(1, 1));
2372 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
2373 gfx::Size surface_size(30, 30);
2374 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2375 root->SetBounds(gfx::Size(5, 5));
2376 scoped_ptr<LayerImpl> root_scrolling =
2377 LayerImpl::Create(host_impl_->active_tree(), 2);
2378 root_scrolling->SetBounds(surface_size);
2379 root_scrolling->SetContentBounds(surface_size);
2380 root_scrolling->SetScrollClipLayer(root->id());
2381 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2382 LayerImpl* root_scrolling_ptr = root_scrolling.get();
2383 root->AddChild(root_scrolling.Pass());
2384 int child_scroll_layer_id = 3;
2385 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
2386 child_scroll_layer_id, surface_size, root_scrolling_ptr);
2387 LayerImpl* child = child_scrolling.get();
2388 root_scrolling_ptr->AddChild(child_scrolling.Pass());
2389 host_impl_->active_tree()->SetRootLayer(root.Pass());
2390 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2391 host_impl_->active_tree()->DidBecomeActive();
2392 host_impl_->SetViewportSize(surface_size);
2395 gfx::Vector2d scroll_delta(0, 10);
2396 gfx::Vector2d expected_scroll_delta(scroll_delta);
2397 gfx::Vector2d expected_max_scroll(child->MaxScrollOffset());
2398 EXPECT_EQ(InputHandler::ScrollStarted,
2399 host_impl_->ScrollBegin(gfx::Point(5, 5),
2400 InputHandler::Wheel));
2401 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2402 host_impl_->ScrollEnd();
2404 float page_scale = 2.f;
2405 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2411 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2413 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
2415 // The scroll range should not have changed.
2416 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
2418 // The page scale delta remains constant because the impl thread did not
2420 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2423 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
2424 // Scroll a child layer beyond its maximum scroll range and make sure the
2425 // parent layer is scrolled on the axis on which the child was unable to
2427 gfx::Size surface_size(10, 10);
2428 gfx::Size content_size(20, 20);
2429 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2430 root->SetBounds(surface_size);
2432 scoped_ptr<LayerImpl> grand_child =
2433 CreateScrollableLayer(3, content_size, root.get());
2435 scoped_ptr<LayerImpl> child =
2436 CreateScrollableLayer(2, content_size, root.get());
2437 LayerImpl* grand_child_layer = grand_child.get();
2438 child->AddChild(grand_child.Pass());
2440 LayerImpl* child_layer = child.get();
2441 root->AddChild(child.Pass());
2442 host_impl_->active_tree()->SetRootLayer(root.Pass());
2443 host_impl_->active_tree()->DidBecomeActive();
2444 host_impl_->SetViewportSize(surface_size);
2445 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 5));
2446 child_layer->SetScrollOffset(gfx::Vector2d(3, 0));
2450 gfx::Vector2d scroll_delta(-8, -7);
2451 EXPECT_EQ(InputHandler::ScrollStarted,
2452 host_impl_->ScrollBegin(gfx::Point(),
2453 InputHandler::Wheel));
2454 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2455 host_impl_->ScrollEnd();
2457 scoped_ptr<ScrollAndScaleSet> scroll_info =
2458 host_impl_->ProcessScrollDeltas();
2460 // The grand child should have scrolled up to its limit.
2461 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2462 LayerImpl* grand_child = child->children()[0];
2463 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
2465 // The child should have only scrolled on the other axis.
2466 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
2470 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
2471 // Scroll a child layer beyond its maximum scroll range and make sure the
2472 // the scroll doesn't bubble up to the parent layer.
2473 gfx::Size surface_size(20, 20);
2474 gfx::Size viewport_size(10, 10);
2475 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2476 scoped_ptr<LayerImpl> root_scrolling =
2477 CreateScrollableLayer(2, surface_size, root.get());
2478 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2480 scoped_ptr<LayerImpl> grand_child =
2481 CreateScrollableLayer(4, surface_size, root.get());
2483 scoped_ptr<LayerImpl> child =
2484 CreateScrollableLayer(3, surface_size, root.get());
2485 LayerImpl* grand_child_layer = grand_child.get();
2486 child->AddChild(grand_child.Pass());
2488 LayerImpl* child_layer = child.get();
2489 root_scrolling->AddChild(child.Pass());
2490 root->AddChild(root_scrolling.Pass());
2491 EXPECT_EQ(viewport_size, root->bounds());
2492 host_impl_->active_tree()->SetRootLayer(root.Pass());
2493 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2494 host_impl_->active_tree()->DidBecomeActive();
2495 host_impl_->SetViewportSize(viewport_size);
2497 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
2498 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
2502 gfx::Vector2d scroll_delta(0, -10);
2503 EXPECT_EQ(InputHandler::ScrollStarted,
2504 host_impl_->ScrollBegin(gfx::Point(),
2505 InputHandler::NonBubblingGesture));
2506 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2507 host_impl_->ScrollEnd();
2509 scoped_ptr<ScrollAndScaleSet> scroll_info =
2510 host_impl_->ProcessScrollDeltas();
2512 // The grand child should have scrolled up to its limit.
2514 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
2515 LayerImpl* grand_child = child->children()[0];
2516 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2518 // The child should not have scrolled.
2519 ExpectNone(*scroll_info.get(), child->id());
2521 // The next time we scroll we should only scroll the parent.
2522 scroll_delta = gfx::Vector2d(0, -3);
2523 EXPECT_EQ(InputHandler::ScrollStarted,
2524 host_impl_->ScrollBegin(gfx::Point(5, 5),
2525 InputHandler::NonBubblingGesture));
2526 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2527 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2528 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
2529 host_impl_->ScrollEnd();
2531 scroll_info = host_impl_->ProcessScrollDeltas();
2533 // The child should have scrolled up to its limit.
2534 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2536 // The grand child should not have scrolled.
2537 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2539 // After scrolling the parent, another scroll on the opposite direction
2540 // should still scroll the child.
2541 scroll_delta = gfx::Vector2d(0, 7);
2542 EXPECT_EQ(InputHandler::ScrollStarted,
2543 host_impl_->ScrollBegin(gfx::Point(5, 5),
2544 InputHandler::NonBubblingGesture));
2545 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2546 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2547 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2548 host_impl_->ScrollEnd();
2550 scroll_info = host_impl_->ProcessScrollDeltas();
2552 // The grand child should have scrolled.
2553 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
2555 // The child should not have scrolled.
2556 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2559 // Scrolling should be adjusted from viewport space.
2560 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
2561 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2563 scroll_delta = gfx::Vector2d(0, -2);
2564 EXPECT_EQ(InputHandler::ScrollStarted,
2565 host_impl_->ScrollBegin(gfx::Point(1, 1),
2566 InputHandler::NonBubblingGesture));
2567 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
2568 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2569 host_impl_->ScrollEnd();
2571 scroll_info = host_impl_->ProcessScrollDeltas();
2573 // Should have scrolled by half the amount in layer space (5 - 2/2)
2574 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
2577 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
2578 // When we try to scroll a non-scrollable child layer, the scroll delta
2579 // should be applied to one of its ancestors if possible.
2580 gfx::Size surface_size(10, 10);
2581 gfx::Size content_size(20, 20);
2582 scoped_ptr<LayerImpl> root_clip =
2583 LayerImpl::Create(host_impl_->active_tree(), 3);
2584 scoped_ptr<LayerImpl> root =
2585 CreateScrollableLayer(1, content_size, root_clip.get());
2586 // Make 'root' the clip layer for child: since they have the same sizes the
2587 // child will have zero max_scroll_offset and scrolls will bubble.
2588 scoped_ptr<LayerImpl> child =
2589 CreateScrollableLayer(2, content_size, root.get());
2590 child->SetIsContainerForFixedPositionLayers(true);
2591 root->SetBounds(content_size);
2593 int root_scroll_id = root->id();
2594 root->AddChild(child.Pass());
2595 root_clip->AddChild(root.Pass());
2597 host_impl_->SetViewportSize(surface_size);
2598 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2599 host_impl_->active_tree()->SetViewportLayersFromIds(3, 2, Layer::INVALID_ID);
2600 host_impl_->active_tree()->DidBecomeActive();
2603 gfx::Vector2d scroll_delta(0, 4);
2604 EXPECT_EQ(InputHandler::ScrollStarted,
2605 host_impl_->ScrollBegin(gfx::Point(5, 5),
2606 InputHandler::Wheel));
2607 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2608 host_impl_->ScrollEnd();
2610 scoped_ptr<ScrollAndScaleSet> scroll_info =
2611 host_impl_->ProcessScrollDeltas();
2613 // Only the root scroll should have scrolled.
2614 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
2615 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
2619 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
2620 gfx::Size surface_size(10, 10);
2621 scoped_ptr<LayerImpl> root_clip =
2622 LayerImpl::Create(host_impl_->active_tree(), 1);
2623 scoped_ptr<LayerImpl> root_scroll =
2624 CreateScrollableLayer(2, surface_size, root_clip.get());
2625 root_scroll->SetIsContainerForFixedPositionLayers(true);
2626 root_clip->AddChild(root_scroll.Pass());
2627 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2628 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2629 host_impl_->active_tree()->DidBecomeActive();
2630 host_impl_->SetViewportSize(surface_size);
2632 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
2635 host_impl_->active_tree()->DetachLayerTree();
2636 scoped_ptr<LayerImpl> root_clip2 =
2637 LayerImpl::Create(host_impl_->active_tree(), 3);
2638 scoped_ptr<LayerImpl> root_scroll2 =
2639 CreateScrollableLayer(4, surface_size, root_clip2.get());
2640 root_scroll2->SetIsContainerForFixedPositionLayers(true);
2641 root_clip2->AddChild(root_scroll2.Pass());
2642 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
2643 host_impl_->active_tree()->SetViewportLayersFromIds(3, 4, Layer::INVALID_ID);
2644 host_impl_->active_tree()->DidBecomeActive();
2646 // Scrolling should still work even though we did not draw yet.
2647 EXPECT_EQ(InputHandler::ScrollStarted,
2648 host_impl_->ScrollBegin(gfx::Point(5, 5),
2649 InputHandler::Wheel));
2652 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
2653 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2655 // Rotate the root layer 90 degrees counter-clockwise about its center.
2656 gfx::Transform rotate_transform;
2657 rotate_transform.Rotate(-90.0);
2658 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
2660 gfx::Size surface_size(50, 50);
2661 host_impl_->SetViewportSize(surface_size);
2664 // Scroll to the right in screen coordinates with a gesture.
2665 gfx::Vector2d gesture_scroll_delta(10, 0);
2666 EXPECT_EQ(InputHandler::ScrollStarted,
2667 host_impl_->ScrollBegin(gfx::Point(),
2668 InputHandler::Gesture));
2669 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2670 host_impl_->ScrollEnd();
2672 // The layer should have scrolled down in its local coordinates.
2673 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2674 ExpectContains(*scroll_info.get(),
2676 gfx::Vector2d(0, gesture_scroll_delta.x()));
2678 // Reset and scroll down with the wheel.
2679 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2680 gfx::Vector2d wheel_scroll_delta(0, 10);
2681 EXPECT_EQ(InputHandler::ScrollStarted,
2682 host_impl_->ScrollBegin(gfx::Point(),
2683 InputHandler::Wheel));
2684 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2685 host_impl_->ScrollEnd();
2687 // The layer should have scrolled down in its local coordinates.
2688 scroll_info = host_impl_->ProcessScrollDeltas();
2689 ExpectContains(*scroll_info.get(),
2691 wheel_scroll_delta);
2694 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
2695 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2696 int child_clip_layer_id = 6;
2697 int child_layer_id = 7;
2698 float child_layer_angle = -20.f;
2700 // Create a child layer that is rotated to a non-axis-aligned angle.
2701 scoped_ptr<LayerImpl> clip_layer =
2702 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
2703 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
2704 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
2705 gfx::Transform rotate_transform;
2706 rotate_transform.Translate(-50.0, -50.0);
2707 rotate_transform.Rotate(child_layer_angle);
2708 rotate_transform.Translate(50.0, 50.0);
2709 clip_layer->SetTransform(rotate_transform);
2711 // Only allow vertical scrolling.
2712 clip_layer->SetBounds(
2713 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
2714 // The rotation depends on the layer's anchor point, and the child layer is a
2715 // different size than the clip, so make sure the clip layer's anchor lines
2716 // up over the child.
2717 clip_layer->SetAnchorPoint(gfx::PointF(0.5, 1.0));
2718 LayerImpl* child_ptr = child.get();
2719 clip_layer->AddChild(child.Pass());
2720 scroll_layer->AddChild(clip_layer.Pass());
2722 gfx::Size surface_size(50, 50);
2723 host_impl_->SetViewportSize(surface_size);
2726 // Scroll down in screen coordinates with a gesture.
2727 gfx::Vector2d gesture_scroll_delta(0, 10);
2728 EXPECT_EQ(InputHandler::ScrollStarted,
2729 host_impl_->ScrollBegin(gfx::Point(1, 1),
2730 InputHandler::Gesture));
2731 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2732 host_impl_->ScrollEnd();
2734 // The child layer should have scrolled down in its local coordinates an
2735 // amount proportional to the angle between it and the input scroll delta.
2736 gfx::Vector2d expected_scroll_delta(
2738 gesture_scroll_delta.y() *
2739 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
2740 scoped_ptr<ScrollAndScaleSet> scroll_info =
2741 host_impl_->ProcessScrollDeltas();
2742 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2744 // The root scroll layer should not have scrolled, because the input delta
2745 // was close to the layer's axis of movement.
2746 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
2749 // Now reset and scroll the same amount horizontally.
2750 child_ptr->SetScrollDelta(gfx::Vector2dF());
2751 gfx::Vector2d gesture_scroll_delta(10, 0);
2752 EXPECT_EQ(InputHandler::ScrollStarted,
2753 host_impl_->ScrollBegin(gfx::Point(1, 1),
2754 InputHandler::Gesture));
2755 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2756 host_impl_->ScrollEnd();
2758 // The child layer should have scrolled down in its local coordinates an
2759 // amount proportional to the angle between it and the input scroll delta.
2760 gfx::Vector2d expected_scroll_delta(
2762 -gesture_scroll_delta.x() *
2763 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
2764 scoped_ptr<ScrollAndScaleSet> scroll_info =
2765 host_impl_->ProcessScrollDeltas();
2766 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2768 // The root scroll layer should have scrolled more, since the input scroll
2769 // delta was mostly orthogonal to the child layer's vertical scroll axis.
2770 gfx::Vector2d expected_root_scroll_delta(
2771 gesture_scroll_delta.x() *
2772 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
2774 ExpectContains(*scroll_info.get(),
2776 expected_root_scroll_delta);
2780 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
2781 LayerImpl* scroll_layer =
2782 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2784 // Scale the layer to twice its normal size.
2786 gfx::Transform scale_transform;
2787 scale_transform.Scale(scale, scale);
2788 scroll_layer->SetTransform(scale_transform);
2790 gfx::Size surface_size(50, 50);
2791 host_impl_->SetViewportSize(surface_size);
2794 // Scroll down in screen coordinates with a gesture.
2795 gfx::Vector2d scroll_delta(0, 10);
2796 EXPECT_EQ(InputHandler::ScrollStarted,
2797 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2798 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2799 host_impl_->ScrollEnd();
2801 // The layer should have scrolled down in its local coordinates, but half the
2803 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2804 ExpectContains(*scroll_info.get(),
2806 gfx::Vector2d(0, scroll_delta.y() / scale));
2808 // Reset and scroll down with the wheel.
2809 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2810 gfx::Vector2d wheel_scroll_delta(0, 10);
2811 EXPECT_EQ(InputHandler::ScrollStarted,
2812 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2813 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2814 host_impl_->ScrollEnd();
2816 // The scale should not have been applied to the scroll delta.
2817 scroll_info = host_impl_->ProcessScrollDeltas();
2818 ExpectContains(*scroll_info.get(),
2820 wheel_scroll_delta);
2823 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
2825 TestScrollOffsetDelegate()
2826 : page_scale_factor_(0.f),
2827 min_page_scale_factor_(-1.f),
2828 max_page_scale_factor_(-1.f) {}
2830 virtual ~TestScrollOffsetDelegate() {}
2832 virtual void SetMaxScrollOffset(
2833 const gfx::Vector2dF& max_scroll_offset) OVERRIDE {
2834 max_scroll_offset_ = max_scroll_offset;
2837 virtual void SetTotalScrollOffset(const gfx::Vector2dF& new_value) OVERRIDE {
2838 last_set_scroll_offset_ = new_value;
2841 virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
2842 return getter_return_value_;
2845 virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
2847 virtual void SetTotalPageScaleFactorAndLimits(
2848 float page_scale_factor,
2849 float min_page_scale_factor,
2850 float max_page_scale_factor) OVERRIDE {
2851 page_scale_factor_ = page_scale_factor;
2852 min_page_scale_factor_ = min_page_scale_factor;
2853 max_page_scale_factor_ = max_page_scale_factor;
2856 virtual void SetScrollableSize(const gfx::SizeF& scrollable_size) OVERRIDE {
2857 scrollable_size_ = scrollable_size;
2860 gfx::Vector2dF last_set_scroll_offset() {
2861 return last_set_scroll_offset_;
2864 void set_getter_return_value(const gfx::Vector2dF& value) {
2865 getter_return_value_ = value;
2868 gfx::Vector2dF max_scroll_offset() const {
2869 return max_scroll_offset_;
2872 gfx::SizeF scrollable_size() const {
2873 return scrollable_size_;
2876 float page_scale_factor() const {
2877 return page_scale_factor_;
2880 float min_page_scale_factor() const {
2881 return min_page_scale_factor_;
2884 float max_page_scale_factor() const {
2885 return max_page_scale_factor_;
2889 gfx::Vector2dF last_set_scroll_offset_;
2890 gfx::Vector2dF getter_return_value_;
2891 gfx::Vector2dF max_scroll_offset_;
2892 gfx::SizeF scrollable_size_;
2893 float page_scale_factor_;
2894 float min_page_scale_factor_;
2895 float max_page_scale_factor_;
2898 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
2899 TestScrollOffsetDelegate scroll_delegate;
2900 host_impl_->SetViewportSize(gfx::Size(10, 20));
2901 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2902 LayerImpl* clip_layer = scroll_layer->parent()->parent();
2903 clip_layer->SetBounds(gfx::Size(10, 20));
2905 // Setting the delegate results in the current scroll offset being set.
2906 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
2907 scroll_layer->SetScrollOffset(gfx::Vector2d());
2908 scroll_layer->SetScrollDelta(initial_scroll_delta);
2909 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
2910 EXPECT_EQ(initial_scroll_delta.ToString(),
2911 scroll_delegate.last_set_scroll_offset().ToString());
2913 // Setting the delegate results in the scrollable_size, max_scroll_offset,
2914 // page_scale_factor and {min|max}_page_scale_factor being set.
2915 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
2916 EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
2917 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
2918 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
2919 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
2921 // Updating page scale immediately updates the delegate.
2922 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
2923 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
2924 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
2925 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
2926 host_impl_->active_tree()->SetPageScaleDelta(1.5f);
2927 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
2928 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
2929 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
2930 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2931 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
2932 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
2933 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
2934 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
2936 // Scrolling should be relative to the offset as returned by the delegate.
2937 gfx::Vector2dF scroll_delta(0.f, 10.f);
2938 gfx::Vector2dF current_offset(7.f, 8.f);
2940 scroll_delegate.set_getter_return_value(current_offset);
2941 EXPECT_EQ(InputHandler::ScrollStarted,
2942 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2944 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2945 EXPECT_EQ(current_offset + scroll_delta,
2946 scroll_delegate.last_set_scroll_offset());
2948 current_offset = gfx::Vector2dF(42.f, 41.f);
2949 scroll_delegate.set_getter_return_value(current_offset);
2950 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2951 EXPECT_EQ(current_offset + scroll_delta,
2952 scroll_delegate.last_set_scroll_offset());
2953 host_impl_->ScrollEnd();
2955 // Forces a full tree synchronization and ensures that the scroll delegate
2956 // sees the correct size of the new tree.
2957 gfx::Size new_size(42, 24);
2958 host_impl_->CreatePendingTree();
2959 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
2960 host_impl_->ActivatePendingTree();
2961 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
2963 // Un-setting the delegate should propagate the delegate's current offset to
2964 // the root scrollable layer.
2965 current_offset = gfx::Vector2dF(13.f, 12.f);
2966 scroll_delegate.set_getter_return_value(current_offset);
2967 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
2969 EXPECT_EQ(current_offset.ToString(),
2970 scroll_layer->TotalScrollOffset().ToString());
2973 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
2974 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2975 host_impl_->SetViewportSize(gfx::Size(50, 50));
2976 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
2978 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2979 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2981 // In-bounds scrolling does not affect overscroll.
2982 EXPECT_EQ(InputHandler::ScrollStarted,
2983 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2984 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2985 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2986 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2988 // Overscroll events are reflected immediately.
2989 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
2990 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
2991 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2993 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
2994 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
2995 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
2996 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
2997 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
2998 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
2999 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3000 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
3001 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
3002 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
3003 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
3004 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
3005 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3007 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
3008 // as no scroll occurs.
3009 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3010 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
3011 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3012 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
3013 // Overscroll resets on valid scroll.
3014 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3015 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3016 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3017 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3018 host_impl_->ScrollEnd();
3020 EXPECT_EQ(InputHandler::ScrollStarted,
3021 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3022 // Fling velocity is reflected immediately.
3023 host_impl_->NotifyCurrentFlingVelocity(gfx::Vector2dF(10, 0));
3024 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
3025 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3026 EXPECT_EQ(gfx::Vector2dF(0, -20), host_impl_->accumulated_root_overscroll());
3027 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
3031 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
3032 // Scroll child layers beyond their maximum scroll range and make sure root
3033 // overscroll does not accumulate.
3034 gfx::Size surface_size(10, 10);
3035 scoped_ptr<LayerImpl> root_clip =
3036 LayerImpl::Create(host_impl_->active_tree(), 4);
3037 scoped_ptr<LayerImpl> root =
3038 CreateScrollableLayer(1, surface_size, root_clip.get());
3040 scoped_ptr<LayerImpl> grand_child =
3041 CreateScrollableLayer(3, surface_size, root_clip.get());
3043 scoped_ptr<LayerImpl> child =
3044 CreateScrollableLayer(2, surface_size, root_clip.get());
3045 LayerImpl* grand_child_layer = grand_child.get();
3046 child->AddChild(grand_child.Pass());
3048 LayerImpl* child_layer = child.get();
3049 root->AddChild(child.Pass());
3050 root_clip->AddChild(root.Pass());
3051 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
3052 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
3053 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3054 host_impl_->active_tree()->DidBecomeActive();
3055 host_impl_->SetViewportSize(surface_size);
3058 gfx::Vector2d scroll_delta(0, -10);
3059 EXPECT_EQ(InputHandler::ScrollStarted,
3060 host_impl_->ScrollBegin(gfx::Point(),
3061 InputHandler::NonBubblingGesture));
3062 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3063 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3064 host_impl_->ScrollEnd();
3066 // The next time we scroll we should only scroll the parent, but overscroll
3067 // should still not reach the root layer.
3068 scroll_delta = gfx::Vector2d(0, -30);
3069 EXPECT_EQ(InputHandler::ScrollStarted,
3070 host_impl_->ScrollBegin(gfx::Point(5, 5),
3071 InputHandler::NonBubblingGesture));
3072 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3073 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3074 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3075 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
3076 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3077 host_impl_->ScrollEnd();
3079 // After scrolling the parent, another scroll on the opposite direction
3080 // should scroll the child, resetting the fling velocity.
3081 scroll_delta = gfx::Vector2d(0, 70);
3082 host_impl_->NotifyCurrentFlingVelocity(gfx::Vector2dF(10, 0));
3083 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
3084 EXPECT_EQ(InputHandler::ScrollStarted,
3085 host_impl_->ScrollBegin(gfx::Point(5, 5),
3086 InputHandler::NonBubblingGesture));
3087 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3088 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3089 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3090 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3091 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
3092 host_impl_->ScrollEnd();
3096 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
3097 // When we try to scroll a non-scrollable child layer, the scroll delta
3098 // should be applied to one of its ancestors if possible. Overscroll should
3099 // be reflected only when it has bubbled up to the root scrolling layer.
3100 gfx::Size surface_size(10, 10);
3101 gfx::Size content_size(20, 20);
3102 scoped_ptr<LayerImpl> root_clip =
3103 LayerImpl::Create(host_impl_->active_tree(), 3);
3104 scoped_ptr<LayerImpl> root =
3105 CreateScrollableLayer(1, content_size, root_clip.get());
3106 root->SetIsContainerForFixedPositionLayers(true);
3107 scoped_ptr<LayerImpl> child =
3108 CreateScrollableLayer(2, content_size, root_clip.get());
3110 child->SetScrollClipLayer(Layer::INVALID_ID);
3111 root->AddChild(child.Pass());
3112 root_clip->AddChild(root.Pass());
3114 host_impl_->SetViewportSize(surface_size);
3115 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3116 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3117 host_impl_->active_tree()->DidBecomeActive();
3120 gfx::Vector2d scroll_delta(0, 8);
3121 EXPECT_EQ(InputHandler::ScrollStarted,
3122 host_impl_->ScrollBegin(gfx::Point(5, 5),
3123 InputHandler::Wheel));
3124 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3125 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3126 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3127 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
3128 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3129 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
3130 host_impl_->ScrollEnd();
3134 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
3135 LayerTreeSettings settings;
3136 CreateHostImpl(settings, CreateOutputSurface());
3138 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
3139 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3140 clip_layer->SetBounds(gfx::Size(50, 50));
3141 host_impl_->SetViewportSize(gfx::Size(50, 50));
3142 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3144 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3145 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
3147 // Even though the layer can't scroll the overscroll still happens.
3148 EXPECT_EQ(InputHandler::ScrollStarted,
3149 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3150 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3151 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3152 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
3155 class BlendStateCheckLayer : public LayerImpl {
3157 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
3159 ResourceProvider* resource_provider) {
3160 return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(tree_impl,
3162 resource_provider));
3165 virtual void AppendQuads(QuadSink* quad_sink,
3166 AppendQuadsData* append_quads_data) OVERRIDE {
3167 quads_appended_ = true;
3169 gfx::Rect opaque_rect;
3170 if (contents_opaque())
3171 opaque_rect = quad_rect_;
3173 opaque_rect = opaque_content_rect_;
3175 SharedQuadState* shared_quad_state =
3176 quad_sink->UseSharedQuadState(CreateSharedQuadState());
3177 scoped_ptr<TileDrawQuad> test_blending_draw_quad = TileDrawQuad::Create();
3178 test_blending_draw_quad->SetNew(shared_quad_state,
3182 gfx::RectF(0.f, 0.f, 1.f, 1.f),
3185 test_blending_draw_quad->visible_rect = quad_visible_rect_;
3186 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
3187 EXPECT_EQ(has_render_surface_, !!render_surface());
3188 quad_sink->Append(test_blending_draw_quad.PassAs<DrawQuad>(),
3192 void SetExpectation(bool blend, bool has_render_surface) {
3194 has_render_surface_ = has_render_surface;
3195 quads_appended_ = false;
3198 bool quads_appended() const { return quads_appended_; }
3200 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
3201 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
3202 void SetOpaqueContentRect(const gfx::Rect& rect) {
3203 opaque_content_rect_ = rect;
3207 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
3209 ResourceProvider* resource_provider)
3210 : LayerImpl(tree_impl, id),
3212 has_render_surface_(false),
3213 quads_appended_(false),
3214 quad_rect_(5, 5, 5, 5),
3215 quad_visible_rect_(5, 5, 5, 5),
3216 resource_id_(resource_provider->CreateResource(
3219 ResourceProvider::TextureUsageAny,
3221 resource_provider->AllocateForTesting(resource_id_);
3222 SetAnchorPoint(gfx::PointF());
3223 SetBounds(gfx::Size(10, 10));
3224 SetContentBounds(gfx::Size(10, 10));
3225 SetDrawsContent(true);
3229 bool has_render_surface_;
3230 bool quads_appended_;
3231 gfx::Rect quad_rect_;
3232 gfx::Rect opaque_content_rect_;
3233 gfx::Rect quad_visible_rect_;
3234 ResourceProvider::ResourceId resource_id_;
3237 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
3239 scoped_ptr<LayerImpl> root =
3240 LayerImpl::Create(host_impl_->active_tree(), 1);
3241 root->SetAnchorPoint(gfx::PointF());
3242 root->SetBounds(gfx::Size(10, 10));
3243 root->SetContentBounds(root->bounds());
3244 root->SetDrawsContent(false);
3245 host_impl_->active_tree()->SetRootLayer(root.Pass());
3247 LayerImpl* root = host_impl_->active_tree()->root_layer();
3250 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3252 host_impl_->resource_provider()));
3253 BlendStateCheckLayer* layer1 =
3254 static_cast<BlendStateCheckLayer*>(root->children()[0]);
3255 layer1->SetPosition(gfx::PointF(2.f, 2.f));
3257 LayerTreeHostImpl::FrameData frame;
3259 // Opaque layer, drawn without blending.
3260 layer1->SetContentsOpaque(true);
3261 layer1->SetExpectation(false, false);
3262 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3263 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3264 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3265 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3266 EXPECT_TRUE(layer1->quads_appended());
3267 host_impl_->DidDrawAllLayers(frame);
3269 // Layer with translucent content and painting, so drawn with blending.
3270 layer1->SetContentsOpaque(false);
3271 layer1->SetExpectation(true, false);
3272 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3273 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3274 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3275 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3276 EXPECT_TRUE(layer1->quads_appended());
3277 host_impl_->DidDrawAllLayers(frame);
3279 // Layer with translucent opacity, drawn with blending.
3280 layer1->SetContentsOpaque(true);
3281 layer1->SetOpacity(0.5f);
3282 layer1->SetExpectation(true, false);
3283 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3284 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3285 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3286 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3287 EXPECT_TRUE(layer1->quads_appended());
3288 host_impl_->DidDrawAllLayers(frame);
3290 // Layer with translucent opacity and painting, drawn with blending.
3291 layer1->SetContentsOpaque(true);
3292 layer1->SetOpacity(0.5f);
3293 layer1->SetExpectation(true, false);
3294 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3295 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3296 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3297 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3298 EXPECT_TRUE(layer1->quads_appended());
3299 host_impl_->DidDrawAllLayers(frame);
3302 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3304 host_impl_->resource_provider()));
3305 BlendStateCheckLayer* layer2 =
3306 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
3307 layer2->SetPosition(gfx::PointF(4.f, 4.f));
3309 // 2 opaque layers, drawn without blending.
3310 layer1->SetContentsOpaque(true);
3311 layer1->SetOpacity(1.f);
3312 layer1->SetExpectation(false, false);
3313 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3314 layer2->SetContentsOpaque(true);
3315 layer2->SetOpacity(1.f);
3316 layer2->SetExpectation(false, false);
3317 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3318 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3319 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3320 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3321 EXPECT_TRUE(layer1->quads_appended());
3322 EXPECT_TRUE(layer2->quads_appended());
3323 host_impl_->DidDrawAllLayers(frame);
3325 // Parent layer with translucent content, drawn with blending.
3326 // Child layer with opaque content, drawn without blending.
3327 layer1->SetContentsOpaque(false);
3328 layer1->SetExpectation(true, false);
3329 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3330 layer2->SetExpectation(false, false);
3331 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3332 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3333 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3334 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3335 EXPECT_TRUE(layer1->quads_appended());
3336 EXPECT_TRUE(layer2->quads_appended());
3337 host_impl_->DidDrawAllLayers(frame);
3339 // Parent layer with translucent content but opaque painting, drawn without
3341 // Child layer with opaque content, drawn without blending.
3342 layer1->SetContentsOpaque(true);
3343 layer1->SetExpectation(false, false);
3344 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3345 layer2->SetExpectation(false, false);
3346 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3347 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3348 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3349 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3350 EXPECT_TRUE(layer1->quads_appended());
3351 EXPECT_TRUE(layer2->quads_appended());
3352 host_impl_->DidDrawAllLayers(frame);
3354 // Parent layer with translucent opacity and opaque content. Since it has a
3355 // drawing child, it's drawn to a render surface which carries the opacity,
3356 // so it's itself drawn without blending.
3357 // Child layer with opaque content, drawn without blending (parent surface
3358 // carries the inherited opacity).
3359 layer1->SetContentsOpaque(true);
3360 layer1->SetOpacity(0.5f);
3361 layer1->SetExpectation(false, true);
3362 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3363 layer2->SetExpectation(false, false);
3364 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3365 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3366 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3367 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3368 EXPECT_TRUE(layer1->quads_appended());
3369 EXPECT_TRUE(layer2->quads_appended());
3370 host_impl_->DidDrawAllLayers(frame);
3372 // Draw again, but with child non-opaque, to make sure
3373 // layer1 not culled.
3374 layer1->SetContentsOpaque(true);
3375 layer1->SetOpacity(1.f);
3376 layer1->SetExpectation(false, false);
3377 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3378 layer2->SetContentsOpaque(true);
3379 layer2->SetOpacity(0.5f);
3380 layer2->SetExpectation(true, false);
3381 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3382 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3383 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3384 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3385 EXPECT_TRUE(layer1->quads_appended());
3386 EXPECT_TRUE(layer2->quads_appended());
3387 host_impl_->DidDrawAllLayers(frame);
3389 // A second way of making the child non-opaque.
3390 layer1->SetContentsOpaque(true);
3391 layer1->SetOpacity(1.f);
3392 layer1->SetExpectation(false, false);
3393 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3394 layer2->SetContentsOpaque(false);
3395 layer2->SetOpacity(1.f);
3396 layer2->SetExpectation(true, false);
3397 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3398 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3399 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3400 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3401 EXPECT_TRUE(layer1->quads_appended());
3402 EXPECT_TRUE(layer2->quads_appended());
3403 host_impl_->DidDrawAllLayers(frame);
3405 // And when the layer says its not opaque but is painted opaque, it is not
3407 layer1->SetContentsOpaque(true);
3408 layer1->SetOpacity(1.f);
3409 layer1->SetExpectation(false, false);
3410 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3411 layer2->SetContentsOpaque(true);
3412 layer2->SetOpacity(1.f);
3413 layer2->SetExpectation(false, false);
3414 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3415 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3416 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3417 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3418 EXPECT_TRUE(layer1->quads_appended());
3419 EXPECT_TRUE(layer2->quads_appended());
3420 host_impl_->DidDrawAllLayers(frame);
3422 // Layer with partially opaque contents, drawn with blending.
3423 layer1->SetContentsOpaque(false);
3424 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3425 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
3426 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3427 layer1->SetExpectation(true, false);
3428 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3429 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3430 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3431 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3432 EXPECT_TRUE(layer1->quads_appended());
3433 host_impl_->DidDrawAllLayers(frame);
3435 // Layer with partially opaque contents partially culled, drawn with blending.
3436 layer1->SetContentsOpaque(false);
3437 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3438 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
3439 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3440 layer1->SetExpectation(true, false);
3441 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3442 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3443 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3444 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3445 EXPECT_TRUE(layer1->quads_appended());
3446 host_impl_->DidDrawAllLayers(frame);
3448 // Layer with partially opaque contents culled, drawn with blending.
3449 layer1->SetContentsOpaque(false);
3450 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3451 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
3452 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3453 layer1->SetExpectation(true, false);
3454 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3455 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3456 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3457 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3458 EXPECT_TRUE(layer1->quads_appended());
3459 host_impl_->DidDrawAllLayers(frame);
3461 // Layer with partially opaque contents and translucent contents culled, drawn
3462 // without blending.
3463 layer1->SetContentsOpaque(false);
3464 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3465 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
3466 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3467 layer1->SetExpectation(false, false);
3468 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3469 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3470 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3471 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3472 EXPECT_TRUE(layer1->quads_appended());
3473 host_impl_->DidDrawAllLayers(frame);
3476 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
3478 LayerTreeHostImplViewportCoveredTest() :
3479 gutter_quad_material_(DrawQuad::SOLID_COLOR),
3481 did_activate_pending_tree_(false) {}
3483 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
3485 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
3486 .PassAs<OutputSurface>();
3488 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
3491 void SetupActiveTreeLayers() {
3492 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
3493 host_impl_->active_tree()->SetRootLayer(
3494 LayerImpl::Create(host_impl_->active_tree(), 1));
3495 host_impl_->active_tree()->root_layer()->AddChild(
3496 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3498 host_impl_->resource_provider()));
3499 child_ = static_cast<BlendStateCheckLayer*>(
3500 host_impl_->active_tree()->root_layer()->children()[0]);
3501 child_->SetExpectation(false, false);
3502 child_->SetContentsOpaque(true);
3505 // Expect no gutter rects.
3506 void TestLayerCoversFullViewport() {
3507 gfx::Rect layer_rect(viewport_size_);
3508 child_->SetPosition(layer_rect.origin());
3509 child_->SetBounds(layer_rect.size());
3510 child_->SetContentBounds(layer_rect.size());
3511 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3512 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3514 LayerTreeHostImpl::FrameData frame;
3515 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3516 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3517 ASSERT_EQ(1u, frame.render_passes.size());
3519 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3520 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3521 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3523 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3524 host_impl_->DidDrawAllLayers(frame);
3527 // Expect fullscreen gutter rect.
3528 void TestEmptyLayer() {
3529 gfx::Rect layer_rect(0, 0, 0, 0);
3530 child_->SetPosition(layer_rect.origin());
3531 child_->SetBounds(layer_rect.size());
3532 child_->SetContentBounds(layer_rect.size());
3533 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3534 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3536 LayerTreeHostImpl::FrameData frame;
3537 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3538 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3539 ASSERT_EQ(1u, frame.render_passes.size());
3541 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
3542 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3543 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3545 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3546 host_impl_->DidDrawAllLayers(frame);
3549 // Expect four surrounding gutter rects.
3550 void TestLayerInMiddleOfViewport() {
3551 gfx::Rect layer_rect(500, 500, 200, 200);
3552 child_->SetPosition(layer_rect.origin());
3553 child_->SetBounds(layer_rect.size());
3554 child_->SetContentBounds(layer_rect.size());
3555 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3556 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3558 LayerTreeHostImpl::FrameData frame;
3559 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3560 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3561 ASSERT_EQ(1u, frame.render_passes.size());
3563 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
3564 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
3565 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3567 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3568 host_impl_->DidDrawAllLayers(frame);
3571 // Expect no gutter rects.
3572 void TestLayerIsLargerThanViewport() {
3573 gfx::Rect layer_rect(viewport_size_.width() + 10,
3574 viewport_size_.height() + 10);
3575 child_->SetPosition(layer_rect.origin());
3576 child_->SetBounds(layer_rect.size());
3577 child_->SetContentBounds(layer_rect.size());
3578 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3579 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3581 LayerTreeHostImpl::FrameData frame;
3582 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3583 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3584 ASSERT_EQ(1u, frame.render_passes.size());
3586 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3587 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3588 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3590 host_impl_->DidDrawAllLayers(frame);
3593 virtual void DidActivatePendingTree() OVERRIDE {
3594 did_activate_pending_tree_ = true;
3597 void set_gutter_quad_material(DrawQuad::Material material) {
3598 gutter_quad_material_ = material;
3600 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
3601 gutter_texture_size_ = gutter_texture_size;
3605 size_t CountGutterQuads(const QuadList& quad_list) {
3606 size_t num_gutter_quads = 0;
3607 for (size_t i = 0; i < quad_list.size(); ++i) {
3608 num_gutter_quads += (quad_list[i]->material ==
3609 gutter_quad_material_) ? 1 : 0;
3611 return num_gutter_quads;
3614 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
3615 LayerTestCommon::VerifyQuadsExactlyCoverRect(
3616 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
3619 // Make sure that the texture coordinates match their expectations.
3620 void ValidateTextureDrawQuads(const QuadList& quad_list) {
3621 for (size_t i = 0; i < quad_list.size(); ++i) {
3622 if (quad_list[i]->material != DrawQuad::TEXTURE_CONTENT)
3624 const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(quad_list[i]);
3625 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
3626 gutter_texture_size_, host_impl_->device_scale_factor());
3627 EXPECT_EQ(quad->uv_top_left.x(),
3628 quad->rect.x() / gutter_texture_size_pixels.width());
3629 EXPECT_EQ(quad->uv_top_left.y(),
3630 quad->rect.y() / gutter_texture_size_pixels.height());
3631 EXPECT_EQ(quad->uv_bottom_right.x(),
3632 quad->rect.right() / gutter_texture_size_pixels.width());
3633 EXPECT_EQ(quad->uv_bottom_right.y(),
3634 quad->rect.bottom() / gutter_texture_size_pixels.height());
3638 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
3639 return gfx::ToRoundedSize(
3640 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
3643 DrawQuad::Material gutter_quad_material_;
3644 gfx::Size gutter_texture_size_;
3645 gfx::Size viewport_size_;
3646 BlendStateCheckLayer* child_;
3647 bool did_activate_pending_tree_;
3650 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
3651 viewport_size_ = gfx::Size(1000, 1000);
3653 bool always_draw = false;
3654 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3656 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3657 SetupActiveTreeLayers();
3658 TestLayerCoversFullViewport();
3660 TestLayerInMiddleOfViewport();
3661 TestLayerIsLargerThanViewport();
3664 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
3665 viewport_size_ = gfx::Size(1000, 1000);
3667 bool always_draw = false;
3668 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3670 host_impl_->SetDeviceScaleFactor(2.f);
3671 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3672 SetupActiveTreeLayers();
3673 TestLayerCoversFullViewport();
3675 TestLayerInMiddleOfViewport();
3676 TestLayerIsLargerThanViewport();
3679 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
3680 viewport_size_ = gfx::Size(1000, 1000);
3682 bool always_draw = false;
3683 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3685 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3686 SetupActiveTreeLayers();
3689 skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
3690 skbitmap.allocPixels();
3691 skbitmap.setImmutable();
3693 // Specify an overhang bitmap to use.
3694 UIResourceBitmap ui_resource_bitmap(skbitmap);
3695 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
3696 UIResourceId ui_resource_id = 12345;
3697 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
3698 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
3699 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
3700 set_gutter_texture_size(gfx::Size(32, 32));
3702 TestLayerCoversFullViewport();
3704 TestLayerInMiddleOfViewport();
3705 TestLayerIsLargerThanViewport();
3707 // Change the resource size.
3708 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
3709 set_gutter_texture_size(gfx::Size(128, 16));
3711 TestLayerCoversFullViewport();
3713 TestLayerInMiddleOfViewport();
3714 TestLayerIsLargerThanViewport();
3716 // Change the device scale factor
3717 host_impl_->SetDeviceScaleFactor(2.f);
3718 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3720 TestLayerCoversFullViewport();
3722 TestLayerInMiddleOfViewport();
3723 TestLayerIsLargerThanViewport();
3726 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
3727 viewport_size_ = gfx::Size(1000, 1000);
3729 bool always_draw = true;
3730 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3732 // Pending tree to force active_tree size invalid. Not used otherwise.
3733 host_impl_->CreatePendingTree();
3734 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3735 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3737 SetupActiveTreeLayers();
3739 TestLayerInMiddleOfViewport();
3740 TestLayerIsLargerThanViewport();
3743 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
3744 viewport_size_ = gfx::Size(1000, 1000);
3746 bool always_draw = true;
3747 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3749 // Set larger viewport and activate it to active tree.
3750 host_impl_->CreatePendingTree();
3751 gfx::Size larger_viewport(viewport_size_.width() + 100,
3752 viewport_size_.height() + 100);
3753 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
3754 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3755 host_impl_->ActivatePendingTree();
3756 EXPECT_TRUE(did_activate_pending_tree_);
3757 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
3759 // Shrink pending tree viewport without activating.
3760 host_impl_->CreatePendingTree();
3761 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3762 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3764 SetupActiveTreeLayers();
3766 TestLayerInMiddleOfViewport();
3767 TestLayerIsLargerThanViewport();
3770 class FakeDrawableLayerImpl: public LayerImpl {
3772 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
3773 return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(tree_impl, id));
3776 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
3777 : LayerImpl(tree_impl, id) {}
3780 // Only reshape when we know we are going to draw. Otherwise, the reshape
3781 // can leave the window at the wrong size if we never draw and the proper
3782 // viewport size is never set.
3783 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
3784 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
3785 scoped_ptr<OutputSurface> output_surface(
3786 FakeOutputSurface::Create3d(provider));
3787 CreateHostImpl(DefaultSettings(), output_surface.Pass());
3789 scoped_ptr<LayerImpl> root =
3790 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
3791 root->SetAnchorPoint(gfx::PointF());
3792 root->SetBounds(gfx::Size(10, 10));
3793 root->SetContentBounds(gfx::Size(10, 10));
3794 root->SetDrawsContent(true);
3795 host_impl_->active_tree()->SetRootLayer(root.Pass());
3796 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
3797 provider->TestContext3d()->clear_reshape_called();
3799 LayerTreeHostImpl::FrameData frame;
3800 host_impl_->SetViewportSize(gfx::Size(10, 10));
3801 host_impl_->SetDeviceScaleFactor(1.f);
3802 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3803 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3804 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3805 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
3806 EXPECT_EQ(provider->TestContext3d()->width(), 10);
3807 EXPECT_EQ(provider->TestContext3d()->height(), 10);
3808 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
3809 host_impl_->DidDrawAllLayers(frame);
3810 provider->TestContext3d()->clear_reshape_called();
3812 host_impl_->SetViewportSize(gfx::Size(20, 30));
3813 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3814 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3815 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3816 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
3817 EXPECT_EQ(provider->TestContext3d()->width(), 20);
3818 EXPECT_EQ(provider->TestContext3d()->height(), 30);
3819 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
3820 host_impl_->DidDrawAllLayers(frame);
3821 provider->TestContext3d()->clear_reshape_called();
3823 host_impl_->SetDeviceScaleFactor(2.f);
3824 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3825 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3826 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3827 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
3828 EXPECT_EQ(provider->TestContext3d()->width(), 20);
3829 EXPECT_EQ(provider->TestContext3d()->height(), 30);
3830 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
3831 host_impl_->DidDrawAllLayers(frame);
3832 provider->TestContext3d()->clear_reshape_called();
3835 // Make sure damage tracking propagates all the way to the graphics context,
3836 // where it should request to swap only the sub-buffer that is damaged.
3837 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
3838 scoped_refptr<TestContextProvider> context_provider(
3839 TestContextProvider::Create());
3840 context_provider->BindToCurrentThread();
3841 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
3843 scoped_ptr<OutputSurface> output_surface(
3844 FakeOutputSurface::Create3d(context_provider));
3846 // This test creates its own LayerTreeHostImpl, so
3847 // that we can force partial swap enabled.
3848 LayerTreeSettings settings;
3849 settings.partial_swap_enabled = true;
3850 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
3851 LayerTreeHostImpl::Create(
3852 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
3853 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
3854 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
3856 scoped_ptr<LayerImpl> root =
3857 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
3858 scoped_ptr<LayerImpl> child =
3859 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
3860 child->SetPosition(gfx::PointF(12.f, 13.f));
3861 child->SetAnchorPoint(gfx::PointF());
3862 child->SetBounds(gfx::Size(14, 15));
3863 child->SetContentBounds(gfx::Size(14, 15));
3864 child->SetDrawsContent(true);
3865 root->SetAnchorPoint(gfx::PointF());
3866 root->SetBounds(gfx::Size(500, 500));
3867 root->SetContentBounds(gfx::Size(500, 500));
3868 root->SetDrawsContent(true);
3869 root->AddChild(child.Pass());
3870 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
3872 LayerTreeHostImpl::FrameData frame;
3874 // First frame, the entire screen should get swapped.
3875 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3876 layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3877 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3878 layer_tree_host_impl->DidDrawAllLayers(frame);
3879 layer_tree_host_impl->SwapBuffers(frame);
3880 EXPECT_EQ(TestContextSupport::SWAP,
3881 context_provider->support()->last_swap_type());
3883 // Second frame, only the damaged area should get swapped. Damage should be
3884 // the union of old and new child rects.
3885 // expected damage rect: gfx::Rect(26, 28);
3886 // expected swap rect: vertically flipped, with origin at bottom left corner.
3887 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
3889 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3890 layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3891 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3892 host_impl_->DidDrawAllLayers(frame);
3893 layer_tree_host_impl->SwapBuffers(frame);
3895 // Make sure that partial swap is constrained to the viewport dimensions
3896 // expected damage rect: gfx::Rect(500, 500);
3897 // expected swap rect: flipped damage rect, but also clamped to viewport
3898 EXPECT_EQ(TestContextSupport::PARTIAL_SWAP,
3899 context_provider->support()->last_swap_type());
3900 gfx::Rect expected_swap_rect(0, 500-28, 26, 28);
3901 EXPECT_EQ(expected_swap_rect.ToString(),
3902 context_provider->support()->
3903 last_partial_swap_rect().ToString());
3905 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
3906 // This will damage everything.
3907 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
3909 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3910 layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3911 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3912 host_impl_->DidDrawAllLayers(frame);
3913 layer_tree_host_impl->SwapBuffers(frame);
3915 EXPECT_EQ(TestContextSupport::SWAP,
3916 context_provider->support()->last_swap_type());
3919 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
3920 scoped_ptr<LayerImpl> root =
3921 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
3922 scoped_ptr<LayerImpl> child =
3923 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
3924 child->SetAnchorPoint(gfx::PointF());
3925 child->SetBounds(gfx::Size(10, 10));
3926 child->SetContentBounds(gfx::Size(10, 10));
3927 child->SetDrawsContent(true);
3928 root->SetAnchorPoint(gfx::PointF());
3929 root->SetBounds(gfx::Size(10, 10));
3930 root->SetContentBounds(gfx::Size(10, 10));
3931 root->SetDrawsContent(true);
3932 root->SetForceRenderSurface(true);
3933 root->AddChild(child.Pass());
3935 host_impl_->active_tree()->SetRootLayer(root.Pass());
3937 LayerTreeHostImpl::FrameData frame;
3939 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
3940 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3941 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
3942 EXPECT_EQ(1u, frame.render_passes.size());
3943 host_impl_->DidDrawAllLayers(frame);
3946 class FakeLayerWithQuads : public LayerImpl {
3948 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
3949 return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(tree_impl, id));
3952 virtual void AppendQuads(QuadSink* quad_sink,
3953 AppendQuadsData* append_quads_data) OVERRIDE {
3954 SharedQuadState* shared_quad_state =
3955 quad_sink->UseSharedQuadState(CreateSharedQuadState());
3957 SkColor gray = SkColorSetRGB(100, 100, 100);
3958 gfx::Rect quad_rect(content_bounds());
3959 scoped_ptr<SolidColorDrawQuad> my_quad = SolidColorDrawQuad::Create();
3960 my_quad->SetNew(shared_quad_state, quad_rect, gray, false);
3961 quad_sink->Append(my_quad.PassAs<DrawQuad>(), append_quads_data);
3965 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
3966 : LayerImpl(tree_impl, id) {}
3969 class MockContext : public TestWebGraphicsContext3D {
3971 MOCK_METHOD1(useProgram, void(GLuint program));
3972 MOCK_METHOD5(uniform4f, void(GLint location,
3977 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
3979 GLboolean transpose,
3980 const GLfloat* value));
3981 MOCK_METHOD4(drawElements, void(GLenum mode,
3985 MOCK_METHOD1(enable, void(GLenum cap));
3986 MOCK_METHOD1(disable, void(GLenum cap));
3987 MOCK_METHOD4(scissor, void(GLint x,
3993 class MockContextHarness {
3995 MockContext* context_;
3998 explicit MockContextHarness(MockContext* context)
3999 : context_(context) {
4000 context_->set_have_post_sub_buffer(true);
4002 // Catch "uninteresting" calls
4003 EXPECT_CALL(*context_, useProgram(_))
4006 EXPECT_CALL(*context_, drawElements(_, _, _, _))
4009 // These are not asserted
4010 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
4011 .WillRepeatedly(Return());
4013 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
4014 .WillRepeatedly(Return());
4016 // Any un-sanctioned calls to enable() are OK
4017 EXPECT_CALL(*context_, enable(_))
4018 .WillRepeatedly(Return());
4020 // Any un-sanctioned calls to disable() are OK
4021 EXPECT_CALL(*context_, disable(_))
4022 .WillRepeatedly(Return());
4025 void MustDrawSolidQuad() {
4026 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
4028 .RetiresOnSaturation();
4030 EXPECT_CALL(*context_, useProgram(_))
4032 .RetiresOnSaturation();
4035 void MustSetScissor(int x, int y, int width, int height) {
4036 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4037 .WillRepeatedly(Return());
4039 EXPECT_CALL(*context_, scissor(x, y, width, height))
4041 .WillRepeatedly(Return());
4044 void MustSetNoScissor() {
4045 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
4046 .WillRepeatedly(Return());
4048 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4051 EXPECT_CALL(*context_, scissor(_, _, _, _))
4056 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
4057 scoped_ptr<MockContext> mock_context_owned(new MockContext);
4058 MockContext* mock_context = mock_context_owned.get();
4060 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4061 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4062 MockContextHarness harness(mock_context);
4065 LayerTreeSettings settings = DefaultSettings();
4066 settings.partial_swap_enabled = false;
4067 CreateHostImpl(settings, output_surface.Pass());
4068 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4070 // Without partial swap, and no clipping, no scissor is set.
4071 harness.MustDrawSolidQuad();
4072 harness.MustSetNoScissor();
4074 LayerTreeHostImpl::FrameData frame;
4075 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4076 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4077 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4078 host_impl_->DidDrawAllLayers(frame);
4080 Mock::VerifyAndClearExpectations(&mock_context);
4082 // Without partial swap, but a layer does clip its subtree, one scissor is
4084 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
4085 harness.MustDrawSolidQuad();
4086 harness.MustSetScissor(0, 0, 10, 10);
4088 LayerTreeHostImpl::FrameData frame;
4089 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4090 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4091 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4092 host_impl_->DidDrawAllLayers(frame);
4094 Mock::VerifyAndClearExpectations(&mock_context);
4097 TEST_F(LayerTreeHostImplTest, PartialSwap) {
4098 scoped_ptr<MockContext> context_owned(new MockContext);
4099 MockContext* mock_context = context_owned.get();
4100 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4101 context_owned.PassAs<TestWebGraphicsContext3D>()));
4102 MockContextHarness harness(mock_context);
4104 LayerTreeSettings settings = DefaultSettings();
4105 settings.partial_swap_enabled = true;
4106 CreateHostImpl(settings, output_surface.Pass());
4107 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4109 // The first frame is not a partially-swapped one.
4110 harness.MustSetScissor(0, 0, 10, 10);
4111 harness.MustDrawSolidQuad();
4113 LayerTreeHostImpl::FrameData frame;
4114 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4115 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4116 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4117 host_impl_->DidDrawAllLayers(frame);
4119 Mock::VerifyAndClearExpectations(&mock_context);
4121 // Damage a portion of the frame.
4122 host_impl_->active_tree()->root_layer()->SetUpdateRect(
4123 gfx::Rect(0, 0, 2, 3));
4125 // The second frame will be partially-swapped (the y coordinates are flipped).
4126 harness.MustSetScissor(0, 7, 2, 3);
4127 harness.MustDrawSolidQuad();
4129 LayerTreeHostImpl::FrameData frame;
4130 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4131 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4132 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4133 host_impl_->DidDrawAllLayers(frame);
4135 Mock::VerifyAndClearExpectations(&mock_context);
4138 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
4140 LayerTreeHostImplClient* client,
4142 RenderingStatsInstrumentation* stats_instrumentation) {
4143 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4144 scoped_ptr<OutputSurface> output_surface(
4145 FakeOutputSurface::Create3d(provider));
4146 provider->BindToCurrentThread();
4147 provider->TestContext3d()->set_have_post_sub_buffer(true);
4149 LayerTreeSettings settings;
4150 settings.partial_swap_enabled = partial_swap;
4151 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
4152 settings, client, proxy, stats_instrumentation, NULL, 0);
4153 my_host_impl->InitializeRenderer(output_surface.Pass());
4154 my_host_impl->SetViewportSize(gfx::Size(100, 100));
4157 Layers are created as follows:
4159 +--------------------+
4163 | | +-------------------+
4165 | | +-------------------+
4170 +--------------------+
4172 Layers 1, 2 have render surfaces
4174 scoped_ptr<LayerImpl> root =
4175 LayerImpl::Create(my_host_impl->active_tree(), 1);
4176 scoped_ptr<LayerImpl> child =
4177 LayerImpl::Create(my_host_impl->active_tree(), 2);
4178 scoped_ptr<LayerImpl> grand_child =
4179 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
4181 gfx::Rect root_rect(0, 0, 100, 100);
4182 gfx::Rect child_rect(10, 10, 50, 50);
4183 gfx::Rect grand_child_rect(5, 5, 150, 150);
4185 root->CreateRenderSurface();
4186 root->SetAnchorPoint(gfx::PointF());
4187 root->SetPosition(root_rect.origin());
4188 root->SetBounds(root_rect.size());
4189 root->SetContentBounds(root->bounds());
4190 root->draw_properties().visible_content_rect = root_rect;
4191 root->SetDrawsContent(false);
4192 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
4194 child->SetAnchorPoint(gfx::PointF());
4195 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
4196 child->SetOpacity(0.5f);
4197 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
4198 child->SetContentBounds(child->bounds());
4199 child->draw_properties().visible_content_rect = child_rect;
4200 child->SetDrawsContent(false);
4201 child->SetForceRenderSurface(true);
4203 grand_child->SetAnchorPoint(gfx::PointF());
4204 grand_child->SetPosition(grand_child_rect.origin());
4205 grand_child->SetBounds(grand_child_rect.size());
4206 grand_child->SetContentBounds(grand_child->bounds());
4207 grand_child->draw_properties().visible_content_rect = grand_child_rect;
4208 grand_child->SetDrawsContent(true);
4210 child->AddChild(grand_child.Pass());
4211 root->AddChild(child.Pass());
4213 my_host_impl->active_tree()->SetRootLayer(root.Pass());
4214 return my_host_impl.Pass();
4217 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
4218 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4219 SetupLayersForOpacity(true, this, &proxy_, &stats_instrumentation_);
4221 LayerTreeHostImpl::FrameData frame;
4222 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4223 my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
4225 // Verify all quads have been computed
4226 ASSERT_EQ(2U, frame.render_passes.size());
4227 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4228 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4229 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4230 frame.render_passes[0]->quad_list[0]->material);
4231 EXPECT_EQ(DrawQuad::RENDER_PASS,
4232 frame.render_passes[1]->quad_list[0]->material);
4234 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4235 my_host_impl->DidDrawAllLayers(frame);
4239 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
4240 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4241 SetupLayersForOpacity(false, this, &proxy_, &stats_instrumentation_);
4243 LayerTreeHostImpl::FrameData frame;
4244 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4245 my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
4247 // Verify all quads have been computed
4248 ASSERT_EQ(2U, frame.render_passes.size());
4249 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4250 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4251 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4252 frame.render_passes[0]->quad_list[0]->material);
4253 EXPECT_EQ(DrawQuad::RENDER_PASS,
4254 frame.render_passes[1]->quad_list[0]->material);
4256 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4257 my_host_impl->DidDrawAllLayers(frame);
4261 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
4262 scoped_ptr<TestWebGraphicsContext3D> context =
4263 TestWebGraphicsContext3D::Create();
4264 TestWebGraphicsContext3D* context3d = context.get();
4265 scoped_ptr<OutputSurface> output_surface(
4266 FakeOutputSurface::Create3d(context.Pass()));
4267 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4269 scoped_ptr<LayerImpl> root_layer =
4270 LayerImpl::Create(host_impl_->active_tree(), 1);
4271 root_layer->SetBounds(gfx::Size(10, 10));
4272 root_layer->SetAnchorPoint(gfx::PointF());
4274 scoped_refptr<VideoFrame> softwareFrame =
4275 media::VideoFrame::CreateColorFrame(
4276 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
4277 FakeVideoFrameProvider provider;
4278 provider.set_frame(softwareFrame);
4279 scoped_ptr<VideoLayerImpl> video_layer =
4280 VideoLayerImpl::Create(host_impl_->active_tree(), 4, &provider);
4281 video_layer->SetBounds(gfx::Size(10, 10));
4282 video_layer->SetAnchorPoint(gfx::PointF());
4283 video_layer->SetContentBounds(gfx::Size(10, 10));
4284 video_layer->SetDrawsContent(true);
4285 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
4287 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
4288 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
4289 io_surface_layer->SetBounds(gfx::Size(10, 10));
4290 io_surface_layer->SetAnchorPoint(gfx::PointF());
4291 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
4292 io_surface_layer->SetDrawsContent(true);
4293 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
4294 root_layer->AddChild(io_surface_layer.PassAs<LayerImpl>());
4296 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
4298 EXPECT_EQ(0u, context3d->NumTextures());
4300 LayerTreeHostImpl::FrameData frame;
4301 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4302 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4303 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4304 host_impl_->DidDrawAllLayers(frame);
4305 host_impl_->SwapBuffers(frame);
4307 EXPECT_GT(context3d->NumTextures(), 0u);
4309 // Kill the layer tree.
4310 host_impl_->active_tree()->SetRootLayer(
4311 LayerImpl::Create(host_impl_->active_tree(), 100));
4312 // There should be no textures left in use after.
4313 EXPECT_EQ(0u, context3d->NumTextures());
4316 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
4318 MOCK_METHOD1(useProgram, void(GLuint program));
4319 MOCK_METHOD4(drawElements, void(GLenum mode,
4325 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
4326 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
4327 new MockDrawQuadsToFillScreenContext);
4328 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
4330 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4331 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4334 LayerTreeSettings settings = DefaultSettings();
4335 settings.partial_swap_enabled = false;
4336 CreateHostImpl(settings, output_surface.Pass());
4337 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
4338 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
4340 // Verify one quad is drawn when transparent background set is not set.
4341 host_impl_->active_tree()->set_has_transparent_background(false);
4342 EXPECT_CALL(*mock_context, useProgram(_))
4344 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
4346 LayerTreeHostImpl::FrameData frame;
4347 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4348 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4349 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4350 host_impl_->DidDrawAllLayers(frame);
4351 Mock::VerifyAndClearExpectations(&mock_context);
4353 // Verify no quads are drawn when transparent background is set.
4354 host_impl_->active_tree()->set_has_transparent_background(true);
4355 host_impl_->SetFullRootLayerDamage();
4356 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4357 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4358 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4359 host_impl_->DidDrawAllLayers(frame);
4360 Mock::VerifyAndClearExpectations(&mock_context);
4363 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
4364 set_reduce_memory_result(false);
4366 // If changing the memory limit wouldn't result in changing what was
4367 // committed, then no commit should be requested.
4368 set_reduce_memory_result(false);
4369 host_impl_->set_max_memory_needed_bytes(
4370 host_impl_->memory_allocation_limit_bytes() - 1);
4371 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4372 host_impl_->memory_allocation_limit_bytes() - 1));
4373 EXPECT_FALSE(did_request_commit_);
4374 did_request_commit_ = false;
4376 // If changing the memory limit would result in changing what was
4377 // committed, then a commit should be requested, even though nothing was
4379 set_reduce_memory_result(false);
4380 host_impl_->set_max_memory_needed_bytes(
4381 host_impl_->memory_allocation_limit_bytes());
4382 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4383 host_impl_->memory_allocation_limit_bytes() - 1));
4384 EXPECT_TRUE(did_request_commit_);
4385 did_request_commit_ = false;
4387 // Especially if changing the memory limit caused evictions, we need
4389 set_reduce_memory_result(true);
4390 host_impl_->set_max_memory_needed_bytes(1);
4391 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4392 host_impl_->memory_allocation_limit_bytes() - 1));
4393 EXPECT_TRUE(did_request_commit_);
4394 did_request_commit_ = false;
4396 // But if we set it to the same value that it was before, we shouldn't
4398 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4399 host_impl_->memory_allocation_limit_bytes()));
4400 EXPECT_FALSE(did_request_commit_);
4403 class LayerTreeHostImplTestWithDelegatingRenderer
4404 : public LayerTreeHostImplTest {
4406 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
4407 return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
4410 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
4411 bool expect_to_draw = !expected_damage.IsEmpty();
4413 LayerTreeHostImpl::FrameData frame;
4414 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4415 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4417 if (!expect_to_draw) {
4418 // With no damage, we don't draw, and no quads are created.
4419 ASSERT_EQ(0u, frame.render_passes.size());
4421 ASSERT_EQ(1u, frame.render_passes.size());
4423 // Verify the damage rect for the root render pass.
4424 const RenderPass* root_render_pass = frame.render_passes.back();
4425 EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
4427 // Verify the root and child layers' quads are generated and not being
4429 ASSERT_EQ(2u, root_render_pass->quad_list.size());
4431 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
4432 gfx::RectF expected_child_visible_rect(child->content_bounds());
4433 EXPECT_RECT_EQ(expected_child_visible_rect,
4434 root_render_pass->quad_list[0]->visible_rect);
4436 LayerImpl* root = host_impl_->active_tree()->root_layer();
4437 gfx::RectF expected_root_visible_rect(root->content_bounds());
4438 EXPECT_RECT_EQ(expected_root_visible_rect,
4439 root_render_pass->quad_list[1]->visible_rect);
4442 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4443 host_impl_->DidDrawAllLayers(frame);
4444 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
4448 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
4449 scoped_ptr<SolidColorLayerImpl> root =
4450 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4451 root->SetAnchorPoint(gfx::PointF());
4452 root->SetPosition(gfx::PointF());
4453 root->SetBounds(gfx::Size(10, 10));
4454 root->SetContentBounds(gfx::Size(10, 10));
4455 root->SetDrawsContent(true);
4457 // Child layer is in the bottom right corner.
4458 scoped_ptr<SolidColorLayerImpl> child =
4459 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
4460 child->SetAnchorPoint(gfx::PointF(0.f, 0.f));
4461 child->SetPosition(gfx::PointF(9.f, 9.f));
4462 child->SetBounds(gfx::Size(1, 1));
4463 child->SetContentBounds(gfx::Size(1, 1));
4464 child->SetDrawsContent(true);
4465 root->AddChild(child.PassAs<LayerImpl>());
4467 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
4469 // Draw a frame. In the first frame, the entire viewport should be damaged.
4470 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
4471 DrawFrameAndTestDamage(full_frame_damage);
4473 // The second frame has damage that doesn't touch the child layer. Its quads
4474 // should still be generated.
4475 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
4476 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
4477 DrawFrameAndTestDamage(small_damage);
4479 // The third frame should have no damage, so no quads should be generated.
4480 gfx::Rect no_damage;
4481 DrawFrameAndTestDamage(no_damage);
4484 // TODO(reveman): Remove this test and the ability to prevent on demand raster
4485 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
4486 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
4487 LayerTreeSettings settings;
4488 CreateHostImpl(settings, CreateOutputSurface());
4489 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
4492 class FakeMaskLayerImpl : public LayerImpl {
4494 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
4496 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
4499 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
4504 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
4505 : LayerImpl(tree_impl, id) {}
4508 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
4509 LayerTreeSettings settings;
4510 settings.layer_transforms_should_scale_layer_contents = true;
4511 CreateHostImpl(settings, CreateOutputSurface());
4515 // +-- Scaling Layer (adds a 2x scale)
4517 // +-- Content Layer
4519 scoped_ptr<LayerImpl> scoped_root =
4520 LayerImpl::Create(host_impl_->active_tree(), 1);
4521 LayerImpl* root = scoped_root.get();
4522 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4524 scoped_ptr<LayerImpl> scoped_scaling_layer =
4525 LayerImpl::Create(host_impl_->active_tree(), 2);
4526 LayerImpl* scaling_layer = scoped_scaling_layer.get();
4527 root->AddChild(scoped_scaling_layer.Pass());
4529 scoped_ptr<LayerImpl> scoped_content_layer =
4530 LayerImpl::Create(host_impl_->active_tree(), 3);
4531 LayerImpl* content_layer = scoped_content_layer.get();
4532 scaling_layer->AddChild(scoped_content_layer.Pass());
4534 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4535 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4536 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4537 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4539 gfx::Size root_size(100, 100);
4540 root->SetBounds(root_size);
4541 root->SetContentBounds(root_size);
4542 root->SetPosition(gfx::PointF());
4543 root->SetAnchorPoint(gfx::PointF());
4545 gfx::Size scaling_layer_size(50, 50);
4546 scaling_layer->SetBounds(scaling_layer_size);
4547 scaling_layer->SetContentBounds(scaling_layer_size);
4548 scaling_layer->SetPosition(gfx::PointF());
4549 scaling_layer->SetAnchorPoint(gfx::PointF());
4550 gfx::Transform scale;
4551 scale.Scale(2.f, 2.f);
4552 scaling_layer->SetTransform(scale);
4554 content_layer->SetBounds(scaling_layer_size);
4555 content_layer->SetContentBounds(scaling_layer_size);
4556 content_layer->SetPosition(gfx::PointF());
4557 content_layer->SetAnchorPoint(gfx::PointF());
4558 content_layer->SetDrawsContent(true);
4560 mask_layer->SetBounds(scaling_layer_size);
4561 mask_layer->SetContentBounds(scaling_layer_size);
4562 mask_layer->SetPosition(gfx::PointF());
4563 mask_layer->SetAnchorPoint(gfx::PointF());
4564 mask_layer->SetDrawsContent(true);
4567 // Check that the tree scaling is correctly taken into account for the mask,
4568 // that should fully map onto the quad.
4569 float device_scale_factor = 1.f;
4570 host_impl_->SetViewportSize(root_size);
4571 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4573 LayerTreeHostImpl::FrameData frame;
4574 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4575 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4577 ASSERT_EQ(1u, frame.render_passes.size());
4578 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4579 ASSERT_EQ(DrawQuad::RENDER_PASS,
4580 frame.render_passes[0]->quad_list[0]->material);
4581 const RenderPassDrawQuad* render_pass_quad =
4582 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4583 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4584 render_pass_quad->rect.ToString());
4585 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4586 render_pass_quad->mask_uv_rect.ToString());
4588 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4589 host_impl_->DidDrawAllLayers(frame);
4593 // Applying a DSF should change the render surface size, but won't affect
4594 // which part of the mask is used.
4595 device_scale_factor = 2.f;
4596 gfx::Size device_viewport =
4597 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4598 host_impl_->SetViewportSize(device_viewport);
4599 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4600 host_impl_->active_tree()->set_needs_update_draw_properties();
4602 LayerTreeHostImpl::FrameData frame;
4603 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4604 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4606 ASSERT_EQ(1u, frame.render_passes.size());
4607 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4608 ASSERT_EQ(DrawQuad::RENDER_PASS,
4609 frame.render_passes[0]->quad_list[0]->material);
4610 const RenderPassDrawQuad* render_pass_quad =
4611 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4612 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4613 render_pass_quad->rect.ToString());
4614 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4615 render_pass_quad->mask_uv_rect.ToString());
4617 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4618 host_impl_->DidDrawAllLayers(frame);
4622 // Applying an equivalent content scale on the content layer and the mask
4623 // should still result in the same part of the mask being used.
4624 gfx::Size content_bounds =
4625 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
4626 device_scale_factor));
4627 content_layer->SetContentBounds(content_bounds);
4628 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4629 mask_layer->SetContentBounds(content_bounds);
4630 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4631 host_impl_->active_tree()->set_needs_update_draw_properties();
4633 LayerTreeHostImpl::FrameData frame;
4634 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4635 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4637 ASSERT_EQ(1u, frame.render_passes.size());
4638 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4639 ASSERT_EQ(DrawQuad::RENDER_PASS,
4640 frame.render_passes[0]->quad_list[0]->material);
4641 const RenderPassDrawQuad* render_pass_quad =
4642 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4643 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4644 render_pass_quad->rect.ToString());
4645 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4646 render_pass_quad->mask_uv_rect.ToString());
4648 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4649 host_impl_->DidDrawAllLayers(frame);
4653 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
4654 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4657 scoped_ptr<LayerImpl> scoped_root =
4658 LayerImpl::Create(host_impl_->active_tree(), 1);
4659 LayerImpl* root = scoped_root.get();
4660 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4662 scoped_ptr<LayerImpl> scoped_content_layer =
4663 LayerImpl::Create(host_impl_->active_tree(), 3);
4664 LayerImpl* content_layer = scoped_content_layer.get();
4665 root->AddChild(scoped_content_layer.Pass());
4667 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4668 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4669 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4670 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4672 gfx::Size root_size(100, 100);
4673 root->SetBounds(root_size);
4674 root->SetContentBounds(root_size);
4675 root->SetPosition(gfx::PointF());
4676 root->SetAnchorPoint(gfx::PointF());
4678 gfx::Size layer_size(50, 50);
4679 content_layer->SetBounds(layer_size);
4680 content_layer->SetContentBounds(layer_size);
4681 content_layer->SetPosition(gfx::PointF());
4682 content_layer->SetAnchorPoint(gfx::PointF());
4683 content_layer->SetDrawsContent(true);
4685 gfx::Size mask_size(100, 100);
4686 mask_layer->SetBounds(mask_size);
4687 mask_layer->SetContentBounds(mask_size);
4688 mask_layer->SetPosition(gfx::PointF());
4689 mask_layer->SetAnchorPoint(gfx::PointF());
4690 mask_layer->SetDrawsContent(true);
4692 // Check that the mask fills the surface.
4693 float device_scale_factor = 1.f;
4694 host_impl_->SetViewportSize(root_size);
4695 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4697 LayerTreeHostImpl::FrameData frame;
4698 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4699 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4701 ASSERT_EQ(1u, frame.render_passes.size());
4702 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4703 ASSERT_EQ(DrawQuad::RENDER_PASS,
4704 frame.render_passes[0]->quad_list[0]->material);
4705 const RenderPassDrawQuad* render_pass_quad =
4706 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4707 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4708 render_pass_quad->rect.ToString());
4709 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4710 render_pass_quad->mask_uv_rect.ToString());
4712 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4713 host_impl_->DidDrawAllLayers(frame);
4716 // Applying a DSF should change the render surface size, but won't affect
4717 // which part of the mask is used.
4718 device_scale_factor = 2.f;
4719 gfx::Size device_viewport =
4720 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4721 host_impl_->SetViewportSize(device_viewport);
4722 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4723 host_impl_->active_tree()->set_needs_update_draw_properties();
4725 LayerTreeHostImpl::FrameData frame;
4726 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4727 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4729 ASSERT_EQ(1u, frame.render_passes.size());
4730 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4731 ASSERT_EQ(DrawQuad::RENDER_PASS,
4732 frame.render_passes[0]->quad_list[0]->material);
4733 const RenderPassDrawQuad* render_pass_quad =
4734 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4735 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4736 render_pass_quad->rect.ToString());
4737 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4738 render_pass_quad->mask_uv_rect.ToString());
4740 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4741 host_impl_->DidDrawAllLayers(frame);
4744 // Applying an equivalent content scale on the content layer and the mask
4745 // should still result in the same part of the mask being used.
4746 gfx::Size layer_size_large =
4747 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
4748 content_layer->SetContentBounds(layer_size_large);
4749 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4750 gfx::Size mask_size_large =
4751 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
4752 mask_layer->SetContentBounds(mask_size_large);
4753 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4754 host_impl_->active_tree()->set_needs_update_draw_properties();
4756 LayerTreeHostImpl::FrameData frame;
4757 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4758 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4760 ASSERT_EQ(1u, frame.render_passes.size());
4761 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4762 ASSERT_EQ(DrawQuad::RENDER_PASS,
4763 frame.render_passes[0]->quad_list[0]->material);
4764 const RenderPassDrawQuad* render_pass_quad =
4765 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4766 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4767 render_pass_quad->rect.ToString());
4768 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4769 render_pass_quad->mask_uv_rect.ToString());
4771 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4772 host_impl_->DidDrawAllLayers(frame);
4775 // Applying a different contents scale to the mask layer means it will have
4776 // a larger texture, but it should use the same tex coords to cover the
4778 mask_layer->SetContentBounds(mask_size);
4779 mask_layer->SetContentsScale(1.f, 1.f);
4780 host_impl_->active_tree()->set_needs_update_draw_properties();
4782 LayerTreeHostImpl::FrameData frame;
4783 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4784 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4786 ASSERT_EQ(1u, frame.render_passes.size());
4787 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4788 ASSERT_EQ(DrawQuad::RENDER_PASS,
4789 frame.render_passes[0]->quad_list[0]->material);
4790 const RenderPassDrawQuad* render_pass_quad =
4791 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4792 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4793 render_pass_quad->rect.ToString());
4794 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4795 render_pass_quad->mask_uv_rect.ToString());
4797 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4798 host_impl_->DidDrawAllLayers(frame);
4802 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
4803 // The replica's mask layer has bounds 100x100 but the replica is of a
4804 // layer with bounds 50x50.
4806 scoped_ptr<LayerImpl> scoped_root =
4807 LayerImpl::Create(host_impl_->active_tree(), 1);
4808 LayerImpl* root = scoped_root.get();
4809 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4811 scoped_ptr<LayerImpl> scoped_content_layer =
4812 LayerImpl::Create(host_impl_->active_tree(), 3);
4813 LayerImpl* content_layer = scoped_content_layer.get();
4814 root->AddChild(scoped_content_layer.Pass());
4816 scoped_ptr<LayerImpl> scoped_replica_layer =
4817 LayerImpl::Create(host_impl_->active_tree(), 2);
4818 LayerImpl* replica_layer = scoped_replica_layer.get();
4819 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
4821 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4822 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4823 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4824 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4826 gfx::Size root_size(100, 100);
4827 root->SetBounds(root_size);
4828 root->SetContentBounds(root_size);
4829 root->SetPosition(gfx::PointF());
4830 root->SetAnchorPoint(gfx::PointF());
4832 gfx::Size layer_size(50, 50);
4833 content_layer->SetBounds(layer_size);
4834 content_layer->SetContentBounds(layer_size);
4835 content_layer->SetPosition(gfx::PointF());
4836 content_layer->SetAnchorPoint(gfx::PointF());
4837 content_layer->SetDrawsContent(true);
4839 gfx::Size mask_size(100, 100);
4840 mask_layer->SetBounds(mask_size);
4841 mask_layer->SetContentBounds(mask_size);
4842 mask_layer->SetPosition(gfx::PointF());
4843 mask_layer->SetAnchorPoint(gfx::PointF());
4844 mask_layer->SetDrawsContent(true);
4846 // Check that the mask fills the surface.
4847 float device_scale_factor = 1.f;
4848 host_impl_->SetViewportSize(root_size);
4849 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4851 LayerTreeHostImpl::FrameData frame;
4852 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4853 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4855 ASSERT_EQ(1u, frame.render_passes.size());
4856 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4857 ASSERT_EQ(DrawQuad::RENDER_PASS,
4858 frame.render_passes[0]->quad_list[1]->material);
4859 const RenderPassDrawQuad* replica_quad =
4860 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4861 EXPECT_TRUE(replica_quad->is_replica);
4862 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4863 replica_quad->rect.ToString());
4864 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4865 replica_quad->mask_uv_rect.ToString());
4867 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4868 host_impl_->DidDrawAllLayers(frame);
4871 // Applying a DSF should change the render surface size, but won't affect
4872 // which part of the mask is used.
4873 device_scale_factor = 2.f;
4874 gfx::Size device_viewport =
4875 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4876 host_impl_->SetViewportSize(device_viewport);
4877 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4878 host_impl_->active_tree()->set_needs_update_draw_properties();
4880 LayerTreeHostImpl::FrameData frame;
4881 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4882 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4884 ASSERT_EQ(1u, frame.render_passes.size());
4885 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4886 ASSERT_EQ(DrawQuad::RENDER_PASS,
4887 frame.render_passes[0]->quad_list[1]->material);
4888 const RenderPassDrawQuad* replica_quad =
4889 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4890 EXPECT_TRUE(replica_quad->is_replica);
4891 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4892 replica_quad->rect.ToString());
4893 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4894 replica_quad->mask_uv_rect.ToString());
4896 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4897 host_impl_->DidDrawAllLayers(frame);
4900 // Applying an equivalent content scale on the content layer and the mask
4901 // should still result in the same part of the mask being used.
4902 gfx::Size layer_size_large =
4903 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
4904 content_layer->SetContentBounds(layer_size_large);
4905 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4906 gfx::Size mask_size_large =
4907 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
4908 mask_layer->SetContentBounds(mask_size_large);
4909 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4910 host_impl_->active_tree()->set_needs_update_draw_properties();
4912 LayerTreeHostImpl::FrameData frame;
4913 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4914 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4916 ASSERT_EQ(1u, frame.render_passes.size());
4917 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4918 ASSERT_EQ(DrawQuad::RENDER_PASS,
4919 frame.render_passes[0]->quad_list[1]->material);
4920 const RenderPassDrawQuad* replica_quad =
4921 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4922 EXPECT_TRUE(replica_quad->is_replica);
4923 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4924 replica_quad->rect.ToString());
4925 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4926 replica_quad->mask_uv_rect.ToString());
4928 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4929 host_impl_->DidDrawAllLayers(frame);
4932 // Applying a different contents scale to the mask layer means it will have
4933 // a larger texture, but it should use the same tex coords to cover the
4935 mask_layer->SetContentBounds(mask_size);
4936 mask_layer->SetContentsScale(1.f, 1.f);
4937 host_impl_->active_tree()->set_needs_update_draw_properties();
4939 LayerTreeHostImpl::FrameData frame;
4940 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
4941 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4943 ASSERT_EQ(1u, frame.render_passes.size());
4944 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4945 ASSERT_EQ(DrawQuad::RENDER_PASS,
4946 frame.render_passes[0]->quad_list[1]->material);
4947 const RenderPassDrawQuad* replica_quad =
4948 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4949 EXPECT_TRUE(replica_quad->is_replica);
4950 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4951 replica_quad->rect.ToString());
4952 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4953 replica_quad->mask_uv_rect.ToString());
4955 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4956 host_impl_->DidDrawAllLayers(frame);
4960 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
4961 // The replica is of a layer with bounds 50x50, but it has a child that causes
4962 // the surface bounds to be larger.
4964 scoped_ptr<LayerImpl> scoped_root =
4965 LayerImpl::Create(host_impl_->active_tree(), 1);
4966 LayerImpl* root = scoped_root.get();
4967 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4969 scoped_ptr<LayerImpl> scoped_content_layer =
4970 LayerImpl::Create(host_impl_->active_tree(), 2);
4971 LayerImpl* content_layer = scoped_content_layer.get();
4972 root->AddChild(scoped_content_layer.Pass());
4974 scoped_ptr<LayerImpl> scoped_content_child_layer =
4975 LayerImpl::Create(host_impl_->active_tree(), 3);
4976 LayerImpl* content_child_layer = scoped_content_child_layer.get();
4977 content_layer->AddChild(scoped_content_child_layer.Pass());
4979 scoped_ptr<LayerImpl> scoped_replica_layer =
4980 LayerImpl::Create(host_impl_->active_tree(), 4);
4981 LayerImpl* replica_layer = scoped_replica_layer.get();
4982 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
4984 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4985 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
4986 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4987 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4989 gfx::Size root_size(100, 100);
4990 root->SetBounds(root_size);
4991 root->SetContentBounds(root_size);
4992 root->SetPosition(gfx::PointF());
4993 root->SetAnchorPoint(gfx::PointF());
4995 gfx::Size layer_size(50, 50);
4996 content_layer->SetBounds(layer_size);
4997 content_layer->SetContentBounds(layer_size);
4998 content_layer->SetPosition(gfx::PointF());
4999 content_layer->SetAnchorPoint(gfx::PointF());
5000 content_layer->SetDrawsContent(true);
5002 gfx::Size child_size(50, 50);
5003 content_child_layer->SetBounds(child_size);
5004 content_child_layer->SetContentBounds(child_size);
5005 content_child_layer->SetPosition(gfx::Point(50, 0));
5006 content_child_layer->SetAnchorPoint(gfx::PointF());
5007 content_child_layer->SetDrawsContent(true);
5009 gfx::Size mask_size(50, 50);
5010 mask_layer->SetBounds(mask_size);
5011 mask_layer->SetContentBounds(mask_size);
5012 mask_layer->SetPosition(gfx::PointF());
5013 mask_layer->SetAnchorPoint(gfx::PointF());
5014 mask_layer->SetDrawsContent(true);
5016 float device_scale_factor = 1.f;
5017 host_impl_->SetViewportSize(root_size);
5018 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5020 LayerTreeHostImpl::FrameData frame;
5021 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5022 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5024 ASSERT_EQ(1u, frame.render_passes.size());
5025 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5027 // The surface is 100x50.
5028 ASSERT_EQ(DrawQuad::RENDER_PASS,
5029 frame.render_passes[0]->quad_list[0]->material);
5030 const RenderPassDrawQuad* render_pass_quad =
5031 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5032 EXPECT_FALSE(render_pass_quad->is_replica);
5033 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5034 render_pass_quad->rect.ToString());
5036 // The mask covers the owning layer only.
5037 ASSERT_EQ(DrawQuad::RENDER_PASS,
5038 frame.render_passes[0]->quad_list[1]->material);
5039 const RenderPassDrawQuad* replica_quad =
5040 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5041 EXPECT_TRUE(replica_quad->is_replica);
5042 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5043 replica_quad->rect.ToString());
5044 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
5045 replica_quad->mask_uv_rect.ToString());
5047 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5048 host_impl_->DidDrawAllLayers(frame);
5051 // Move the child to (-50, 0) instead. Now the mask should be moved to still
5052 // cover the layer being replicated.
5053 content_child_layer->SetPosition(gfx::Point(-50, 0));
5055 LayerTreeHostImpl::FrameData frame;
5056 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5057 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5059 ASSERT_EQ(1u, frame.render_passes.size());
5060 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5062 // The surface is 100x50 with its origin at (-50, 0).
5063 ASSERT_EQ(DrawQuad::RENDER_PASS,
5064 frame.render_passes[0]->quad_list[0]->material);
5065 const RenderPassDrawQuad* render_pass_quad =
5066 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5067 EXPECT_FALSE(render_pass_quad->is_replica);
5068 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5069 render_pass_quad->rect.ToString());
5071 // The mask covers the owning layer only.
5072 ASSERT_EQ(DrawQuad::RENDER_PASS,
5073 frame.render_passes[0]->quad_list[1]->material);
5074 const RenderPassDrawQuad* replica_quad =
5075 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5076 EXPECT_TRUE(replica_quad->is_replica);
5077 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5078 replica_quad->rect.ToString());
5079 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
5080 replica_quad->mask_uv_rect.ToString());
5082 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5083 host_impl_->DidDrawAllLayers(frame);
5087 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
5088 // The masked layer has bounds 50x50, but it has a child that causes
5089 // the surface bounds to be larger. It also has a parent that clips the
5090 // masked layer and its surface.
5092 scoped_ptr<LayerImpl> scoped_root =
5093 LayerImpl::Create(host_impl_->active_tree(), 1);
5094 LayerImpl* root = scoped_root.get();
5095 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5097 scoped_ptr<LayerImpl> scoped_clipping_layer =
5098 LayerImpl::Create(host_impl_->active_tree(), 2);
5099 LayerImpl* clipping_layer = scoped_clipping_layer.get();
5100 root->AddChild(scoped_clipping_layer.Pass());
5102 scoped_ptr<LayerImpl> scoped_content_layer =
5103 LayerImpl::Create(host_impl_->active_tree(), 3);
5104 LayerImpl* content_layer = scoped_content_layer.get();
5105 clipping_layer->AddChild(scoped_content_layer.Pass());
5107 scoped_ptr<LayerImpl> scoped_content_child_layer =
5108 LayerImpl::Create(host_impl_->active_tree(), 4);
5109 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5110 content_layer->AddChild(scoped_content_child_layer.Pass());
5112 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5113 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
5114 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5115 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5117 gfx::Size root_size(100, 100);
5118 root->SetBounds(root_size);
5119 root->SetContentBounds(root_size);
5120 root->SetPosition(gfx::PointF());
5121 root->SetAnchorPoint(gfx::PointF());
5123 gfx::Rect clipping_rect(20, 10, 10, 20);
5124 clipping_layer->SetBounds(clipping_rect.size());
5125 clipping_layer->SetContentBounds(clipping_rect.size());
5126 clipping_layer->SetPosition(clipping_rect.origin());
5127 clipping_layer->SetAnchorPoint(gfx::PointF());
5128 clipping_layer->SetMasksToBounds(true);
5130 gfx::Size layer_size(50, 50);
5131 content_layer->SetBounds(layer_size);
5132 content_layer->SetContentBounds(layer_size);
5133 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
5134 content_layer->SetAnchorPoint(gfx::PointF());
5135 content_layer->SetDrawsContent(true);
5137 gfx::Size child_size(50, 50);
5138 content_child_layer->SetBounds(child_size);
5139 content_child_layer->SetContentBounds(child_size);
5140 content_child_layer->SetPosition(gfx::Point(50, 0));
5141 content_child_layer->SetAnchorPoint(gfx::PointF());
5142 content_child_layer->SetDrawsContent(true);
5144 gfx::Size mask_size(100, 100);
5145 mask_layer->SetBounds(mask_size);
5146 mask_layer->SetContentBounds(mask_size);
5147 mask_layer->SetPosition(gfx::PointF());
5148 mask_layer->SetAnchorPoint(gfx::PointF());
5149 mask_layer->SetDrawsContent(true);
5151 float device_scale_factor = 1.f;
5152 host_impl_->SetViewportSize(root_size);
5153 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5155 LayerTreeHostImpl::FrameData frame;
5156 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5157 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5159 ASSERT_EQ(1u, frame.render_passes.size());
5160 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5162 // The surface is clipped to 10x20.
5163 ASSERT_EQ(DrawQuad::RENDER_PASS,
5164 frame.render_passes[0]->quad_list[0]->material);
5165 const RenderPassDrawQuad* render_pass_quad =
5166 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5167 EXPECT_FALSE(render_pass_quad->is_replica);
5168 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
5169 render_pass_quad->rect.ToString());
5171 // The masked layer is 50x50, but the surface size is 10x20. So the texture
5172 // coords in the mask are scaled by 10/50 and 20/50.
5173 // The surface is clipped to (20,10) so the mask texture coords are offset
5174 // by 20/50 and 10/50
5175 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f),
5176 1.f / 50.f).ToString(),
5177 render_pass_quad->mask_uv_rect.ToString());
5179 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5180 host_impl_->DidDrawAllLayers(frame);
5184 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
5186 using GLRenderer::SetupQuadForAntialiasing;
5189 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
5190 // Due to precision issues (especially on Android), sometimes far
5191 // away quads can end up thinking they need AA.
5192 float device_scale_factor = 4.f / 3.f;
5193 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5194 gfx::Size root_size(2000, 1000);
5195 gfx::Size device_viewport_size =
5196 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
5197 host_impl_->SetViewportSize(device_viewport_size);
5199 host_impl_->CreatePendingTree();
5200 host_impl_->pending_tree()
5201 ->SetPageScaleFactorAndLimits(1.f, 1.f / 16.f, 16.f);
5203 scoped_ptr<LayerImpl> scoped_root =
5204 LayerImpl::Create(host_impl_->pending_tree(), 1);
5205 LayerImpl* root = scoped_root.get();
5207 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
5209 scoped_ptr<LayerImpl> scoped_scrolling_layer =
5210 LayerImpl::Create(host_impl_->pending_tree(), 2);
5211 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
5212 root->AddChild(scoped_scrolling_layer.Pass());
5214 gfx::Size content_layer_bounds(100000, 100);
5215 gfx::Size pile_tile_size(3000, 3000);
5216 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
5217 pile_tile_size, content_layer_bounds));
5219 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
5220 FakePictureLayerImpl::CreateWithPile(host_impl_->pending_tree(), 3, pile);
5221 LayerImpl* content_layer = scoped_content_layer.get();
5222 scrolling_layer->AddChild(scoped_content_layer.PassAs<LayerImpl>());
5223 content_layer->SetBounds(content_layer_bounds);
5224 content_layer->SetDrawsContent(true);
5226 root->SetBounds(root_size);
5228 gfx::Vector2d scroll_offset(100000, 0);
5229 scrolling_layer->SetScrollClipLayer(root->id());
5230 scrolling_layer->SetScrollOffset(scroll_offset);
5232 host_impl_->ActivatePendingTree();
5234 host_impl_->active_tree()->UpdateDrawProperties();
5235 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
5237 LayerTreeHostImpl::FrameData frame;
5238 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5239 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5241 ASSERT_EQ(1u, frame.render_passes.size());
5242 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
5243 const DrawQuad* quad = frame.render_passes[0]->quad_list[0];
5246 gfx::QuadF device_layer_quad;
5248 GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
5249 quad->quadTransform(), quad, &device_layer_quad, edge);
5250 EXPECT_FALSE(antialiased);
5252 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5253 host_impl_->DidDrawAllLayers(frame);
5257 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
5259 CompositorFrameMetadataTest()
5260 : swap_buffers_complete_(0) {}
5262 virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {
5263 swap_buffers_complete_++;
5266 int swap_buffers_complete_;
5269 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
5270 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5272 LayerTreeHostImpl::FrameData frame;
5273 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5274 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5275 host_impl_->DrawLayers(&frame, base::TimeTicks());
5276 host_impl_->DidDrawAllLayers(frame);
5278 CompositorFrameAck ack;
5279 host_impl_->ReclaimResources(&ack);
5280 host_impl_->OnSwapBuffersComplete();
5281 EXPECT_EQ(swap_buffers_complete_, 1);
5284 class CountingSoftwareDevice : public SoftwareOutputDevice {
5286 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5288 virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
5290 return SoftwareOutputDevice::BeginPaint(damage_rect);
5292 virtual void EndPaint(SoftwareFrameData* frame_data) OVERRIDE {
5294 SoftwareOutputDevice::EndPaint(frame_data);
5297 int frames_began_, frames_ended_;
5300 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
5301 // No main thread evictions in resourceless software mode.
5302 set_reduce_memory_result(false);
5303 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
5304 FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
5305 scoped_ptr<SoftwareOutputDevice>(software_device)).release();
5306 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5307 scoped_ptr<OutputSurface>(output_surface)));
5308 host_impl_->SetViewportSize(gfx::Size(50, 50));
5310 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5312 output_surface->set_forced_draw_to_software_device(true);
5313 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5315 EXPECT_EQ(0, software_device->frames_began_);
5316 EXPECT_EQ(0, software_device->frames_ended_);
5320 EXPECT_EQ(1, software_device->frames_began_);
5321 EXPECT_EQ(1, software_device->frames_ended_);
5323 // Call other API methods that are likely to hit NULL pointer in this mode.
5324 EXPECT_TRUE(host_impl_->AsValue());
5325 EXPECT_TRUE(host_impl_->ActivationStateAsValue());
5328 TEST_F(LayerTreeHostImplTest,
5329 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
5330 set_reduce_memory_result(false);
5331 FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
5332 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())).release();
5333 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5334 scoped_ptr<OutputSurface>(output_surface)));
5336 output_surface->set_forced_draw_to_software_device(true);
5337 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5339 // SolidColorLayerImpl will be drawn.
5340 scoped_ptr<SolidColorLayerImpl> root_layer =
5341 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5343 // VideoLayerImpl will not be drawn.
5344 FakeVideoFrameProvider provider;
5345 scoped_ptr<VideoLayerImpl> video_layer =
5346 VideoLayerImpl::Create(host_impl_->active_tree(), 2, &provider);
5347 video_layer->SetBounds(gfx::Size(10, 10));
5348 video_layer->SetContentBounds(gfx::Size(10, 10));
5349 video_layer->SetDrawsContent(true);
5350 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
5351 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5353 LayerTreeHostImpl::FrameData frame;
5354 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5355 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5356 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5357 host_impl_->DidDrawAllLayers(frame);
5359 EXPECT_EQ(1u, frame.will_draw_layers.size());
5360 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
5363 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
5365 virtual void SetUp() OVERRIDE {
5366 LayerTreeHostImplTest::SetUp();
5368 set_reduce_memory_result(false);
5370 scoped_ptr<FakeOutputSurface> output_surface(
5371 FakeOutputSurface::CreateDeferredGL(
5372 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())));
5373 output_surface_ = output_surface.get();
5375 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5376 output_surface.PassAs<OutputSurface>()));
5378 scoped_ptr<SolidColorLayerImpl> root_layer =
5379 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5380 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5382 onscreen_context_provider_ = TestContextProvider::Create();
5383 offscreen_context_provider_ = TestContextProvider::Create();
5386 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {
5387 did_update_renderer_capabilities_ = true;
5390 FakeOutputSurface* output_surface_;
5391 scoped_refptr<TestContextProvider> onscreen_context_provider_;
5392 scoped_refptr<TestContextProvider> offscreen_context_provider_;
5393 bool did_update_renderer_capabilities_;
5397 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
5401 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5402 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5404 // DeferredInitialize and hardware draw.
5405 did_update_renderer_capabilities_ = false;
5406 EXPECT_TRUE(output_surface_->InitializeAndSetContext3d(
5407 onscreen_context_provider_, offscreen_context_provider_));
5408 EXPECT_EQ(onscreen_context_provider_,
5409 host_impl_->output_surface()->context_provider());
5410 EXPECT_EQ(offscreen_context_provider_,
5411 host_impl_->offscreen_context_provider());
5412 EXPECT_TRUE(did_update_renderer_capabilities_);
5414 // Defer intialized GL draw.
5417 // Revert back to software.
5418 did_update_renderer_capabilities_ = false;
5419 output_surface_->ReleaseGL();
5420 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5421 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5422 EXPECT_TRUE(did_update_renderer_capabilities_);
5424 // Software draw again.
5428 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_0) {
5432 // Fail initialization of the onscreen context before the OutputSurface binds
5433 // it to the thread.
5434 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5436 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5437 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5439 // DeferredInitialize fails.
5440 did_update_renderer_capabilities_ = false;
5441 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5442 onscreen_context_provider_, offscreen_context_provider_));
5443 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5444 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5445 EXPECT_FALSE(did_update_renderer_capabilities_);
5447 // Software draw again.
5451 // TODO(boliu): After r239415, fails_OnscreenContext_1 and 2 are exactly the
5452 // same as 0. They were supposed to test makeCurrent failing in the
5453 // OutputSurface, LayerTreeHostImpl, and GLRenderer respectively.
5454 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_1) {
5458 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5459 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5461 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5463 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5464 // DeferredInitialize fails.
5465 did_update_renderer_capabilities_ = false;
5466 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5467 onscreen_context_provider_, offscreen_context_provider_));
5468 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5469 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5470 EXPECT_FALSE(did_update_renderer_capabilities_);
5473 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_2) {
5477 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5478 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5480 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5482 // DeferredInitialize fails.
5483 did_update_renderer_capabilities_ = false;
5484 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5485 onscreen_context_provider_, offscreen_context_provider_));
5486 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5487 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5488 EXPECT_FALSE(did_update_renderer_capabilities_);
5491 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OffscreenContext) {
5495 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5496 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5498 // Fail initialization of the offscreen context.
5499 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5501 // DeferredInitialize fails.
5502 did_update_renderer_capabilities_ = false;
5503 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5504 onscreen_context_provider_, offscreen_context_provider_));
5505 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5506 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5507 EXPECT_FALSE(did_update_renderer_capabilities_);
5510 // Checks that we have a non-0 default allocation if we pass a context that
5511 // doesn't support memory management extensions.
5512 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5513 LayerTreeSettings settings;
5514 host_impl_ = LayerTreeHostImpl::Create(
5515 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
5517 scoped_ptr<OutputSurface> output_surface(
5518 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5519 host_impl_->InitializeRenderer(output_surface.Pass());
5520 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5523 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5524 ManagedMemoryPolicy policy1(
5525 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5526 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5527 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5528 int required_only_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5529 gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY);
5530 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5531 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5533 // GPU rasterization should be disabled by default.
5534 EXPECT_EQ(host_impl_->settings().gpu_rasterization, false);
5536 host_impl_->SetVisible(true);
5537 host_impl_->SetMemoryPolicy(policy1);
5538 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5539 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5541 host_impl_->SetVisible(false);
5542 EXPECT_EQ(0u, current_limit_bytes_);
5543 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5545 host_impl_->SetVisible(true);
5546 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5547 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5549 // Now enable GPU rasterization and test if we get required only cutoff,
5551 LayerTreeSettings settings;
5552 settings.gpu_rasterization = true;
5553 host_impl_ = LayerTreeHostImpl::Create(
5554 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
5556 host_impl_->SetVisible(true);
5557 host_impl_->SetMemoryPolicy(policy1);
5558 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5559 EXPECT_EQ(required_only_cutoff_value, current_priority_cutoff_value_);
5561 host_impl_->SetVisible(false);
5562 EXPECT_EQ(0u, current_limit_bytes_);
5563 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5566 class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
5568 virtual void SetUp() OVERRIDE {
5569 LayerTreeSettings settings;
5570 settings.impl_side_painting = true;
5572 fake_host_impl_ = new FakeLayerTreeHostImpl(settings, &proxy_);
5573 host_impl_.reset(fake_host_impl_);
5574 host_impl_->InitializeRenderer(CreateOutputSurface());
5575 host_impl_->SetViewportSize(gfx::Size(10, 10));
5578 FakeLayerTreeHostImpl* fake_host_impl_;
5581 TEST_F(LayerTreeHostImplTestManageTiles, ManageTilesWhenInvisible) {
5582 fake_host_impl_->DidModifyTilePriorities();
5583 EXPECT_TRUE(fake_host_impl_->manage_tiles_needed());
5584 fake_host_impl_->SetVisible(false);
5585 EXPECT_FALSE(fake_host_impl_->manage_tiles_needed());
5588 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
5589 scoped_ptr<TestWebGraphicsContext3D> context =
5590 TestWebGraphicsContext3D::Create();
5591 TestWebGraphicsContext3D* context3d = context.get();
5592 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5593 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5595 EXPECT_EQ(0u, context3d->NumTextures());
5598 skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
5599 skbitmap.allocPixels();
5600 skbitmap.setImmutable();
5602 UIResourceId ui_resource_id = 1;
5603 UIResourceBitmap bitmap(skbitmap);
5604 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5605 EXPECT_EQ(1u, context3d->NumTextures());
5606 ResourceProvider::ResourceId id1 =
5607 host_impl_->ResourceIdForUIResource(ui_resource_id);
5610 // Multiple requests with the same id is allowed. The previous texture is
5612 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5613 EXPECT_EQ(1u, context3d->NumTextures());
5614 ResourceProvider::ResourceId id2 =
5615 host_impl_->ResourceIdForUIResource(ui_resource_id);
5617 EXPECT_NE(id1, id2);
5619 // Deleting invalid UIResourceId is allowed and does not change state.
5620 host_impl_->DeleteUIResource(-1);
5621 EXPECT_EQ(1u, context3d->NumTextures());
5623 // Should return zero for invalid UIResourceId. Number of textures should
5625 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
5626 EXPECT_EQ(1u, context3d->NumTextures());
5628 host_impl_->DeleteUIResource(ui_resource_id);
5629 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
5630 EXPECT_EQ(0u, context3d->NumTextures());
5632 // Should not change state for multiple deletion on one UIResourceId
5633 host_impl_->DeleteUIResource(ui_resource_id);
5634 EXPECT_EQ(0u, context3d->NumTextures());
5637 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
5638 scoped_ptr<TestWebGraphicsContext3D> context =
5639 TestWebGraphicsContext3D::Create();
5640 TestWebGraphicsContext3D* context3d = context.get();
5641 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5642 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5644 EXPECT_EQ(0u, context3d->NumTextures());
5646 gfx::Size size(4, 4);
5647 // SkImageInfo has no support for ETC1. The |info| below contains the right
5648 // total pixel size for the bitmap but not the right height and width. The
5649 // correct width/height are passed directly to UIResourceBitmap.
5651 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
5652 skia::RefPtr<SkPixelRef> pixel_ref =
5653 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
5654 pixel_ref->setImmutable();
5655 UIResourceBitmap bitmap(pixel_ref, size);
5656 UIResourceId ui_resource_id = 1;
5657 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5658 EXPECT_EQ(1u, context3d->NumTextures());
5659 ResourceProvider::ResourceId id1 =
5660 host_impl_->ResourceIdForUIResource(ui_resource_id);
5664 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
5667 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
5668 scoped_refptr<TestContextProvider> context_provider =
5669 TestContextProvider::Create();
5673 FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>());
5675 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5677 ScopedPtrVector<CopyOutputRequest> requests;
5678 requests.push_back(CopyOutputRequest::CreateRequest(
5679 base::Bind(&ShutdownReleasesContext_Callback)));
5681 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
5683 LayerTreeHostImpl::FrameData frame;
5684 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5685 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5686 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5687 host_impl_->DidDrawAllLayers(frame);
5689 // The CopyOutputResult's callback has a ref on the ContextProvider and a
5690 // texture in a texture mailbox.
5691 EXPECT_FALSE(context_provider->HasOneRef());
5692 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
5696 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
5697 // released, and the texture deleted.
5698 EXPECT_TRUE(context_provider->HasOneRef());
5699 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
5702 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
5703 // When flinging via touch, only the child should scroll (we should not
5705 gfx::Size surface_size(10, 10);
5706 gfx::Size content_size(20, 20);
5707 scoped_ptr<LayerImpl> root_clip =
5708 LayerImpl::Create(host_impl_->active_tree(), 3);
5709 scoped_ptr<LayerImpl> root =
5710 CreateScrollableLayer(1, content_size, root_clip.get());
5711 root->SetIsContainerForFixedPositionLayers(true);
5712 scoped_ptr<LayerImpl> child =
5713 CreateScrollableLayer(2, content_size, root_clip.get());
5715 root->AddChild(child.Pass());
5716 int root_id = root->id();
5717 root_clip->AddChild(root.Pass());
5719 host_impl_->SetViewportSize(surface_size);
5720 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
5721 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
5722 host_impl_->active_tree()->DidBecomeActive();
5725 EXPECT_EQ(InputHandler::ScrollStarted,
5726 host_impl_->ScrollBegin(gfx::Point(),
5727 InputHandler::Gesture));
5729 EXPECT_EQ(InputHandler::ScrollStarted,
5730 host_impl_->FlingScrollBegin());
5732 gfx::Vector2d scroll_delta(0, 100);
5733 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5734 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5736 host_impl_->ScrollEnd();
5738 scoped_ptr<ScrollAndScaleSet> scroll_info =
5739 host_impl_->ProcessScrollDeltas();
5741 // Only the child should have scrolled.
5742 ASSERT_EQ(1u, scroll_info->scrolls.size());
5743 ExpectNone(*scroll_info.get(), root_id);
5747 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
5748 // Scroll a child layer beyond its maximum scroll range and make sure the
5749 // the scroll doesn't bubble up to the parent layer.
5750 gfx::Size surface_size(10, 10);
5751 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
5752 scoped_ptr<LayerImpl> root_scrolling =
5753 CreateScrollableLayer(2, surface_size, root.get());
5755 scoped_ptr<LayerImpl> grand_child =
5756 CreateScrollableLayer(4, surface_size, root.get());
5757 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
5759 scoped_ptr<LayerImpl> child =
5760 CreateScrollableLayer(3, surface_size, root.get());
5761 child->SetScrollOffset(gfx::Vector2d(0, 4));
5762 child->AddChild(grand_child.Pass());
5764 root_scrolling->AddChild(child.Pass());
5765 root->AddChild(root_scrolling.Pass());
5766 host_impl_->active_tree()->SetRootLayer(root.Pass());
5767 host_impl_->active_tree()->DidBecomeActive();
5768 host_impl_->SetViewportSize(surface_size);
5771 scoped_ptr<ScrollAndScaleSet> scroll_info;
5773 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
5774 LayerImpl* grand_child = child->children()[0];
5776 gfx::Vector2d scroll_delta(0, -2);
5777 EXPECT_EQ(InputHandler::ScrollStarted,
5778 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
5779 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5781 // The grand child should have scrolled up to its limit.
5782 scroll_info = host_impl_->ProcessScrollDeltas();
5783 ASSERT_EQ(1u, scroll_info->scrolls.size());
5784 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5785 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
5787 // The child should have received the bubbled delta, but the locked
5788 // scrolling layer should remain set as the grand child.
5789 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5790 scroll_info = host_impl_->ProcessScrollDeltas();
5791 ASSERT_EQ(2u, scroll_info->scrolls.size());
5792 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5793 ExpectContains(*scroll_info, child->id(), scroll_delta);
5794 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
5796 // The first |ScrollBy| after the fling should re-lock the scrolling
5797 // layer to the first layer that scrolled, which is the child.
5798 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
5799 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5800 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
5802 // The child should have scrolled up to its limit.
5803 scroll_info = host_impl_->ProcessScrollDeltas();
5804 ASSERT_EQ(2u, scroll_info->scrolls.size());
5805 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5806 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
5808 // As the locked layer is at it's limit, no further scrolling can occur.
5809 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5810 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
5811 host_impl_->ScrollEnd();
5815 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
5816 // When flinging via wheel, the root should eventually scroll (we should
5818 gfx::Size surface_size(10, 10);
5819 gfx::Size content_size(20, 20);
5820 scoped_ptr<LayerImpl> root_clip =
5821 LayerImpl::Create(host_impl_->active_tree(), 3);
5822 scoped_ptr<LayerImpl> root_scroll =
5823 CreateScrollableLayer(1, content_size, root_clip.get());
5824 int root_scroll_id = root_scroll->id();
5825 scoped_ptr<LayerImpl> child =
5826 CreateScrollableLayer(2, content_size, root_clip.get());
5828 root_scroll->AddChild(child.Pass());
5829 root_clip->AddChild(root_scroll.Pass());
5831 host_impl_->SetViewportSize(surface_size);
5832 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
5833 host_impl_->active_tree()->DidBecomeActive();
5836 EXPECT_EQ(InputHandler::ScrollStarted,
5837 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
5839 EXPECT_EQ(InputHandler::ScrollStarted,
5840 host_impl_->FlingScrollBegin());
5842 gfx::Vector2d scroll_delta(0, 100);
5843 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5844 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5846 host_impl_->ScrollEnd();
5848 scoped_ptr<ScrollAndScaleSet> scroll_info =
5849 host_impl_->ProcessScrollDeltas();
5851 // The root should have scrolled.
5852 ASSERT_EQ(2u, scroll_info->scrolls.size());
5853 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
5857 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
5858 // to CompositorFrameMetadata after SwapBuffers();
5859 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
5860 scoped_ptr<SolidColorLayerImpl> root =
5861 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5862 root->SetAnchorPoint(gfx::PointF());
5863 root->SetPosition(gfx::PointF());
5864 root->SetBounds(gfx::Size(10, 10));
5865 root->SetContentBounds(gfx::Size(10, 10));
5866 root->SetDrawsContent(true);
5868 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
5870 FakeOutputSurface* fake_output_surface =
5871 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
5873 const std::vector<ui::LatencyInfo>& metadata_latency_before =
5874 fake_output_surface->last_sent_frame().metadata.latency_info;
5875 EXPECT_TRUE(metadata_latency_before.empty());
5877 ui::LatencyInfo latency_info;
5878 latency_info.AddLatencyNumber(
5879 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
5880 scoped_ptr<SwapPromise> swap_promise(
5881 new LatencyInfoSwapPromise(latency_info));
5882 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
5883 host_impl_->SetNeedsRedraw();
5885 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
5886 LayerTreeHostImpl::FrameData frame;
5887 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS,
5888 host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5889 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5890 host_impl_->DidDrawAllLayers(frame);
5891 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
5893 const std::vector<ui::LatencyInfo>& metadata_latency_after =
5894 fake_output_surface->last_sent_frame().metadata.latency_info;
5895 EXPECT_EQ(1u, metadata_latency_after.size());
5896 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
5897 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
5900 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
5902 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
5903 LayerTreeHostImpl* layer_tree_host_impl,
5904 int* set_needs_commit_count,
5905 int* set_needs_redraw_count)
5906 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
5907 set_needs_commit_count_(set_needs_commit_count),
5908 set_needs_redraw_count_(set_needs_redraw_count) {}
5910 virtual ~SimpleSwapPromiseMonitor() {}
5912 virtual void OnSetNeedsCommitOnMain() OVERRIDE {
5913 (*set_needs_commit_count_)++;
5916 virtual void OnSetNeedsRedrawOnImpl() OVERRIDE {
5917 (*set_needs_redraw_count_)++;
5921 int* set_needs_commit_count_;
5922 int* set_needs_redraw_count_;
5925 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
5926 int set_needs_commit_count = 0;
5927 int set_needs_redraw_count = 0;
5930 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
5931 new SimpleSwapPromiseMonitor(NULL,
5933 &set_needs_commit_count,
5934 &set_needs_redraw_count));
5935 host_impl_->SetNeedsRedraw();
5936 EXPECT_EQ(0, set_needs_commit_count);
5937 EXPECT_EQ(1, set_needs_redraw_count);
5940 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
5942 host_impl_->SetNeedsRedraw();
5943 EXPECT_EQ(0, set_needs_commit_count);
5944 EXPECT_EQ(1, set_needs_redraw_count);
5947 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
5948 new SimpleSwapPromiseMonitor(NULL,
5950 &set_needs_commit_count,
5951 &set_needs_redraw_count));
5952 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
5953 EXPECT_EQ(0, set_needs_commit_count);
5954 EXPECT_EQ(2, set_needs_redraw_count);
5958 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
5959 new SimpleSwapPromiseMonitor(NULL,
5961 &set_needs_commit_count,
5962 &set_needs_redraw_count));
5963 // Empty damage rect won't signal the monitor.
5964 host_impl_->SetNeedsRedrawRect(gfx::Rect());
5965 EXPECT_EQ(0, set_needs_commit_count);
5966 EXPECT_EQ(2, set_needs_redraw_count);
5970 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
5972 virtual void SetUp() OVERRIDE {
5973 LayerTreeSettings settings = DefaultSettings();
5974 settings.calculate_top_controls_position = true;
5975 CreateHostImpl(settings, CreateOutputSurface());
5979 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
5980 SetupScrollAndContentsLayers(gfx::Size(100, 100))
5981 ->SetScrollOffset(gfx::Vector2d(0, 10));
5982 host_impl_->Animate(base::TimeTicks(), base::Time());
5983 EXPECT_FALSE(did_request_redraw_);