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/render_surface_impl.h"
24 #include "cc/layers/solid_color_layer_impl.h"
25 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
26 #include "cc/layers/texture_layer_impl.h"
27 #include "cc/layers/tiled_layer_impl.h"
28 #include "cc/layers/video_layer_impl.h"
29 #include "cc/output/begin_frame_args.h"
30 #include "cc/output/compositor_frame_ack.h"
31 #include "cc/output/compositor_frame_metadata.h"
32 #include "cc/output/copy_output_request.h"
33 #include "cc/output/copy_output_result.h"
34 #include "cc/output/gl_renderer.h"
35 #include "cc/quads/render_pass_draw_quad.h"
36 #include "cc/quads/solid_color_draw_quad.h"
37 #include "cc/quads/texture_draw_quad.h"
38 #include "cc/quads/tile_draw_quad.h"
39 #include "cc/resources/layer_tiling_data.h"
40 #include "cc/test/animation_test_common.h"
41 #include "cc/test/fake_layer_tree_host_impl.h"
42 #include "cc/test/fake_output_surface.h"
43 #include "cc/test/fake_output_surface_client.h"
44 #include "cc/test/fake_picture_layer_impl.h"
45 #include "cc/test/fake_picture_pile_impl.h"
46 #include "cc/test/fake_proxy.h"
47 #include "cc/test/fake_rendering_stats_instrumentation.h"
48 #include "cc/test/fake_video_frame_provider.h"
49 #include "cc/test/geometry_test_utils.h"
50 #include "cc/test/layer_test_common.h"
51 #include "cc/test/render_pass_test_common.h"
52 #include "cc/test/test_shared_bitmap_manager.h"
53 #include "cc/test/test_web_graphics_context_3d.h"
54 #include "cc/trees/layer_tree_impl.h"
55 #include "cc/trees/single_thread_proxy.h"
56 #include "media/base/media.h"
57 #include "testing/gmock/include/gmock/gmock.h"
58 #include "testing/gtest/include/gtest/gtest.h"
59 #include "third_party/skia/include/core/SkMallocPixelRef.h"
60 #include "ui/gfx/frame_time.h"
61 #include "ui/gfx/rect_conversions.h"
62 #include "ui/gfx/size_conversions.h"
63 #include "ui/gfx/vector2d_conversions.h"
65 using ::testing::Mock;
66 using ::testing::Return;
67 using ::testing::AnyNumber;
68 using ::testing::AtLeast;
70 using media::VideoFrame;
75 class LayerTreeHostImplTest : public testing::Test,
76 public LayerTreeHostImplClient {
78 LayerTreeHostImplTest()
79 : proxy_(base::MessageLoopProxy::current(),
80 base::MessageLoopProxy::current()),
81 always_impl_thread_(&proxy_),
82 always_main_thread_blocked_(&proxy_),
83 shared_bitmap_manager_(new TestSharedBitmapManager()),
84 on_can_draw_state_changed_called_(false),
85 did_notify_ready_to_activate_(false),
86 did_request_commit_(false),
87 did_request_redraw_(false),
88 did_request_animate_(false),
89 did_request_manage_tiles_(false),
90 did_upload_visible_tile_(false),
91 reduce_memory_result_(true),
92 current_limit_bytes_(0),
93 current_priority_cutoff_value_(0) {
94 media::InitializeMediaLibraryForTesting();
97 LayerTreeSettings DefaultSettings() {
98 LayerTreeSettings settings;
99 settings.minimum_occlusion_tracking_size = gfx::Size();
100 settings.impl_side_painting = true;
101 settings.texture_id_allocation_chunk_size = 1;
102 settings.report_overscroll_only_for_scrollable_axes = true;
106 virtual void SetUp() OVERRIDE {
107 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
110 virtual void TearDown() OVERRIDE {}
112 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {}
113 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
114 virtual void CommitVSyncParameters(base::TimeTicks timebase,
115 base::TimeDelta interval) OVERRIDE {}
116 virtual void SetEstimatedParentDrawTime(base::TimeDelta draw_time) OVERRIDE {}
117 virtual void SetMaxSwapsPendingOnImplThread(int max) OVERRIDE {}
118 virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
119 virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {}
120 virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {}
121 virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
122 on_can_draw_state_changed_called_ = true;
124 virtual void NotifyReadyToActivate() OVERRIDE {
125 did_notify_ready_to_activate_ = true;
126 host_impl_->ActivateSyncTree();
128 virtual void SetNeedsRedrawOnImplThread() OVERRIDE {
129 did_request_redraw_ = true;
131 virtual void SetNeedsRedrawRectOnImplThread(
132 const gfx::Rect& damage_rect) OVERRIDE {
133 did_request_redraw_ = true;
135 virtual void SetNeedsAnimateOnImplThread() OVERRIDE {
136 did_request_animate_ = true;
138 virtual void SetNeedsManageTilesOnImplThread() OVERRIDE {
139 did_request_manage_tiles_ = true;
141 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {
142 did_upload_visible_tile_ = true;
144 virtual void SetNeedsCommitOnImplThread() OVERRIDE {
145 did_request_commit_ = true;
147 virtual void PostAnimationEventsToMainThreadOnImplThread(
148 scoped_ptr<AnimationEventsVector> events) OVERRIDE {}
149 virtual bool ReduceContentsTextureMemoryOnImplThread(
150 size_t limit_bytes, int priority_cutoff) OVERRIDE {
151 current_limit_bytes_ = limit_bytes;
152 current_priority_cutoff_value_ = priority_cutoff;
153 return reduce_memory_result_;
155 virtual bool IsInsideDraw() OVERRIDE { return false; }
156 virtual void RenewTreePriority() OVERRIDE {}
157 virtual void PostDelayedScrollbarFadeOnImplThread(
158 const base::Closure& start_fade,
159 base::TimeDelta delay) OVERRIDE {
160 scrollbar_fade_start_ = start_fade;
161 requested_scrollbar_animation_delay_ = delay;
163 virtual void DidActivateSyncTree() OVERRIDE {}
164 virtual void DidManageTiles() OVERRIDE {}
166 void set_reduce_memory_result(bool reduce_memory_result) {
167 reduce_memory_result_ = reduce_memory_result;
170 bool CreateHostImpl(const LayerTreeSettings& settings,
171 scoped_ptr<OutputSurface> output_surface) {
172 host_impl_ = LayerTreeHostImpl::Create(settings,
175 &stats_instrumentation_,
176 shared_bitmap_manager_.get(),
178 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
179 host_impl_->SetViewportSize(gfx::Size(10, 10));
183 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
184 root->SetPosition(gfx::PointF());
185 root->SetBounds(gfx::Size(10, 10));
186 root->SetContentBounds(gfx::Size(10, 10));
187 root->SetDrawsContent(true);
188 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
189 host_impl_->active_tree()->SetRootLayer(root.Pass());
192 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
193 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
194 for (size_t i = 0; i < layer->children().size(); ++i)
195 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
198 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
200 const gfx::Vector2d& scroll_delta) {
201 int times_encountered = 0;
203 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
204 if (scroll_info.scrolls[i].layer_id != id)
206 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
210 ASSERT_EQ(1, times_encountered);
213 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
214 int times_encountered = 0;
216 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
217 if (scroll_info.scrolls[i].layer_id != id)
222 ASSERT_EQ(0, times_encountered);
225 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
226 const gfx::Size& content_size) {
227 const int kInnerViewportScrollLayerId = 2;
228 const int kInnerViewportClipLayerId = 4;
229 const int kPageScaleLayerId = 5;
230 scoped_ptr<LayerImpl> root =
231 LayerImpl::Create(layer_tree_impl, 1);
232 root->SetBounds(content_size);
233 root->SetContentBounds(content_size);
234 root->SetPosition(gfx::PointF());
236 scoped_ptr<LayerImpl> scroll =
237 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
238 LayerImpl* scroll_layer = scroll.get();
239 scroll->SetIsContainerForFixedPositionLayers(true);
240 scroll->SetScrollOffset(gfx::Vector2d());
242 scoped_ptr<LayerImpl> clip =
243 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
245 gfx::Size(content_size.width() / 2, content_size.height() / 2));
247 scoped_ptr<LayerImpl> page_scale =
248 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
250 scroll->SetScrollClipLayer(clip->id());
251 scroll->SetBounds(content_size);
252 scroll->SetContentBounds(content_size);
253 scroll->SetPosition(gfx::PointF());
254 scroll->SetIsContainerForFixedPositionLayers(true);
256 scoped_ptr<LayerImpl> contents =
257 LayerImpl::Create(layer_tree_impl, 3);
258 contents->SetDrawsContent(true);
259 contents->SetBounds(content_size);
260 contents->SetContentBounds(content_size);
261 contents->SetPosition(gfx::PointF());
263 scroll->AddChild(contents.Pass());
264 page_scale->AddChild(scroll.Pass());
265 clip->AddChild(page_scale.Pass());
266 root->AddChild(clip.Pass());
268 layer_tree_impl->SetRootLayer(root.Pass());
269 layer_tree_impl->SetViewportLayersFromIds(
270 kPageScaleLayerId, kInnerViewportScrollLayerId, Layer::INVALID_ID);
275 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
276 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
277 host_impl_->active_tree(), content_size);
278 host_impl_->active_tree()->DidBecomeActive();
282 // TODO(wjmaclean) Add clip-layer pointer to parameters.
283 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
284 const gfx::Size& size,
285 LayerImpl* clip_layer) {
287 DCHECK(id != clip_layer->id());
288 scoped_ptr<LayerImpl> layer =
289 LayerImpl::Create(host_impl_->active_tree(), id);
290 layer->SetScrollClipLayer(clip_layer->id());
291 layer->SetDrawsContent(true);
292 layer->SetBounds(size);
293 layer->SetContentBounds(size);
294 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
299 LayerTreeHostImpl::FrameData frame;
300 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
301 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
302 host_impl_->DidDrawAllLayers(frame);
305 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
306 void pinch_zoom_pan_viewport_test(float device_scale_factor);
307 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
308 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
309 float device_scale_factor);
311 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
312 // Note: It is not possible to disable the renderer once it has been set,
313 // so we do not need to test that disabling the renderer notifies us
314 // that can_draw changed.
315 EXPECT_FALSE(host_impl_->CanDraw());
316 on_can_draw_state_changed_called_ = false;
318 // Set up the root layer, which allows us to draw.
319 SetupScrollAndContentsLayers(gfx::Size(100, 100));
320 EXPECT_TRUE(host_impl_->CanDraw());
321 EXPECT_TRUE(on_can_draw_state_changed_called_);
322 on_can_draw_state_changed_called_ = false;
324 // Toggle the root layer to make sure it toggles can_draw
325 host_impl_->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
326 EXPECT_FALSE(host_impl_->CanDraw());
327 EXPECT_TRUE(on_can_draw_state_changed_called_);
328 on_can_draw_state_changed_called_ = false;
330 SetupScrollAndContentsLayers(gfx::Size(100, 100));
331 EXPECT_TRUE(host_impl_->CanDraw());
332 EXPECT_TRUE(on_can_draw_state_changed_called_);
333 on_can_draw_state_changed_called_ = false;
335 // Toggle the device viewport size to make sure it toggles can_draw.
336 host_impl_->SetViewportSize(gfx::Size());
338 EXPECT_TRUE(host_impl_->CanDraw());
340 EXPECT_FALSE(host_impl_->CanDraw());
342 EXPECT_TRUE(on_can_draw_state_changed_called_);
343 on_can_draw_state_changed_called_ = false;
345 host_impl_->SetViewportSize(gfx::Size(100, 100));
346 EXPECT_TRUE(host_impl_->CanDraw());
347 EXPECT_TRUE(on_can_draw_state_changed_called_);
348 on_can_draw_state_changed_called_ = false;
350 // Toggle contents textures purged without causing any evictions,
351 // and make sure that it does not change can_draw.
352 set_reduce_memory_result(false);
353 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
354 host_impl_->memory_allocation_limit_bytes() - 1));
355 EXPECT_TRUE(host_impl_->CanDraw());
356 EXPECT_FALSE(on_can_draw_state_changed_called_);
357 on_can_draw_state_changed_called_ = false;
359 // Toggle contents textures purged to make sure it toggles can_draw.
360 set_reduce_memory_result(true);
361 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
362 host_impl_->memory_allocation_limit_bytes() - 1));
364 EXPECT_TRUE(host_impl_->CanDraw());
366 EXPECT_FALSE(host_impl_->CanDraw());
368 EXPECT_TRUE(on_can_draw_state_changed_called_);
369 on_can_draw_state_changed_called_ = false;
371 host_impl_->active_tree()->ResetContentsTexturesPurged();
372 EXPECT_TRUE(host_impl_->CanDraw());
373 EXPECT_TRUE(on_can_draw_state_changed_called_);
374 on_can_draw_state_changed_called_ = false;
377 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
380 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
381 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
384 void DrawOneFrame() {
385 LayerTreeHostImpl::FrameData frame_data;
386 host_impl_->PrepareToDraw(&frame_data);
387 host_impl_->DidDrawAllLayers(frame_data);
391 DebugScopedSetImplThread always_impl_thread_;
392 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
394 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
395 scoped_ptr<LayerTreeHostImpl> host_impl_;
396 FakeRenderingStatsInstrumentation stats_instrumentation_;
397 bool on_can_draw_state_changed_called_;
398 bool did_notify_ready_to_activate_;
399 bool did_request_commit_;
400 bool did_request_redraw_;
401 bool did_request_animate_;
402 bool did_request_manage_tiles_;
403 bool did_upload_visible_tile_;
404 bool reduce_memory_result_;
405 base::Closure scrollbar_fade_start_;
406 base::TimeDelta requested_scrollbar_animation_delay_;
407 size_t current_limit_bytes_;
408 int current_priority_cutoff_value_;
411 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
412 bool always_draw = false;
413 CheckNotifyCalledIfCanDrawChanged(always_draw);
416 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
417 scoped_ptr<FakeOutputSurface> output_surface(
418 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
419 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
421 bool always_draw = true;
422 CheckNotifyCalledIfCanDrawChanged(always_draw);
425 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
426 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
428 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
429 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
432 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
434 scoped_ptr<LayerImpl> root =
435 LayerImpl::Create(host_impl_->active_tree(), 1);
436 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
437 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
438 root->children()[1]->AddChild(
439 LayerImpl::Create(host_impl_->active_tree(), 4));
440 root->children()[1]->AddChild(
441 LayerImpl::Create(host_impl_->active_tree(), 5));
442 root->children()[1]->children()[0]->AddChild(
443 LayerImpl::Create(host_impl_->active_tree(), 6));
444 host_impl_->active_tree()->SetRootLayer(root.Pass());
446 LayerImpl* root = host_impl_->active_tree()->root_layer();
448 ExpectClearedScrollDeltasRecursive(root);
450 scoped_ptr<ScrollAndScaleSet> scroll_info;
452 scroll_info = host_impl_->ProcessScrollDeltas();
453 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
454 ExpectClearedScrollDeltasRecursive(root);
456 scroll_info = host_impl_->ProcessScrollDeltas();
457 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
458 ExpectClearedScrollDeltasRecursive(root);
461 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
462 gfx::Vector2d scroll_offset(20, 30);
463 gfx::Vector2d scroll_delta(11, -15);
465 scoped_ptr<LayerImpl> root_clip =
466 LayerImpl::Create(host_impl_->active_tree(), 2);
467 scoped_ptr<LayerImpl> root =
468 LayerImpl::Create(host_impl_->active_tree(), 1);
469 root_clip->SetBounds(gfx::Size(10, 10));
470 LayerImpl* root_layer = root.get();
471 root_clip->AddChild(root.Pass());
472 root_layer->SetBounds(gfx::Size(110, 110));
473 root_layer->SetScrollClipLayer(root_clip->id());
474 root_layer->SetScrollOffset(scroll_offset);
475 root_layer->ScrollBy(scroll_delta);
476 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
478 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
480 scoped_ptr<ScrollAndScaleSet> scroll_info;
482 scroll_info = host_impl_->ProcessScrollDeltas();
483 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
484 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta);
485 ExpectContains(*scroll_info, root->id(), scroll_delta);
487 gfx::Vector2d scroll_delta2(-5, 27);
488 root->ScrollBy(scroll_delta2);
489 scroll_info = host_impl_->ProcessScrollDeltas();
490 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
491 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
492 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
494 root->ScrollBy(gfx::Vector2d());
495 scroll_info = host_impl_->ProcessScrollDeltas();
496 EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
499 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
500 SetupScrollAndContentsLayers(gfx::Size(100, 100));
501 host_impl_->SetViewportSize(gfx::Size(50, 50));
504 EXPECT_EQ(InputHandler::ScrollStarted,
505 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
506 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
507 InputHandler::Wheel));
508 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
509 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
510 InputHandler::Wheel));
511 host_impl_->ScrollEnd();
512 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
513 InputHandler::Wheel));
514 EXPECT_TRUE(did_request_redraw_);
515 EXPECT_TRUE(did_request_commit_);
518 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
519 // We should not crash when trying to scroll an empty layer tree.
520 EXPECT_EQ(InputHandler::ScrollIgnored,
521 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
524 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
525 scoped_ptr<TestWebGraphicsContext3D> context_owned =
526 TestWebGraphicsContext3D::Create();
527 context_owned->set_context_lost(true);
529 scoped_ptr<FakeOutputSurface> output_surface(FakeOutputSurface::Create3d(
530 context_owned.Pass()));
532 // Initialization will fail.
533 EXPECT_FALSE(CreateHostImpl(DefaultSettings(),
534 output_surface.PassAs<OutputSurface>()));
536 SetupScrollAndContentsLayers(gfx::Size(100, 100));
538 // We should not crash when trying to scroll after the renderer initialization
540 EXPECT_EQ(InputHandler::ScrollStarted,
541 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
544 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
545 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
546 host_impl_->SetViewportSize(gfx::Size(50, 50));
549 // We should not crash if the tree is replaced while we are scrolling.
550 EXPECT_EQ(InputHandler::ScrollStarted,
551 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
552 host_impl_->active_tree()->DetachLayerTree();
554 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
556 // We should still be scrolling, because the scrolled layer also exists in the
558 gfx::Vector2d scroll_delta(0, 10);
559 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
560 host_impl_->ScrollEnd();
561 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
562 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
565 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
566 SetupScrollAndContentsLayers(gfx::Size(100, 100));
567 host_impl_->SetViewportSize(gfx::Size(50, 50));
570 // We should be able to scroll even if the root layer loses its render surface
571 // after the most recent render.
572 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
573 host_impl_->active_tree()->set_needs_update_draw_properties();
575 EXPECT_EQ(InputHandler::ScrollStarted,
576 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
579 TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
580 SetupScrollAndContentsLayers(gfx::Size(100, 100));
581 host_impl_->SetViewportSize(gfx::Size(50, 50));
583 LayerImpl* root = host_impl_->active_tree()->root_layer();
585 root->SetHaveWheelEventHandlers(true);
587 // With registered event handlers, wheel scrolls have to go to the main
589 EXPECT_EQ(InputHandler::ScrollOnMainThread,
590 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
592 // But gesture scrolls can still be handled.
593 EXPECT_EQ(InputHandler::ScrollStarted,
594 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
597 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
598 SetupScrollAndContentsLayers(gfx::Size(100, 100));
599 host_impl_->SetViewportSize(gfx::Size(50, 50));
602 // Ignore the fling since no layer is being scrolled
603 EXPECT_EQ(InputHandler::ScrollIgnored,
604 host_impl_->FlingScrollBegin());
606 // Start scrolling a layer
607 EXPECT_EQ(InputHandler::ScrollStarted,
608 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
610 // Now the fling should go ahead since we've started scrolling a layer
611 EXPECT_EQ(InputHandler::ScrollStarted,
612 host_impl_->FlingScrollBegin());
615 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
616 SetupScrollAndContentsLayers(gfx::Size(100, 100));
617 host_impl_->SetViewportSize(gfx::Size(50, 50));
620 // Ignore the fling since no layer is being scrolled
621 EXPECT_EQ(InputHandler::ScrollIgnored,
622 host_impl_->FlingScrollBegin());
624 // Start scrolling a layer
625 EXPECT_EQ(InputHandler::ScrollStarted,
626 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
628 // Now the fling should go ahead since we've started scrolling a layer
629 EXPECT_EQ(InputHandler::ScrollStarted,
630 host_impl_->FlingScrollBegin());
633 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
634 SetupScrollAndContentsLayers(gfx::Size(100, 100));
635 host_impl_->SetViewportSize(gfx::Size(50, 50));
637 LayerImpl* root = host_impl_->active_tree()->root_layer();
639 root->SetShouldScrollOnMainThread(true);
641 // Start scrolling a layer
642 EXPECT_EQ(InputHandler::ScrollOnMainThread,
643 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
645 // The fling should be ignored since there's no layer being scrolled impl-side
646 EXPECT_EQ(InputHandler::ScrollIgnored,
647 host_impl_->FlingScrollBegin());
650 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
651 SetupScrollAndContentsLayers(gfx::Size(100, 100));
652 host_impl_->SetViewportSize(gfx::Size(50, 50));
654 LayerImpl* root = host_impl_->active_tree()->root_layer();
656 root->SetShouldScrollOnMainThread(true);
658 EXPECT_EQ(InputHandler::ScrollOnMainThread,
659 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
660 EXPECT_EQ(InputHandler::ScrollOnMainThread,
661 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
664 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
665 SetupScrollAndContentsLayers(gfx::Size(200, 200));
666 host_impl_->SetViewportSize(gfx::Size(100, 100));
668 LayerImpl* root = host_impl_->active_tree()->root_layer();
669 root->SetContentsScale(2.f, 2.f);
670 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
674 // All scroll types inside the non-fast scrollable region should fail.
675 EXPECT_EQ(InputHandler::ScrollOnMainThread,
676 host_impl_->ScrollBegin(gfx::Point(25, 25),
677 InputHandler::Wheel));
678 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
679 InputHandler::Wheel));
680 EXPECT_EQ(InputHandler::ScrollOnMainThread,
681 host_impl_->ScrollBegin(gfx::Point(25, 25),
682 InputHandler::Gesture));
683 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
684 InputHandler::Gesture));
686 // All scroll types outside this region should succeed.
687 EXPECT_EQ(InputHandler::ScrollStarted,
688 host_impl_->ScrollBegin(gfx::Point(75, 75),
689 InputHandler::Wheel));
690 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
691 InputHandler::Gesture));
692 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
693 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
694 InputHandler::Gesture));
695 host_impl_->ScrollEnd();
696 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
697 InputHandler::Gesture));
698 EXPECT_EQ(InputHandler::ScrollStarted,
699 host_impl_->ScrollBegin(gfx::Point(75, 75),
700 InputHandler::Gesture));
701 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
702 InputHandler::Gesture));
703 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
704 host_impl_->ScrollEnd();
705 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
706 InputHandler::Gesture));
709 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
710 SetupScrollAndContentsLayers(gfx::Size(200, 200));
711 host_impl_->SetViewportSize(gfx::Size(100, 100));
713 LayerImpl* root = host_impl_->active_tree()->root_layer();
714 root->SetContentsScale(2.f, 2.f);
715 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
716 root->SetPosition(gfx::PointF(-25.f, 0.f));
720 // This point would fall into the non-fast scrollable region except that we've
721 // moved the layer down by 25 pixels.
722 EXPECT_EQ(InputHandler::ScrollStarted,
723 host_impl_->ScrollBegin(gfx::Point(40, 10),
724 InputHandler::Wheel));
725 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
726 InputHandler::Wheel));
727 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
728 host_impl_->ScrollEnd();
730 // This point is still inside the non-fast region.
731 EXPECT_EQ(InputHandler::ScrollOnMainThread,
732 host_impl_->ScrollBegin(gfx::Point(10, 10),
733 InputHandler::Wheel));
736 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
737 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
738 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
739 host_impl_->SetViewportSize(gfx::Size(50, 50));
742 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
743 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
744 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
745 host_impl_->ScrollEnd();
746 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
749 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
750 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
751 scroll_layer->SetHaveScrollEventHandlers(true);
752 host_impl_->SetViewportSize(gfx::Size(50, 50));
755 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
756 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
757 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
758 host_impl_->ScrollEnd();
759 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
762 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
763 SetupScrollAndContentsLayers(gfx::Size(200, 200));
764 host_impl_->SetViewportSize(gfx::Size(100, 100));
768 EXPECT_EQ(InputHandler::ScrollStarted,
769 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
771 // Trying to scroll to the left/top will not succeed.
772 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
773 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
774 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
776 // Scrolling to the right/bottom will succeed.
777 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
778 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
779 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
781 // Scrolling to left/top will now succeed.
782 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
783 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
784 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
786 // Scrolling diagonally against an edge will succeed.
787 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
788 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
789 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
791 // Trying to scroll more than the available space will also succeed.
792 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
795 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
796 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
797 host_impl_->SetViewportSize(gfx::Size(100, 1000));
801 EXPECT_EQ(InputHandler::ScrollStarted,
802 host_impl_->ScrollBegin(gfx::Point(),
803 InputHandler::Wheel));
805 // Trying to scroll without a vertical scrollbar will fail.
806 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
807 gfx::Point(), SCROLL_FORWARD));
808 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
809 gfx::Point(), SCROLL_BACKWARD));
811 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
812 PaintedScrollbarLayerImpl::Create(
813 host_impl_->active_tree(),
816 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
817 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
818 vertical_scrollbar.get());
820 // Trying to scroll with a vertical scrollbar will succeed.
821 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
822 gfx::Point(), SCROLL_FORWARD));
823 EXPECT_FLOAT_EQ(875.f,
824 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
825 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
826 gfx::Point(), SCROLL_BACKWARD));
829 // The user-scrollability breaks for zoomed-in pages. So disable this.
830 // http://crbug.com/322223
831 TEST_F(LayerTreeHostImplTest, DISABLED_ScrollWithUserUnscrollableLayers) {
832 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
833 host_impl_->SetViewportSize(gfx::Size(100, 100));
835 gfx::Size overflow_size(400, 400);
836 ASSERT_EQ(1u, scroll_layer->children().size());
837 LayerImpl* overflow = scroll_layer->children()[0];
838 overflow->SetBounds(overflow_size);
839 overflow->SetContentBounds(overflow_size);
840 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
841 overflow->SetScrollOffset(gfx::Vector2d());
842 overflow->SetPosition(gfx::PointF());
845 gfx::Point scroll_position(10, 10);
847 EXPECT_EQ(InputHandler::ScrollStarted,
848 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
849 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
850 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->TotalScrollOffset());
852 gfx::Vector2dF scroll_delta(10, 10);
853 host_impl_->ScrollBy(scroll_position, scroll_delta);
854 host_impl_->ScrollEnd();
855 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
856 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
858 overflow->set_user_scrollable_horizontal(false);
860 EXPECT_EQ(InputHandler::ScrollStarted,
861 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
862 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
863 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
865 host_impl_->ScrollBy(scroll_position, scroll_delta);
866 host_impl_->ScrollEnd();
867 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
868 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
870 overflow->set_user_scrollable_vertical(false);
872 EXPECT_EQ(InputHandler::ScrollStarted,
873 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
874 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
875 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
877 host_impl_->ScrollBy(scroll_position, scroll_delta);
878 host_impl_->ScrollEnd();
879 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->TotalScrollOffset());
880 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
883 TEST_F(LayerTreeHostImplTest,
884 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
885 SetupScrollAndContentsLayers(gfx::Size(100, 100));
886 host_impl_->SetViewportSize(gfx::Size(50, 50));
889 // We should be able to hit test for touch event handlers even if the root
890 // layer loses its render surface after the most recent render.
891 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
892 host_impl_->active_tree()->set_needs_update_draw_properties();
894 EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
897 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
898 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
899 host_impl_->SetViewportSize(gfx::Size(50, 50));
902 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
903 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
904 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
906 float min_page_scale = 1.f, max_page_scale = 4.f;
907 float page_scale_factor = 1.f;
909 // The impl-based pinch zoom should adjust the max scroll position.
911 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
912 page_scale_factor, min_page_scale, max_page_scale);
913 host_impl_->active_tree()->SetPageScaleDelta(1.f);
914 scroll_layer->SetScrollDelta(gfx::Vector2d());
916 float page_scale_delta = 2.f;
917 gfx::Vector2dF expected_container_size_delta(
918 container_layer->bounds().width(), container_layer->bounds().height());
919 expected_container_size_delta.Scale((1.f - page_scale_delta) /
920 (page_scale_factor * page_scale_delta));
922 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
923 host_impl_->PinchGestureBegin();
924 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
925 // While the gesture is still active, the scroll layer should have a
926 // container size delta = container->bounds() * ((1.f -
927 // page_scale_delta)/())
928 EXPECT_EQ(expected_container_size_delta,
929 scroll_layer->FixedContainerSizeDelta());
930 host_impl_->PinchGestureEnd();
931 host_impl_->ScrollEnd();
932 EXPECT_FALSE(did_request_animate_);
933 EXPECT_TRUE(did_request_redraw_);
934 EXPECT_TRUE(did_request_commit_);
935 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
937 scoped_ptr<ScrollAndScaleSet> scroll_info =
938 host_impl_->ProcessScrollDeltas();
939 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
941 EXPECT_EQ(gfx::Vector2d(75, 75).ToString(),
942 scroll_layer->MaxScrollOffset().ToString());
945 // Scrolling after a pinch gesture should always be in local space. The
946 // scroll deltas do not have the page scale factor applied.
948 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
949 page_scale_factor, min_page_scale, max_page_scale);
950 host_impl_->active_tree()->SetPageScaleDelta(1.f);
951 scroll_layer->SetScrollDelta(gfx::Vector2d());
953 float page_scale_delta = 2.f;
954 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
955 host_impl_->PinchGestureBegin();
956 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
957 host_impl_->PinchGestureEnd();
958 host_impl_->ScrollEnd();
960 gfx::Vector2d scroll_delta(0, 10);
961 EXPECT_EQ(InputHandler::ScrollStarted,
962 host_impl_->ScrollBegin(gfx::Point(5, 5),
963 InputHandler::Wheel));
964 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
965 host_impl_->ScrollEnd();
967 scoped_ptr<ScrollAndScaleSet> scroll_info =
968 host_impl_->ProcessScrollDeltas();
969 ExpectContains(*scroll_info.get(),
975 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
976 ui::LatencyInfo latency_info;
977 latency_info.trace_id = 1234;
978 scoped_ptr<SwapPromise> swap_promise(
979 new LatencyInfoSwapPromise(latency_info));
981 SetupScrollAndContentsLayers(gfx::Size(100, 100));
982 EXPECT_EQ(InputHandler::ScrollStarted,
983 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
984 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
985 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
986 host_impl_->ScrollEnd();
988 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
989 EXPECT_EQ(1u, scroll_info->swap_promises.size());
990 EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId());
993 TEST_F(LayerTreeHostImplTest, MasksToBoundsDoesntClobberInnerContainerSize) {
994 SetupScrollAndContentsLayers(gfx::Size(100, 100));
995 host_impl_->SetViewportSize(gfx::Size(50, 50));
998 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
999 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
1000 DCHECK(scroll_layer);
1002 float min_page_scale = 1.f;
1003 float max_page_scale = 4.f;
1004 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1008 // If the container's masks_to_bounds is false, the viewport size should
1009 // overwrite the inner viewport container layer's size.
1011 EXPECT_EQ(gfx::Size(50, 50),
1012 container_layer->bounds());
1013 container_layer->SetMasksToBounds(false);
1015 container_layer->SetBounds(gfx::Size(30, 25));
1016 EXPECT_EQ(gfx::Size(30, 25),
1017 container_layer->bounds());
1019 // This should cause a reset of the inner viewport container layer's bounds.
1020 host_impl_->DidChangeTopControlsPosition();
1022 EXPECT_EQ(gfx::Size(50, 50),
1023 container_layer->bounds());
1026 host_impl_->SetViewportSize(gfx::Size(50, 50));
1027 container_layer->SetBounds(gfx::Size(50, 50));
1029 // If the container's masks_to_bounds is true, the viewport size should
1030 // *NOT* overwrite the inner viewport container layer's size.
1032 EXPECT_EQ(gfx::Size(50, 50),
1033 container_layer->bounds());
1034 container_layer->SetMasksToBounds(true);
1036 container_layer->SetBounds(gfx::Size(30, 25));
1037 EXPECT_EQ(gfx::Size(30, 25),
1038 container_layer->bounds());
1040 // This should cause a reset of the inner viewport container layer's bounds.
1041 host_impl_->DidChangeTopControlsPosition();
1043 EXPECT_EQ(gfx::Size(30, 25),
1044 container_layer->bounds());
1048 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1049 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1050 host_impl_->SetViewportSize(gfx::Size(50, 50));
1053 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1054 DCHECK(scroll_layer);
1056 float min_page_scale = 1.f;
1057 float max_page_scale = 4.f;
1059 // Basic pinch zoom in gesture
1061 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1064 scroll_layer->SetScrollDelta(gfx::Vector2d());
1066 float page_scale_delta = 2.f;
1067 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1068 host_impl_->PinchGestureBegin();
1069 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1070 host_impl_->PinchGestureEnd();
1071 host_impl_->ScrollEnd();
1072 EXPECT_FALSE(did_request_animate_);
1073 EXPECT_TRUE(did_request_redraw_);
1074 EXPECT_TRUE(did_request_commit_);
1076 scoped_ptr<ScrollAndScaleSet> scroll_info =
1077 host_impl_->ProcessScrollDeltas();
1078 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1083 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1086 scroll_layer->SetScrollDelta(gfx::Vector2d());
1087 float page_scale_delta = 10.f;
1089 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1090 host_impl_->PinchGestureBegin();
1091 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1092 host_impl_->PinchGestureEnd();
1093 host_impl_->ScrollEnd();
1095 scoped_ptr<ScrollAndScaleSet> scroll_info =
1096 host_impl_->ProcessScrollDeltas();
1097 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1100 // Zoom-out clamping
1102 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1105 scroll_layer->SetScrollDelta(gfx::Vector2d());
1106 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1108 float page_scale_delta = 0.1f;
1109 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1110 host_impl_->PinchGestureBegin();
1111 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1112 host_impl_->PinchGestureEnd();
1113 host_impl_->ScrollEnd();
1115 scoped_ptr<ScrollAndScaleSet> scroll_info =
1116 host_impl_->ProcessScrollDeltas();
1117 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1119 EXPECT_TRUE(scroll_info->scrolls.empty());
1122 // Two-finger panning should not happen based on pinch events only
1124 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1127 scroll_layer->SetScrollDelta(gfx::Vector2d());
1128 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1130 float page_scale_delta = 1.f;
1131 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1132 host_impl_->PinchGestureBegin();
1133 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1134 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1135 host_impl_->PinchGestureEnd();
1136 host_impl_->ScrollEnd();
1138 scoped_ptr<ScrollAndScaleSet> scroll_info =
1139 host_impl_->ProcessScrollDeltas();
1140 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1141 EXPECT_TRUE(scroll_info->scrolls.empty());
1144 // Two-finger panning should work with interleaved scroll events
1146 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1149 scroll_layer->SetScrollDelta(gfx::Vector2d());
1150 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1152 float page_scale_delta = 1.f;
1153 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1154 host_impl_->PinchGestureBegin();
1155 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1156 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1157 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1158 host_impl_->PinchGestureEnd();
1159 host_impl_->ScrollEnd();
1161 scoped_ptr<ScrollAndScaleSet> scroll_info =
1162 host_impl_->ProcessScrollDeltas();
1163 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1164 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1167 // Two-finger panning should work when starting fully zoomed out.
1169 host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
1172 scroll_layer->SetScrollDelta(gfx::Vector2d());
1173 scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
1175 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
1176 host_impl_->PinchGestureBegin();
1177 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1178 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1179 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1180 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1181 host_impl_->PinchGestureEnd();
1182 host_impl_->ScrollEnd();
1184 scoped_ptr<ScrollAndScaleSet> scroll_info =
1185 host_impl_->ProcessScrollDeltas();
1186 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1187 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1191 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1192 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1193 host_impl_->SetViewportSize(gfx::Size(50, 50));
1196 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1197 DCHECK(scroll_layer);
1199 float min_page_scale = 0.5f;
1200 float max_page_scale = 4.f;
1201 base::TimeTicks start_time = base::TimeTicks() +
1202 base::TimeDelta::FromSeconds(1);
1203 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1204 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1205 base::TimeTicks end_time = start_time + duration;
1207 // Non-anchor zoom-in
1209 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1212 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1214 did_request_redraw_ = false;
1215 did_request_animate_ = false;
1216 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), false, 2.f, duration);
1217 EXPECT_FALSE(did_request_redraw_);
1218 EXPECT_TRUE(did_request_animate_);
1220 did_request_redraw_ = false;
1221 did_request_animate_ = false;
1222 host_impl_->Animate(start_time);
1223 EXPECT_TRUE(did_request_redraw_);
1224 EXPECT_TRUE(did_request_animate_);
1226 did_request_redraw_ = false;
1227 did_request_animate_ = false;
1228 host_impl_->Animate(halfway_through_animation);
1229 EXPECT_TRUE(did_request_redraw_);
1230 EXPECT_TRUE(did_request_animate_);
1232 did_request_redraw_ = false;
1233 did_request_animate_ = false;
1234 did_request_commit_ = false;
1235 host_impl_->Animate(end_time);
1236 EXPECT_TRUE(did_request_commit_);
1237 EXPECT_FALSE(did_request_animate_);
1239 scoped_ptr<ScrollAndScaleSet> scroll_info =
1240 host_impl_->ProcessScrollDeltas();
1241 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1242 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1247 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1250 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1252 did_request_redraw_ = false;
1253 did_request_animate_ = false;
1254 host_impl_->StartPageScaleAnimation(
1255 gfx::Vector2d(25, 25), true, min_page_scale, duration);
1256 EXPECT_FALSE(did_request_redraw_);
1257 EXPECT_TRUE(did_request_animate_);
1259 did_request_redraw_ = false;
1260 did_request_animate_ = false;
1261 host_impl_->Animate(start_time);
1262 EXPECT_TRUE(did_request_redraw_);
1263 EXPECT_TRUE(did_request_animate_);
1265 did_request_redraw_ = false;
1266 did_request_commit_ = false;
1267 did_request_animate_ = false;
1268 host_impl_->Animate(end_time);
1269 EXPECT_TRUE(did_request_redraw_);
1270 EXPECT_FALSE(did_request_animate_);
1271 EXPECT_TRUE(did_request_commit_);
1273 scoped_ptr<ScrollAndScaleSet> scroll_info =
1274 host_impl_->ProcessScrollDeltas();
1275 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1276 // Pushed to (0,0) via clamping against contents layer size.
1277 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1281 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1282 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1283 host_impl_->SetViewportSize(gfx::Size(50, 50));
1286 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1287 DCHECK(scroll_layer);
1289 float min_page_scale = 0.5f;
1290 float max_page_scale = 4.f;
1291 base::TimeTicks start_time = base::TimeTicks() +
1292 base::TimeDelta::FromSeconds(1);
1293 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1294 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1295 base::TimeTicks end_time = start_time + duration;
1297 // Anchor zoom with unchanged page scale should not change scroll or scale.
1299 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1302 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1304 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), true, 1.f, duration);
1305 host_impl_->Animate(start_time);
1306 host_impl_->Animate(halfway_through_animation);
1307 EXPECT_TRUE(did_request_redraw_);
1308 host_impl_->Animate(end_time);
1309 EXPECT_TRUE(did_request_commit_);
1311 scoped_ptr<ScrollAndScaleSet> scroll_info =
1312 host_impl_->ProcessScrollDeltas();
1313 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1314 ExpectNone(*scroll_info, scroll_layer->id());
1318 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1320 LayerTreeHostImplOverridePhysicalTime(
1321 const LayerTreeSettings& settings,
1322 LayerTreeHostImplClient* client,
1324 SharedBitmapManager* manager,
1325 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1326 : LayerTreeHostImpl(settings,
1329 rendering_stats_instrumentation,
1333 virtual base::TimeTicks CurrentFrameTimeTicks() OVERRIDE {
1334 return fake_current_physical_time_;
1337 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1338 fake_current_physical_time_ = fake_now;
1342 base::TimeTicks fake_current_physical_time_;
1345 #define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST() \
1346 gfx::Size viewport_size(10, 10); \
1347 gfx::Size content_size(100, 100); \
1349 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = \
1350 new LayerTreeHostImplOverridePhysicalTime(settings, \
1353 shared_bitmap_manager_.get(), \
1354 &stats_instrumentation_); \
1355 host_impl_ = make_scoped_ptr(host_impl_override_time); \
1356 host_impl_->InitializeRenderer(CreateOutputSurface()); \
1357 host_impl_->SetViewportSize(viewport_size); \
1359 scoped_ptr<LayerImpl> root = \
1360 LayerImpl::Create(host_impl_->active_tree(), 1); \
1361 root->SetBounds(viewport_size); \
1363 scoped_ptr<LayerImpl> scroll = \
1364 LayerImpl::Create(host_impl_->active_tree(), 2); \
1365 scroll->SetScrollClipLayer(root->id()); \
1366 scroll->SetScrollOffset(gfx::Vector2d()); \
1367 root->SetBounds(viewport_size); \
1368 scroll->SetBounds(content_size); \
1369 scroll->SetContentBounds(content_size); \
1370 scroll->SetIsContainerForFixedPositionLayers(true); \
1372 scoped_ptr<LayerImpl> contents = \
1373 LayerImpl::Create(host_impl_->active_tree(), 3); \
1374 contents->SetDrawsContent(true); \
1375 contents->SetBounds(content_size); \
1376 contents->SetContentBounds(content_size); \
1378 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = \
1379 SolidColorScrollbarLayerImpl::Create( \
1380 host_impl_->active_tree(), 4, VERTICAL, 10, 0, false, true); \
1381 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); \
1383 scroll->AddChild(contents.Pass()); \
1384 root->AddChild(scroll.Pass()); \
1385 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1); \
1386 root->AddChild(scrollbar.PassAs<LayerImpl>()); \
1388 host_impl_->active_tree()->SetRootLayer(root.Pass()); \
1389 host_impl_->active_tree()->SetViewportLayersFromIds( \
1390 1, 2, Layer::INVALID_ID); \
1391 host_impl_->active_tree()->DidBecomeActive(); \
1394 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1395 LayerTreeSettings settings;
1396 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1397 settings.scrollbar_fade_delay_ms = 20;
1398 settings.scrollbar_fade_duration_ms = 20;
1400 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1402 base::TimeTicks fake_now = gfx::FrameTime::Now();
1404 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1405 EXPECT_FALSE(did_request_redraw_);
1407 // If no scroll happened during a scroll gesture, it should have no effect.
1408 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1409 host_impl_->ScrollEnd();
1410 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1411 EXPECT_FALSE(did_request_redraw_);
1412 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1414 // After a scroll, a fade animation should be scheduled about 20ms from now.
1415 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1416 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1417 host_impl_->ScrollEnd();
1418 did_request_redraw_ = false;
1419 did_request_animate_ = false;
1420 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1421 requested_scrollbar_animation_delay_);
1422 EXPECT_FALSE(did_request_redraw_);
1423 EXPECT_FALSE(did_request_animate_);
1424 requested_scrollbar_animation_delay_ = base::TimeDelta();
1425 scrollbar_fade_start_.Run();
1426 host_impl_->Animate(fake_now);
1428 // After the fade begins, we should start getting redraws instead of a
1429 // scheduled animation.
1430 fake_now += base::TimeDelta::FromMilliseconds(25);
1431 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1432 EXPECT_TRUE(did_request_animate_);
1433 did_request_animate_ = false;
1435 // Setting the scroll offset outside a scroll should also cause the scrollbar
1436 // to appear and to schedule a fade.
1437 host_impl_->InnerViewportScrollLayer()->SetScrollOffset(gfx::Vector2d(5, 5));
1438 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1439 requested_scrollbar_animation_delay_);
1440 EXPECT_FALSE(did_request_redraw_);
1441 EXPECT_FALSE(did_request_animate_);
1442 requested_scrollbar_animation_delay_ = base::TimeDelta();
1445 TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) {
1446 LayerTreeSettings settings;
1447 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1448 settings.scrollbar_fade_delay_ms = 20;
1449 settings.scrollbar_fade_duration_ms = 20;
1450 settings.use_pinch_zoom_scrollbars = true;
1452 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1454 base::TimeTicks fake_now = gfx::FrameTime::Now();
1456 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
1458 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1459 EXPECT_FALSE(did_request_animate_);
1461 // If no scroll happened during a scroll gesture, it should have no effect.
1462 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1463 host_impl_->ScrollEnd();
1464 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1465 EXPECT_FALSE(did_request_animate_);
1466 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1468 // After a scroll, no fade animation should be scheduled.
1469 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1470 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1471 host_impl_->ScrollEnd();
1472 did_request_redraw_ = false;
1473 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1474 EXPECT_FALSE(did_request_animate_);
1475 requested_scrollbar_animation_delay_ = base::TimeDelta();
1477 // We should not see any draw requests.
1478 fake_now += base::TimeDelta::FromMilliseconds(25);
1479 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1480 EXPECT_FALSE(did_request_animate_);
1482 // Make page scale > min so that subsequent scrolls will trigger fades.
1483 host_impl_->active_tree()->SetPageScaleDelta(1.1f);
1485 // After a scroll, a fade animation should be scheduled about 20ms from now.
1486 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1487 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1488 host_impl_->ScrollEnd();
1489 did_request_redraw_ = false;
1490 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1491 requested_scrollbar_animation_delay_);
1492 EXPECT_FALSE(did_request_animate_);
1493 requested_scrollbar_animation_delay_ = base::TimeDelta();
1494 scrollbar_fade_start_.Run();
1496 // After the fade begins, we should start getting redraws instead of a
1497 // scheduled animation.
1498 fake_now += base::TimeDelta::FromMilliseconds(25);
1499 host_impl_->Animate(fake_now);
1500 EXPECT_TRUE(did_request_animate_);
1503 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1504 float device_scale_factor) {
1505 LayerTreeSettings settings;
1506 settings.scrollbar_fade_delay_ms = 500;
1507 settings.scrollbar_fade_duration_ms = 300;
1508 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1510 gfx::Size viewport_size(300, 200);
1511 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1512 gfx::ScaleSize(viewport_size, device_scale_factor));
1513 gfx::Size content_size(1000, 1000);
1515 CreateHostImpl(settings, CreateOutputSurface());
1516 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1517 host_impl_->SetViewportSize(device_viewport_size);
1519 scoped_ptr<LayerImpl> root =
1520 LayerImpl::Create(host_impl_->active_tree(), 1);
1521 root->SetBounds(viewport_size);
1523 scoped_ptr<LayerImpl> scroll =
1524 LayerImpl::Create(host_impl_->active_tree(), 2);
1525 scroll->SetScrollClipLayer(root->id());
1526 scroll->SetScrollOffset(gfx::Vector2d());
1527 scroll->SetBounds(content_size);
1528 scroll->SetContentBounds(content_size);
1529 scroll->SetIsContainerForFixedPositionLayers(true);
1531 scoped_ptr<LayerImpl> contents =
1532 LayerImpl::Create(host_impl_->active_tree(), 3);
1533 contents->SetDrawsContent(true);
1534 contents->SetBounds(content_size);
1535 contents->SetContentBounds(content_size);
1537 // The scrollbar is on the right side.
1538 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1539 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1540 scrollbar->SetDrawsContent(true);
1541 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1542 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1543 scrollbar->SetPosition(gfx::Point(285, 0));
1545 scroll->AddChild(contents.Pass());
1546 root->AddChild(scroll.Pass());
1547 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1548 root->AddChild(scrollbar.PassAs<LayerImpl>());
1550 host_impl_->active_tree()->SetRootLayer(root.Pass());
1551 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
1552 host_impl_->active_tree()->DidBecomeActive();
1555 LayerImpl* root_scroll =
1556 host_impl_->active_tree()->InnerViewportScrollLayer();
1557 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1558 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1559 static_cast<ScrollbarAnimationControllerThinning*>(
1560 root_scroll->scrollbar_animation_controller());
1561 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1563 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1564 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1566 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1567 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1569 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1570 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1572 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1573 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1574 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1576 did_request_redraw_ = false;
1577 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1578 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1579 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1580 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1581 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1582 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1583 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1586 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1587 SetupMouseMoveAtWithDeviceScale(1.f);
1590 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1591 SetupMouseMoveAtWithDeviceScale(2.f);
1594 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1595 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1596 host_impl_->SetViewportSize(gfx::Size(50, 50));
1597 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
1600 CompositorFrameMetadata metadata =
1601 host_impl_->MakeCompositorFrameMetadata();
1602 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1603 EXPECT_EQ(1.f, metadata.page_scale_factor);
1604 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
1605 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1606 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1607 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1610 // Scrolling should update metadata immediately.
1611 EXPECT_EQ(InputHandler::ScrollStarted,
1612 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1613 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1615 CompositorFrameMetadata metadata =
1616 host_impl_->MakeCompositorFrameMetadata();
1617 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1619 host_impl_->ScrollEnd();
1621 CompositorFrameMetadata metadata =
1622 host_impl_->MakeCompositorFrameMetadata();
1623 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1626 // Page scale should update metadata correctly (shrinking only the viewport).
1627 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1628 host_impl_->PinchGestureBegin();
1629 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1630 host_impl_->PinchGestureEnd();
1631 host_impl_->ScrollEnd();
1633 CompositorFrameMetadata metadata =
1634 host_impl_->MakeCompositorFrameMetadata();
1635 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1636 EXPECT_EQ(2.f, metadata.page_scale_factor);
1637 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
1638 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1639 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1640 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1643 // Likewise if set from the main thread.
1644 host_impl_->ProcessScrollDeltas();
1645 host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
1646 host_impl_->active_tree()->SetPageScaleDelta(1.f);
1648 CompositorFrameMetadata metadata =
1649 host_impl_->MakeCompositorFrameMetadata();
1650 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1651 EXPECT_EQ(4.f, metadata.page_scale_factor);
1652 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
1653 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1654 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1655 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1659 class DidDrawCheckLayer : public LayerImpl {
1661 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1662 return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(tree_impl, id));
1665 virtual bool WillDraw(DrawMode draw_mode, ResourceProvider* provider)
1667 will_draw_called_ = true;
1668 if (will_draw_returns_false_)
1670 return LayerImpl::WillDraw(draw_mode, provider);
1673 virtual void AppendQuads(RenderPass* render_pass,
1674 const OcclusionTracker<LayerImpl>& occlusion_tracker,
1675 AppendQuadsData* append_quads_data) OVERRIDE {
1676 append_quads_called_ = true;
1677 LayerImpl::AppendQuads(render_pass, occlusion_tracker, append_quads_data);
1680 virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
1681 did_draw_called_ = true;
1682 LayerImpl::DidDraw(provider);
1685 bool will_draw_called() const { return will_draw_called_; }
1686 bool append_quads_called() const { return append_quads_called_; }
1687 bool did_draw_called() const { return did_draw_called_; }
1689 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1691 void ClearDidDrawCheck() {
1692 will_draw_called_ = false;
1693 append_quads_called_ = false;
1694 did_draw_called_ = false;
1698 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1699 : LayerImpl(tree_impl, id),
1700 will_draw_returns_false_(false),
1701 will_draw_called_(false),
1702 append_quads_called_(false),
1703 did_draw_called_(false) {
1704 SetBounds(gfx::Size(10, 10));
1705 SetContentBounds(gfx::Size(10, 10));
1706 SetDrawsContent(true);
1707 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1711 bool will_draw_returns_false_;
1712 bool will_draw_called_;
1713 bool append_quads_called_;
1714 bool did_draw_called_;
1717 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1718 // The root layer is always drawn, so run this test on a child layer that
1719 // will be masked out by the root layer's bounds.
1720 host_impl_->active_tree()->SetRootLayer(
1721 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1722 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1723 host_impl_->active_tree()->root_layer());
1725 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1726 DidDrawCheckLayer* layer =
1727 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1730 LayerTreeHostImpl::FrameData frame;
1731 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1732 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1733 host_impl_->DidDrawAllLayers(frame);
1735 EXPECT_TRUE(layer->will_draw_called());
1736 EXPECT_TRUE(layer->append_quads_called());
1737 EXPECT_TRUE(layer->did_draw_called());
1740 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
1743 LayerTreeHostImpl::FrameData frame;
1745 layer->set_will_draw_returns_false();
1746 layer->ClearDidDrawCheck();
1748 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1749 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1750 host_impl_->DidDrawAllLayers(frame);
1752 EXPECT_TRUE(layer->will_draw_called());
1753 EXPECT_FALSE(layer->append_quads_called());
1754 EXPECT_FALSE(layer->did_draw_called());
1758 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1759 // The root layer is always drawn, so run this test on a child layer that
1760 // will be masked out by the root layer's bounds.
1761 host_impl_->active_tree()->SetRootLayer(
1762 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1763 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1764 host_impl_->active_tree()->root_layer());
1765 root->SetMasksToBounds(true);
1767 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1768 DidDrawCheckLayer* layer =
1769 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1770 // Ensure visible_content_rect for layer is empty.
1771 layer->SetPosition(gfx::PointF(100.f, 100.f));
1772 layer->SetBounds(gfx::Size(10, 10));
1773 layer->SetContentBounds(gfx::Size(10, 10));
1775 LayerTreeHostImpl::FrameData frame;
1777 EXPECT_FALSE(layer->will_draw_called());
1778 EXPECT_FALSE(layer->did_draw_called());
1780 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1781 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1782 host_impl_->DidDrawAllLayers(frame);
1784 EXPECT_FALSE(layer->will_draw_called());
1785 EXPECT_FALSE(layer->did_draw_called());
1787 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1789 // Ensure visible_content_rect for layer is not empty
1790 layer->SetPosition(gfx::PointF());
1792 EXPECT_FALSE(layer->will_draw_called());
1793 EXPECT_FALSE(layer->did_draw_called());
1795 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1796 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1797 host_impl_->DidDrawAllLayers(frame);
1799 EXPECT_TRUE(layer->will_draw_called());
1800 EXPECT_TRUE(layer->did_draw_called());
1802 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1805 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1806 gfx::Size big_size(1000, 1000);
1807 host_impl_->SetViewportSize(big_size);
1809 host_impl_->active_tree()->SetRootLayer(
1810 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1811 DidDrawCheckLayer* root =
1812 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1814 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1815 DidDrawCheckLayer* occluded_layer =
1816 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1818 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1819 DidDrawCheckLayer* top_layer =
1820 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1821 // This layer covers the occluded_layer above. Make this layer large so it can
1823 top_layer->SetBounds(big_size);
1824 top_layer->SetContentBounds(big_size);
1825 top_layer->SetContentsOpaque(true);
1827 LayerTreeHostImpl::FrameData frame;
1829 EXPECT_FALSE(occluded_layer->will_draw_called());
1830 EXPECT_FALSE(occluded_layer->did_draw_called());
1831 EXPECT_FALSE(top_layer->will_draw_called());
1832 EXPECT_FALSE(top_layer->did_draw_called());
1834 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1835 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1836 host_impl_->DidDrawAllLayers(frame);
1838 EXPECT_FALSE(occluded_layer->will_draw_called());
1839 EXPECT_FALSE(occluded_layer->did_draw_called());
1840 EXPECT_TRUE(top_layer->will_draw_called());
1841 EXPECT_TRUE(top_layer->did_draw_called());
1844 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1845 host_impl_->active_tree()->SetRootLayer(
1846 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1847 DidDrawCheckLayer* root =
1848 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1850 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1851 DidDrawCheckLayer* layer1 =
1852 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1854 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1855 DidDrawCheckLayer* layer2 =
1856 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1858 layer1->SetOpacity(0.3f);
1859 layer1->SetShouldFlattenTransform(true);
1861 EXPECT_FALSE(root->did_draw_called());
1862 EXPECT_FALSE(layer1->did_draw_called());
1863 EXPECT_FALSE(layer2->did_draw_called());
1865 LayerTreeHostImpl::FrameData frame;
1866 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
1867 host_impl_->active_tree()->root_layer());
1868 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1869 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1870 host_impl_->DidDrawAllLayers(frame);
1872 EXPECT_TRUE(root->did_draw_called());
1873 EXPECT_TRUE(layer1->did_draw_called());
1874 EXPECT_TRUE(layer2->did_draw_called());
1876 EXPECT_NE(root->render_surface(), layer1->render_surface());
1877 EXPECT_TRUE(!!layer1->render_surface());
1880 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1882 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1885 bool had_incomplete_tile,
1887 ResourceProvider* resource_provider) {
1888 return scoped_ptr<LayerImpl>(
1889 new MissingTextureAnimatingLayer(tree_impl,
1892 had_incomplete_tile,
1894 resource_provider));
1897 virtual void AppendQuads(RenderPass* render_pass,
1898 const OcclusionTracker<LayerImpl>& occlusion_tracker,
1899 AppendQuadsData* append_quads_data) OVERRIDE {
1900 LayerImpl::AppendQuads(render_pass, occlusion_tracker, append_quads_data);
1901 if (had_incomplete_tile_)
1902 append_quads_data->num_incomplete_tiles++;
1904 append_quads_data->num_missing_tiles++;
1908 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1911 bool had_incomplete_tile,
1913 ResourceProvider* resource_provider)
1914 : DidDrawCheckLayer(tree_impl, id),
1915 tile_missing_(tile_missing),
1916 had_incomplete_tile_(had_incomplete_tile) {
1918 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1922 bool had_incomplete_tile_;
1925 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsOnDefault) {
1926 host_impl_->active_tree()->SetRootLayer(
1927 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1928 DidDrawCheckLayer* root =
1929 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1931 bool tile_missing = false;
1932 bool had_incomplete_tile = false;
1933 bool is_animating = false;
1935 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1938 had_incomplete_tile,
1940 host_impl_->resource_provider()));
1942 LayerTreeHostImpl::FrameData frame;
1944 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1945 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1946 host_impl_->DidDrawAllLayers(frame);
1949 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) {
1950 host_impl_->active_tree()->SetRootLayer(
1951 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1952 DidDrawCheckLayer* root =
1953 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1954 bool tile_missing = false;
1955 bool had_incomplete_tile = false;
1956 bool is_animating = true;
1958 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1961 had_incomplete_tile,
1963 host_impl_->resource_provider()));
1965 LayerTreeHostImpl::FrameData frame;
1967 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1968 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1969 host_impl_->DidDrawAllLayers(frame);
1972 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithMissingTiles) {
1973 host_impl_->active_tree()->SetRootLayer(
1974 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1975 DidDrawCheckLayer* root =
1976 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1978 bool tile_missing = true;
1979 bool had_incomplete_tile = false;
1980 bool is_animating = false;
1982 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1985 had_incomplete_tile,
1987 host_impl_->resource_provider()));
1988 LayerTreeHostImpl::FrameData frame;
1989 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1990 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1991 host_impl_->DidDrawAllLayers(frame);
1994 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithIncompleteTile) {
1995 host_impl_->active_tree()->SetRootLayer(
1996 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1997 DidDrawCheckLayer* root =
1998 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2000 bool tile_missing = false;
2001 bool had_incomplete_tile = true;
2002 bool is_animating = false;
2004 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2007 had_incomplete_tile,
2009 host_impl_->resource_provider()));
2010 LayerTreeHostImpl::FrameData frame;
2011 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2012 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2013 host_impl_->DidDrawAllLayers(frame);
2016 TEST_F(LayerTreeHostImplTest,
2017 PrepareToDrawFailsWithAnimationAndMissingTilesUsesCheckerboard) {
2018 host_impl_->active_tree()->SetRootLayer(
2019 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
2020 DidDrawCheckLayer* root =
2021 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2022 bool tile_missing = true;
2023 bool had_incomplete_tile = false;
2024 bool is_animating = true;
2026 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2029 had_incomplete_tile,
2031 host_impl_->resource_provider()));
2032 LayerTreeHostImpl::FrameData frame;
2033 EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS,
2034 host_impl_->PrepareToDraw(&frame));
2035 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2036 host_impl_->DidDrawAllLayers(frame);
2039 TEST_F(LayerTreeHostImplTest,
2040 PrepareToDrawSucceedsWithAnimationAndIncompleteTiles) {
2041 host_impl_->active_tree()->SetRootLayer(
2042 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
2043 DidDrawCheckLayer* root =
2044 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2045 bool tile_missing = false;
2046 bool had_incomplete_tile = true;
2047 bool is_animating = true;
2049 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2052 had_incomplete_tile,
2054 host_impl_->resource_provider()));
2055 LayerTreeHostImpl::FrameData frame;
2056 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2057 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2058 host_impl_->DidDrawAllLayers(frame);
2061 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenHighResRequired) {
2062 host_impl_->active_tree()->SetRootLayer(
2063 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2064 DidDrawCheckLayer* root =
2065 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2066 bool tile_missing = false;
2067 bool had_incomplete_tile = false;
2068 bool is_animating = false;
2070 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2073 had_incomplete_tile,
2075 host_impl_->resource_provider()));
2076 host_impl_->active_tree()->SetRequiresHighResToDraw();
2077 LayerTreeHostImpl::FrameData frame;
2078 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2079 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2080 host_impl_->DidDrawAllLayers(frame);
2083 TEST_F(LayerTreeHostImplTest,
2084 PrepareToDrawFailsWhenHighResRequiredAndIncompleteTiles) {
2085 host_impl_->active_tree()->SetRootLayer(
2086 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2087 DidDrawCheckLayer* root =
2088 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2089 bool tile_missing = false;
2090 bool had_incomplete_tile = true;
2091 bool is_animating = false;
2093 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2096 had_incomplete_tile,
2098 host_impl_->resource_provider()));
2099 host_impl_->active_tree()->SetRequiresHighResToDraw();
2100 LayerTreeHostImpl::FrameData frame;
2101 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2102 host_impl_->PrepareToDraw(&frame));
2103 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2104 host_impl_->DidDrawAllLayers(frame);
2107 TEST_F(LayerTreeHostImplTest,
2108 PrepareToDrawFailsWhenHighResRequiredAndMissingTile) {
2109 host_impl_->active_tree()->SetRootLayer(
2110 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2111 DidDrawCheckLayer* root =
2112 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2113 bool tile_missing = true;
2114 bool had_incomplete_tile = false;
2115 bool is_animating = false;
2117 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2120 had_incomplete_tile,
2122 host_impl_->resource_provider()));
2123 host_impl_->active_tree()->SetRequiresHighResToDraw();
2124 LayerTreeHostImpl::FrameData frame;
2125 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2126 host_impl_->PrepareToDraw(&frame));
2127 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2128 host_impl_->DidDrawAllLayers(frame);
2131 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2132 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2133 root->SetScrollClipLayer(Layer::INVALID_ID);
2134 host_impl_->active_tree()->SetRootLayer(root.Pass());
2137 // Scroll event is ignored because layer is not scrollable.
2138 EXPECT_EQ(InputHandler::ScrollIgnored,
2139 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2140 EXPECT_FALSE(did_request_redraw_);
2141 EXPECT_FALSE(did_request_commit_);
2144 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2146 LayerTreeHostImplTopControlsTest()
2147 // Make the clip size the same as the layer (content) size so the layer is
2149 : layer_size_(10, 10),
2150 clip_size_(layer_size_) {
2151 settings_.calculate_top_controls_position = true;
2152 settings_.top_controls_height = 50;
2155 gfx::Size(clip_size_.width(),
2156 clip_size_.height() + settings_.top_controls_height);
2159 void SetupTopControlsAndScrollLayer() {
2160 CreateHostImpl(settings_, CreateOutputSurface());
2162 scoped_ptr<LayerImpl> root =
2163 LayerImpl::Create(host_impl_->active_tree(), 1);
2164 scoped_ptr<LayerImpl> root_clip =
2165 LayerImpl::Create(host_impl_->active_tree(), 2);
2166 root_clip->SetBounds(clip_size_);
2167 root->SetScrollClipLayer(root_clip->id());
2168 root->SetBounds(layer_size_);
2169 root->SetContentBounds(layer_size_);
2170 root->SetPosition(gfx::PointF());
2171 root->SetDrawsContent(false);
2172 root->SetIsContainerForFixedPositionLayers(true);
2173 int inner_viewport_scroll_layer_id = root->id();
2174 int page_scale_layer_id = root_clip->id();
2175 root_clip->AddChild(root.Pass());
2176 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2177 host_impl_->active_tree()->SetViewportLayersFromIds(
2178 page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
2179 // Set a viewport size that is large enough to contain both the top controls
2180 // and some content.
2181 host_impl_->SetViewportSize(viewport_size_);
2182 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2183 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2187 gfx::Size layer_size_;
2188 gfx::Size clip_size_;
2189 gfx::Size viewport_size_;
2191 LayerTreeSettings settings_;
2192 }; // class LayerTreeHostImplTopControlsTest
2194 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2195 SetupTopControlsAndScrollLayer();
2198 EXPECT_EQ(InputHandler::ScrollStarted,
2199 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2201 // Make the test scroll delta a fractional amount, to verify that the
2202 // fixed container size delta is (1) non-zero, and (2) fractional, and
2203 // (3) matches the movement of the top controls.
2204 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2205 host_impl_->top_controls_manager()->ScrollBegin();
2206 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2207 host_impl_->top_controls_manager()->ScrollEnd();
2209 LayerImpl* inner_viewport_scroll_layer =
2210 host_impl_->active_tree()->InnerViewportScrollLayer();
2211 DCHECK(inner_viewport_scroll_layer);
2212 host_impl_->ScrollEnd();
2213 EXPECT_EQ(top_controls_scroll_delta,
2214 inner_viewport_scroll_layer->FixedContainerSizeDelta());
2217 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsWithPageScale) {
2218 SetupTopControlsAndScrollLayer();
2221 EXPECT_EQ(InputHandler::ScrollStarted,
2222 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2224 float page_scale = 1.5f;
2225 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale, 1.f, 2.f);
2227 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.f);
2228 gfx::Vector2dF expected_container_size_delta =
2229 ScaleVector2d(top_controls_scroll_delta, 1.f / page_scale);
2230 host_impl_->top_controls_manager()->ScrollBegin();
2231 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2232 host_impl_->top_controls_manager()->ScrollEnd();
2234 LayerImpl* inner_viewport_scroll_layer =
2235 host_impl_->active_tree()->InnerViewportScrollLayer();
2236 DCHECK(inner_viewport_scroll_layer);
2237 host_impl_->ScrollEnd();
2239 // Use a tolerance that requires the container size delta to be within 0.01
2241 double tolerance = 0.0001;
2243 (expected_container_size_delta -
2244 inner_viewport_scroll_layer->FixedContainerSizeDelta()).LengthSquared(),
2248 TEST_F(LayerTreeHostImplTopControlsTest,
2249 ScrollNonScrollableRootWithTopControls) {
2250 SetupTopControlsAndScrollLayer();
2253 EXPECT_EQ(InputHandler::ScrollStarted,
2254 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2256 host_impl_->top_controls_manager()->ScrollBegin();
2257 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
2258 host_impl_->top_controls_manager()->ScrollEnd();
2259 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->content_top_offset());
2260 // Now that top controls have moved, expect the clip to resize.
2261 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2262 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2264 host_impl_->ScrollEnd();
2266 EXPECT_EQ(InputHandler::ScrollStarted,
2267 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2269 float scroll_increment_y = -25.f;
2270 host_impl_->top_controls_manager()->ScrollBegin();
2271 host_impl_->top_controls_manager()->ScrollBy(
2272 gfx::Vector2dF(0.f, scroll_increment_y));
2273 EXPECT_EQ(-scroll_increment_y,
2274 host_impl_->top_controls_manager()->content_top_offset());
2275 // Now that top controls have moved, expect the clip to resize.
2276 EXPECT_EQ(gfx::Size(viewport_size_.width(),
2277 viewport_size_.height() + scroll_increment_y),
2278 root_clip_ptr->bounds());
2280 host_impl_->top_controls_manager()->ScrollBy(
2281 gfx::Vector2dF(0.f, scroll_increment_y));
2282 host_impl_->top_controls_manager()->ScrollEnd();
2283 EXPECT_EQ(-2 * scroll_increment_y,
2284 host_impl_->top_controls_manager()->content_top_offset());
2285 // Now that top controls have moved, expect the clip to resize.
2286 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2288 host_impl_->ScrollEnd();
2290 // Verify the layer is once-again non-scrollable.
2293 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
2295 EXPECT_EQ(InputHandler::ScrollStarted,
2296 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2299 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
2300 // Test the configuration where a non-composited root layer is embedded in a
2301 // scrollable outer layer.
2302 gfx::Size surface_size(10, 10);
2303 gfx::Size contents_size(20, 20);
2305 scoped_ptr<LayerImpl> content_layer =
2306 LayerImpl::Create(host_impl_->active_tree(), 1);
2307 content_layer->SetDrawsContent(true);
2308 content_layer->SetPosition(gfx::PointF());
2309 content_layer->SetBounds(contents_size);
2310 content_layer->SetContentBounds(contents_size);
2311 content_layer->SetContentsScale(2.f, 2.f);
2313 scoped_ptr<LayerImpl> scroll_clip_layer =
2314 LayerImpl::Create(host_impl_->active_tree(), 3);
2315 scroll_clip_layer->SetBounds(surface_size);
2317 scoped_ptr<LayerImpl> scroll_layer =
2318 LayerImpl::Create(host_impl_->active_tree(), 2);
2319 scroll_layer->SetScrollClipLayer(3);
2320 scroll_layer->SetBounds(contents_size);
2321 scroll_layer->SetContentBounds(contents_size);
2322 scroll_layer->SetPosition(gfx::PointF());
2323 scroll_layer->AddChild(content_layer.Pass());
2324 scroll_clip_layer->AddChild(scroll_layer.Pass());
2326 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
2327 host_impl_->SetViewportSize(surface_size);
2330 EXPECT_EQ(InputHandler::ScrollStarted,
2331 host_impl_->ScrollBegin(gfx::Point(5, 5),
2332 InputHandler::Wheel));
2333 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2334 host_impl_->ScrollEnd();
2335 EXPECT_TRUE(did_request_redraw_);
2336 EXPECT_TRUE(did_request_commit_);
2339 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
2340 gfx::Size surface_size(10, 10);
2341 gfx::Size contents_size(20, 20);
2342 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2343 root->SetBounds(surface_size);
2344 root->SetContentBounds(contents_size);
2345 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
2346 host_impl_->active_tree()->SetRootLayer(root.Pass());
2347 host_impl_->SetViewportSize(surface_size);
2350 EXPECT_EQ(InputHandler::ScrollStarted,
2351 host_impl_->ScrollBegin(gfx::Point(5, 5),
2352 InputHandler::Wheel));
2353 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2354 host_impl_->ScrollEnd();
2355 EXPECT_TRUE(did_request_redraw_);
2356 EXPECT_TRUE(did_request_commit_);
2359 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
2360 gfx::Size surface_size(10, 10);
2361 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2362 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
2363 host_impl_->active_tree()->SetRootLayer(root.Pass());
2364 host_impl_->SetViewportSize(surface_size);
2367 // Scroll event is ignored because the input coordinate is outside the layer
2369 EXPECT_EQ(InputHandler::ScrollIgnored,
2370 host_impl_->ScrollBegin(gfx::Point(15, 5),
2371 InputHandler::Wheel));
2372 EXPECT_FALSE(did_request_redraw_);
2373 EXPECT_FALSE(did_request_commit_);
2376 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
2377 gfx::Size surface_size(10, 10);
2378 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2379 scoped_ptr<LayerImpl> child =
2380 CreateScrollableLayer(2, surface_size, root.get());
2381 host_impl_->SetViewportSize(surface_size);
2383 gfx::Transform matrix;
2384 matrix.RotateAboutXAxis(180.0);
2385 child->SetTransform(matrix);
2386 child->SetDoubleSided(false);
2388 root->AddChild(child.Pass());
2389 host_impl_->active_tree()->SetRootLayer(root.Pass());
2392 // Scroll event is ignored because the scrollable layer is not facing the
2393 // viewer and there is nothing scrollable behind it.
2394 EXPECT_EQ(InputHandler::ScrollIgnored,
2395 host_impl_->ScrollBegin(gfx::Point(5, 5),
2396 InputHandler::Wheel));
2397 EXPECT_FALSE(did_request_redraw_);
2398 EXPECT_FALSE(did_request_commit_);
2401 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
2402 gfx::Size surface_size(10, 10);
2403 scoped_ptr<LayerImpl> clip_layer =
2404 LayerImpl::Create(host_impl_->active_tree(), 3);
2405 scoped_ptr<LayerImpl> content_layer =
2406 CreateScrollableLayer(1, surface_size, clip_layer.get());
2407 content_layer->SetShouldScrollOnMainThread(true);
2408 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
2410 // Note: we can use the same clip layer for both since both calls to
2411 // CreateScrollableLayer() use the same surface size.
2412 scoped_ptr<LayerImpl> scroll_layer =
2413 CreateScrollableLayer(2, surface_size, clip_layer.get());
2414 scroll_layer->AddChild(content_layer.Pass());
2415 clip_layer->AddChild(scroll_layer.Pass());
2417 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
2418 host_impl_->SetViewportSize(surface_size);
2421 // Scrolling fails because the content layer is asking to be scrolled on the
2423 EXPECT_EQ(InputHandler::ScrollOnMainThread,
2424 host_impl_->ScrollBegin(gfx::Point(5, 5),
2425 InputHandler::Wheel));
2428 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
2429 gfx::Size surface_size(20, 20);
2430 gfx::Size viewport_size(10, 10);
2431 float page_scale = 2.f;
2432 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2433 scoped_ptr<LayerImpl> root_clip =
2434 LayerImpl::Create(host_impl_->active_tree(), 2);
2435 scoped_ptr<LayerImpl> root_scrolling =
2436 CreateScrollableLayer(3, surface_size, root_clip.get());
2437 EXPECT_EQ(viewport_size, root_clip->bounds());
2438 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2439 root_clip->AddChild(root_scrolling.Pass());
2440 root->AddChild(root_clip.Pass());
2441 host_impl_->active_tree()->SetRootLayer(root.Pass());
2442 // The behaviour in this test assumes the page scale is applied at a layer
2443 // above the clip layer.
2444 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2445 host_impl_->active_tree()->DidBecomeActive();
2446 host_impl_->SetViewportSize(viewport_size);
2449 LayerImpl* root_scroll =
2450 host_impl_->active_tree()->InnerViewportScrollLayer();
2451 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2453 gfx::Vector2d scroll_delta(0, 10);
2454 gfx::Vector2d expected_scroll_delta = scroll_delta;
2455 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2456 EXPECT_EQ(InputHandler::ScrollStarted,
2457 host_impl_->ScrollBegin(gfx::Point(5, 5),
2458 InputHandler::Wheel));
2459 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2460 host_impl_->ScrollEnd();
2462 // Set new page scale from main thread.
2463 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2467 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2468 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2470 // The scroll range should also have been updated.
2471 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2473 // The page scale delta remains constant because the impl thread did not
2475 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2478 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
2479 gfx::Size surface_size(20, 20);
2480 gfx::Size viewport_size(10, 10);
2481 float page_scale = 2.f;
2482 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2483 scoped_ptr<LayerImpl> root_clip =
2484 LayerImpl::Create(host_impl_->active_tree(), 2);
2485 scoped_ptr<LayerImpl> root_scrolling =
2486 CreateScrollableLayer(3, surface_size, root_clip.get());
2487 EXPECT_EQ(viewport_size, root_clip->bounds());
2488 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2489 root_clip->AddChild(root_scrolling.Pass());
2490 root->AddChild(root_clip.Pass());
2491 host_impl_->active_tree()->SetRootLayer(root.Pass());
2492 // The behaviour in this test assumes the page scale is applied at a layer
2493 // above the clip layer.
2494 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2495 host_impl_->active_tree()->DidBecomeActive();
2496 host_impl_->SetViewportSize(viewport_size);
2497 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
2500 LayerImpl* root_scroll =
2501 host_impl_->active_tree()->InnerViewportScrollLayer();
2502 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2504 gfx::Vector2d scroll_delta(0, 10);
2505 gfx::Vector2d expected_scroll_delta = scroll_delta;
2506 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2507 EXPECT_EQ(InputHandler::ScrollStarted,
2508 host_impl_->ScrollBegin(gfx::Point(5, 5),
2509 InputHandler::Wheel));
2510 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2511 host_impl_->ScrollEnd();
2513 // Set new page scale on impl thread by pinching.
2514 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2515 host_impl_->PinchGestureBegin();
2516 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
2517 host_impl_->PinchGestureEnd();
2518 host_impl_->ScrollEnd();
2521 // The scroll delta is not scaled because the main thread did not scale.
2522 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2523 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2525 // The scroll range should also have been updated.
2526 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2528 // The page scale delta should match the new scale on the impl side.
2529 EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
2532 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
2533 gfx::Size surface_size(10, 10);
2534 float default_page_scale = 1.f;
2535 gfx::Transform default_page_scale_matrix;
2536 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
2538 float new_page_scale = 2.f;
2539 gfx::Transform new_page_scale_matrix;
2540 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
2542 // Create a normal scrollable root layer and another scrollable child layer.
2543 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
2544 LayerImpl* root = host_impl_->active_tree()->root_layer();
2545 LayerImpl* child = scroll->children()[0];
2547 scoped_ptr<LayerImpl> scrollable_child_clip =
2548 LayerImpl::Create(host_impl_->active_tree(), 6);
2549 scoped_ptr<LayerImpl> scrollable_child =
2550 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
2551 scrollable_child_clip->AddChild(scrollable_child.Pass());
2552 child->AddChild(scrollable_child_clip.Pass());
2553 LayerImpl* grand_child = child->children()[0];
2555 // Set new page scale on impl thread by pinching.
2556 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2557 host_impl_->PinchGestureBegin();
2558 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
2559 host_impl_->PinchGestureEnd();
2560 host_impl_->ScrollEnd();
2563 EXPECT_EQ(1.f, root->contents_scale_x());
2564 EXPECT_EQ(1.f, root->contents_scale_y());
2565 EXPECT_EQ(1.f, scroll->contents_scale_x());
2566 EXPECT_EQ(1.f, scroll->contents_scale_y());
2567 EXPECT_EQ(1.f, child->contents_scale_x());
2568 EXPECT_EQ(1.f, child->contents_scale_y());
2569 EXPECT_EQ(1.f, grand_child->contents_scale_x());
2570 EXPECT_EQ(1.f, grand_child->contents_scale_y());
2572 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
2573 // the page scale delta on the root layer is applied hierarchically.
2574 LayerTreeHostImpl::FrameData frame;
2575 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2576 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2577 host_impl_->DidDrawAllLayers(frame);
2579 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
2580 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
2581 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
2582 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
2583 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
2584 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
2585 EXPECT_EQ(new_page_scale,
2586 grand_child->draw_transform().matrix().getDouble(0, 0));
2587 EXPECT_EQ(new_page_scale,
2588 grand_child->draw_transform().matrix().getDouble(1, 1));
2591 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
2592 gfx::Size surface_size(30, 30);
2593 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2594 root->SetBounds(gfx::Size(5, 5));
2595 scoped_ptr<LayerImpl> root_scrolling =
2596 LayerImpl::Create(host_impl_->active_tree(), 2);
2597 root_scrolling->SetBounds(surface_size);
2598 root_scrolling->SetContentBounds(surface_size);
2599 root_scrolling->SetScrollClipLayer(root->id());
2600 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2601 LayerImpl* root_scrolling_ptr = root_scrolling.get();
2602 root->AddChild(root_scrolling.Pass());
2603 int child_scroll_layer_id = 3;
2604 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
2605 child_scroll_layer_id, surface_size, root_scrolling_ptr);
2606 LayerImpl* child = child_scrolling.get();
2607 root_scrolling_ptr->AddChild(child_scrolling.Pass());
2608 host_impl_->active_tree()->SetRootLayer(root.Pass());
2609 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2610 host_impl_->active_tree()->DidBecomeActive();
2611 host_impl_->SetViewportSize(surface_size);
2614 gfx::Vector2d scroll_delta(0, 10);
2615 gfx::Vector2d expected_scroll_delta(scroll_delta);
2616 gfx::Vector2d expected_max_scroll(child->MaxScrollOffset());
2617 EXPECT_EQ(InputHandler::ScrollStarted,
2618 host_impl_->ScrollBegin(gfx::Point(5, 5),
2619 InputHandler::Wheel));
2620 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2621 host_impl_->ScrollEnd();
2623 float page_scale = 2.f;
2624 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2630 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2632 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
2634 // The scroll range should not have changed.
2635 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
2637 // The page scale delta remains constant because the impl thread did not
2639 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2642 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
2643 // Scroll a child layer beyond its maximum scroll range and make sure the
2644 // parent layer is scrolled on the axis on which the child was unable to
2646 gfx::Size surface_size(10, 10);
2647 gfx::Size content_size(20, 20);
2648 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2649 root->SetBounds(surface_size);
2651 scoped_ptr<LayerImpl> grand_child =
2652 CreateScrollableLayer(3, content_size, root.get());
2654 scoped_ptr<LayerImpl> child =
2655 CreateScrollableLayer(2, content_size, root.get());
2656 LayerImpl* grand_child_layer = grand_child.get();
2657 child->AddChild(grand_child.Pass());
2659 LayerImpl* child_layer = child.get();
2660 root->AddChild(child.Pass());
2661 host_impl_->active_tree()->SetRootLayer(root.Pass());
2662 host_impl_->active_tree()->DidBecomeActive();
2663 host_impl_->SetViewportSize(surface_size);
2664 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 5));
2665 child_layer->SetScrollOffset(gfx::Vector2d(3, 0));
2669 gfx::Vector2d scroll_delta(-8, -7);
2670 EXPECT_EQ(InputHandler::ScrollStarted,
2671 host_impl_->ScrollBegin(gfx::Point(),
2672 InputHandler::Wheel));
2673 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2674 host_impl_->ScrollEnd();
2676 scoped_ptr<ScrollAndScaleSet> scroll_info =
2677 host_impl_->ProcessScrollDeltas();
2679 // The grand child should have scrolled up to its limit.
2680 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2681 LayerImpl* grand_child = child->children()[0];
2682 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
2684 // The child should have only scrolled on the other axis.
2685 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
2689 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
2690 // Scroll a child layer beyond its maximum scroll range and make sure the
2691 // the scroll doesn't bubble up to the parent layer.
2692 gfx::Size surface_size(20, 20);
2693 gfx::Size viewport_size(10, 10);
2694 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2695 scoped_ptr<LayerImpl> root_scrolling =
2696 CreateScrollableLayer(2, surface_size, root.get());
2697 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2699 scoped_ptr<LayerImpl> grand_child =
2700 CreateScrollableLayer(4, surface_size, root.get());
2702 scoped_ptr<LayerImpl> child =
2703 CreateScrollableLayer(3, surface_size, root.get());
2704 LayerImpl* grand_child_layer = grand_child.get();
2705 child->AddChild(grand_child.Pass());
2707 LayerImpl* child_layer = child.get();
2708 root_scrolling->AddChild(child.Pass());
2709 root->AddChild(root_scrolling.Pass());
2710 EXPECT_EQ(viewport_size, root->bounds());
2711 host_impl_->active_tree()->SetRootLayer(root.Pass());
2712 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2713 host_impl_->active_tree()->DidBecomeActive();
2714 host_impl_->SetViewportSize(viewport_size);
2716 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
2717 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
2721 gfx::Vector2d scroll_delta(0, -10);
2722 EXPECT_EQ(InputHandler::ScrollStarted,
2723 host_impl_->ScrollBegin(gfx::Point(),
2724 InputHandler::NonBubblingGesture));
2725 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2726 host_impl_->ScrollEnd();
2728 scoped_ptr<ScrollAndScaleSet> scroll_info =
2729 host_impl_->ProcessScrollDeltas();
2731 // The grand child should have scrolled up to its limit.
2733 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
2734 LayerImpl* grand_child = child->children()[0];
2735 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2737 // The child should not have scrolled.
2738 ExpectNone(*scroll_info.get(), child->id());
2740 // The next time we scroll we should only scroll the parent.
2741 scroll_delta = gfx::Vector2d(0, -3);
2742 EXPECT_EQ(InputHandler::ScrollStarted,
2743 host_impl_->ScrollBegin(gfx::Point(5, 5),
2744 InputHandler::NonBubblingGesture));
2745 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2746 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2747 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
2748 host_impl_->ScrollEnd();
2750 scroll_info = host_impl_->ProcessScrollDeltas();
2752 // The child should have scrolled up to its limit.
2753 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2755 // The grand child should not have scrolled.
2756 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2758 // After scrolling the parent, another scroll on the opposite direction
2759 // should still scroll the child.
2760 scroll_delta = gfx::Vector2d(0, 7);
2761 EXPECT_EQ(InputHandler::ScrollStarted,
2762 host_impl_->ScrollBegin(gfx::Point(5, 5),
2763 InputHandler::NonBubblingGesture));
2764 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2765 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2766 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2767 host_impl_->ScrollEnd();
2769 scroll_info = host_impl_->ProcessScrollDeltas();
2771 // The grand child should have scrolled.
2772 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
2774 // The child should not have scrolled.
2775 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2778 // Scrolling should be adjusted from viewport space.
2779 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
2780 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2782 scroll_delta = gfx::Vector2d(0, -2);
2783 EXPECT_EQ(InputHandler::ScrollStarted,
2784 host_impl_->ScrollBegin(gfx::Point(1, 1),
2785 InputHandler::NonBubblingGesture));
2786 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
2787 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2788 host_impl_->ScrollEnd();
2790 scroll_info = host_impl_->ProcessScrollDeltas();
2792 // Should have scrolled by half the amount in layer space (5 - 2/2)
2793 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
2796 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
2797 // When we try to scroll a non-scrollable child layer, the scroll delta
2798 // should be applied to one of its ancestors if possible.
2799 gfx::Size surface_size(10, 10);
2800 gfx::Size content_size(20, 20);
2801 scoped_ptr<LayerImpl> root_clip =
2802 LayerImpl::Create(host_impl_->active_tree(), 3);
2803 scoped_ptr<LayerImpl> root =
2804 CreateScrollableLayer(1, content_size, root_clip.get());
2805 // Make 'root' the clip layer for child: since they have the same sizes the
2806 // child will have zero max_scroll_offset and scrolls will bubble.
2807 scoped_ptr<LayerImpl> child =
2808 CreateScrollableLayer(2, content_size, root.get());
2809 child->SetIsContainerForFixedPositionLayers(true);
2810 root->SetBounds(content_size);
2812 int root_scroll_id = root->id();
2813 root->AddChild(child.Pass());
2814 root_clip->AddChild(root.Pass());
2816 host_impl_->SetViewportSize(surface_size);
2817 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2818 host_impl_->active_tree()->SetViewportLayersFromIds(3, 2, Layer::INVALID_ID);
2819 host_impl_->active_tree()->DidBecomeActive();
2822 gfx::Vector2d scroll_delta(0, 4);
2823 EXPECT_EQ(InputHandler::ScrollStarted,
2824 host_impl_->ScrollBegin(gfx::Point(5, 5),
2825 InputHandler::Wheel));
2826 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2827 host_impl_->ScrollEnd();
2829 scoped_ptr<ScrollAndScaleSet> scroll_info =
2830 host_impl_->ProcessScrollDeltas();
2832 // Only the root scroll should have scrolled.
2833 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
2834 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
2838 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
2839 gfx::Size surface_size(10, 10);
2840 scoped_ptr<LayerImpl> root_clip =
2841 LayerImpl::Create(host_impl_->active_tree(), 1);
2842 scoped_ptr<LayerImpl> root_scroll =
2843 CreateScrollableLayer(2, surface_size, root_clip.get());
2844 root_scroll->SetIsContainerForFixedPositionLayers(true);
2845 root_clip->AddChild(root_scroll.Pass());
2846 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2847 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2848 host_impl_->active_tree()->DidBecomeActive();
2849 host_impl_->SetViewportSize(surface_size);
2851 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
2854 host_impl_->active_tree()->DetachLayerTree();
2855 scoped_ptr<LayerImpl> root_clip2 =
2856 LayerImpl::Create(host_impl_->active_tree(), 3);
2857 scoped_ptr<LayerImpl> root_scroll2 =
2858 CreateScrollableLayer(4, surface_size, root_clip2.get());
2859 root_scroll2->SetIsContainerForFixedPositionLayers(true);
2860 root_clip2->AddChild(root_scroll2.Pass());
2861 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
2862 host_impl_->active_tree()->SetViewportLayersFromIds(3, 4, Layer::INVALID_ID);
2863 host_impl_->active_tree()->DidBecomeActive();
2865 // Scrolling should still work even though we did not draw yet.
2866 EXPECT_EQ(InputHandler::ScrollStarted,
2867 host_impl_->ScrollBegin(gfx::Point(5, 5),
2868 InputHandler::Wheel));
2871 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
2872 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2874 // Rotate the root layer 90 degrees counter-clockwise about its center.
2875 gfx::Transform rotate_transform;
2876 rotate_transform.Rotate(-90.0);
2877 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
2879 gfx::Size surface_size(50, 50);
2880 host_impl_->SetViewportSize(surface_size);
2883 // Scroll to the right in screen coordinates with a gesture.
2884 gfx::Vector2d gesture_scroll_delta(10, 0);
2885 EXPECT_EQ(InputHandler::ScrollStarted,
2886 host_impl_->ScrollBegin(gfx::Point(),
2887 InputHandler::Gesture));
2888 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2889 host_impl_->ScrollEnd();
2891 // The layer should have scrolled down in its local coordinates.
2892 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2893 ExpectContains(*scroll_info.get(),
2895 gfx::Vector2d(0, gesture_scroll_delta.x()));
2897 // Reset and scroll down with the wheel.
2898 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2899 gfx::Vector2d wheel_scroll_delta(0, 10);
2900 EXPECT_EQ(InputHandler::ScrollStarted,
2901 host_impl_->ScrollBegin(gfx::Point(),
2902 InputHandler::Wheel));
2903 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2904 host_impl_->ScrollEnd();
2906 // The layer should have scrolled down in its local coordinates.
2907 scroll_info = host_impl_->ProcessScrollDeltas();
2908 ExpectContains(*scroll_info.get(),
2910 wheel_scroll_delta);
2913 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
2914 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2915 int child_clip_layer_id = 6;
2916 int child_layer_id = 7;
2917 float child_layer_angle = -20.f;
2919 // Create a child layer that is rotated to a non-axis-aligned angle.
2920 scoped_ptr<LayerImpl> clip_layer =
2921 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
2922 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
2923 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
2924 gfx::Transform rotate_transform;
2925 rotate_transform.Translate(-50.0, -50.0);
2926 rotate_transform.Rotate(child_layer_angle);
2927 rotate_transform.Translate(50.0, 50.0);
2928 clip_layer->SetTransform(rotate_transform);
2930 // Only allow vertical scrolling.
2931 clip_layer->SetBounds(
2932 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
2933 // The rotation depends on the layer's transform origin, and the child layer
2934 // is a different size than the clip, so make sure the clip layer's origin
2935 // lines up over the child.
2936 clip_layer->SetTransformOrigin(gfx::Point3F(
2937 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
2938 LayerImpl* child_ptr = child.get();
2939 clip_layer->AddChild(child.Pass());
2940 scroll_layer->AddChild(clip_layer.Pass());
2942 gfx::Size surface_size(50, 50);
2943 host_impl_->SetViewportSize(surface_size);
2946 // Scroll down in screen coordinates with a gesture.
2947 gfx::Vector2d gesture_scroll_delta(0, 10);
2948 EXPECT_EQ(InputHandler::ScrollStarted,
2949 host_impl_->ScrollBegin(gfx::Point(1, 1),
2950 InputHandler::Gesture));
2951 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2952 host_impl_->ScrollEnd();
2954 // The child layer should have scrolled down in its local coordinates an
2955 // amount proportional to the angle between it and the input scroll delta.
2956 gfx::Vector2d expected_scroll_delta(
2958 gesture_scroll_delta.y() *
2959 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
2960 scoped_ptr<ScrollAndScaleSet> scroll_info =
2961 host_impl_->ProcessScrollDeltas();
2962 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2964 // The root scroll layer should not have scrolled, because the input delta
2965 // was close to the layer's axis of movement.
2966 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
2969 // Now reset and scroll the same amount horizontally.
2970 child_ptr->SetScrollDelta(gfx::Vector2dF());
2971 gfx::Vector2d gesture_scroll_delta(10, 0);
2972 EXPECT_EQ(InputHandler::ScrollStarted,
2973 host_impl_->ScrollBegin(gfx::Point(1, 1),
2974 InputHandler::Gesture));
2975 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2976 host_impl_->ScrollEnd();
2978 // The child layer should have scrolled down in its local coordinates an
2979 // amount proportional to the angle between it and the input scroll delta.
2980 gfx::Vector2d expected_scroll_delta(
2982 -gesture_scroll_delta.x() *
2983 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
2984 scoped_ptr<ScrollAndScaleSet> scroll_info =
2985 host_impl_->ProcessScrollDeltas();
2986 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2988 // The root scroll layer should have scrolled more, since the input scroll
2989 // delta was mostly orthogonal to the child layer's vertical scroll axis.
2990 gfx::Vector2d expected_root_scroll_delta(
2991 gesture_scroll_delta.x() *
2992 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
2994 ExpectContains(*scroll_info.get(),
2996 expected_root_scroll_delta);
3000 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
3001 LayerImpl* scroll_layer =
3002 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3004 // Scale the layer to twice its normal size.
3006 gfx::Transform scale_transform;
3007 scale_transform.Scale(scale, scale);
3008 scroll_layer->SetTransform(scale_transform);
3010 gfx::Size surface_size(50, 50);
3011 host_impl_->SetViewportSize(surface_size);
3014 // Scroll down in screen coordinates with a gesture.
3015 gfx::Vector2d scroll_delta(0, 10);
3016 EXPECT_EQ(InputHandler::ScrollStarted,
3017 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3018 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3019 host_impl_->ScrollEnd();
3021 // The layer should have scrolled down in its local coordinates, but half the
3023 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3024 ExpectContains(*scroll_info.get(),
3026 gfx::Vector2d(0, scroll_delta.y() / scale));
3028 // Reset and scroll down with the wheel.
3029 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3030 gfx::Vector2d wheel_scroll_delta(0, 10);
3031 EXPECT_EQ(InputHandler::ScrollStarted,
3032 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3033 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3034 host_impl_->ScrollEnd();
3036 // The scale should not have been applied to the scroll delta.
3037 scroll_info = host_impl_->ProcessScrollDeltas();
3038 ExpectContains(*scroll_info.get(),
3040 wheel_scroll_delta);
3043 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
3047 SetupScrollAndContentsLayers(gfx::Size(width, height));
3048 host_impl_->SetViewportSize(gfx::Size(width * scale - 1, height * scale));
3049 host_impl_->SetDeviceScaleFactor(scale);
3050 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3052 LayerImpl* inner_viewport_scroll_layer =
3053 host_impl_->active_tree()->InnerViewportScrollLayer();
3054 EXPECT_EQ(gfx::Vector2d(0, 0),
3055 inner_viewport_scroll_layer->MaxScrollOffset());
3058 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
3060 TestScrollOffsetDelegate()
3061 : page_scale_factor_(0.f),
3062 min_page_scale_factor_(-1.f),
3063 max_page_scale_factor_(-1.f) {}
3065 virtual ~TestScrollOffsetDelegate() {}
3067 virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
3068 return getter_return_value_;
3071 virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
3073 virtual void UpdateRootLayerState(const gfx::Vector2dF& total_scroll_offset,
3074 const gfx::Vector2dF& max_scroll_offset,
3075 const gfx::SizeF& scrollable_size,
3076 float page_scale_factor,
3077 float min_page_scale_factor,
3078 float max_page_scale_factor) OVERRIDE {
3079 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
3080 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
3081 last_set_scroll_offset_ = total_scroll_offset;
3082 max_scroll_offset_ = max_scroll_offset;
3083 scrollable_size_ = scrollable_size;
3084 page_scale_factor_ = page_scale_factor;
3085 min_page_scale_factor_ = min_page_scale_factor;
3086 max_page_scale_factor_ = max_page_scale_factor;
3089 gfx::Vector2dF last_set_scroll_offset() {
3090 return last_set_scroll_offset_;
3093 void set_getter_return_value(const gfx::Vector2dF& value) {
3094 getter_return_value_ = value;
3097 gfx::Vector2dF max_scroll_offset() const {
3098 return max_scroll_offset_;
3101 gfx::SizeF scrollable_size() const {
3102 return scrollable_size_;
3105 float page_scale_factor() const {
3106 return page_scale_factor_;
3109 float min_page_scale_factor() const {
3110 return min_page_scale_factor_;
3113 float max_page_scale_factor() const {
3114 return max_page_scale_factor_;
3118 gfx::Vector2dF last_set_scroll_offset_;
3119 gfx::Vector2dF getter_return_value_;
3120 gfx::Vector2dF max_scroll_offset_;
3121 gfx::SizeF scrollable_size_;
3122 float page_scale_factor_;
3123 float min_page_scale_factor_;
3124 float max_page_scale_factor_;
3127 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
3128 TestScrollOffsetDelegate scroll_delegate;
3129 host_impl_->SetViewportSize(gfx::Size(10, 20));
3130 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3131 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3132 clip_layer->SetBounds(gfx::Size(10, 20));
3134 // Setting the delegate results in the current scroll offset being set.
3135 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
3136 scroll_layer->SetScrollOffset(gfx::Vector2d());
3137 scroll_layer->SetScrollDelta(initial_scroll_delta);
3138 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3139 EXPECT_EQ(initial_scroll_delta.ToString(),
3140 scroll_delegate.last_set_scroll_offset().ToString());
3142 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3143 // page_scale_factor and {min|max}_page_scale_factor being set.
3144 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
3145 EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
3146 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3147 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
3148 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
3150 // Updating page scale immediately updates the delegate.
3151 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
3152 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
3153 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3154 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3155 host_impl_->active_tree()->SetPageScaleDelta(1.5f);
3156 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
3157 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3158 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3159 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3160 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3161 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3162 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3163 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3165 // The pinch gesture doesn't put the delegate into a state where the scroll
3166 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3168 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3169 host_impl_->PinchGestureBegin();
3170 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
3171 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
3172 host_impl_->PinchGestureEnd();
3173 host_impl_->ScrollEnd();
3175 // Scrolling should be relative to the offset as returned by the delegate.
3176 gfx::Vector2dF scroll_delta(0.f, 10.f);
3177 gfx::Vector2dF current_offset(7.f, 8.f);
3179 scroll_delegate.set_getter_return_value(current_offset);
3180 EXPECT_EQ(InputHandler::ScrollStarted,
3181 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3183 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3184 EXPECT_EQ(current_offset + scroll_delta,
3185 scroll_delegate.last_set_scroll_offset());
3187 current_offset = gfx::Vector2dF(42.f, 41.f);
3188 scroll_delegate.set_getter_return_value(current_offset);
3189 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3190 EXPECT_EQ(current_offset + scroll_delta,
3191 scroll_delegate.last_set_scroll_offset());
3192 host_impl_->ScrollEnd();
3193 scroll_delegate.set_getter_return_value(gfx::Vector2dF());
3195 // Forces a full tree synchronization and ensures that the scroll delegate
3196 // sees the correct size of the new tree.
3197 gfx::Size new_size(42, 24);
3198 host_impl_->CreatePendingTree();
3199 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
3200 host_impl_->ActivateSyncTree();
3201 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
3203 // Un-setting the delegate should propagate the delegate's current offset to
3204 // the root scrollable layer.
3205 current_offset = gfx::Vector2dF(13.f, 12.f);
3206 scroll_delegate.set_getter_return_value(current_offset);
3207 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3209 EXPECT_EQ(current_offset.ToString(),
3210 scroll_layer->TotalScrollOffset().ToString());
3213 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
3214 const gfx::Transform target_space_transform =
3215 layer->draw_properties().target_space_transform;
3216 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
3217 gfx::Point translated_point;
3218 target_space_transform.TransformPoint(&translated_point);
3219 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
3220 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
3223 TEST_F(LayerTreeHostImplTest,
3224 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
3225 TestScrollOffsetDelegate scroll_delegate;
3226 host_impl_->SetViewportSize(gfx::Size(10, 20));
3227 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3228 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3229 clip_layer->SetBounds(gfx::Size(10, 20));
3230 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3232 // Draw first frame to clear any pending draws and check scroll.
3234 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
3235 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
3237 // Set external scroll delta on delegate and notify LayerTreeHost.
3238 gfx::Vector2dF scroll_delta(10.f, 10.f);
3239 scroll_delegate.set_getter_return_value(scroll_delta);
3240 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
3242 // Check scroll delta reflected in layer.
3244 CheckLayerScrollDelta(scroll_layer, scroll_delta);
3246 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3249 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
3250 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3251 host_impl_->SetViewportSize(gfx::Size(50, 50));
3252 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3254 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3256 // In-bounds scrolling does not affect overscroll.
3257 EXPECT_EQ(InputHandler::ScrollStarted,
3258 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3259 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3260 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3262 // Overscroll events are reflected immediately.
3263 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
3264 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3266 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
3267 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
3268 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3269 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
3270 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3271 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
3272 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3273 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
3274 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
3275 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
3276 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
3277 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
3278 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3280 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
3281 // as no scroll occurs.
3282 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3283 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
3284 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3285 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
3286 // Overscroll resets on valid scroll.
3287 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3288 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3289 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3290 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3291 host_impl_->ScrollEnd();
3295 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
3296 // Scroll child layers beyond their maximum scroll range and make sure root
3297 // overscroll does not accumulate.
3298 gfx::Size surface_size(10, 10);
3299 scoped_ptr<LayerImpl> root_clip =
3300 LayerImpl::Create(host_impl_->active_tree(), 4);
3301 scoped_ptr<LayerImpl> root =
3302 CreateScrollableLayer(1, surface_size, root_clip.get());
3304 scoped_ptr<LayerImpl> grand_child =
3305 CreateScrollableLayer(3, surface_size, root_clip.get());
3307 scoped_ptr<LayerImpl> child =
3308 CreateScrollableLayer(2, surface_size, root_clip.get());
3309 LayerImpl* grand_child_layer = grand_child.get();
3310 child->AddChild(grand_child.Pass());
3312 LayerImpl* child_layer = child.get();
3313 root->AddChild(child.Pass());
3314 root_clip->AddChild(root.Pass());
3315 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
3316 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
3317 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3318 host_impl_->active_tree()->DidBecomeActive();
3319 host_impl_->SetViewportSize(surface_size);
3322 gfx::Vector2d scroll_delta(0, -10);
3323 EXPECT_EQ(InputHandler::ScrollStarted,
3324 host_impl_->ScrollBegin(gfx::Point(),
3325 InputHandler::NonBubblingGesture));
3326 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3327 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3328 host_impl_->ScrollEnd();
3330 // The next time we scroll we should only scroll the parent, but overscroll
3331 // should still not reach the root layer.
3332 scroll_delta = gfx::Vector2d(0, -30);
3333 EXPECT_EQ(InputHandler::ScrollStarted,
3334 host_impl_->ScrollBegin(gfx::Point(5, 5),
3335 InputHandler::NonBubblingGesture));
3336 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3337 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3338 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3339 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
3340 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3341 host_impl_->ScrollEnd();
3343 // After scrolling the parent, another scroll on the opposite direction
3344 // should scroll the child.
3345 scroll_delta = gfx::Vector2d(0, 70);
3346 EXPECT_EQ(InputHandler::ScrollStarted,
3347 host_impl_->ScrollBegin(gfx::Point(5, 5),
3348 InputHandler::NonBubblingGesture));
3349 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3350 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3351 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3352 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3353 host_impl_->ScrollEnd();
3357 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
3358 // When we try to scroll a non-scrollable child layer, the scroll delta
3359 // should be applied to one of its ancestors if possible. Overscroll should
3360 // be reflected only when it has bubbled up to the root scrolling layer.
3361 gfx::Size surface_size(10, 10);
3362 gfx::Size content_size(20, 20);
3363 scoped_ptr<LayerImpl> root_clip =
3364 LayerImpl::Create(host_impl_->active_tree(), 3);
3365 scoped_ptr<LayerImpl> root =
3366 CreateScrollableLayer(1, content_size, root_clip.get());
3367 root->SetIsContainerForFixedPositionLayers(true);
3368 scoped_ptr<LayerImpl> child =
3369 CreateScrollableLayer(2, content_size, root_clip.get());
3371 child->SetScrollClipLayer(Layer::INVALID_ID);
3372 root->AddChild(child.Pass());
3373 root_clip->AddChild(root.Pass());
3375 host_impl_->SetViewportSize(surface_size);
3376 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3377 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3378 host_impl_->active_tree()->DidBecomeActive();
3381 gfx::Vector2d scroll_delta(0, 8);
3382 EXPECT_EQ(InputHandler::ScrollStarted,
3383 host_impl_->ScrollBegin(gfx::Point(5, 5),
3384 InputHandler::Wheel));
3385 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3386 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3387 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3388 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
3389 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3390 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
3391 host_impl_->ScrollEnd();
3395 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
3396 LayerTreeSettings settings;
3397 CreateHostImpl(settings, CreateOutputSurface());
3399 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
3400 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3401 clip_layer->SetBounds(gfx::Size(50, 50));
3402 host_impl_->SetViewportSize(gfx::Size(50, 50));
3403 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3405 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3407 // Even though the layer can't scroll the overscroll still happens.
3408 EXPECT_EQ(InputHandler::ScrollStarted,
3409 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3410 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3411 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3414 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
3415 gfx::Size surface_size(980, 1439);
3416 gfx::Size content_size(980, 1438);
3417 float device_scale_factor = 1.5f;
3418 scoped_ptr<LayerImpl> root_clip =
3419 LayerImpl::Create(host_impl_->active_tree(), 3);
3420 scoped_ptr<LayerImpl> root =
3421 CreateScrollableLayer(1, content_size, root_clip.get());
3422 root->SetIsContainerForFixedPositionLayers(true);
3423 scoped_ptr<LayerImpl> child =
3424 CreateScrollableLayer(2, content_size, root_clip.get());
3425 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
3426 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
3427 0.326531f, 0.326531f, 5.f);
3428 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3429 child->SetScrollClipLayer(Layer::INVALID_ID);
3430 root->AddChild(child.Pass());
3431 root_clip->AddChild(root.Pass());
3433 host_impl_->SetViewportSize(surface_size);
3434 host_impl_->SetDeviceScaleFactor(device_scale_factor);
3435 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3436 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3437 host_impl_->active_tree()->DidBecomeActive();
3440 // Horizontal & Vertical GlowEffect should not be applied when
3441 // content size is less then view port size. For Example Horizontal &
3442 // vertical GlowEffect should not be applied in about:blank page.
3443 EXPECT_EQ(InputHandler::ScrollStarted,
3444 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3445 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
3446 EXPECT_EQ(gfx::Vector2dF().ToString(),
3447 host_impl_->accumulated_root_overscroll().ToString());
3449 host_impl_->ScrollEnd();
3453 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
3454 gfx::Size surface_size(100, 100);
3455 gfx::Size content_size(200, 200);
3456 scoped_ptr<LayerImpl> root_clip =
3457 LayerImpl::Create(host_impl_->active_tree(), 3);
3458 scoped_ptr<LayerImpl> root =
3459 CreateScrollableLayer(1, content_size, root_clip.get());
3460 root->SetIsContainerForFixedPositionLayers(true);
3461 scoped_ptr<LayerImpl> child =
3462 CreateScrollableLayer(2, content_size, root_clip.get());
3464 child->SetScrollClipLayer(Layer::INVALID_ID);
3465 root->AddChild(child.Pass());
3466 root_clip->AddChild(root.Pass());
3468 host_impl_->SetViewportSize(surface_size);
3469 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3470 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3471 host_impl_->active_tree()->DidBecomeActive();
3474 // Edge glow effect should be applicable only upon reaching Edges
3475 // of the content. unnecessary glow effect calls shouldn't be
3476 // called while scrolling up without reaching the edge of the content.
3477 EXPECT_EQ(InputHandler::ScrollStarted,
3478 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3479 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
3480 EXPECT_EQ(gfx::Vector2dF().ToString(),
3481 host_impl_->accumulated_root_overscroll().ToString());
3482 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
3483 EXPECT_EQ(gfx::Vector2dF().ToString(),
3484 host_impl_->accumulated_root_overscroll().ToString());
3485 host_impl_->ScrollEnd();
3486 // unusedrootDelta should be subtracted from applied delta so that
3487 // unwanted glow effect calls are not called.
3488 EXPECT_EQ(InputHandler::ScrollStarted,
3489 host_impl_->ScrollBegin(gfx::Point(0, 0),
3490 InputHandler::NonBubblingGesture));
3491 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
3492 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
3493 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3494 host_impl_->accumulated_root_overscroll().ToString());
3496 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
3497 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3498 host_impl_->accumulated_root_overscroll().ToString());
3499 host_impl_->ScrollEnd();
3500 // TestCase to check kEpsilon, which prevents minute values to trigger
3501 // gloweffect without reaching edge.
3502 EXPECT_EQ(InputHandler::ScrollStarted,
3503 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3504 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
3505 EXPECT_EQ(gfx::Vector2dF().ToString(),
3506 host_impl_->accumulated_root_overscroll().ToString());
3507 host_impl_->ScrollEnd();
3511 class BlendStateCheckLayer : public LayerImpl {
3513 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
3515 ResourceProvider* resource_provider) {
3516 return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(tree_impl,
3518 resource_provider));
3521 virtual void AppendQuads(RenderPass* render_pass,
3522 const OcclusionTracker<LayerImpl>& occlusion_tracker,
3523 AppendQuadsData* append_quads_data) OVERRIDE {
3524 quads_appended_ = true;
3526 gfx::Rect opaque_rect;
3527 if (contents_opaque())
3528 opaque_rect = quad_rect_;
3530 opaque_rect = opaque_content_rect_;
3531 gfx::Rect visible_quad_rect = quad_rect_;
3533 SharedQuadState* shared_quad_state =
3534 render_pass->CreateAndAppendSharedQuadState();
3535 PopulateSharedQuadState(shared_quad_state);
3537 TileDrawQuad* test_blending_draw_quad =
3538 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
3539 test_blending_draw_quad->SetNew(shared_quad_state,
3544 gfx::RectF(0.f, 0.f, 1.f, 1.f),
3547 test_blending_draw_quad->visible_rect = quad_visible_rect_;
3548 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
3549 EXPECT_EQ(has_render_surface_, !!render_surface());
3552 void SetExpectation(bool blend, bool has_render_surface) {
3554 has_render_surface_ = has_render_surface;
3555 quads_appended_ = false;
3558 bool quads_appended() const { return quads_appended_; }
3560 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
3561 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
3562 void SetOpaqueContentRect(const gfx::Rect& rect) {
3563 opaque_content_rect_ = rect;
3567 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
3569 ResourceProvider* resource_provider)
3570 : LayerImpl(tree_impl, id),
3572 has_render_surface_(false),
3573 quads_appended_(false),
3574 quad_rect_(5, 5, 5, 5),
3575 quad_visible_rect_(5, 5, 5, 5),
3576 resource_id_(resource_provider->CreateResource(
3579 ResourceProvider::TextureUsageAny,
3581 resource_provider->AllocateForTesting(resource_id_);
3582 SetBounds(gfx::Size(10, 10));
3583 SetContentBounds(gfx::Size(10, 10));
3584 SetDrawsContent(true);
3588 bool has_render_surface_;
3589 bool quads_appended_;
3590 gfx::Rect quad_rect_;
3591 gfx::Rect opaque_content_rect_;
3592 gfx::Rect quad_visible_rect_;
3593 ResourceProvider::ResourceId resource_id_;
3596 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
3598 scoped_ptr<LayerImpl> root =
3599 LayerImpl::Create(host_impl_->active_tree(), 1);
3600 root->SetBounds(gfx::Size(10, 10));
3601 root->SetContentBounds(root->bounds());
3602 root->SetDrawsContent(false);
3603 host_impl_->active_tree()->SetRootLayer(root.Pass());
3605 LayerImpl* root = host_impl_->active_tree()->root_layer();
3608 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3610 host_impl_->resource_provider()));
3611 BlendStateCheckLayer* layer1 =
3612 static_cast<BlendStateCheckLayer*>(root->children()[0]);
3613 layer1->SetPosition(gfx::PointF(2.f, 2.f));
3615 LayerTreeHostImpl::FrameData frame;
3617 // Opaque layer, drawn without blending.
3618 layer1->SetContentsOpaque(true);
3619 layer1->SetExpectation(false, false);
3620 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3621 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3622 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3623 EXPECT_TRUE(layer1->quads_appended());
3624 host_impl_->DidDrawAllLayers(frame);
3626 // Layer with translucent content and painting, so drawn with blending.
3627 layer1->SetContentsOpaque(false);
3628 layer1->SetExpectation(true, false);
3629 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3630 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3631 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3632 EXPECT_TRUE(layer1->quads_appended());
3633 host_impl_->DidDrawAllLayers(frame);
3635 // Layer with translucent opacity, drawn with blending.
3636 layer1->SetContentsOpaque(true);
3637 layer1->SetOpacity(0.5f);
3638 layer1->SetExpectation(true, false);
3639 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3640 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3641 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3642 EXPECT_TRUE(layer1->quads_appended());
3643 host_impl_->DidDrawAllLayers(frame);
3645 // Layer with translucent opacity and painting, drawn with blending.
3646 layer1->SetContentsOpaque(true);
3647 layer1->SetOpacity(0.5f);
3648 layer1->SetExpectation(true, false);
3649 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3650 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3651 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3652 EXPECT_TRUE(layer1->quads_appended());
3653 host_impl_->DidDrawAllLayers(frame);
3656 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3658 host_impl_->resource_provider()));
3659 BlendStateCheckLayer* layer2 =
3660 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
3661 layer2->SetPosition(gfx::PointF(4.f, 4.f));
3663 // 2 opaque layers, drawn without blending.
3664 layer1->SetContentsOpaque(true);
3665 layer1->SetOpacity(1.f);
3666 layer1->SetExpectation(false, false);
3667 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3668 layer2->SetContentsOpaque(true);
3669 layer2->SetOpacity(1.f);
3670 layer2->SetExpectation(false, false);
3671 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3672 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3673 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3674 EXPECT_TRUE(layer1->quads_appended());
3675 EXPECT_TRUE(layer2->quads_appended());
3676 host_impl_->DidDrawAllLayers(frame);
3678 // Parent layer with translucent content, drawn with blending.
3679 // Child layer with opaque content, drawn without blending.
3680 layer1->SetContentsOpaque(false);
3681 layer1->SetExpectation(true, false);
3682 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3683 layer2->SetExpectation(false, false);
3684 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3685 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3686 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3687 EXPECT_TRUE(layer1->quads_appended());
3688 EXPECT_TRUE(layer2->quads_appended());
3689 host_impl_->DidDrawAllLayers(frame);
3691 // Parent layer with translucent content but opaque painting, drawn without
3693 // Child layer with opaque content, drawn without blending.
3694 layer1->SetContentsOpaque(true);
3695 layer1->SetExpectation(false, false);
3696 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3697 layer2->SetExpectation(false, false);
3698 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3699 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3700 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3701 EXPECT_TRUE(layer1->quads_appended());
3702 EXPECT_TRUE(layer2->quads_appended());
3703 host_impl_->DidDrawAllLayers(frame);
3705 // Parent layer with translucent opacity and opaque content. Since it has a
3706 // drawing child, it's drawn to a render surface which carries the opacity,
3707 // so it's itself drawn without blending.
3708 // Child layer with opaque content, drawn without blending (parent surface
3709 // carries the inherited opacity).
3710 layer1->SetContentsOpaque(true);
3711 layer1->SetOpacity(0.5f);
3712 layer1->SetExpectation(false, true);
3713 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3714 layer2->SetExpectation(false, false);
3715 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3716 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
3717 host_impl_->active_tree()->root_layer());
3718 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3719 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3720 EXPECT_TRUE(layer1->quads_appended());
3721 EXPECT_TRUE(layer2->quads_appended());
3722 host_impl_->DidDrawAllLayers(frame);
3724 // Draw again, but with child non-opaque, to make sure
3725 // layer1 not culled.
3726 layer1->SetContentsOpaque(true);
3727 layer1->SetOpacity(1.f);
3728 layer1->SetExpectation(false, false);
3729 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3730 layer2->SetContentsOpaque(true);
3731 layer2->SetOpacity(0.5f);
3732 layer2->SetExpectation(true, false);
3733 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3734 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3735 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3736 EXPECT_TRUE(layer1->quads_appended());
3737 EXPECT_TRUE(layer2->quads_appended());
3738 host_impl_->DidDrawAllLayers(frame);
3740 // A second way of making the child non-opaque.
3741 layer1->SetContentsOpaque(true);
3742 layer1->SetOpacity(1.f);
3743 layer1->SetExpectation(false, false);
3744 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3745 layer2->SetContentsOpaque(false);
3746 layer2->SetOpacity(1.f);
3747 layer2->SetExpectation(true, false);
3748 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3749 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3750 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3751 EXPECT_TRUE(layer1->quads_appended());
3752 EXPECT_TRUE(layer2->quads_appended());
3753 host_impl_->DidDrawAllLayers(frame);
3755 // And when the layer says its not opaque but is painted opaque, it is not
3757 layer1->SetContentsOpaque(true);
3758 layer1->SetOpacity(1.f);
3759 layer1->SetExpectation(false, false);
3760 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3761 layer2->SetContentsOpaque(true);
3762 layer2->SetOpacity(1.f);
3763 layer2->SetExpectation(false, false);
3764 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3765 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3766 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3767 EXPECT_TRUE(layer1->quads_appended());
3768 EXPECT_TRUE(layer2->quads_appended());
3769 host_impl_->DidDrawAllLayers(frame);
3771 // Layer with partially opaque contents, drawn with blending.
3772 layer1->SetContentsOpaque(false);
3773 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3774 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
3775 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3776 layer1->SetExpectation(true, false);
3777 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3778 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3779 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3780 EXPECT_TRUE(layer1->quads_appended());
3781 host_impl_->DidDrawAllLayers(frame);
3783 // Layer with partially opaque contents partially culled, drawn with blending.
3784 layer1->SetContentsOpaque(false);
3785 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3786 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
3787 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3788 layer1->SetExpectation(true, false);
3789 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3790 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3791 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3792 EXPECT_TRUE(layer1->quads_appended());
3793 host_impl_->DidDrawAllLayers(frame);
3795 // Layer with partially opaque contents culled, drawn with blending.
3796 layer1->SetContentsOpaque(false);
3797 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3798 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
3799 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3800 layer1->SetExpectation(true, false);
3801 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3802 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3803 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3804 EXPECT_TRUE(layer1->quads_appended());
3805 host_impl_->DidDrawAllLayers(frame);
3807 // Layer with partially opaque contents and translucent contents culled, drawn
3808 // without blending.
3809 layer1->SetContentsOpaque(false);
3810 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3811 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
3812 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3813 layer1->SetExpectation(false, false);
3814 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3815 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3816 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3817 EXPECT_TRUE(layer1->quads_appended());
3818 host_impl_->DidDrawAllLayers(frame);
3821 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
3823 LayerTreeHostImplViewportCoveredTest() :
3824 gutter_quad_material_(DrawQuad::SOLID_COLOR),
3826 did_activate_pending_tree_(false) {}
3828 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
3830 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
3831 .PassAs<OutputSurface>();
3833 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
3836 void SetupActiveTreeLayers() {
3837 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
3838 host_impl_->active_tree()->SetRootLayer(
3839 LayerImpl::Create(host_impl_->active_tree(), 1));
3840 host_impl_->active_tree()->root_layer()->AddChild(
3841 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3843 host_impl_->resource_provider()));
3844 child_ = static_cast<BlendStateCheckLayer*>(
3845 host_impl_->active_tree()->root_layer()->children()[0]);
3846 child_->SetExpectation(false, false);
3847 child_->SetContentsOpaque(true);
3850 // Expect no gutter rects.
3851 void TestLayerCoversFullViewport() {
3852 gfx::Rect layer_rect(viewport_size_);
3853 child_->SetPosition(layer_rect.origin());
3854 child_->SetBounds(layer_rect.size());
3855 child_->SetContentBounds(layer_rect.size());
3856 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3857 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3859 LayerTreeHostImpl::FrameData frame;
3860 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3861 ASSERT_EQ(1u, frame.render_passes.size());
3863 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3864 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3865 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3867 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3868 host_impl_->DidDrawAllLayers(frame);
3871 // Expect fullscreen gutter rect.
3872 void TestEmptyLayer() {
3873 gfx::Rect layer_rect(0, 0, 0, 0);
3874 child_->SetPosition(layer_rect.origin());
3875 child_->SetBounds(layer_rect.size());
3876 child_->SetContentBounds(layer_rect.size());
3877 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3878 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3880 LayerTreeHostImpl::FrameData frame;
3881 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3882 ASSERT_EQ(1u, frame.render_passes.size());
3884 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
3885 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3886 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3888 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3889 host_impl_->DidDrawAllLayers(frame);
3892 // Expect four surrounding gutter rects.
3893 void TestLayerInMiddleOfViewport() {
3894 gfx::Rect layer_rect(500, 500, 200, 200);
3895 child_->SetPosition(layer_rect.origin());
3896 child_->SetBounds(layer_rect.size());
3897 child_->SetContentBounds(layer_rect.size());
3898 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3899 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3901 LayerTreeHostImpl::FrameData frame;
3902 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3903 ASSERT_EQ(1u, frame.render_passes.size());
3905 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
3906 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
3907 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3909 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3910 host_impl_->DidDrawAllLayers(frame);
3913 // Expect no gutter rects.
3914 void TestLayerIsLargerThanViewport() {
3915 gfx::Rect layer_rect(viewport_size_.width() + 10,
3916 viewport_size_.height() + 10);
3917 child_->SetPosition(layer_rect.origin());
3918 child_->SetBounds(layer_rect.size());
3919 child_->SetContentBounds(layer_rect.size());
3920 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3921 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3923 LayerTreeHostImpl::FrameData frame;
3924 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3925 ASSERT_EQ(1u, frame.render_passes.size());
3927 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3928 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3929 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3931 host_impl_->DidDrawAllLayers(frame);
3934 virtual void DidActivateSyncTree() OVERRIDE {
3935 did_activate_pending_tree_ = true;
3938 void set_gutter_quad_material(DrawQuad::Material material) {
3939 gutter_quad_material_ = material;
3941 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
3942 gutter_texture_size_ = gutter_texture_size;
3946 size_t CountGutterQuads(const QuadList& quad_list) {
3947 size_t num_gutter_quads = 0;
3948 for (size_t i = 0; i < quad_list.size(); ++i) {
3949 num_gutter_quads += (quad_list[i]->material ==
3950 gutter_quad_material_) ? 1 : 0;
3952 return num_gutter_quads;
3955 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
3956 LayerTestCommon::VerifyQuadsExactlyCoverRect(
3957 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
3960 // Make sure that the texture coordinates match their expectations.
3961 void ValidateTextureDrawQuads(const QuadList& quad_list) {
3962 for (size_t i = 0; i < quad_list.size(); ++i) {
3963 if (quad_list[i]->material != DrawQuad::TEXTURE_CONTENT)
3965 const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(quad_list[i]);
3966 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
3967 gutter_texture_size_, host_impl_->device_scale_factor());
3968 EXPECT_EQ(quad->uv_top_left.x(),
3969 quad->rect.x() / gutter_texture_size_pixels.width());
3970 EXPECT_EQ(quad->uv_top_left.y(),
3971 quad->rect.y() / gutter_texture_size_pixels.height());
3972 EXPECT_EQ(quad->uv_bottom_right.x(),
3973 quad->rect.right() / gutter_texture_size_pixels.width());
3974 EXPECT_EQ(quad->uv_bottom_right.y(),
3975 quad->rect.bottom() / gutter_texture_size_pixels.height());
3979 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
3980 return gfx::ToRoundedSize(
3981 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
3984 DrawQuad::Material gutter_quad_material_;
3985 gfx::Size gutter_texture_size_;
3986 gfx::Size viewport_size_;
3987 BlendStateCheckLayer* child_;
3988 bool did_activate_pending_tree_;
3991 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
3992 viewport_size_ = gfx::Size(1000, 1000);
3994 bool always_draw = false;
3995 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3997 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3998 SetupActiveTreeLayers();
3999 TestLayerCoversFullViewport();
4001 TestLayerInMiddleOfViewport();
4002 TestLayerIsLargerThanViewport();
4005 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
4006 viewport_size_ = gfx::Size(1000, 1000);
4008 bool always_draw = false;
4009 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4011 host_impl_->SetDeviceScaleFactor(2.f);
4012 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4013 SetupActiveTreeLayers();
4014 TestLayerCoversFullViewport();
4016 TestLayerInMiddleOfViewport();
4017 TestLayerIsLargerThanViewport();
4020 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
4021 viewport_size_ = gfx::Size(1000, 1000);
4023 bool always_draw = false;
4024 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4026 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4027 SetupActiveTreeLayers();
4029 // Specify an overhang bitmap to use.
4030 bool is_opaque = false;
4031 UIResourceBitmap ui_resource_bitmap(gfx::Size(2, 2), is_opaque);
4032 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
4033 UIResourceId ui_resource_id = 12345;
4034 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
4035 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
4036 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
4037 set_gutter_texture_size(gfx::Size(32, 32));
4039 TestLayerCoversFullViewport();
4041 TestLayerInMiddleOfViewport();
4042 TestLayerIsLargerThanViewport();
4044 // Change the resource size.
4045 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
4046 set_gutter_texture_size(gfx::Size(128, 16));
4048 TestLayerCoversFullViewport();
4050 TestLayerInMiddleOfViewport();
4051 TestLayerIsLargerThanViewport();
4053 // Change the device scale factor
4054 host_impl_->SetDeviceScaleFactor(2.f);
4055 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4057 TestLayerCoversFullViewport();
4059 TestLayerInMiddleOfViewport();
4060 TestLayerIsLargerThanViewport();
4063 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
4064 viewport_size_ = gfx::Size(1000, 1000);
4066 bool always_draw = true;
4067 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4069 // Pending tree to force active_tree size invalid. Not used otherwise.
4070 host_impl_->CreatePendingTree();
4071 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4072 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4074 SetupActiveTreeLayers();
4076 TestLayerInMiddleOfViewport();
4077 TestLayerIsLargerThanViewport();
4080 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
4081 viewport_size_ = gfx::Size(1000, 1000);
4083 bool always_draw = true;
4084 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4086 // Set larger viewport and activate it to active tree.
4087 host_impl_->CreatePendingTree();
4088 gfx::Size larger_viewport(viewport_size_.width() + 100,
4089 viewport_size_.height() + 100);
4090 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
4091 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4092 host_impl_->ActivateSyncTree();
4093 EXPECT_TRUE(did_activate_pending_tree_);
4094 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
4096 // Shrink pending tree viewport without activating.
4097 host_impl_->CreatePendingTree();
4098 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4099 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4101 SetupActiveTreeLayers();
4103 TestLayerInMiddleOfViewport();
4104 TestLayerIsLargerThanViewport();
4107 class FakeDrawableLayerImpl: public LayerImpl {
4109 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4110 return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(tree_impl, id));
4113 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
4114 : LayerImpl(tree_impl, id) {}
4117 // Only reshape when we know we are going to draw. Otherwise, the reshape
4118 // can leave the window at the wrong size if we never draw and the proper
4119 // viewport size is never set.
4120 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
4121 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4122 scoped_ptr<OutputSurface> output_surface(
4123 FakeOutputSurface::Create3d(provider));
4124 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4126 scoped_ptr<LayerImpl> root =
4127 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4128 root->SetBounds(gfx::Size(10, 10));
4129 root->SetContentBounds(gfx::Size(10, 10));
4130 root->SetDrawsContent(true);
4131 host_impl_->active_tree()->SetRootLayer(root.Pass());
4132 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
4133 provider->TestContext3d()->clear_reshape_called();
4135 LayerTreeHostImpl::FrameData frame;
4136 host_impl_->SetViewportSize(gfx::Size(10, 10));
4137 host_impl_->SetDeviceScaleFactor(1.f);
4138 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4139 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4140 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4141 EXPECT_EQ(provider->TestContext3d()->width(), 10);
4142 EXPECT_EQ(provider->TestContext3d()->height(), 10);
4143 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4144 host_impl_->DidDrawAllLayers(frame);
4145 provider->TestContext3d()->clear_reshape_called();
4147 host_impl_->SetViewportSize(gfx::Size(20, 30));
4148 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4149 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4150 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4151 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4152 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4153 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4154 host_impl_->DidDrawAllLayers(frame);
4155 provider->TestContext3d()->clear_reshape_called();
4157 host_impl_->SetDeviceScaleFactor(2.f);
4158 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4159 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4160 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4161 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4162 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4163 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
4164 host_impl_->DidDrawAllLayers(frame);
4165 provider->TestContext3d()->clear_reshape_called();
4168 // Make sure damage tracking propagates all the way to the graphics context,
4169 // where it should request to swap only the sub-buffer that is damaged.
4170 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
4171 scoped_refptr<TestContextProvider> context_provider(
4172 TestContextProvider::Create());
4173 context_provider->BindToCurrentThread();
4174 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
4176 scoped_ptr<OutputSurface> output_surface(
4177 FakeOutputSurface::Create3d(context_provider));
4179 // This test creates its own LayerTreeHostImpl, so
4180 // that we can force partial swap enabled.
4181 LayerTreeSettings settings;
4182 settings.partial_swap_enabled = true;
4183 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4184 new TestSharedBitmapManager());
4185 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
4186 LayerTreeHostImpl::Create(settings,
4189 &stats_instrumentation_,
4190 shared_bitmap_manager.get(),
4192 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
4193 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
4195 scoped_ptr<LayerImpl> root =
4196 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
4197 scoped_ptr<LayerImpl> child =
4198 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
4199 child->SetPosition(gfx::PointF(12.f, 13.f));
4200 child->SetBounds(gfx::Size(14, 15));
4201 child->SetContentBounds(gfx::Size(14, 15));
4202 child->SetDrawsContent(true);
4203 root->SetBounds(gfx::Size(500, 500));
4204 root->SetContentBounds(gfx::Size(500, 500));
4205 root->SetDrawsContent(true);
4206 root->AddChild(child.Pass());
4207 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
4209 LayerTreeHostImpl::FrameData frame;
4211 // First frame, the entire screen should get swapped.
4212 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4213 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4214 layer_tree_host_impl->DidDrawAllLayers(frame);
4215 layer_tree_host_impl->SwapBuffers(frame);
4216 EXPECT_EQ(TestContextSupport::SWAP,
4217 context_provider->support()->last_swap_type());
4219 // Second frame, only the damaged area should get swapped. Damage should be
4220 // the union of old and new child rects.
4221 // expected damage rect: gfx::Rect(26, 28);
4222 // expected swap rect: vertically flipped, with origin at bottom left corner.
4223 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
4225 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4226 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4227 host_impl_->DidDrawAllLayers(frame);
4228 layer_tree_host_impl->SwapBuffers(frame);
4230 // Make sure that partial swap is constrained to the viewport dimensions
4231 // expected damage rect: gfx::Rect(500, 500);
4232 // expected swap rect: flipped damage rect, but also clamped to viewport
4233 EXPECT_EQ(TestContextSupport::PARTIAL_SWAP,
4234 context_provider->support()->last_swap_type());
4235 gfx::Rect expected_swap_rect(0, 500-28, 26, 28);
4236 EXPECT_EQ(expected_swap_rect.ToString(),
4237 context_provider->support()->
4238 last_partial_swap_rect().ToString());
4240 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
4241 // This will damage everything.
4242 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
4244 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4245 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4246 host_impl_->DidDrawAllLayers(frame);
4247 layer_tree_host_impl->SwapBuffers(frame);
4249 EXPECT_EQ(TestContextSupport::SWAP,
4250 context_provider->support()->last_swap_type());
4253 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
4254 scoped_ptr<LayerImpl> root =
4255 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4256 scoped_ptr<LayerImpl> child =
4257 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
4258 child->SetBounds(gfx::Size(10, 10));
4259 child->SetContentBounds(gfx::Size(10, 10));
4260 child->SetDrawsContent(true);
4261 root->SetBounds(gfx::Size(10, 10));
4262 root->SetContentBounds(gfx::Size(10, 10));
4263 root->SetDrawsContent(true);
4264 root->SetForceRenderSurface(true);
4265 root->AddChild(child.Pass());
4267 host_impl_->active_tree()->SetRootLayer(root.Pass());
4269 LayerTreeHostImpl::FrameData frame;
4271 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4272 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
4273 EXPECT_EQ(1u, frame.render_passes.size());
4274 host_impl_->DidDrawAllLayers(frame);
4277 class FakeLayerWithQuads : public LayerImpl {
4279 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4280 return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(tree_impl, id));
4283 virtual void AppendQuads(RenderPass* render_pass,
4284 const OcclusionTracker<LayerImpl>& occlusion_tracker,
4285 AppendQuadsData* append_quads_data) OVERRIDE {
4286 SharedQuadState* shared_quad_state =
4287 render_pass->CreateAndAppendSharedQuadState();
4288 PopulateSharedQuadState(shared_quad_state);
4290 SkColor gray = SkColorSetRGB(100, 100, 100);
4291 gfx::Rect quad_rect(content_bounds());
4292 gfx::Rect visible_quad_rect(quad_rect);
4293 SolidColorDrawQuad* my_quad =
4294 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4296 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
4300 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
4301 : LayerImpl(tree_impl, id) {}
4304 class MockContext : public TestWebGraphicsContext3D {
4306 MOCK_METHOD1(useProgram, void(GLuint program));
4307 MOCK_METHOD5(uniform4f, void(GLint location,
4312 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
4314 GLboolean transpose,
4315 const GLfloat* value));
4316 MOCK_METHOD4(drawElements, void(GLenum mode,
4320 MOCK_METHOD1(enable, void(GLenum cap));
4321 MOCK_METHOD1(disable, void(GLenum cap));
4322 MOCK_METHOD4(scissor, void(GLint x,
4328 class MockContextHarness {
4330 MockContext* context_;
4333 explicit MockContextHarness(MockContext* context)
4334 : context_(context) {
4335 context_->set_have_post_sub_buffer(true);
4337 // Catch "uninteresting" calls
4338 EXPECT_CALL(*context_, useProgram(_))
4341 EXPECT_CALL(*context_, drawElements(_, _, _, _))
4344 // These are not asserted
4345 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
4346 .WillRepeatedly(Return());
4348 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
4349 .WillRepeatedly(Return());
4351 // Any un-sanctioned calls to enable() are OK
4352 EXPECT_CALL(*context_, enable(_))
4353 .WillRepeatedly(Return());
4355 // Any un-sanctioned calls to disable() are OK
4356 EXPECT_CALL(*context_, disable(_))
4357 .WillRepeatedly(Return());
4360 void MustDrawSolidQuad() {
4361 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
4363 .RetiresOnSaturation();
4365 EXPECT_CALL(*context_, useProgram(_))
4367 .RetiresOnSaturation();
4370 void MustSetScissor(int x, int y, int width, int height) {
4371 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4372 .WillRepeatedly(Return());
4374 EXPECT_CALL(*context_, scissor(x, y, width, height))
4376 .WillRepeatedly(Return());
4379 void MustSetNoScissor() {
4380 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
4381 .WillRepeatedly(Return());
4383 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4386 EXPECT_CALL(*context_, scissor(_, _, _, _))
4391 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
4392 scoped_ptr<MockContext> mock_context_owned(new MockContext);
4393 MockContext* mock_context = mock_context_owned.get();
4395 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4396 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4397 MockContextHarness harness(mock_context);
4400 LayerTreeSettings settings = DefaultSettings();
4401 settings.partial_swap_enabled = false;
4402 CreateHostImpl(settings, output_surface.Pass());
4403 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4405 // Without partial swap, and no clipping, no scissor is set.
4406 harness.MustDrawSolidQuad();
4407 harness.MustSetNoScissor();
4409 LayerTreeHostImpl::FrameData frame;
4410 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4411 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4412 host_impl_->DidDrawAllLayers(frame);
4414 Mock::VerifyAndClearExpectations(&mock_context);
4416 // Without partial swap, but a layer does clip its subtree, one scissor is
4418 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
4419 harness.MustDrawSolidQuad();
4420 harness.MustSetScissor(0, 0, 10, 10);
4422 LayerTreeHostImpl::FrameData frame;
4423 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4424 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4425 host_impl_->DidDrawAllLayers(frame);
4427 Mock::VerifyAndClearExpectations(&mock_context);
4430 TEST_F(LayerTreeHostImplTest, PartialSwap) {
4431 scoped_ptr<MockContext> context_owned(new MockContext);
4432 MockContext* mock_context = context_owned.get();
4433 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4434 context_owned.PassAs<TestWebGraphicsContext3D>()));
4435 MockContextHarness harness(mock_context);
4437 LayerTreeSettings settings = DefaultSettings();
4438 settings.partial_swap_enabled = true;
4439 CreateHostImpl(settings, output_surface.Pass());
4440 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4442 // The first frame is not a partially-swapped one.
4443 harness.MustSetScissor(0, 0, 10, 10);
4444 harness.MustDrawSolidQuad();
4446 LayerTreeHostImpl::FrameData frame;
4447 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4448 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4449 host_impl_->DidDrawAllLayers(frame);
4451 Mock::VerifyAndClearExpectations(&mock_context);
4453 // Damage a portion of the frame.
4454 host_impl_->active_tree()->root_layer()->SetUpdateRect(
4455 gfx::Rect(0, 0, 2, 3));
4457 // The second frame will be partially-swapped (the y coordinates are flipped).
4458 harness.MustSetScissor(0, 7, 2, 3);
4459 harness.MustDrawSolidQuad();
4461 LayerTreeHostImpl::FrameData frame;
4462 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4463 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4464 host_impl_->DidDrawAllLayers(frame);
4466 Mock::VerifyAndClearExpectations(&mock_context);
4469 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
4471 LayerTreeHostImplClient* client,
4473 SharedBitmapManager* manager,
4474 RenderingStatsInstrumentation* stats_instrumentation) {
4475 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4476 scoped_ptr<OutputSurface> output_surface(
4477 FakeOutputSurface::Create3d(provider));
4478 provider->BindToCurrentThread();
4479 provider->TestContext3d()->set_have_post_sub_buffer(true);
4481 LayerTreeSettings settings;
4482 settings.partial_swap_enabled = partial_swap;
4483 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
4484 settings, client, proxy, stats_instrumentation, manager, 0);
4485 my_host_impl->InitializeRenderer(output_surface.Pass());
4486 my_host_impl->SetViewportSize(gfx::Size(100, 100));
4489 Layers are created as follows:
4491 +--------------------+
4495 | | +-------------------+
4497 | | +-------------------+
4502 +--------------------+
4504 Layers 1, 2 have render surfaces
4506 scoped_ptr<LayerImpl> root =
4507 LayerImpl::Create(my_host_impl->active_tree(), 1);
4508 scoped_ptr<LayerImpl> child =
4509 LayerImpl::Create(my_host_impl->active_tree(), 2);
4510 scoped_ptr<LayerImpl> grand_child =
4511 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
4513 gfx::Rect root_rect(0, 0, 100, 100);
4514 gfx::Rect child_rect(10, 10, 50, 50);
4515 gfx::Rect grand_child_rect(5, 5, 150, 150);
4517 root->CreateRenderSurface();
4518 root->SetPosition(root_rect.origin());
4519 root->SetBounds(root_rect.size());
4520 root->SetContentBounds(root->bounds());
4521 root->draw_properties().visible_content_rect = root_rect;
4522 root->SetDrawsContent(false);
4523 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
4525 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
4526 child->SetOpacity(0.5f);
4527 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
4528 child->SetContentBounds(child->bounds());
4529 child->draw_properties().visible_content_rect = child_rect;
4530 child->SetDrawsContent(false);
4531 child->SetForceRenderSurface(true);
4533 grand_child->SetPosition(grand_child_rect.origin());
4534 grand_child->SetBounds(grand_child_rect.size());
4535 grand_child->SetContentBounds(grand_child->bounds());
4536 grand_child->draw_properties().visible_content_rect = grand_child_rect;
4537 grand_child->SetDrawsContent(true);
4539 child->AddChild(grand_child.Pass());
4540 root->AddChild(child.Pass());
4542 my_host_impl->active_tree()->SetRootLayer(root.Pass());
4543 return my_host_impl.Pass();
4546 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
4547 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4548 new TestSharedBitmapManager());
4549 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4550 SetupLayersForOpacity(true,
4553 shared_bitmap_manager.get(),
4554 &stats_instrumentation_);
4556 LayerTreeHostImpl::FrameData frame;
4557 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4559 // Verify all quads have been computed
4560 ASSERT_EQ(2U, frame.render_passes.size());
4561 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4562 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4563 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4564 frame.render_passes[0]->quad_list[0]->material);
4565 EXPECT_EQ(DrawQuad::RENDER_PASS,
4566 frame.render_passes[1]->quad_list[0]->material);
4568 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4569 my_host_impl->DidDrawAllLayers(frame);
4573 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
4574 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4575 new TestSharedBitmapManager());
4576 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4577 SetupLayersForOpacity(false,
4580 shared_bitmap_manager.get(),
4581 &stats_instrumentation_);
4583 LayerTreeHostImpl::FrameData frame;
4584 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4586 // Verify all quads have been computed
4587 ASSERT_EQ(2U, frame.render_passes.size());
4588 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4589 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4590 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4591 frame.render_passes[0]->quad_list[0]->material);
4592 EXPECT_EQ(DrawQuad::RENDER_PASS,
4593 frame.render_passes[1]->quad_list[0]->material);
4595 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4596 my_host_impl->DidDrawAllLayers(frame);
4600 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
4601 scoped_ptr<TestWebGraphicsContext3D> context =
4602 TestWebGraphicsContext3D::Create();
4603 TestWebGraphicsContext3D* context3d = context.get();
4604 scoped_ptr<OutputSurface> output_surface(
4605 FakeOutputSurface::Create3d(context.Pass()));
4606 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4608 scoped_ptr<LayerImpl> root_layer =
4609 LayerImpl::Create(host_impl_->active_tree(), 1);
4610 root_layer->SetBounds(gfx::Size(10, 10));
4612 scoped_refptr<VideoFrame> softwareFrame =
4613 media::VideoFrame::CreateColorFrame(
4614 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
4615 FakeVideoFrameProvider provider;
4616 provider.set_frame(softwareFrame);
4617 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
4618 host_impl_->active_tree(), 4, &provider, media::VIDEO_ROTATION_0);
4619 video_layer->SetBounds(gfx::Size(10, 10));
4620 video_layer->SetContentBounds(gfx::Size(10, 10));
4621 video_layer->SetDrawsContent(true);
4622 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
4624 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
4625 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
4626 io_surface_layer->SetBounds(gfx::Size(10, 10));
4627 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
4628 io_surface_layer->SetDrawsContent(true);
4629 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
4630 root_layer->AddChild(io_surface_layer.PassAs<LayerImpl>());
4632 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
4634 EXPECT_EQ(0u, context3d->NumTextures());
4636 LayerTreeHostImpl::FrameData frame;
4637 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4638 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4639 host_impl_->DidDrawAllLayers(frame);
4640 host_impl_->SwapBuffers(frame);
4642 EXPECT_GT(context3d->NumTextures(), 0u);
4644 // Kill the layer tree.
4645 host_impl_->active_tree()->SetRootLayer(
4646 LayerImpl::Create(host_impl_->active_tree(), 100));
4647 // There should be no textures left in use after.
4648 EXPECT_EQ(0u, context3d->NumTextures());
4651 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
4653 MOCK_METHOD1(useProgram, void(GLuint program));
4654 MOCK_METHOD4(drawElements, void(GLenum mode,
4660 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
4661 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
4662 new MockDrawQuadsToFillScreenContext);
4663 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
4665 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4666 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4669 LayerTreeSettings settings = DefaultSettings();
4670 settings.partial_swap_enabled = false;
4671 CreateHostImpl(settings, output_surface.Pass());
4672 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
4673 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
4675 // Verify one quad is drawn when transparent background set is not set.
4676 host_impl_->active_tree()->set_has_transparent_background(false);
4677 EXPECT_CALL(*mock_context, useProgram(_))
4679 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
4681 LayerTreeHostImpl::FrameData frame;
4682 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4683 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4684 host_impl_->DidDrawAllLayers(frame);
4685 Mock::VerifyAndClearExpectations(&mock_context);
4687 // Verify no quads are drawn when transparent background is set.
4688 host_impl_->active_tree()->set_has_transparent_background(true);
4689 host_impl_->SetFullRootLayerDamage();
4690 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4691 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4692 host_impl_->DidDrawAllLayers(frame);
4693 Mock::VerifyAndClearExpectations(&mock_context);
4696 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
4697 set_reduce_memory_result(false);
4699 // If changing the memory limit wouldn't result in changing what was
4700 // committed, then no commit should be requested.
4701 set_reduce_memory_result(false);
4702 host_impl_->set_max_memory_needed_bytes(
4703 host_impl_->memory_allocation_limit_bytes() - 1);
4704 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4705 host_impl_->memory_allocation_limit_bytes() - 1));
4706 EXPECT_FALSE(did_request_commit_);
4707 did_request_commit_ = false;
4709 // If changing the memory limit would result in changing what was
4710 // committed, then a commit should be requested, even though nothing was
4712 set_reduce_memory_result(false);
4713 host_impl_->set_max_memory_needed_bytes(
4714 host_impl_->memory_allocation_limit_bytes());
4715 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4716 host_impl_->memory_allocation_limit_bytes() - 1));
4717 EXPECT_TRUE(did_request_commit_);
4718 did_request_commit_ = false;
4720 // Especially if changing the memory limit caused evictions, we need
4722 set_reduce_memory_result(true);
4723 host_impl_->set_max_memory_needed_bytes(1);
4724 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4725 host_impl_->memory_allocation_limit_bytes() - 1));
4726 EXPECT_TRUE(did_request_commit_);
4727 did_request_commit_ = false;
4729 // But if we set it to the same value that it was before, we shouldn't
4731 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4732 host_impl_->memory_allocation_limit_bytes()));
4733 EXPECT_FALSE(did_request_commit_);
4736 class LayerTreeHostImplTestWithDelegatingRenderer
4737 : public LayerTreeHostImplTest {
4739 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
4740 return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
4743 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
4744 bool expect_to_draw = !expected_damage.IsEmpty();
4746 LayerTreeHostImpl::FrameData frame;
4747 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4749 if (!expect_to_draw) {
4750 // With no damage, we don't draw, and no quads are created.
4751 ASSERT_EQ(0u, frame.render_passes.size());
4753 ASSERT_EQ(1u, frame.render_passes.size());
4755 // Verify the damage rect for the root render pass.
4756 const RenderPass* root_render_pass = frame.render_passes.back();
4757 EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
4759 // Verify the root and child layers' quads are generated and not being
4761 ASSERT_EQ(2u, root_render_pass->quad_list.size());
4763 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
4764 gfx::RectF expected_child_visible_rect(child->content_bounds());
4765 EXPECT_RECT_EQ(expected_child_visible_rect,
4766 root_render_pass->quad_list[0]->visible_rect);
4768 LayerImpl* root = host_impl_->active_tree()->root_layer();
4769 gfx::RectF expected_root_visible_rect(root->content_bounds());
4770 EXPECT_RECT_EQ(expected_root_visible_rect,
4771 root_render_pass->quad_list[1]->visible_rect);
4774 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4775 host_impl_->DidDrawAllLayers(frame);
4776 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
4780 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
4781 scoped_ptr<SolidColorLayerImpl> root =
4782 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4783 root->SetPosition(gfx::PointF());
4784 root->SetBounds(gfx::Size(10, 10));
4785 root->SetContentBounds(gfx::Size(10, 10));
4786 root->SetDrawsContent(true);
4788 // Child layer is in the bottom right corner.
4789 scoped_ptr<SolidColorLayerImpl> child =
4790 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
4791 child->SetPosition(gfx::PointF(9.f, 9.f));
4792 child->SetBounds(gfx::Size(1, 1));
4793 child->SetContentBounds(gfx::Size(1, 1));
4794 child->SetDrawsContent(true);
4795 root->AddChild(child.PassAs<LayerImpl>());
4797 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
4799 // Draw a frame. In the first frame, the entire viewport should be damaged.
4800 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
4801 DrawFrameAndTestDamage(full_frame_damage);
4803 // The second frame has damage that doesn't touch the child layer. Its quads
4804 // should still be generated.
4805 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
4806 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
4807 DrawFrameAndTestDamage(small_damage);
4809 // The third frame should have no damage, so no quads should be generated.
4810 gfx::Rect no_damage;
4811 DrawFrameAndTestDamage(no_damage);
4814 // TODO(reveman): Remove this test and the ability to prevent on demand raster
4815 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
4816 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
4817 LayerTreeSettings settings;
4818 CreateHostImpl(settings, CreateOutputSurface());
4819 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
4822 class FakeMaskLayerImpl : public LayerImpl {
4824 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
4826 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
4829 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
4834 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
4835 : LayerImpl(tree_impl, id) {}
4838 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
4839 LayerTreeSettings settings;
4840 settings.layer_transforms_should_scale_layer_contents = true;
4841 CreateHostImpl(settings, CreateOutputSurface());
4845 // +-- Scaling Layer (adds a 2x scale)
4847 // +-- Content Layer
4849 scoped_ptr<LayerImpl> scoped_root =
4850 LayerImpl::Create(host_impl_->active_tree(), 1);
4851 LayerImpl* root = scoped_root.get();
4852 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4854 scoped_ptr<LayerImpl> scoped_scaling_layer =
4855 LayerImpl::Create(host_impl_->active_tree(), 2);
4856 LayerImpl* scaling_layer = scoped_scaling_layer.get();
4857 root->AddChild(scoped_scaling_layer.Pass());
4859 scoped_ptr<LayerImpl> scoped_content_layer =
4860 LayerImpl::Create(host_impl_->active_tree(), 3);
4861 LayerImpl* content_layer = scoped_content_layer.get();
4862 scaling_layer->AddChild(scoped_content_layer.Pass());
4864 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4865 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4866 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4867 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4869 gfx::Size root_size(100, 100);
4870 root->SetBounds(root_size);
4871 root->SetContentBounds(root_size);
4872 root->SetPosition(gfx::PointF());
4874 gfx::Size scaling_layer_size(50, 50);
4875 scaling_layer->SetBounds(scaling_layer_size);
4876 scaling_layer->SetContentBounds(scaling_layer_size);
4877 scaling_layer->SetPosition(gfx::PointF());
4878 gfx::Transform scale;
4879 scale.Scale(2.f, 2.f);
4880 scaling_layer->SetTransform(scale);
4882 content_layer->SetBounds(scaling_layer_size);
4883 content_layer->SetContentBounds(scaling_layer_size);
4884 content_layer->SetPosition(gfx::PointF());
4885 content_layer->SetDrawsContent(true);
4887 mask_layer->SetBounds(scaling_layer_size);
4888 mask_layer->SetContentBounds(scaling_layer_size);
4889 mask_layer->SetPosition(gfx::PointF());
4890 mask_layer->SetDrawsContent(true);
4893 // Check that the tree scaling is correctly taken into account for the mask,
4894 // that should fully map onto the quad.
4895 float device_scale_factor = 1.f;
4896 host_impl_->SetViewportSize(root_size);
4897 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4899 LayerTreeHostImpl::FrameData frame;
4900 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4902 ASSERT_EQ(1u, frame.render_passes.size());
4903 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4904 ASSERT_EQ(DrawQuad::RENDER_PASS,
4905 frame.render_passes[0]->quad_list[0]->material);
4906 const RenderPassDrawQuad* render_pass_quad =
4907 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4908 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4909 render_pass_quad->rect.ToString());
4910 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4911 render_pass_quad->mask_uv_rect.ToString());
4913 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4914 host_impl_->DidDrawAllLayers(frame);
4918 // Applying a DSF should change the render surface size, but won't affect
4919 // which part of the mask is used.
4920 device_scale_factor = 2.f;
4921 gfx::Size device_viewport =
4922 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4923 host_impl_->SetViewportSize(device_viewport);
4924 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4925 host_impl_->active_tree()->set_needs_update_draw_properties();
4927 LayerTreeHostImpl::FrameData frame;
4928 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4930 ASSERT_EQ(1u, frame.render_passes.size());
4931 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4932 ASSERT_EQ(DrawQuad::RENDER_PASS,
4933 frame.render_passes[0]->quad_list[0]->material);
4934 const RenderPassDrawQuad* render_pass_quad =
4935 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4936 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4937 render_pass_quad->rect.ToString());
4938 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4939 render_pass_quad->mask_uv_rect.ToString());
4941 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4942 host_impl_->DidDrawAllLayers(frame);
4946 // Applying an equivalent content scale on the content layer and the mask
4947 // should still result in the same part of the mask being used.
4948 gfx::Size content_bounds =
4949 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
4950 device_scale_factor));
4951 content_layer->SetContentBounds(content_bounds);
4952 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4953 mask_layer->SetContentBounds(content_bounds);
4954 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4955 host_impl_->active_tree()->set_needs_update_draw_properties();
4957 LayerTreeHostImpl::FrameData frame;
4958 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4960 ASSERT_EQ(1u, frame.render_passes.size());
4961 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4962 ASSERT_EQ(DrawQuad::RENDER_PASS,
4963 frame.render_passes[0]->quad_list[0]->material);
4964 const RenderPassDrawQuad* render_pass_quad =
4965 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4966 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4967 render_pass_quad->rect.ToString());
4968 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4969 render_pass_quad->mask_uv_rect.ToString());
4971 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4972 host_impl_->DidDrawAllLayers(frame);
4976 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
4977 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4980 scoped_ptr<LayerImpl> scoped_root =
4981 LayerImpl::Create(host_impl_->active_tree(), 1);
4982 LayerImpl* root = scoped_root.get();
4983 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4985 scoped_ptr<LayerImpl> scoped_content_layer =
4986 LayerImpl::Create(host_impl_->active_tree(), 3);
4987 LayerImpl* content_layer = scoped_content_layer.get();
4988 root->AddChild(scoped_content_layer.Pass());
4990 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4991 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4992 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4993 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4995 gfx::Size root_size(100, 100);
4996 root->SetBounds(root_size);
4997 root->SetContentBounds(root_size);
4998 root->SetPosition(gfx::PointF());
5000 gfx::Size layer_size(50, 50);
5001 content_layer->SetBounds(layer_size);
5002 content_layer->SetContentBounds(layer_size);
5003 content_layer->SetPosition(gfx::PointF());
5004 content_layer->SetDrawsContent(true);
5006 gfx::Size mask_size(100, 100);
5007 mask_layer->SetBounds(mask_size);
5008 mask_layer->SetContentBounds(mask_size);
5009 mask_layer->SetPosition(gfx::PointF());
5010 mask_layer->SetDrawsContent(true);
5012 // Check that the mask fills the surface.
5013 float device_scale_factor = 1.f;
5014 host_impl_->SetViewportSize(root_size);
5015 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5017 LayerTreeHostImpl::FrameData frame;
5018 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5020 ASSERT_EQ(1u, frame.render_passes.size());
5021 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5022 ASSERT_EQ(DrawQuad::RENDER_PASS,
5023 frame.render_passes[0]->quad_list[0]->material);
5024 const RenderPassDrawQuad* render_pass_quad =
5025 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5026 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5027 render_pass_quad->rect.ToString());
5028 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5029 render_pass_quad->mask_uv_rect.ToString());
5031 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5032 host_impl_->DidDrawAllLayers(frame);
5035 // Applying a DSF should change the render surface size, but won't affect
5036 // which part of the mask is used.
5037 device_scale_factor = 2.f;
5038 gfx::Size device_viewport =
5039 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5040 host_impl_->SetViewportSize(device_viewport);
5041 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5042 host_impl_->active_tree()->set_needs_update_draw_properties();
5044 LayerTreeHostImpl::FrameData frame;
5045 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5047 ASSERT_EQ(1u, frame.render_passes.size());
5048 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5049 ASSERT_EQ(DrawQuad::RENDER_PASS,
5050 frame.render_passes[0]->quad_list[0]->material);
5051 const RenderPassDrawQuad* render_pass_quad =
5052 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5053 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5054 render_pass_quad->rect.ToString());
5055 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5056 render_pass_quad->mask_uv_rect.ToString());
5058 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5059 host_impl_->DidDrawAllLayers(frame);
5062 // Applying an equivalent content scale on the content layer and the mask
5063 // should still result in the same part of the mask being used.
5064 gfx::Size layer_size_large =
5065 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5066 content_layer->SetContentBounds(layer_size_large);
5067 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5068 gfx::Size mask_size_large =
5069 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5070 mask_layer->SetContentBounds(mask_size_large);
5071 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5072 host_impl_->active_tree()->set_needs_update_draw_properties();
5074 LayerTreeHostImpl::FrameData frame;
5075 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5077 ASSERT_EQ(1u, frame.render_passes.size());
5078 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5079 ASSERT_EQ(DrawQuad::RENDER_PASS,
5080 frame.render_passes[0]->quad_list[0]->material);
5081 const RenderPassDrawQuad* render_pass_quad =
5082 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5083 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5084 render_pass_quad->rect.ToString());
5085 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5086 render_pass_quad->mask_uv_rect.ToString());
5088 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5089 host_impl_->DidDrawAllLayers(frame);
5092 // Applying a different contents scale to the mask layer means it will have
5093 // a larger texture, but it should use the same tex coords to cover the
5095 mask_layer->SetContentBounds(mask_size);
5096 mask_layer->SetContentsScale(1.f, 1.f);
5097 host_impl_->active_tree()->set_needs_update_draw_properties();
5099 LayerTreeHostImpl::FrameData frame;
5100 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5102 ASSERT_EQ(1u, frame.render_passes.size());
5103 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5104 ASSERT_EQ(DrawQuad::RENDER_PASS,
5105 frame.render_passes[0]->quad_list[0]->material);
5106 const RenderPassDrawQuad* render_pass_quad =
5107 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5108 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5109 render_pass_quad->rect.ToString());
5110 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5111 render_pass_quad->mask_uv_rect.ToString());
5113 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5114 host_impl_->DidDrawAllLayers(frame);
5118 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
5119 // The replica's mask layer has bounds 100x100 but the replica is of a
5120 // layer with bounds 50x50.
5122 scoped_ptr<LayerImpl> scoped_root =
5123 LayerImpl::Create(host_impl_->active_tree(), 1);
5124 LayerImpl* root = scoped_root.get();
5125 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5127 scoped_ptr<LayerImpl> scoped_content_layer =
5128 LayerImpl::Create(host_impl_->active_tree(), 3);
5129 LayerImpl* content_layer = scoped_content_layer.get();
5130 root->AddChild(scoped_content_layer.Pass());
5132 scoped_ptr<LayerImpl> scoped_replica_layer =
5133 LayerImpl::Create(host_impl_->active_tree(), 2);
5134 LayerImpl* replica_layer = scoped_replica_layer.get();
5135 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5137 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5138 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5139 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5140 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5142 gfx::Size root_size(100, 100);
5143 root->SetBounds(root_size);
5144 root->SetContentBounds(root_size);
5145 root->SetPosition(gfx::PointF());
5147 gfx::Size layer_size(50, 50);
5148 content_layer->SetBounds(layer_size);
5149 content_layer->SetContentBounds(layer_size);
5150 content_layer->SetPosition(gfx::PointF());
5151 content_layer->SetDrawsContent(true);
5153 gfx::Size mask_size(100, 100);
5154 mask_layer->SetBounds(mask_size);
5155 mask_layer->SetContentBounds(mask_size);
5156 mask_layer->SetPosition(gfx::PointF());
5157 mask_layer->SetDrawsContent(true);
5159 // Check that the mask fills the surface.
5160 float device_scale_factor = 1.f;
5161 host_impl_->SetViewportSize(root_size);
5162 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5164 LayerTreeHostImpl::FrameData frame;
5165 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5167 ASSERT_EQ(1u, frame.render_passes.size());
5168 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5169 ASSERT_EQ(DrawQuad::RENDER_PASS,
5170 frame.render_passes[0]->quad_list[1]->material);
5171 const RenderPassDrawQuad* replica_quad =
5172 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5173 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5174 replica_quad->rect.ToString());
5175 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5176 replica_quad->mask_uv_rect.ToString());
5178 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5179 host_impl_->DidDrawAllLayers(frame);
5182 // Applying a DSF should change the render surface size, but won't affect
5183 // which part of the mask is used.
5184 device_scale_factor = 2.f;
5185 gfx::Size device_viewport =
5186 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5187 host_impl_->SetViewportSize(device_viewport);
5188 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5189 host_impl_->active_tree()->set_needs_update_draw_properties();
5191 LayerTreeHostImpl::FrameData frame;
5192 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5194 ASSERT_EQ(1u, frame.render_passes.size());
5195 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5196 ASSERT_EQ(DrawQuad::RENDER_PASS,
5197 frame.render_passes[0]->quad_list[1]->material);
5198 const RenderPassDrawQuad* replica_quad =
5199 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5200 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5201 replica_quad->rect.ToString());
5202 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5203 replica_quad->mask_uv_rect.ToString());
5205 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5206 host_impl_->DidDrawAllLayers(frame);
5209 // Applying an equivalent content scale on the content layer and the mask
5210 // should still result in the same part of the mask being used.
5211 gfx::Size layer_size_large =
5212 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5213 content_layer->SetContentBounds(layer_size_large);
5214 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5215 gfx::Size mask_size_large =
5216 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5217 mask_layer->SetContentBounds(mask_size_large);
5218 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5219 host_impl_->active_tree()->set_needs_update_draw_properties();
5221 LayerTreeHostImpl::FrameData frame;
5222 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5224 ASSERT_EQ(1u, frame.render_passes.size());
5225 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5226 ASSERT_EQ(DrawQuad::RENDER_PASS,
5227 frame.render_passes[0]->quad_list[1]->material);
5228 const RenderPassDrawQuad* replica_quad =
5229 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5230 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5231 replica_quad->rect.ToString());
5232 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5233 replica_quad->mask_uv_rect.ToString());
5235 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5236 host_impl_->DidDrawAllLayers(frame);
5239 // Applying a different contents scale to the mask layer means it will have
5240 // a larger texture, but it should use the same tex coords to cover the
5242 mask_layer->SetContentBounds(mask_size);
5243 mask_layer->SetContentsScale(1.f, 1.f);
5244 host_impl_->active_tree()->set_needs_update_draw_properties();
5246 LayerTreeHostImpl::FrameData frame;
5247 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5249 ASSERT_EQ(1u, frame.render_passes.size());
5250 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5251 ASSERT_EQ(DrawQuad::RENDER_PASS,
5252 frame.render_passes[0]->quad_list[1]->material);
5253 const RenderPassDrawQuad* replica_quad =
5254 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5255 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5256 replica_quad->rect.ToString());
5257 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5258 replica_quad->mask_uv_rect.ToString());
5260 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5261 host_impl_->DidDrawAllLayers(frame);
5265 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
5266 // The replica is of a layer with bounds 50x50, but it has a child that causes
5267 // the surface bounds to be larger.
5269 scoped_ptr<LayerImpl> scoped_root =
5270 LayerImpl::Create(host_impl_->active_tree(), 1);
5271 LayerImpl* root = scoped_root.get();
5272 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5274 scoped_ptr<LayerImpl> scoped_content_layer =
5275 LayerImpl::Create(host_impl_->active_tree(), 2);
5276 LayerImpl* content_layer = scoped_content_layer.get();
5277 root->AddChild(scoped_content_layer.Pass());
5279 scoped_ptr<LayerImpl> scoped_content_child_layer =
5280 LayerImpl::Create(host_impl_->active_tree(), 3);
5281 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5282 content_layer->AddChild(scoped_content_child_layer.Pass());
5284 scoped_ptr<LayerImpl> scoped_replica_layer =
5285 LayerImpl::Create(host_impl_->active_tree(), 4);
5286 LayerImpl* replica_layer = scoped_replica_layer.get();
5287 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5289 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5290 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
5291 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5292 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5294 gfx::Size root_size(100, 100);
5295 root->SetBounds(root_size);
5296 root->SetContentBounds(root_size);
5297 root->SetPosition(gfx::PointF());
5299 gfx::Size layer_size(50, 50);
5300 content_layer->SetBounds(layer_size);
5301 content_layer->SetContentBounds(layer_size);
5302 content_layer->SetPosition(gfx::PointF());
5303 content_layer->SetDrawsContent(true);
5305 gfx::Size child_size(50, 50);
5306 content_child_layer->SetBounds(child_size);
5307 content_child_layer->SetContentBounds(child_size);
5308 content_child_layer->SetPosition(gfx::Point(50, 0));
5309 content_child_layer->SetDrawsContent(true);
5311 gfx::Size mask_size(50, 50);
5312 mask_layer->SetBounds(mask_size);
5313 mask_layer->SetContentBounds(mask_size);
5314 mask_layer->SetPosition(gfx::PointF());
5315 mask_layer->SetDrawsContent(true);
5317 float device_scale_factor = 1.f;
5318 host_impl_->SetViewportSize(root_size);
5319 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5321 LayerTreeHostImpl::FrameData frame;
5322 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5324 ASSERT_EQ(1u, frame.render_passes.size());
5325 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5327 // The surface is 100x50.
5328 ASSERT_EQ(DrawQuad::RENDER_PASS,
5329 frame.render_passes[0]->quad_list[0]->material);
5330 const RenderPassDrawQuad* render_pass_quad =
5331 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5332 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5333 render_pass_quad->rect.ToString());
5335 // The mask covers the owning layer only.
5336 ASSERT_EQ(DrawQuad::RENDER_PASS,
5337 frame.render_passes[0]->quad_list[1]->material);
5338 const RenderPassDrawQuad* replica_quad =
5339 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5340 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5341 replica_quad->rect.ToString());
5342 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
5343 replica_quad->mask_uv_rect.ToString());
5345 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5346 host_impl_->DidDrawAllLayers(frame);
5349 // Move the child to (-50, 0) instead. Now the mask should be moved to still
5350 // cover the layer being replicated.
5351 content_child_layer->SetPosition(gfx::Point(-50, 0));
5353 LayerTreeHostImpl::FrameData frame;
5354 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5356 ASSERT_EQ(1u, frame.render_passes.size());
5357 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5359 // The surface is 100x50 with its origin at (-50, 0).
5360 ASSERT_EQ(DrawQuad::RENDER_PASS,
5361 frame.render_passes[0]->quad_list[0]->material);
5362 const RenderPassDrawQuad* render_pass_quad =
5363 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5364 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5365 render_pass_quad->rect.ToString());
5367 // The mask covers the owning layer only.
5368 ASSERT_EQ(DrawQuad::RENDER_PASS,
5369 frame.render_passes[0]->quad_list[1]->material);
5370 const RenderPassDrawQuad* replica_quad =
5371 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5372 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5373 replica_quad->rect.ToString());
5374 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
5375 replica_quad->mask_uv_rect.ToString());
5377 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5378 host_impl_->DidDrawAllLayers(frame);
5382 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
5383 // The masked layer has bounds 50x50, but it has a child that causes
5384 // the surface bounds to be larger. It also has a parent that clips the
5385 // masked layer and its surface.
5387 scoped_ptr<LayerImpl> scoped_root =
5388 LayerImpl::Create(host_impl_->active_tree(), 1);
5389 LayerImpl* root = scoped_root.get();
5390 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5392 scoped_ptr<LayerImpl> scoped_clipping_layer =
5393 LayerImpl::Create(host_impl_->active_tree(), 2);
5394 LayerImpl* clipping_layer = scoped_clipping_layer.get();
5395 root->AddChild(scoped_clipping_layer.Pass());
5397 scoped_ptr<LayerImpl> scoped_content_layer =
5398 LayerImpl::Create(host_impl_->active_tree(), 3);
5399 LayerImpl* content_layer = scoped_content_layer.get();
5400 clipping_layer->AddChild(scoped_content_layer.Pass());
5402 scoped_ptr<LayerImpl> scoped_content_child_layer =
5403 LayerImpl::Create(host_impl_->active_tree(), 4);
5404 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5405 content_layer->AddChild(scoped_content_child_layer.Pass());
5407 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5408 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
5409 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5410 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5412 gfx::Size root_size(100, 100);
5413 root->SetBounds(root_size);
5414 root->SetContentBounds(root_size);
5415 root->SetPosition(gfx::PointF());
5417 gfx::Rect clipping_rect(20, 10, 10, 20);
5418 clipping_layer->SetBounds(clipping_rect.size());
5419 clipping_layer->SetContentBounds(clipping_rect.size());
5420 clipping_layer->SetPosition(clipping_rect.origin());
5421 clipping_layer->SetMasksToBounds(true);
5423 gfx::Size layer_size(50, 50);
5424 content_layer->SetBounds(layer_size);
5425 content_layer->SetContentBounds(layer_size);
5426 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
5427 content_layer->SetDrawsContent(true);
5429 gfx::Size child_size(50, 50);
5430 content_child_layer->SetBounds(child_size);
5431 content_child_layer->SetContentBounds(child_size);
5432 content_child_layer->SetPosition(gfx::Point(50, 0));
5433 content_child_layer->SetDrawsContent(true);
5435 gfx::Size mask_size(100, 100);
5436 mask_layer->SetBounds(mask_size);
5437 mask_layer->SetContentBounds(mask_size);
5438 mask_layer->SetPosition(gfx::PointF());
5439 mask_layer->SetDrawsContent(true);
5441 float device_scale_factor = 1.f;
5442 host_impl_->SetViewportSize(root_size);
5443 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5445 LayerTreeHostImpl::FrameData frame;
5446 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5448 ASSERT_EQ(1u, frame.render_passes.size());
5449 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5451 // The surface is clipped to 10x20.
5452 ASSERT_EQ(DrawQuad::RENDER_PASS,
5453 frame.render_passes[0]->quad_list[0]->material);
5454 const RenderPassDrawQuad* render_pass_quad =
5455 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5456 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
5457 render_pass_quad->rect.ToString());
5459 // The masked layer is 50x50, but the surface size is 10x20. So the texture
5460 // coords in the mask are scaled by 10/50 and 20/50.
5461 // The surface is clipped to (20,10) so the mask texture coords are offset
5462 // by 20/50 and 10/50
5463 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f),
5464 1.f / 50.f).ToString(),
5465 render_pass_quad->mask_uv_rect.ToString());
5467 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5468 host_impl_->DidDrawAllLayers(frame);
5472 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
5474 using GLRenderer::SetupQuadForAntialiasing;
5477 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
5478 // Due to precision issues (especially on Android), sometimes far
5479 // away quads can end up thinking they need AA.
5480 float device_scale_factor = 4.f / 3.f;
5481 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5482 gfx::Size root_size(2000, 1000);
5483 gfx::Size device_viewport_size =
5484 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
5485 host_impl_->SetViewportSize(device_viewport_size);
5487 host_impl_->CreatePendingTree();
5488 host_impl_->pending_tree()
5489 ->SetPageScaleFactorAndLimits(1.f, 1.f / 16.f, 16.f);
5491 scoped_ptr<LayerImpl> scoped_root =
5492 LayerImpl::Create(host_impl_->pending_tree(), 1);
5493 LayerImpl* root = scoped_root.get();
5495 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
5497 scoped_ptr<LayerImpl> scoped_scrolling_layer =
5498 LayerImpl::Create(host_impl_->pending_tree(), 2);
5499 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
5500 root->AddChild(scoped_scrolling_layer.Pass());
5502 gfx::Size content_layer_bounds(100000, 100);
5503 gfx::Size pile_tile_size(3000, 3000);
5504 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
5505 pile_tile_size, content_layer_bounds));
5507 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
5508 FakePictureLayerImpl::CreateWithPile(host_impl_->pending_tree(), 3, pile);
5509 LayerImpl* content_layer = scoped_content_layer.get();
5510 scrolling_layer->AddChild(scoped_content_layer.PassAs<LayerImpl>());
5511 content_layer->SetBounds(content_layer_bounds);
5512 content_layer->SetDrawsContent(true);
5514 root->SetBounds(root_size);
5516 gfx::Vector2d scroll_offset(100000, 0);
5517 scrolling_layer->SetScrollClipLayer(root->id());
5518 scrolling_layer->SetScrollOffset(scroll_offset);
5520 host_impl_->ActivateSyncTree();
5522 host_impl_->active_tree()->UpdateDrawProperties();
5523 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
5525 LayerTreeHostImpl::FrameData frame;
5526 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5528 ASSERT_EQ(1u, frame.render_passes.size());
5529 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
5530 const DrawQuad* quad = frame.render_passes[0]->quad_list[0];
5533 gfx::QuadF device_layer_quad;
5535 GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
5536 quad->quadTransform(), quad, &device_layer_quad, edge);
5537 EXPECT_FALSE(antialiased);
5539 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5540 host_impl_->DidDrawAllLayers(frame);
5544 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
5546 CompositorFrameMetadataTest()
5547 : swap_buffers_complete_(0) {}
5549 virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {
5550 swap_buffers_complete_++;
5553 int swap_buffers_complete_;
5556 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
5557 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5559 LayerTreeHostImpl::FrameData frame;
5560 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5561 host_impl_->DrawLayers(&frame, base::TimeTicks());
5562 host_impl_->DidDrawAllLayers(frame);
5564 CompositorFrameAck ack;
5565 host_impl_->ReclaimResources(&ack);
5566 host_impl_->DidSwapBuffersComplete();
5567 EXPECT_EQ(swap_buffers_complete_, 1);
5570 class CountingSoftwareDevice : public SoftwareOutputDevice {
5572 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5574 virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
5576 return SoftwareOutputDevice::BeginPaint(damage_rect);
5578 virtual void EndPaint(SoftwareFrameData* frame_data) OVERRIDE {
5580 SoftwareOutputDevice::EndPaint(frame_data);
5583 int frames_began_, frames_ended_;
5586 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
5587 // No main thread evictions in resourceless software mode.
5588 set_reduce_memory_result(false);
5589 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
5590 bool delegated_rendering = false;
5591 FakeOutputSurface* output_surface =
5592 FakeOutputSurface::CreateDeferredGL(
5593 scoped_ptr<SoftwareOutputDevice>(software_device),
5594 delegated_rendering).release();
5595 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5596 scoped_ptr<OutputSurface>(output_surface)));
5597 host_impl_->SetViewportSize(gfx::Size(50, 50));
5599 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5601 const gfx::Transform external_transform;
5602 const gfx::Rect external_viewport;
5603 const gfx::Rect external_clip;
5604 const bool resourceless_software_draw = true;
5605 host_impl_->SetExternalDrawConstraints(external_transform,
5610 resourceless_software_draw);
5612 EXPECT_EQ(0, software_device->frames_began_);
5613 EXPECT_EQ(0, software_device->frames_ended_);
5617 EXPECT_EQ(1, software_device->frames_began_);
5618 EXPECT_EQ(1, software_device->frames_ended_);
5620 // Call other API methods that are likely to hit NULL pointer in this mode.
5621 EXPECT_TRUE(host_impl_->AsValue());
5622 EXPECT_TRUE(host_impl_->ActivationStateAsValue());
5625 TEST_F(LayerTreeHostImplTest,
5626 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
5627 set_reduce_memory_result(false);
5628 bool delegated_rendering = false;
5629 FakeOutputSurface* output_surface =
5630 FakeOutputSurface::CreateDeferredGL(
5631 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5632 delegated_rendering).release();
5633 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5634 scoped_ptr<OutputSurface>(output_surface)));
5636 const gfx::Transform external_transform;
5637 const gfx::Rect external_viewport;
5638 const gfx::Rect external_clip;
5639 const bool resourceless_software_draw = true;
5640 host_impl_->SetExternalDrawConstraints(external_transform,
5645 resourceless_software_draw);
5647 // SolidColorLayerImpl will be drawn.
5648 scoped_ptr<SolidColorLayerImpl> root_layer =
5649 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5651 // VideoLayerImpl will not be drawn.
5652 FakeVideoFrameProvider provider;
5653 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
5654 host_impl_->active_tree(), 2, &provider, media::VIDEO_ROTATION_0);
5655 video_layer->SetBounds(gfx::Size(10, 10));
5656 video_layer->SetContentBounds(gfx::Size(10, 10));
5657 video_layer->SetDrawsContent(true);
5658 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
5659 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5661 LayerTreeHostImpl::FrameData frame;
5662 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5663 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5664 host_impl_->DidDrawAllLayers(frame);
5666 EXPECT_EQ(1u, frame.will_draw_layers.size());
5667 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
5670 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
5672 virtual void SetUp() OVERRIDE {
5673 LayerTreeHostImplTest::SetUp();
5675 set_reduce_memory_result(false);
5677 bool delegated_rendering = false;
5678 scoped_ptr<FakeOutputSurface> output_surface(
5679 FakeOutputSurface::CreateDeferredGL(
5680 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5681 delegated_rendering));
5682 output_surface_ = output_surface.get();
5684 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5685 output_surface.PassAs<OutputSurface>()));
5687 scoped_ptr<SolidColorLayerImpl> root_layer =
5688 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5689 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5691 onscreen_context_provider_ = TestContextProvider::Create();
5694 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {
5695 did_update_renderer_capabilities_ = true;
5698 FakeOutputSurface* output_surface_;
5699 scoped_refptr<TestContextProvider> onscreen_context_provider_;
5700 bool did_update_renderer_capabilities_;
5704 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
5708 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5710 // DeferredInitialize and hardware draw.
5711 did_update_renderer_capabilities_ = false;
5713 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5714 EXPECT_EQ(onscreen_context_provider_,
5715 host_impl_->output_surface()->context_provider());
5716 EXPECT_TRUE(did_update_renderer_capabilities_);
5718 // Defer intialized GL draw.
5721 // Revert back to software.
5722 did_update_renderer_capabilities_ = false;
5723 output_surface_->ReleaseGL();
5724 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5725 EXPECT_TRUE(did_update_renderer_capabilities_);
5727 // Software draw again.
5731 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails) {
5735 // Fail initialization of the onscreen context before the OutputSurface binds
5736 // it to the thread.
5737 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5739 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5741 // DeferredInitialize fails.
5742 did_update_renderer_capabilities_ = false;
5744 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5745 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5746 EXPECT_FALSE(did_update_renderer_capabilities_);
5748 // Software draw again.
5752 // Checks that we have a non-0 default allocation if we pass a context that
5753 // doesn't support memory management extensions.
5754 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5755 LayerTreeSettings settings;
5756 host_impl_ = LayerTreeHostImpl::Create(settings,
5759 &stats_instrumentation_,
5760 shared_bitmap_manager_.get(),
5763 scoped_ptr<OutputSurface> output_surface(
5764 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5765 host_impl_->InitializeRenderer(output_surface.Pass());
5766 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5769 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5770 ManagedMemoryPolicy policy1(
5771 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5772 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5773 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5774 int allow_nice_to_have_cutoff_value =
5775 ManagedMemoryPolicy::PriorityCutoffToValue(
5776 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
5777 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5778 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5780 // GPU rasterization should be disabled by default on the tree(s)
5781 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
5782 EXPECT_TRUE(host_impl_->pending_tree() == NULL);
5784 host_impl_->SetVisible(true);
5785 host_impl_->SetMemoryPolicy(policy1);
5786 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5787 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5789 host_impl_->SetVisible(false);
5790 EXPECT_EQ(0u, current_limit_bytes_);
5791 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5793 host_impl_->SetVisible(true);
5794 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5795 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5797 // Now enable GPU rasterization and test if we get nice to have cutoff,
5799 LayerTreeSettings settings;
5800 settings.gpu_rasterization_enabled = true;
5801 host_impl_ = LayerTreeHostImpl::Create(
5802 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
5803 host_impl_->SetUseGpuRasterization(true);
5804 host_impl_->SetVisible(true);
5805 host_impl_->SetMemoryPolicy(policy1);
5806 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5807 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
5809 host_impl_->SetVisible(false);
5810 EXPECT_EQ(0u, current_limit_bytes_);
5811 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5814 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
5815 ASSERT_TRUE(host_impl_->active_tree());
5817 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5818 host_impl_->SetVisible(false);
5819 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5820 host_impl_->SetVisible(true);
5821 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5822 host_impl_->SetVisible(false);
5823 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5825 host_impl_->CreatePendingTree();
5826 host_impl_->ActivateSyncTree();
5828 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5829 host_impl_->SetVisible(true);
5830 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5833 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
5834 ASSERT_TRUE(host_impl_->active_tree());
5835 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
5837 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5838 host_impl_->SetUseGpuRasterization(false);
5839 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5840 host_impl_->SetUseGpuRasterization(true);
5841 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5842 host_impl_->SetUseGpuRasterization(false);
5843 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5845 host_impl_->CreatePendingTree();
5846 host_impl_->ActivateSyncTree();
5848 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5849 host_impl_->SetUseGpuRasterization(true);
5850 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5853 class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
5855 virtual void SetUp() OVERRIDE {
5856 LayerTreeSettings settings;
5857 settings.impl_side_painting = true;
5859 fake_host_impl_ = new FakeLayerTreeHostImpl(
5860 settings, &proxy_, shared_bitmap_manager_.get());
5861 host_impl_.reset(fake_host_impl_);
5862 host_impl_->InitializeRenderer(CreateOutputSurface());
5863 host_impl_->SetViewportSize(gfx::Size(10, 10));
5866 FakeLayerTreeHostImpl* fake_host_impl_;
5869 TEST_F(LayerTreeHostImplTestManageTiles, ManageTilesWhenInvisible) {
5870 fake_host_impl_->DidModifyTilePriorities();
5871 EXPECT_TRUE(fake_host_impl_->manage_tiles_needed());
5872 fake_host_impl_->SetVisible(false);
5873 EXPECT_FALSE(fake_host_impl_->manage_tiles_needed());
5876 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
5877 scoped_ptr<TestWebGraphicsContext3D> context =
5878 TestWebGraphicsContext3D::Create();
5879 TestWebGraphicsContext3D* context3d = context.get();
5880 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5881 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5883 EXPECT_EQ(0u, context3d->NumTextures());
5885 UIResourceId ui_resource_id = 1;
5886 bool is_opaque = false;
5887 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
5888 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5889 EXPECT_EQ(1u, context3d->NumTextures());
5890 ResourceProvider::ResourceId id1 =
5891 host_impl_->ResourceIdForUIResource(ui_resource_id);
5894 // Multiple requests with the same id is allowed. The previous texture is
5896 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5897 EXPECT_EQ(1u, context3d->NumTextures());
5898 ResourceProvider::ResourceId id2 =
5899 host_impl_->ResourceIdForUIResource(ui_resource_id);
5901 EXPECT_NE(id1, id2);
5903 // Deleting invalid UIResourceId is allowed and does not change state.
5904 host_impl_->DeleteUIResource(-1);
5905 EXPECT_EQ(1u, context3d->NumTextures());
5907 // Should return zero for invalid UIResourceId. Number of textures should
5909 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
5910 EXPECT_EQ(1u, context3d->NumTextures());
5912 host_impl_->DeleteUIResource(ui_resource_id);
5913 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
5914 EXPECT_EQ(0u, context3d->NumTextures());
5916 // Should not change state for multiple deletion on one UIResourceId
5917 host_impl_->DeleteUIResource(ui_resource_id);
5918 EXPECT_EQ(0u, context3d->NumTextures());
5921 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
5922 scoped_ptr<TestWebGraphicsContext3D> context =
5923 TestWebGraphicsContext3D::Create();
5924 TestWebGraphicsContext3D* context3d = context.get();
5925 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5926 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5928 EXPECT_EQ(0u, context3d->NumTextures());
5930 gfx::Size size(4, 4);
5931 // SkImageInfo has no support for ETC1. The |info| below contains the right
5932 // total pixel size for the bitmap but not the right height and width. The
5933 // correct width/height are passed directly to UIResourceBitmap.
5935 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
5936 skia::RefPtr<SkPixelRef> pixel_ref =
5937 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
5938 pixel_ref->setImmutable();
5939 UIResourceBitmap bitmap(pixel_ref, size);
5940 UIResourceId ui_resource_id = 1;
5941 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5942 EXPECT_EQ(1u, context3d->NumTextures());
5943 ResourceProvider::ResourceId id1 =
5944 host_impl_->ResourceIdForUIResource(ui_resource_id);
5948 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
5951 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
5952 scoped_refptr<TestContextProvider> context_provider =
5953 TestContextProvider::Create();
5957 FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>());
5959 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5961 ScopedPtrVector<CopyOutputRequest> requests;
5962 requests.push_back(CopyOutputRequest::CreateRequest(
5963 base::Bind(&ShutdownReleasesContext_Callback)));
5965 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
5967 LayerTreeHostImpl::FrameData frame;
5968 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5969 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5970 host_impl_->DidDrawAllLayers(frame);
5972 // The CopyOutputResult's callback has a ref on the ContextProvider and a
5973 // texture in a texture mailbox.
5974 EXPECT_FALSE(context_provider->HasOneRef());
5975 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
5979 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
5980 // released, and the texture deleted.
5981 EXPECT_TRUE(context_provider->HasOneRef());
5982 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
5985 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
5986 // When flinging via touch, only the child should scroll (we should not
5988 gfx::Size surface_size(10, 10);
5989 gfx::Size content_size(20, 20);
5990 scoped_ptr<LayerImpl> root_clip =
5991 LayerImpl::Create(host_impl_->active_tree(), 3);
5992 scoped_ptr<LayerImpl> root =
5993 CreateScrollableLayer(1, content_size, root_clip.get());
5994 root->SetIsContainerForFixedPositionLayers(true);
5995 scoped_ptr<LayerImpl> child =
5996 CreateScrollableLayer(2, content_size, root_clip.get());
5998 root->AddChild(child.Pass());
5999 int root_id = root->id();
6000 root_clip->AddChild(root.Pass());
6002 host_impl_->SetViewportSize(surface_size);
6003 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6004 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
6005 host_impl_->active_tree()->DidBecomeActive();
6008 EXPECT_EQ(InputHandler::ScrollStarted,
6009 host_impl_->ScrollBegin(gfx::Point(),
6010 InputHandler::Gesture));
6012 EXPECT_EQ(InputHandler::ScrollStarted,
6013 host_impl_->FlingScrollBegin());
6015 gfx::Vector2d scroll_delta(0, 100);
6016 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6017 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6019 host_impl_->ScrollEnd();
6021 scoped_ptr<ScrollAndScaleSet> scroll_info =
6022 host_impl_->ProcessScrollDeltas();
6024 // Only the child should have scrolled.
6025 ASSERT_EQ(1u, scroll_info->scrolls.size());
6026 ExpectNone(*scroll_info.get(), root_id);
6030 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
6031 // Scroll a child layer beyond its maximum scroll range and make sure the
6032 // the scroll doesn't bubble up to the parent layer.
6033 gfx::Size surface_size(10, 10);
6034 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
6035 scoped_ptr<LayerImpl> root_scrolling =
6036 CreateScrollableLayer(2, surface_size, root.get());
6038 scoped_ptr<LayerImpl> grand_child =
6039 CreateScrollableLayer(4, surface_size, root.get());
6040 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
6042 scoped_ptr<LayerImpl> child =
6043 CreateScrollableLayer(3, surface_size, root.get());
6044 child->SetScrollOffset(gfx::Vector2d(0, 4));
6045 child->AddChild(grand_child.Pass());
6047 root_scrolling->AddChild(child.Pass());
6048 root->AddChild(root_scrolling.Pass());
6049 host_impl_->active_tree()->SetRootLayer(root.Pass());
6050 host_impl_->active_tree()->DidBecomeActive();
6051 host_impl_->SetViewportSize(surface_size);
6054 scoped_ptr<ScrollAndScaleSet> scroll_info;
6056 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6057 LayerImpl* grand_child = child->children()[0];
6059 gfx::Vector2d scroll_delta(0, -2);
6060 EXPECT_EQ(InputHandler::ScrollStarted,
6061 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6062 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6064 // The grand child should have scrolled up to its limit.
6065 scroll_info = host_impl_->ProcessScrollDeltas();
6066 ASSERT_EQ(1u, scroll_info->scrolls.size());
6067 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6068 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6070 // The child should have received the bubbled delta, but the locked
6071 // scrolling layer should remain set as the grand child.
6072 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6073 scroll_info = host_impl_->ProcessScrollDeltas();
6074 ASSERT_EQ(2u, scroll_info->scrolls.size());
6075 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6076 ExpectContains(*scroll_info, child->id(), scroll_delta);
6077 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6079 // The first |ScrollBy| after the fling should re-lock the scrolling
6080 // layer to the first layer that scrolled, which is the child.
6081 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6082 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6083 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6085 // The child should have scrolled up to its limit.
6086 scroll_info = host_impl_->ProcessScrollDeltas();
6087 ASSERT_EQ(2u, scroll_info->scrolls.size());
6088 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6089 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
6091 // As the locked layer is at it's limit, no further scrolling can occur.
6092 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6093 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6094 host_impl_->ScrollEnd();
6098 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6099 // When flinging via wheel, the root should eventually scroll (we should
6101 gfx::Size surface_size(10, 10);
6102 gfx::Size content_size(20, 20);
6103 scoped_ptr<LayerImpl> root_clip =
6104 LayerImpl::Create(host_impl_->active_tree(), 3);
6105 scoped_ptr<LayerImpl> root_scroll =
6106 CreateScrollableLayer(1, content_size, root_clip.get());
6107 int root_scroll_id = root_scroll->id();
6108 scoped_ptr<LayerImpl> child =
6109 CreateScrollableLayer(2, content_size, root_clip.get());
6111 root_scroll->AddChild(child.Pass());
6112 root_clip->AddChild(root_scroll.Pass());
6114 host_impl_->SetViewportSize(surface_size);
6115 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6116 host_impl_->active_tree()->DidBecomeActive();
6119 EXPECT_EQ(InputHandler::ScrollStarted,
6120 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6122 EXPECT_EQ(InputHandler::ScrollStarted,
6123 host_impl_->FlingScrollBegin());
6125 gfx::Vector2d scroll_delta(0, 100);
6126 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6127 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6129 host_impl_->ScrollEnd();
6131 scoped_ptr<ScrollAndScaleSet> scroll_info =
6132 host_impl_->ProcessScrollDeltas();
6134 // The root should have scrolled.
6135 ASSERT_EQ(2u, scroll_info->scrolls.size());
6136 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
6140 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6141 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6142 // we should return ScrollUnknown.
6143 gfx::Size content_size(100, 100);
6144 SetupScrollAndContentsLayers(content_size);
6146 int scroll_layer_id = 2;
6147 LayerImpl* scroll_layer =
6148 host_impl_->active_tree()->LayerById(scroll_layer_id);
6149 scroll_layer->SetDrawsContent(true);
6151 int page_scale_layer_id = 5;
6152 LayerImpl* page_scale_layer =
6153 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6155 int occluder_layer_id = 6;
6156 scoped_ptr<LayerImpl> occluder_layer =
6157 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6158 occluder_layer->SetDrawsContent(true);
6159 occluder_layer->SetBounds(content_size);
6160 occluder_layer->SetContentBounds(content_size);
6161 occluder_layer->SetPosition(gfx::PointF());
6163 // The parent of the occluder is *above* the scroller.
6164 page_scale_layer->AddChild(occluder_layer.Pass());
6168 EXPECT_EQ(InputHandler::ScrollUnknown,
6169 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6172 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6173 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6174 // is not the first scroller we encounter when walking up from the layer, we
6175 // should also return ScrollUnknown.
6176 gfx::Size content_size(100, 100);
6177 SetupScrollAndContentsLayers(content_size);
6179 int scroll_layer_id = 2;
6180 LayerImpl* scroll_layer =
6181 host_impl_->active_tree()->LayerById(scroll_layer_id);
6182 scroll_layer->SetDrawsContent(true);
6184 int occluder_layer_id = 6;
6185 scoped_ptr<LayerImpl> occluder_layer =
6186 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6187 occluder_layer->SetDrawsContent(true);
6188 occluder_layer->SetBounds(content_size);
6189 occluder_layer->SetContentBounds(content_size);
6190 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6192 int child_scroll_clip_layer_id = 7;
6193 scoped_ptr<LayerImpl> child_scroll_clip =
6194 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6196 int child_scroll_layer_id = 8;
6197 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6198 child_scroll_layer_id, content_size, child_scroll_clip.get());
6200 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6202 child_scroll->AddChild(occluder_layer.Pass());
6203 scroll_layer->AddChild(child_scroll.Pass());
6207 EXPECT_EQ(InputHandler::ScrollUnknown,
6208 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6211 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) {
6212 gfx::Size content_size(100, 100);
6213 SetupScrollAndContentsLayers(content_size);
6215 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6217 int scroll_layer_id = 2;
6218 LayerImpl* scroll_layer =
6219 host_impl_->active_tree()->LayerById(scroll_layer_id);
6221 int child_scroll_layer_id = 7;
6222 scoped_ptr<LayerImpl> child_scroll =
6223 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6224 child_scroll->SetDrawsContent(false);
6226 scroll_layer->AddChild(child_scroll.Pass());
6230 // We should not have scrolled |child_scroll| even though we technically "hit"
6231 // it. The reason for this is that if the scrolling the scroll would not move
6232 // any layer that is a drawn RSLL member, then we can ignore the hit.
6234 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6235 // overscrolling the inner viewport.
6236 EXPECT_EQ(InputHandler::ScrollStarted,
6237 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6239 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6242 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6243 // This test case is very similar to the one above with one key difference:
6244 // the invisible scroller has a scroll child that is indeed draw contents.
6245 // If we attempt to initiate a gesture scroll off of the visible scroll child
6246 // we should still start the scroll child.
6247 gfx::Size content_size(100, 100);
6248 SetupScrollAndContentsLayers(content_size);
6250 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6252 int scroll_layer_id = 2;
6253 LayerImpl* scroll_layer =
6254 host_impl_->active_tree()->LayerById(scroll_layer_id);
6256 int scroll_child_id = 6;
6257 scoped_ptr<LayerImpl> scroll_child =
6258 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6259 scroll_child->SetDrawsContent(true);
6260 scroll_child->SetBounds(content_size);
6261 scroll_child->SetContentBounds(content_size);
6262 // Move the scroll child so it's not hit by our test point.
6263 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6265 int invisible_scroll_layer_id = 7;
6266 scoped_ptr<LayerImpl> invisible_scroll =
6267 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6268 invisible_scroll->SetDrawsContent(false);
6270 int container_id = 8;
6271 scoped_ptr<LayerImpl> container =
6272 LayerImpl::Create(host_impl_->active_tree(), container_id);
6274 scoped_ptr<std::set<LayerImpl*> > scroll_children(new std::set<LayerImpl*>());
6275 scroll_children->insert(scroll_child.get());
6276 invisible_scroll->SetScrollChildren(scroll_children.release());
6278 scroll_child->SetScrollParent(invisible_scroll.get());
6280 container->AddChild(invisible_scroll.Pass());
6281 container->AddChild(scroll_child.Pass());
6283 scroll_layer->AddChild(container.Pass());
6287 // We should not have scrolled |child_scroll| even though we technically "hit"
6288 // it. The reason for this is that if the scrolling the scroll would not move
6289 // any layer that is a drawn RSLL member, then we can ignore the hit.
6291 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6292 // overscrolling the inner viewport.
6293 EXPECT_EQ(InputHandler::ScrollStarted,
6294 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6296 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6299 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6300 // to CompositorFrameMetadata after SwapBuffers();
6301 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6302 scoped_ptr<SolidColorLayerImpl> root =
6303 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6304 root->SetPosition(gfx::PointF());
6305 root->SetBounds(gfx::Size(10, 10));
6306 root->SetContentBounds(gfx::Size(10, 10));
6307 root->SetDrawsContent(true);
6309 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
6311 FakeOutputSurface* fake_output_surface =
6312 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6314 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6315 fake_output_surface->last_sent_frame().metadata.latency_info;
6316 EXPECT_TRUE(metadata_latency_before.empty());
6318 ui::LatencyInfo latency_info;
6319 latency_info.AddLatencyNumber(
6320 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6321 scoped_ptr<SwapPromise> swap_promise(
6322 new LatencyInfoSwapPromise(latency_info));
6323 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
6324 host_impl_->SetNeedsRedraw();
6326 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6327 LayerTreeHostImpl::FrameData frame;
6328 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6329 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6330 host_impl_->DidDrawAllLayers(frame);
6331 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6333 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6334 fake_output_surface->last_sent_frame().metadata.latency_info;
6335 EXPECT_EQ(1u, metadata_latency_after.size());
6336 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6337 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6340 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
6341 int root_layer_id = 1;
6342 scoped_ptr<SolidColorLayerImpl> root =
6343 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
6344 root->SetPosition(gfx::PointF());
6345 root->SetBounds(gfx::Size(10, 10));
6346 root->SetContentBounds(gfx::Size(10, 10));
6347 root->SetDrawsContent(true);
6349 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
6351 // Ensure the default frame selection bounds are empty.
6352 FakeOutputSurface* fake_output_surface =
6353 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6354 const ViewportSelectionBound& selection_start_before =
6355 fake_output_surface->last_sent_frame().metadata.selection_start;
6356 const ViewportSelectionBound& selection_end_before =
6357 fake_output_surface->last_sent_frame().metadata.selection_end;
6358 EXPECT_EQ(ViewportSelectionBound(), selection_start_before);
6359 EXPECT_EQ(ViewportSelectionBound(), selection_end_before);
6361 // Plumb the layer-local selection bounds.
6362 gfx::Rect selection_rect(5, 0, 0, 5);
6363 LayerSelectionBound start, end;
6364 start.type = SELECTION_BOUND_CENTER;
6365 start.layer_id = root_layer_id;
6366 start.layer_rect = selection_rect;
6368 host_impl_->active_tree()->RegisterSelection(start, end);
6370 // Trigger a draw-swap sequence.
6371 host_impl_->SetNeedsRedraw();
6373 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6374 LayerTreeHostImpl::FrameData frame;
6375 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6376 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6377 host_impl_->DidDrawAllLayers(frame);
6378 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6380 // Ensure the selection bounds have propagated to the frame metadata.
6381 const ViewportSelectionBound& selection_start_after =
6382 fake_output_surface->last_sent_frame().metadata.selection_start;
6383 const ViewportSelectionBound& selection_end_after =
6384 fake_output_surface->last_sent_frame().metadata.selection_end;
6385 EXPECT_EQ(start.type, selection_start_after.type);
6386 EXPECT_EQ(end.type, selection_end_after.type);
6387 EXPECT_EQ(selection_rect, selection_start_after.viewport_rect);
6388 EXPECT_EQ(selection_rect, selection_start_after.viewport_rect);
6389 EXPECT_TRUE(selection_start_after.visible);
6390 EXPECT_TRUE(selection_start_after.visible);
6393 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
6395 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
6396 LayerTreeHostImpl* layer_tree_host_impl,
6397 int* set_needs_commit_count,
6398 int* set_needs_redraw_count,
6399 int* forward_to_main_count)
6400 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
6401 set_needs_commit_count_(set_needs_commit_count),
6402 set_needs_redraw_count_(set_needs_redraw_count),
6403 forward_to_main_count_(forward_to_main_count) {}
6405 virtual ~SimpleSwapPromiseMonitor() {}
6407 virtual void OnSetNeedsCommitOnMain() OVERRIDE {
6408 (*set_needs_commit_count_)++;
6411 virtual void OnSetNeedsRedrawOnImpl() OVERRIDE {
6412 (*set_needs_redraw_count_)++;
6415 virtual void OnForwardScrollUpdateToMainThreadOnImpl() OVERRIDE {
6416 (*forward_to_main_count_)++;
6420 int* set_needs_commit_count_;
6421 int* set_needs_redraw_count_;
6422 int* forward_to_main_count_;
6425 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
6426 int set_needs_commit_count = 0;
6427 int set_needs_redraw_count = 0;
6428 int forward_to_main_count = 0;
6431 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6432 new SimpleSwapPromiseMonitor(NULL,
6434 &set_needs_commit_count,
6435 &set_needs_redraw_count,
6436 &forward_to_main_count));
6437 host_impl_->SetNeedsRedraw();
6438 EXPECT_EQ(0, set_needs_commit_count);
6439 EXPECT_EQ(1, set_needs_redraw_count);
6440 EXPECT_EQ(0, forward_to_main_count);
6443 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6445 host_impl_->SetNeedsRedraw();
6446 EXPECT_EQ(0, set_needs_commit_count);
6447 EXPECT_EQ(1, set_needs_redraw_count);
6448 EXPECT_EQ(0, forward_to_main_count);
6451 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6452 new SimpleSwapPromiseMonitor(NULL,
6454 &set_needs_commit_count,
6455 &set_needs_redraw_count,
6456 &forward_to_main_count));
6457 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
6458 EXPECT_EQ(0, set_needs_commit_count);
6459 EXPECT_EQ(2, set_needs_redraw_count);
6460 EXPECT_EQ(0, forward_to_main_count);
6464 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6465 new SimpleSwapPromiseMonitor(NULL,
6467 &set_needs_commit_count,
6468 &set_needs_redraw_count,
6469 &forward_to_main_count));
6470 // Empty damage rect won't signal the monitor.
6471 host_impl_->SetNeedsRedrawRect(gfx::Rect());
6472 EXPECT_EQ(0, set_needs_commit_count);
6473 EXPECT_EQ(2, set_needs_redraw_count);
6474 EXPECT_EQ(0, forward_to_main_count);
6478 set_needs_commit_count = 0;
6479 set_needs_redraw_count = 0;
6480 forward_to_main_count = 0;
6481 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6482 new SimpleSwapPromiseMonitor(NULL,
6484 &set_needs_commit_count,
6485 &set_needs_redraw_count,
6486 &forward_to_main_count));
6487 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
6489 // Scrolling normally should not trigger any forwarding.
6490 EXPECT_EQ(InputHandler::ScrollStarted,
6491 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6492 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
6493 host_impl_->ScrollEnd();
6495 EXPECT_EQ(0, set_needs_commit_count);
6496 EXPECT_EQ(1, set_needs_redraw_count);
6497 EXPECT_EQ(0, forward_to_main_count);
6499 // Scrolling with a scroll handler should defer the swap to the main
6501 scroll_layer->SetHaveScrollEventHandlers(true);
6502 EXPECT_EQ(InputHandler::ScrollStarted,
6503 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6504 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
6505 host_impl_->ScrollEnd();
6507 EXPECT_EQ(0, set_needs_commit_count);
6508 EXPECT_EQ(2, set_needs_redraw_count);
6509 EXPECT_EQ(1, forward_to_main_count);
6513 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
6515 virtual void SetUp() OVERRIDE {
6516 LayerTreeSettings settings = DefaultSettings();
6517 settings.calculate_top_controls_position = true;
6518 settings.top_controls_height = top_controls_height_;
6519 CreateHostImpl(settings, CreateOutputSurface());
6523 static const int top_controls_height_;
6526 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
6528 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
6529 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6530 ->SetScrollOffset(gfx::Vector2d(0, 10));
6531 host_impl_->Animate(base::TimeTicks());
6532 EXPECT_FALSE(did_request_redraw_);
6535 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
6536 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6537 ->SetScrollOffset(gfx::Vector2d(0, 10));
6538 host_impl_->DidChangeTopControlsPosition();
6539 EXPECT_TRUE(did_request_animate_);
6540 EXPECT_TRUE(did_request_redraw_);
6543 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
6544 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6545 host_impl_->SetViewportSize(gfx::Size(100, 100));
6548 EXPECT_EQ(InputHandler::ScrollStarted,
6549 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6550 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6551 EXPECT_EQ(gfx::Vector2dF().ToString(),
6552 scroll_layer->TotalScrollOffset().ToString());
6554 // Scroll just the top controls and verify that the scroll succeeds.
6555 const float residue = 10;
6556 float offset = top_controls_height_ - residue;
6557 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6558 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->controls_top_offset());
6559 EXPECT_EQ(gfx::Vector2dF().ToString(),
6560 scroll_layer->TotalScrollOffset().ToString());
6562 // Scroll across the boundary
6563 const float content_scroll = 20;
6564 offset = residue + content_scroll;
6565 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6566 EXPECT_EQ(-top_controls_height_,
6567 host_impl_->top_controls_manager()->controls_top_offset());
6568 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
6569 scroll_layer->TotalScrollOffset().ToString());
6571 // Now scroll back to the top of the content
6572 offset = -content_scroll;
6573 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6574 EXPECT_EQ(-top_controls_height_,
6575 host_impl_->top_controls_manager()->controls_top_offset());
6576 EXPECT_EQ(gfx::Vector2dF().ToString(),
6577 scroll_layer->TotalScrollOffset().ToString());
6579 // And scroll the top controls completely into view
6580 offset = -top_controls_height_;
6581 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6582 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6583 EXPECT_EQ(gfx::Vector2dF().ToString(),
6584 scroll_layer->TotalScrollOffset().ToString());
6586 // And attempt to scroll past the end
6587 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6588 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6589 EXPECT_EQ(gfx::Vector2dF().ToString(),
6590 scroll_layer->TotalScrollOffset().ToString());
6592 host_impl_->ScrollEnd();
6595 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
6596 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6597 host_impl_->SetViewportSize(gfx::Size(100, 200));
6600 EXPECT_EQ(InputHandler::ScrollStarted,
6601 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6602 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6603 EXPECT_EQ(gfx::Vector2dF().ToString(),
6604 scroll_layer->TotalScrollOffset().ToString());
6606 // Scroll the top controls partially.
6607 const float residue = 35;
6608 float offset = top_controls_height_ - residue;
6609 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6610 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->controls_top_offset());
6611 EXPECT_EQ(gfx::Vector2dF().ToString(),
6612 scroll_layer->TotalScrollOffset().ToString());
6614 did_request_redraw_ = false;
6615 did_request_animate_ = false;
6616 did_request_commit_ = false;
6618 // End the scroll while the controls are still offset from their limit.
6619 host_impl_->ScrollEnd();
6620 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
6621 EXPECT_TRUE(did_request_animate_);
6622 EXPECT_TRUE(did_request_redraw_);
6623 EXPECT_FALSE(did_request_commit_);
6625 // The top controls should properly animate until finished, despite the scroll
6626 // offset being at the origin.
6627 base::TimeTicks animation_time = gfx::FrameTime::Now();
6628 while (did_request_animate_) {
6629 did_request_redraw_ = false;
6630 did_request_animate_ = false;
6631 did_request_commit_ = false;
6634 host_impl_->top_controls_manager()->controls_top_offset();
6636 animation_time += base::TimeDelta::FromMilliseconds(5);
6637 host_impl_->Animate(animation_time);
6638 EXPECT_EQ(gfx::Vector2dF().ToString(),
6639 scroll_layer->TotalScrollOffset().ToString());
6642 host_impl_->top_controls_manager()->controls_top_offset();
6644 // No commit is needed as the controls are animating the content offset,
6645 // not the scroll offset.
6646 EXPECT_FALSE(did_request_commit_);
6648 if (new_offset != old_offset)
6649 EXPECT_TRUE(did_request_redraw_);
6651 if (new_offset != 0) {
6652 EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
6653 EXPECT_TRUE(did_request_animate_);
6656 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
6659 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
6660 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6661 host_impl_->SetViewportSize(gfx::Size(100, 100));
6662 float initial_scroll_offset = 50;
6663 scroll_layer->SetScrollOffset(gfx::Vector2d(0, initial_scroll_offset));
6666 EXPECT_EQ(InputHandler::ScrollStarted,
6667 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6668 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6669 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
6670 scroll_layer->TotalScrollOffset().ToString());
6672 // Scroll the top controls partially.
6673 const float residue = 15;
6674 float offset = top_controls_height_ - residue;
6675 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6676 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->controls_top_offset());
6677 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
6678 scroll_layer->TotalScrollOffset().ToString());
6680 did_request_redraw_ = false;
6681 did_request_animate_ = false;
6682 did_request_commit_ = false;
6684 // End the scroll while the controls are still offset from the limit.
6685 host_impl_->ScrollEnd();
6686 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
6687 EXPECT_TRUE(did_request_animate_);
6688 EXPECT_TRUE(did_request_redraw_);
6689 EXPECT_FALSE(did_request_commit_);
6691 // Animate the top controls to the limit.
6692 base::TimeTicks animation_time = gfx::FrameTime::Now();
6693 while (did_request_animate_) {
6694 did_request_redraw_ = false;
6695 did_request_animate_ = false;
6696 did_request_commit_ = false;
6699 host_impl_->top_controls_manager()->controls_top_offset();
6701 animation_time += base::TimeDelta::FromMilliseconds(5);
6702 host_impl_->Animate(animation_time);
6705 host_impl_->top_controls_manager()->controls_top_offset();
6707 if (new_offset != old_offset) {
6708 EXPECT_TRUE(did_request_redraw_);
6709 EXPECT_TRUE(did_request_commit_);
6712 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
6715 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
6717 void SetupVirtualViewportLayers(const gfx::Size& content_size,
6718 const gfx::Size& outer_viewport,
6719 const gfx::Size& inner_viewport) {
6720 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
6721 const int kOuterViewportClipLayerId = 6;
6722 const int kOuterViewportScrollLayerId = 7;
6723 const int kInnerViewportScrollLayerId = 2;
6724 const int kInnerViewportClipLayerId = 4;
6725 const int kPageScaleLayerId = 5;
6727 scoped_ptr<LayerImpl> inner_scroll =
6728 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
6729 inner_scroll->SetIsContainerForFixedPositionLayers(true);
6730 inner_scroll->SetScrollOffset(gfx::Vector2d());
6732 scoped_ptr<LayerImpl> inner_clip =
6733 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
6734 inner_clip->SetBounds(inner_viewport);
6736 scoped_ptr<LayerImpl> page_scale =
6737 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
6739 inner_scroll->SetScrollClipLayer(inner_clip->id());
6740 inner_scroll->SetBounds(outer_viewport);
6741 inner_scroll->SetContentBounds(outer_viewport);
6742 inner_scroll->SetPosition(gfx::PointF());
6744 scoped_ptr<LayerImpl> outer_clip =
6745 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
6746 outer_clip->SetBounds(outer_viewport);
6747 outer_clip->SetIsContainerForFixedPositionLayers(true);
6749 scoped_ptr<LayerImpl> outer_scroll =
6750 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
6751 outer_scroll->SetScrollClipLayer(outer_clip->id());
6752 outer_scroll->SetScrollOffset(gfx::Vector2d());
6753 outer_scroll->SetBounds(content_size);
6754 outer_scroll->SetContentBounds(content_size);
6755 outer_scroll->SetPosition(gfx::PointF());
6757 scoped_ptr<LayerImpl> contents =
6758 LayerImpl::Create(layer_tree_impl, 8);
6759 contents->SetDrawsContent(true);
6760 contents->SetBounds(content_size);
6761 contents->SetContentBounds(content_size);
6762 contents->SetPosition(gfx::PointF());
6764 outer_scroll->AddChild(contents.Pass());
6765 outer_clip->AddChild(outer_scroll.Pass());
6766 inner_scroll->AddChild(outer_clip.Pass());
6767 page_scale->AddChild(inner_scroll.Pass());
6768 inner_clip->AddChild(page_scale.Pass());
6770 layer_tree_impl->SetRootLayer(inner_clip.Pass());
6771 layer_tree_impl->SetViewportLayersFromIds(kPageScaleLayerId,
6772 kInnerViewportScrollLayerId, kOuterViewportScrollLayerId);
6774 host_impl_->active_tree()->DidBecomeActive();
6778 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
6779 gfx::Size content_size = gfx::Size(100, 160);
6780 gfx::Size outer_viewport = gfx::Size(50, 80);
6781 gfx::Size inner_viewport = gfx::Size(25, 40);
6783 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
6785 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
6786 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
6789 gfx::Vector2dF inner_expected;
6790 gfx::Vector2dF outer_expected;
6791 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6792 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6794 // Make sure the fling goes to the outer viewport first
6795 EXPECT_EQ(InputHandler::ScrollStarted,
6796 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6797 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6799 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
6800 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6801 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6803 host_impl_->ScrollEnd();
6805 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6806 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6808 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
6809 EXPECT_EQ(InputHandler::ScrollStarted,
6810 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6811 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6813 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6814 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6816 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6817 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6819 host_impl_->ScrollEnd();
6821 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6822 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6826 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
6828 virtual void SetUp() OVERRIDE {
6829 LayerTreeSettings settings = DefaultSettings();
6830 settings.max_memory_for_prepaint_percentage = 50;
6831 CreateHostImpl(settings, CreateOutputSurface());
6835 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
6836 // Set up a memory policy and percentages which could cause
6837 // 32-bit integer overflows.
6838 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
6840 // Verify implicit limits are calculated correctly with no overflows
6841 host_impl_->SetMemoryPolicy(mem_policy);
6842 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
6843 300u * 1024u * 1024u);
6844 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
6845 150u * 1024u * 1024u);
6848 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
6849 const gfx::Size layer_size(100, 100);
6850 gfx::Transform external_transform;
6851 const gfx::Rect external_viewport(layer_size);
6852 const gfx::Rect external_clip(layer_size);
6853 const bool resourceless_software_draw = false;
6854 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
6856 host_impl_->SetExternalDrawConstraints(external_transform,
6861 resourceless_software_draw);
6863 EXPECT_TRANSFORMATION_MATRIX_EQ(
6864 external_transform, layer->draw_properties().target_space_transform);
6866 external_transform.Translate(20, 20);
6867 host_impl_->SetExternalDrawConstraints(external_transform,
6872 resourceless_software_draw);
6874 EXPECT_TRANSFORMATION_MATRIX_EQ(
6875 external_transform, layer->draw_properties().target_space_transform);
6878 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
6879 SetupScrollAndContentsLayers(gfx::Size(100, 150));
6880 host_impl_->SetViewportSize(gfx::Size(50, 50));
6883 base::TimeTicks start_time =
6884 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
6886 EXPECT_EQ(InputHandler::ScrollStarted,
6887 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
6889 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
6891 host_impl_->Animate(start_time);
6892 host_impl_->UpdateAnimationState(true);
6894 EXPECT_EQ(gfx::Vector2dF(), scrolling_layer->TotalScrollOffset());
6896 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
6897 host_impl_->UpdateAnimationState(true);
6899 float y = scrolling_layer->TotalScrollOffset().y();
6900 EXPECT_TRUE(y > 1 && y < 49);
6903 EXPECT_EQ(InputHandler::ScrollStarted,
6904 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
6906 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
6907 host_impl_->UpdateAnimationState(true);
6909 y = scrolling_layer->TotalScrollOffset().y();
6910 EXPECT_TRUE(y > 50 && y < 100);
6911 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
6913 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
6914 host_impl_->UpdateAnimationState(true);
6916 EXPECT_EQ(gfx::Vector2dF(0, 100), scrolling_layer->TotalScrollOffset());
6917 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
6920 TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairs) {
6921 host_impl_->CreatePendingTree();
6922 host_impl_->ActivateSyncTree();
6923 host_impl_->CreatePendingTree();
6925 LayerTreeImpl* active_tree = host_impl_->active_tree();
6926 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
6927 EXPECT_NE(active_tree, pending_tree);
6929 scoped_ptr<FakePictureLayerImpl> active_layer =
6930 FakePictureLayerImpl::Create(active_tree, 10);
6931 scoped_ptr<FakePictureLayerImpl> pending_layer =
6932 FakePictureLayerImpl::Create(pending_tree, 10);
6934 std::vector<PictureLayerImpl::Pair> layer_pairs;
6935 host_impl_->GetPictureLayerImplPairs(&layer_pairs);
6937 EXPECT_EQ(2u, layer_pairs.size());
6938 if (layer_pairs[0].active) {
6939 EXPECT_EQ(active_layer.get(), layer_pairs[0].active);
6940 EXPECT_EQ(NULL, layer_pairs[0].pending);
6942 EXPECT_EQ(pending_layer.get(), layer_pairs[0].pending);
6943 EXPECT_EQ(NULL, layer_pairs[0].active);
6946 if (layer_pairs[1].active) {
6947 EXPECT_EQ(active_layer.get(), layer_pairs[1].active);
6948 EXPECT_EQ(NULL, layer_pairs[1].pending);
6950 EXPECT_EQ(pending_layer.get(), layer_pairs[1].pending);
6951 EXPECT_EQ(NULL, layer_pairs[1].active);
6954 active_layer->set_twin_layer(pending_layer.get());
6955 pending_layer->set_twin_layer(active_layer.get());
6957 layer_pairs.clear();
6958 host_impl_->GetPictureLayerImplPairs(&layer_pairs);
6959 EXPECT_EQ(1u, layer_pairs.size());
6961 EXPECT_EQ(active_layer.get(), layer_pairs[0].active);
6962 EXPECT_EQ(pending_layer.get(), layer_pairs[0].pending);
6965 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
6966 host_impl_->CreatePendingTree();
6967 host_impl_->ActivateSyncTree();
6968 host_impl_->CreatePendingTree();
6970 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
6972 scoped_ptr<FakePictureLayerImpl> pending_layer =
6973 FakePictureLayerImpl::Create(pending_tree, 10);
6974 pending_layer->DoPostCommitInitializationIfNeeded();
6975 FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
6976 pending_tree->SetRootLayer(pending_layer.PassAs<LayerImpl>());
6977 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
6979 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
6980 pending_tree->DidBecomeActive();
6981 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
6983 scoped_ptr<FakePictureLayerImpl> mask_layer =
6984 FakePictureLayerImpl::Create(pending_tree, 11);
6985 mask_layer->DoPostCommitInitializationIfNeeded();
6986 FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
6987 raw_pending_layer->SetMaskLayer(mask_layer.PassAs<LayerImpl>());
6988 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
6990 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
6991 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
6992 pending_tree->DidBecomeActive();
6993 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
6994 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
6996 scoped_ptr<FakePictureLayerImpl> replica_layer =
6997 FakePictureLayerImpl::Create(pending_tree, 12);
6998 scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
6999 FakePictureLayerImpl::Create(pending_tree, 13);
7000 replica_mask_layer->DoPostCommitInitializationIfNeeded();
7001 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
7002 replica_layer->SetMaskLayer(replica_mask_layer.PassAs<LayerImpl>());
7003 raw_pending_layer->SetReplicaLayer(replica_layer.PassAs<LayerImpl>());
7004 ASSERT_EQ(raw_replica_mask_layer,
7005 raw_pending_layer->replica_layer()->mask_layer());
7007 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7008 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7009 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
7010 pending_tree->DidBecomeActive();
7011 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
7012 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
7013 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
7016 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
7018 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7019 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {
7020 num_lost_surfaces_++;
7024 int num_lost_surfaces_;
7027 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
7028 // The medium term, we plan to remove LayerTreeHostImpl::IsContextLost().
7029 // Until then, we need the state variable
7030 // LayerTreeHostImpl::have_valid_output_surface_ and we can
7031 // enforce the following behaviour, where calling DidLoseOutputSurface
7032 // twice in a row only causes one subsequent
7033 // call to LayerTreeHostImplClient::DidLoseOutputSurfaceOnImplThread().
7034 // Really we just need at least one client notification each time
7035 // we go from having a valid output surface to not having a valid output
7037 EXPECT_EQ(0, num_lost_surfaces_);
7038 EXPECT_FALSE(host_impl_->IsContextLost());
7039 host_impl_->DidLoseOutputSurface();
7040 EXPECT_TRUE(host_impl_->IsContextLost());
7041 EXPECT_EQ(1, num_lost_surfaces_);
7042 host_impl_->DidLoseOutputSurface();
7043 EXPECT_TRUE(host_impl_->IsContextLost());
7044 EXPECT_EQ(1, num_lost_surfaces_);