cc: Don't swap PictureLayerTilingSet on activate.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blobc8e27a90ab7c6e552464ec40c3e5731bfd8c8297
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host_impl.h"
7 #include <algorithm>
8 #include <cmath>
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/containers/scoped_ptr_hash_map.h"
14 #include "cc/animation/scrollbar_animation_controller_thinning.h"
15 #include "cc/base/latency_info_swap_promise.h"
16 #include "cc/base/math_util.h"
17 #include "cc/input/page_scale_animation.h"
18 #include "cc/input/top_controls_manager.h"
19 #include "cc/layers/append_quads_data.h"
20 #include "cc/layers/delegated_renderer_layer_impl.h"
21 #include "cc/layers/heads_up_display_layer_impl.h"
22 #include "cc/layers/io_surface_layer_impl.h"
23 #include "cc/layers/layer_impl.h"
24 #include "cc/layers/painted_scrollbar_layer_impl.h"
25 #include "cc/layers/render_surface_impl.h"
26 #include "cc/layers/solid_color_layer_impl.h"
27 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
28 #include "cc/layers/texture_layer_impl.h"
29 #include "cc/layers/tiled_layer_impl.h"
30 #include "cc/layers/video_layer_impl.h"
31 #include "cc/output/begin_frame_args.h"
32 #include "cc/output/compositor_frame_ack.h"
33 #include "cc/output/compositor_frame_metadata.h"
34 #include "cc/output/copy_output_request.h"
35 #include "cc/output/copy_output_result.h"
36 #include "cc/output/gl_renderer.h"
37 #include "cc/quads/render_pass_draw_quad.h"
38 #include "cc/quads/solid_color_draw_quad.h"
39 #include "cc/quads/texture_draw_quad.h"
40 #include "cc/quads/tile_draw_quad.h"
41 #include "cc/resources/layer_tiling_data.h"
42 #include "cc/test/animation_test_common.h"
43 #include "cc/test/begin_frame_args_test.h"
44 #include "cc/test/fake_layer_tree_host_impl.h"
45 #include "cc/test/fake_output_surface.h"
46 #include "cc/test/fake_output_surface_client.h"
47 #include "cc/test/fake_picture_layer_impl.h"
48 #include "cc/test/fake_picture_pile_impl.h"
49 #include "cc/test/fake_proxy.h"
50 #include "cc/test/fake_video_frame_provider.h"
51 #include "cc/test/geometry_test_utils.h"
52 #include "cc/test/layer_test_common.h"
53 #include "cc/test/render_pass_test_common.h"
54 #include "cc/test/test_gpu_memory_buffer_manager.h"
55 #include "cc/test/test_shared_bitmap_manager.h"
56 #include "cc/test/test_web_graphics_context_3d.h"
57 #include "cc/trees/layer_tree_impl.h"
58 #include "cc/trees/single_thread_proxy.h"
59 #include "media/base/media.h"
60 #include "testing/gmock/include/gmock/gmock.h"
61 #include "testing/gtest/include/gtest/gtest.h"
62 #include "third_party/skia/include/core/SkMallocPixelRef.h"
63 #include "ui/gfx/frame_time.h"
64 #include "ui/gfx/geometry/rect_conversions.h"
65 #include "ui/gfx/geometry/size_conversions.h"
66 #include "ui/gfx/geometry/vector2d_conversions.h"
68 using ::testing::Mock;
69 using ::testing::Return;
70 using ::testing::AnyNumber;
71 using ::testing::AtLeast;
72 using ::testing::_;
73 using media::VideoFrame;
75 namespace cc {
76 namespace {
78 class LayerTreeHostImplTest : public testing::Test,
79 public LayerTreeHostImplClient {
80 public:
81 LayerTreeHostImplTest()
82 : proxy_(base::MessageLoopProxy::current(),
83 base::MessageLoopProxy::current()),
84 always_impl_thread_(&proxy_),
85 always_main_thread_blocked_(&proxy_),
86 shared_bitmap_manager_(new TestSharedBitmapManager),
87 gpu_memory_buffer_manager_(new TestGpuMemoryBufferManager),
88 on_can_draw_state_changed_called_(false),
89 did_notify_ready_to_activate_(false),
90 did_request_commit_(false),
91 did_request_redraw_(false),
92 did_request_animate_(false),
93 did_request_prepare_tiles_(false),
94 reduce_memory_result_(true),
95 current_limit_bytes_(0),
96 current_priority_cutoff_value_(0) {
97 media::InitializeMediaLibraryForTesting();
100 LayerTreeSettings DefaultSettings() {
101 LayerTreeSettings settings;
102 settings.minimum_occlusion_tracking_size = gfx::Size();
103 settings.impl_side_painting = true;
104 settings.renderer_settings.texture_id_allocation_chunk_size = 1;
105 settings.report_overscroll_only_for_scrollable_axes = true;
106 settings.use_pinch_virtual_viewport = true;
107 return settings;
110 void SetUp() override {
111 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
114 void TearDown() override {}
116 void UpdateRendererCapabilitiesOnImplThread() override {}
117 void DidLoseOutputSurfaceOnImplThread() override {}
118 void CommitVSyncParameters(base::TimeTicks timebase,
119 base::TimeDelta interval) override {}
120 void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {}
121 void SetMaxSwapsPendingOnImplThread(int max) override {}
122 void DidSwapBuffersOnImplThread() override {}
123 void DidSwapBuffersCompleteOnImplThread() override {}
124 void OnCanDrawStateChanged(bool can_draw) override {
125 on_can_draw_state_changed_called_ = true;
127 void NotifyReadyToActivate() override {
128 did_notify_ready_to_activate_ = true;
129 host_impl_->ActivateSyncTree();
131 void NotifyReadyToDraw() override {}
132 void SetNeedsRedrawOnImplThread() override { did_request_redraw_ = true; }
133 void SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) override {
134 did_request_redraw_ = true;
136 void SetNeedsAnimateOnImplThread() override { did_request_animate_ = true; }
137 void SetNeedsPrepareTilesOnImplThread() override {
138 did_request_prepare_tiles_ = true;
140 void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; }
141 void PostAnimationEventsToMainThreadOnImplThread(
142 scoped_ptr<AnimationEventsVector> events) override {}
143 bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
144 int priority_cutoff) override {
145 current_limit_bytes_ = limit_bytes;
146 current_priority_cutoff_value_ = priority_cutoff;
147 return reduce_memory_result_;
149 bool IsInsideDraw() override { return false; }
150 void RenewTreePriority() override {}
151 void PostDelayedScrollbarFadeOnImplThread(const base::Closure& start_fade,
152 base::TimeDelta delay) override {
153 scrollbar_fade_start_ = start_fade;
154 requested_scrollbar_animation_delay_ = delay;
156 void DidActivateSyncTree() override {}
157 void DidPrepareTiles() override {}
159 void set_reduce_memory_result(bool reduce_memory_result) {
160 reduce_memory_result_ = reduce_memory_result;
163 virtual bool CreateHostImpl(const LayerTreeSettings& settings,
164 scoped_ptr<OutputSurface> output_surface) {
165 host_impl_ = LayerTreeHostImpl::Create(settings,
166 this,
167 &proxy_,
168 &stats_instrumentation_,
169 shared_bitmap_manager_.get(),
170 gpu_memory_buffer_manager_.get(),
172 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
173 host_impl_->SetViewportSize(gfx::Size(10, 10));
174 return init;
177 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
178 root->SetPosition(gfx::PointF());
179 root->SetBounds(gfx::Size(10, 10));
180 root->SetContentBounds(gfx::Size(10, 10));
181 root->SetDrawsContent(true);
182 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
183 host_impl_->active_tree()->SetRootLayer(root.Pass());
186 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
187 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
188 for (size_t i = 0; i < layer->children().size(); ++i)
189 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
192 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
193 int id,
194 const gfx::Vector2d& scroll_delta) {
195 int times_encountered = 0;
197 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
198 if (scroll_info.scrolls[i].layer_id != id)
199 continue;
200 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
201 times_encountered++;
204 ASSERT_EQ(1, times_encountered);
207 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
208 int times_encountered = 0;
210 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
211 if (scroll_info.scrolls[i].layer_id != id)
212 continue;
213 times_encountered++;
216 ASSERT_EQ(0, times_encountered);
219 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
220 const gfx::Size& content_size) {
221 const int kInnerViewportScrollLayerId = 2;
222 const int kInnerViewportClipLayerId = 4;
223 const int kPageScaleLayerId = 5;
224 scoped_ptr<LayerImpl> root =
225 LayerImpl::Create(layer_tree_impl, 1);
226 root->SetBounds(content_size);
227 root->SetContentBounds(content_size);
228 root->SetPosition(gfx::PointF());
230 scoped_ptr<LayerImpl> scroll =
231 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
232 LayerImpl* scroll_layer = scroll.get();
233 scroll->SetIsContainerForFixedPositionLayers(true);
234 scroll->SetScrollOffset(gfx::ScrollOffset());
236 scoped_ptr<LayerImpl> clip =
237 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
238 clip->SetBounds(
239 gfx::Size(content_size.width() / 2, content_size.height() / 2));
241 scoped_ptr<LayerImpl> page_scale =
242 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
244 scroll->SetScrollClipLayer(clip->id());
245 scroll->SetBounds(content_size);
246 scroll->SetContentBounds(content_size);
247 scroll->SetPosition(gfx::PointF());
248 scroll->SetIsContainerForFixedPositionLayers(true);
250 scoped_ptr<LayerImpl> contents =
251 LayerImpl::Create(layer_tree_impl, 3);
252 contents->SetDrawsContent(true);
253 contents->SetBounds(content_size);
254 contents->SetContentBounds(content_size);
255 contents->SetPosition(gfx::PointF());
257 scroll->AddChild(contents.Pass());
258 page_scale->AddChild(scroll.Pass());
259 clip->AddChild(page_scale.Pass());
260 root->AddChild(clip.Pass());
262 layer_tree_impl->SetRootLayer(root.Pass());
263 layer_tree_impl->SetViewportLayersFromIds(
264 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
265 Layer::INVALID_ID);
267 return scroll_layer;
270 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
271 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
272 host_impl_->active_tree(), content_size);
273 host_impl_->active_tree()->DidBecomeActive();
274 return scroll_layer;
277 // TODO(wjmaclean) Add clip-layer pointer to parameters.
278 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
279 const gfx::Size& size,
280 LayerImpl* clip_layer) {
281 DCHECK(clip_layer);
282 DCHECK(id != clip_layer->id());
283 scoped_ptr<LayerImpl> layer =
284 LayerImpl::Create(host_impl_->active_tree(), id);
285 layer->SetScrollClipLayer(clip_layer->id());
286 layer->SetDrawsContent(true);
287 layer->SetBounds(size);
288 layer->SetContentBounds(size);
289 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
290 return layer.Pass();
293 void DrawFrame() {
294 LayerTreeHostImpl::FrameData frame;
295 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
296 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
297 host_impl_->DidDrawAllLayers(frame);
300 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
301 void pinch_zoom_pan_viewport_test(float device_scale_factor);
302 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
303 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
304 float device_scale_factor);
306 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
307 // Note: It is not possible to disable the renderer once it has been set,
308 // so we do not need to test that disabling the renderer notifies us
309 // that can_draw changed.
310 EXPECT_FALSE(host_impl_->CanDraw());
311 on_can_draw_state_changed_called_ = false;
313 // Set up the root layer, which allows us to draw.
314 SetupScrollAndContentsLayers(gfx::Size(100, 100));
315 EXPECT_TRUE(host_impl_->CanDraw());
316 EXPECT_TRUE(on_can_draw_state_changed_called_);
317 on_can_draw_state_changed_called_ = false;
319 // Toggle the root layer to make sure it toggles can_draw
320 host_impl_->active_tree()->SetRootLayer(nullptr);
321 EXPECT_FALSE(host_impl_->CanDraw());
322 EXPECT_TRUE(on_can_draw_state_changed_called_);
323 on_can_draw_state_changed_called_ = false;
325 SetupScrollAndContentsLayers(gfx::Size(100, 100));
326 EXPECT_TRUE(host_impl_->CanDraw());
327 EXPECT_TRUE(on_can_draw_state_changed_called_);
328 on_can_draw_state_changed_called_ = false;
330 // Toggle the device viewport size to make sure it toggles can_draw.
331 host_impl_->SetViewportSize(gfx::Size());
332 if (always_draw) {
333 EXPECT_TRUE(host_impl_->CanDraw());
334 } else {
335 EXPECT_FALSE(host_impl_->CanDraw());
337 EXPECT_TRUE(on_can_draw_state_changed_called_);
338 on_can_draw_state_changed_called_ = false;
340 host_impl_->SetViewportSize(gfx::Size(100, 100));
341 EXPECT_TRUE(host_impl_->CanDraw());
342 EXPECT_TRUE(on_can_draw_state_changed_called_);
343 on_can_draw_state_changed_called_ = false;
345 // Toggle contents textures purged without causing any evictions,
346 // and make sure that it does not change can_draw.
347 set_reduce_memory_result(false);
348 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
349 host_impl_->memory_allocation_limit_bytes() - 1));
350 EXPECT_TRUE(host_impl_->CanDraw());
351 EXPECT_FALSE(on_can_draw_state_changed_called_);
352 on_can_draw_state_changed_called_ = false;
354 // Toggle contents textures purged to make sure it toggles can_draw.
355 set_reduce_memory_result(true);
356 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
357 host_impl_->memory_allocation_limit_bytes() - 1));
358 if (always_draw) {
359 EXPECT_TRUE(host_impl_->CanDraw());
360 } else {
361 EXPECT_FALSE(host_impl_->CanDraw());
363 EXPECT_TRUE(on_can_draw_state_changed_called_);
364 on_can_draw_state_changed_called_ = false;
366 host_impl_->active_tree()->ResetContentsTexturesPurged();
367 EXPECT_TRUE(host_impl_->CanDraw());
368 EXPECT_TRUE(on_can_draw_state_changed_called_);
369 on_can_draw_state_changed_called_ = false;
372 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
374 protected:
375 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
376 return FakeOutputSurface::Create3d();
379 void DrawOneFrame() {
380 LayerTreeHostImpl::FrameData frame_data;
381 host_impl_->PrepareToDraw(&frame_data);
382 host_impl_->DidDrawAllLayers(frame_data);
385 FakeProxy proxy_;
386 DebugScopedSetImplThread always_impl_thread_;
387 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
389 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
390 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
391 scoped_ptr<LayerTreeHostImpl> host_impl_;
392 FakeRenderingStatsInstrumentation stats_instrumentation_;
393 bool on_can_draw_state_changed_called_;
394 bool did_notify_ready_to_activate_;
395 bool did_request_commit_;
396 bool did_request_redraw_;
397 bool did_request_animate_;
398 bool did_request_prepare_tiles_;
399 bool reduce_memory_result_;
400 base::Closure scrollbar_fade_start_;
401 base::TimeDelta requested_scrollbar_animation_delay_;
402 size_t current_limit_bytes_;
403 int current_priority_cutoff_value_;
406 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
407 bool always_draw = false;
408 CheckNotifyCalledIfCanDrawChanged(always_draw);
411 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
412 CreateHostImpl(DefaultSettings(),
413 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
415 bool always_draw = true;
416 CheckNotifyCalledIfCanDrawChanged(always_draw);
419 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
420 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
422 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
423 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
426 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
428 scoped_ptr<LayerImpl> root =
429 LayerImpl::Create(host_impl_->active_tree(), 1);
430 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
431 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
432 root->children()[1]->AddChild(
433 LayerImpl::Create(host_impl_->active_tree(), 4));
434 root->children()[1]->AddChild(
435 LayerImpl::Create(host_impl_->active_tree(), 5));
436 root->children()[1]->children()[0]->AddChild(
437 LayerImpl::Create(host_impl_->active_tree(), 6));
438 host_impl_->active_tree()->SetRootLayer(root.Pass());
440 LayerImpl* root = host_impl_->active_tree()->root_layer();
442 ExpectClearedScrollDeltasRecursive(root);
444 scoped_ptr<ScrollAndScaleSet> scroll_info;
446 scroll_info = host_impl_->ProcessScrollDeltas();
447 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
448 ExpectClearedScrollDeltasRecursive(root);
450 scroll_info = host_impl_->ProcessScrollDeltas();
451 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
452 ExpectClearedScrollDeltasRecursive(root);
455 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
456 gfx::ScrollOffset scroll_offset(20, 30);
457 gfx::Vector2d scroll_delta(11, -15);
459 scoped_ptr<LayerImpl> root_clip =
460 LayerImpl::Create(host_impl_->active_tree(), 2);
461 scoped_ptr<LayerImpl> root =
462 LayerImpl::Create(host_impl_->active_tree(), 1);
463 root_clip->SetBounds(gfx::Size(10, 10));
464 LayerImpl* root_layer = root.get();
465 root_clip->AddChild(root.Pass());
466 root_layer->SetBounds(gfx::Size(110, 110));
467 root_layer->SetScrollClipLayer(root_clip->id());
468 root_layer->SetScrollOffset(scroll_offset);
469 root_layer->ScrollBy(scroll_delta);
470 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
472 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
474 scoped_ptr<ScrollAndScaleSet> scroll_info;
476 scroll_info = host_impl_->ProcessScrollDeltas();
477 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
478 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta);
479 ExpectContains(*scroll_info, root->id(), scroll_delta);
481 gfx::Vector2d scroll_delta2(-5, 27);
482 root->ScrollBy(scroll_delta2);
483 scroll_info = host_impl_->ProcessScrollDeltas();
484 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
485 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
486 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
488 root->ScrollBy(gfx::Vector2d());
489 scroll_info = host_impl_->ProcessScrollDeltas();
490 EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
493 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
494 SetupScrollAndContentsLayers(gfx::Size(100, 100));
495 host_impl_->SetViewportSize(gfx::Size(50, 50));
496 DrawFrame();
498 EXPECT_EQ(InputHandler::ScrollStarted,
499 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
500 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
501 InputHandler::Wheel));
502 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
503 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
504 InputHandler::Wheel));
505 host_impl_->ScrollEnd();
506 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
507 InputHandler::Wheel));
508 EXPECT_TRUE(did_request_redraw_);
509 EXPECT_TRUE(did_request_commit_);
512 TEST_F(LayerTreeHostImplTest, ScrollActiveOnlyAfterScrollMovement) {
513 SetupScrollAndContentsLayers(gfx::Size(100, 100));
514 host_impl_->SetViewportSize(gfx::Size(50, 50));
515 DrawFrame();
517 EXPECT_EQ(InputHandler::ScrollStarted,
518 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
519 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
520 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
521 EXPECT_TRUE(host_impl_->IsActivelyScrolling());
522 host_impl_->ScrollEnd();
523 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
526 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
527 // We should not crash when trying to scroll an empty layer tree.
528 EXPECT_EQ(InputHandler::ScrollIgnored,
529 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
532 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
533 scoped_ptr<TestWebGraphicsContext3D> context_owned =
534 TestWebGraphicsContext3D::Create();
535 context_owned->set_context_lost(true);
537 // Initialization will fail.
538 EXPECT_FALSE(CreateHostImpl(
539 DefaultSettings(), FakeOutputSurface::Create3d(context_owned.Pass())));
541 SetupScrollAndContentsLayers(gfx::Size(100, 100));
543 // We should not crash when trying to scroll after the renderer initialization
544 // fails.
545 EXPECT_EQ(InputHandler::ScrollStarted,
546 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
549 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
550 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
551 host_impl_->SetViewportSize(gfx::Size(50, 50));
552 DrawFrame();
554 // We should not crash if the tree is replaced while we are scrolling.
555 EXPECT_EQ(InputHandler::ScrollStarted,
556 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
557 host_impl_->active_tree()->DetachLayerTree();
559 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
561 // We should still be scrolling, because the scrolled layer also exists in the
562 // new tree.
563 gfx::Vector2d scroll_delta(0, 10);
564 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
565 host_impl_->ScrollEnd();
566 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
567 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
570 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
571 SetupScrollAndContentsLayers(gfx::Size(100, 100));
572 host_impl_->SetViewportSize(gfx::Size(50, 50));
573 DrawFrame();
575 // We should be able to scroll even if the root layer loses its render surface
576 // after the most recent render.
577 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
578 host_impl_->active_tree()->set_needs_update_draw_properties();
580 EXPECT_EQ(InputHandler::ScrollStarted,
581 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
584 TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
585 SetupScrollAndContentsLayers(gfx::Size(100, 100));
586 host_impl_->SetViewportSize(gfx::Size(50, 50));
587 DrawFrame();
588 LayerImpl* root = host_impl_->active_tree()->root_layer();
590 root->SetHaveWheelEventHandlers(true);
592 // With registered event handlers, wheel scrolls have to go to the main
593 // thread.
594 EXPECT_EQ(InputHandler::ScrollOnMainThread,
595 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
597 // But gesture scrolls can still be handled.
598 EXPECT_EQ(InputHandler::ScrollStarted,
599 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
602 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
603 SetupScrollAndContentsLayers(gfx::Size(100, 100));
604 host_impl_->SetViewportSize(gfx::Size(50, 50));
605 DrawFrame();
607 // Ignore the fling since no layer is being scrolled
608 EXPECT_EQ(InputHandler::ScrollIgnored,
609 host_impl_->FlingScrollBegin());
611 // Start scrolling a layer
612 EXPECT_EQ(InputHandler::ScrollStarted,
613 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
615 // Now the fling should go ahead since we've started scrolling a layer
616 EXPECT_EQ(InputHandler::ScrollStarted,
617 host_impl_->FlingScrollBegin());
620 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
621 SetupScrollAndContentsLayers(gfx::Size(100, 100));
622 host_impl_->SetViewportSize(gfx::Size(50, 50));
623 DrawFrame();
625 // Ignore the fling since no layer is being scrolled
626 EXPECT_EQ(InputHandler::ScrollIgnored,
627 host_impl_->FlingScrollBegin());
629 // Start scrolling a layer
630 EXPECT_EQ(InputHandler::ScrollStarted,
631 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
633 // Now the fling should go ahead since we've started scrolling a layer
634 EXPECT_EQ(InputHandler::ScrollStarted,
635 host_impl_->FlingScrollBegin());
638 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
639 SetupScrollAndContentsLayers(gfx::Size(100, 100));
640 host_impl_->SetViewportSize(gfx::Size(50, 50));
641 DrawFrame();
642 LayerImpl* root = host_impl_->active_tree()->root_layer();
644 root->SetShouldScrollOnMainThread(true);
646 // Start scrolling a layer
647 EXPECT_EQ(InputHandler::ScrollOnMainThread,
648 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
650 // The fling should be ignored since there's no layer being scrolled impl-side
651 EXPECT_EQ(InputHandler::ScrollIgnored,
652 host_impl_->FlingScrollBegin());
655 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
656 SetupScrollAndContentsLayers(gfx::Size(100, 100));
657 host_impl_->SetViewportSize(gfx::Size(50, 50));
658 DrawFrame();
659 LayerImpl* root = host_impl_->active_tree()->root_layer();
661 root->SetShouldScrollOnMainThread(true);
663 EXPECT_EQ(InputHandler::ScrollOnMainThread,
664 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
665 EXPECT_EQ(InputHandler::ScrollOnMainThread,
666 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
669 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
670 SetupScrollAndContentsLayers(gfx::Size(200, 200));
671 host_impl_->SetViewportSize(gfx::Size(100, 100));
673 LayerImpl* root = host_impl_->active_tree()->root_layer();
674 root->SetContentsScale(2.f, 2.f);
675 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
677 DrawFrame();
679 // All scroll types inside the non-fast scrollable region should fail.
680 EXPECT_EQ(InputHandler::ScrollOnMainThread,
681 host_impl_->ScrollBegin(gfx::Point(25, 25),
682 InputHandler::Wheel));
683 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
684 InputHandler::Wheel));
685 EXPECT_EQ(InputHandler::ScrollOnMainThread,
686 host_impl_->ScrollBegin(gfx::Point(25, 25),
687 InputHandler::Gesture));
688 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
689 InputHandler::Gesture));
691 // All scroll types outside this region should succeed.
692 EXPECT_EQ(InputHandler::ScrollStarted,
693 host_impl_->ScrollBegin(gfx::Point(75, 75),
694 InputHandler::Wheel));
695 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
696 InputHandler::Gesture));
697 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
698 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
699 InputHandler::Gesture));
700 host_impl_->ScrollEnd();
701 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
702 InputHandler::Gesture));
703 EXPECT_EQ(InputHandler::ScrollStarted,
704 host_impl_->ScrollBegin(gfx::Point(75, 75),
705 InputHandler::Gesture));
706 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
707 InputHandler::Gesture));
708 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
709 host_impl_->ScrollEnd();
710 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
711 InputHandler::Gesture));
714 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
715 SetupScrollAndContentsLayers(gfx::Size(200, 200));
716 host_impl_->SetViewportSize(gfx::Size(100, 100));
718 LayerImpl* root = host_impl_->active_tree()->root_layer();
719 root->SetContentsScale(2.f, 2.f);
720 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
721 root->SetPosition(gfx::PointF(-25.f, 0.f));
723 DrawFrame();
725 // This point would fall into the non-fast scrollable region except that we've
726 // moved the layer down by 25 pixels.
727 EXPECT_EQ(InputHandler::ScrollStarted,
728 host_impl_->ScrollBegin(gfx::Point(40, 10),
729 InputHandler::Wheel));
730 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
731 InputHandler::Wheel));
732 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
733 host_impl_->ScrollEnd();
735 // This point is still inside the non-fast region.
736 EXPECT_EQ(InputHandler::ScrollOnMainThread,
737 host_impl_->ScrollBegin(gfx::Point(10, 10),
738 InputHandler::Wheel));
741 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
742 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
743 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
744 host_impl_->SetViewportSize(gfx::Size(50, 50));
745 DrawFrame();
747 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
748 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
749 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
750 host_impl_->ScrollEnd();
751 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
754 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
755 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
756 scroll_layer->SetHaveScrollEventHandlers(true);
757 host_impl_->SetViewportSize(gfx::Size(50, 50));
758 DrawFrame();
760 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
761 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
762 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
763 host_impl_->ScrollEnd();
764 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
767 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
768 SetupScrollAndContentsLayers(gfx::Size(200, 200));
769 host_impl_->SetViewportSize(gfx::Size(100, 100));
771 DrawFrame();
773 EXPECT_EQ(InputHandler::ScrollStarted,
774 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
776 // Trying to scroll to the left/top will not succeed.
777 EXPECT_FALSE(
778 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
779 EXPECT_FALSE(
780 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
781 EXPECT_FALSE(
782 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
784 // Scrolling to the right/bottom will succeed.
785 EXPECT_TRUE(
786 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll);
787 EXPECT_TRUE(
788 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
789 EXPECT_TRUE(
790 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll);
792 // Scrolling to left/top will now succeed.
793 EXPECT_TRUE(
794 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
795 EXPECT_TRUE(
796 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
797 EXPECT_TRUE(
798 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
800 // Scrolling diagonally against an edge will succeed.
801 EXPECT_TRUE(
802 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll);
803 EXPECT_TRUE(
804 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
805 EXPECT_TRUE(
806 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll);
808 // Trying to scroll more than the available space will also succeed.
809 EXPECT_TRUE(
810 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll);
813 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
814 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
815 host_impl_->SetViewportSize(gfx::Size(100, 1000));
817 DrawFrame();
819 EXPECT_EQ(InputHandler::ScrollStarted,
820 host_impl_->ScrollBegin(gfx::Point(),
821 InputHandler::Wheel));
823 // Trying to scroll without a vertical scrollbar will fail.
824 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
825 gfx::Point(), SCROLL_FORWARD));
826 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
827 gfx::Point(), SCROLL_BACKWARD));
829 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
830 PaintedScrollbarLayerImpl::Create(
831 host_impl_->active_tree(),
833 VERTICAL));
834 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
835 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
836 vertical_scrollbar.get());
838 // Trying to scroll with a vertical scrollbar will succeed.
839 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
840 gfx::Point(), SCROLL_FORWARD));
841 EXPECT_FLOAT_EQ(875.f,
842 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
843 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
844 gfx::Point(), SCROLL_BACKWARD));
847 TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
848 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
849 host_impl_->SetViewportSize(gfx::Size(100, 100));
851 gfx::Size overflow_size(400, 400);
852 ASSERT_EQ(1u, scroll_layer->children().size());
853 LayerImpl* overflow = scroll_layer->children()[0];
854 overflow->SetBounds(overflow_size);
855 overflow->SetContentBounds(overflow_size);
856 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
857 overflow->SetScrollOffset(gfx::ScrollOffset());
858 overflow->SetPosition(gfx::PointF());
860 DrawFrame();
861 gfx::Point scroll_position(10, 10);
863 EXPECT_EQ(InputHandler::ScrollStarted,
864 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
865 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
866 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->TotalScrollOffset());
868 gfx::Vector2dF scroll_delta(10, 10);
869 host_impl_->ScrollBy(scroll_position, scroll_delta);
870 host_impl_->ScrollEnd();
871 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
872 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
874 overflow->set_user_scrollable_horizontal(false);
876 EXPECT_EQ(InputHandler::ScrollStarted,
877 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
878 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
879 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
881 host_impl_->ScrollBy(scroll_position, scroll_delta);
882 host_impl_->ScrollEnd();
883 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
884 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
886 overflow->set_user_scrollable_vertical(false);
888 EXPECT_EQ(InputHandler::ScrollStarted,
889 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
890 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
891 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
893 host_impl_->ScrollBy(scroll_position, scroll_delta);
894 host_impl_->ScrollEnd();
895 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->TotalScrollOffset());
896 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
899 TEST_F(LayerTreeHostImplTest,
900 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
901 SetupScrollAndContentsLayers(gfx::Size(100, 100));
902 host_impl_->SetViewportSize(gfx::Size(50, 50));
903 DrawFrame();
905 // We should be able to hit test for touch event handlers even if the root
906 // layer loses its render surface after the most recent render.
907 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
908 host_impl_->active_tree()->set_needs_update_draw_properties();
910 EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
913 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
914 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
915 host_impl_->SetViewportSize(gfx::Size(50, 50));
916 DrawFrame();
918 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
919 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
920 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
922 float min_page_scale = 1.f, max_page_scale = 4.f;
923 float page_scale_factor = 1.f;
925 // The impl-based pinch zoom should adjust the max scroll position.
927 host_impl_->active_tree()->PushPageScaleFromMainThread(
928 page_scale_factor, min_page_scale, max_page_scale);
929 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
930 scroll_layer->SetScrollDelta(gfx::Vector2d());
932 float page_scale_delta = 2.f;
934 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
935 host_impl_->PinchGestureBegin();
936 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
937 host_impl_->PinchGestureEnd();
938 host_impl_->ScrollEnd();
939 EXPECT_FALSE(did_request_animate_);
940 EXPECT_TRUE(did_request_redraw_);
941 EXPECT_TRUE(did_request_commit_);
942 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
944 scoped_ptr<ScrollAndScaleSet> scroll_info =
945 host_impl_->ProcessScrollDeltas();
946 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
948 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
949 scroll_layer->MaxScrollOffset().ToString());
952 // Scrolling after a pinch gesture should always be in local space. The
953 // scroll deltas have the page scale factor applied.
955 host_impl_->active_tree()->PushPageScaleFromMainThread(
956 page_scale_factor, min_page_scale, max_page_scale);
957 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
958 scroll_layer->SetScrollDelta(gfx::Vector2d());
960 float page_scale_delta = 2.f;
961 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
962 host_impl_->PinchGestureBegin();
963 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
964 host_impl_->PinchGestureEnd();
965 host_impl_->ScrollEnd();
967 gfx::Vector2d scroll_delta(0, 10);
968 EXPECT_EQ(InputHandler::ScrollStarted,
969 host_impl_->ScrollBegin(gfx::Point(5, 5),
970 InputHandler::Wheel));
971 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
972 host_impl_->ScrollEnd();
974 scoped_ptr<ScrollAndScaleSet> scroll_info =
975 host_impl_->ProcessScrollDeltas();
976 ExpectContains(*scroll_info.get(), scroll_layer->id(),
977 gfx::Vector2d(0, scroll_delta.y() / page_scale_delta));
981 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
982 ui::LatencyInfo latency_info;
983 latency_info.trace_id = 1234;
984 scoped_ptr<SwapPromise> swap_promise(
985 new LatencyInfoSwapPromise(latency_info));
987 SetupScrollAndContentsLayers(gfx::Size(100, 100));
988 EXPECT_EQ(InputHandler::ScrollStarted,
989 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
990 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
991 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
992 host_impl_->ScrollEnd();
994 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
995 EXPECT_EQ(1u, scroll_info->swap_promises.size());
996 EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId());
999 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1000 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1001 host_impl_->SetViewportSize(gfx::Size(50, 50));
1002 DrawFrame();
1004 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1005 DCHECK(scroll_layer);
1007 float min_page_scale = 1.f;
1008 float max_page_scale = 4.f;
1010 // Basic pinch zoom in gesture
1012 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1013 max_page_scale);
1014 scroll_layer->SetScrollDelta(gfx::Vector2d());
1016 float page_scale_delta = 2.f;
1017 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1018 host_impl_->PinchGestureBegin();
1019 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1020 host_impl_->PinchGestureEnd();
1021 host_impl_->ScrollEnd();
1022 EXPECT_FALSE(did_request_animate_);
1023 EXPECT_TRUE(did_request_redraw_);
1024 EXPECT_TRUE(did_request_commit_);
1026 scoped_ptr<ScrollAndScaleSet> scroll_info =
1027 host_impl_->ProcessScrollDeltas();
1028 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1031 // Zoom-in clamping
1033 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1034 max_page_scale);
1035 scroll_layer->SetScrollDelta(gfx::Vector2d());
1036 float page_scale_delta = 10.f;
1038 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1039 host_impl_->PinchGestureBegin();
1040 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1041 host_impl_->PinchGestureEnd();
1042 host_impl_->ScrollEnd();
1044 scoped_ptr<ScrollAndScaleSet> scroll_info =
1045 host_impl_->ProcessScrollDeltas();
1046 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1049 // Zoom-out clamping
1051 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1052 max_page_scale);
1053 scroll_layer->SetScrollDelta(gfx::Vector2d());
1054 scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
1056 float page_scale_delta = 0.1f;
1057 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1058 host_impl_->PinchGestureBegin();
1059 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1060 host_impl_->PinchGestureEnd();
1061 host_impl_->ScrollEnd();
1063 scoped_ptr<ScrollAndScaleSet> scroll_info =
1064 host_impl_->ProcessScrollDeltas();
1065 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1067 EXPECT_TRUE(scroll_info->scrolls.empty());
1070 // Two-finger panning should not happen based on pinch events only
1072 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1073 max_page_scale);
1074 scroll_layer->SetScrollDelta(gfx::Vector2d());
1075 scroll_layer->SetScrollOffset(gfx::ScrollOffset(20, 20));
1077 float page_scale_delta = 1.f;
1078 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1079 host_impl_->PinchGestureBegin();
1080 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1081 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1082 host_impl_->PinchGestureEnd();
1083 host_impl_->ScrollEnd();
1085 scoped_ptr<ScrollAndScaleSet> scroll_info =
1086 host_impl_->ProcessScrollDeltas();
1087 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1088 EXPECT_TRUE(scroll_info->scrolls.empty());
1091 // Two-finger panning should work with interleaved scroll events
1093 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1094 max_page_scale);
1095 scroll_layer->SetScrollDelta(gfx::Vector2d());
1096 scroll_layer->SetScrollOffset(gfx::ScrollOffset(20, 20));
1098 float page_scale_delta = 1.f;
1099 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1100 host_impl_->PinchGestureBegin();
1101 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1102 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1103 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1104 host_impl_->PinchGestureEnd();
1105 host_impl_->ScrollEnd();
1107 scoped_ptr<ScrollAndScaleSet> scroll_info =
1108 host_impl_->ProcessScrollDeltas();
1109 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1110 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1113 // Two-finger panning should work when starting fully zoomed out.
1115 host_impl_->active_tree()->PushPageScaleFromMainThread(0.5f, 0.5f, 4.f);
1116 scroll_layer->SetScrollDelta(gfx::Vector2d());
1117 scroll_layer->SetScrollOffset(gfx::ScrollOffset(0, 0));
1119 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
1120 host_impl_->PinchGestureBegin();
1121 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1122 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1123 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1124 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1125 host_impl_->PinchGestureEnd();
1126 host_impl_->ScrollEnd();
1128 scoped_ptr<ScrollAndScaleSet> scroll_info =
1129 host_impl_->ProcessScrollDeltas();
1130 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1131 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1135 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1136 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1137 host_impl_->SetViewportSize(gfx::Size(50, 50));
1138 DrawFrame();
1140 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1141 DCHECK(scroll_layer);
1143 float min_page_scale = 0.5f;
1144 float max_page_scale = 4.f;
1145 base::TimeTicks start_time = base::TimeTicks() +
1146 base::TimeDelta::FromSeconds(1);
1147 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1148 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1149 base::TimeTicks end_time = start_time + duration;
1151 // Non-anchor zoom-in
1153 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1154 max_page_scale);
1155 scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
1157 did_request_redraw_ = false;
1158 did_request_animate_ = false;
1159 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1160 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1161 gfx::Vector2d(),
1162 false,
1163 2.f,
1164 duration)));
1165 host_impl_->ActivateSyncTree();
1166 EXPECT_FALSE(did_request_redraw_);
1167 EXPECT_TRUE(did_request_animate_);
1169 did_request_redraw_ = false;
1170 did_request_animate_ = false;
1171 host_impl_->Animate(start_time);
1172 EXPECT_TRUE(did_request_redraw_);
1173 EXPECT_TRUE(did_request_animate_);
1175 did_request_redraw_ = false;
1176 did_request_animate_ = false;
1177 host_impl_->Animate(halfway_through_animation);
1178 EXPECT_TRUE(did_request_redraw_);
1179 EXPECT_TRUE(did_request_animate_);
1181 did_request_redraw_ = false;
1182 did_request_animate_ = false;
1183 did_request_commit_ = false;
1184 host_impl_->Animate(end_time);
1185 EXPECT_TRUE(did_request_commit_);
1186 EXPECT_FALSE(did_request_animate_);
1188 scoped_ptr<ScrollAndScaleSet> scroll_info =
1189 host_impl_->ProcessScrollDeltas();
1190 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1191 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1194 // Anchor zoom-out
1196 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1197 max_page_scale);
1198 scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
1200 did_request_redraw_ = false;
1201 did_request_animate_ = false;
1202 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1203 scoped_ptr<PendingPageScaleAnimation> (new PendingPageScaleAnimation(
1204 gfx::Vector2d(25, 25),
1205 true,
1206 min_page_scale,
1207 duration)));
1208 host_impl_->ActivateSyncTree();
1209 EXPECT_FALSE(did_request_redraw_);
1210 EXPECT_TRUE(did_request_animate_);
1212 did_request_redraw_ = false;
1213 did_request_animate_ = false;
1214 host_impl_->Animate(start_time);
1215 EXPECT_TRUE(did_request_redraw_);
1216 EXPECT_TRUE(did_request_animate_);
1218 did_request_redraw_ = false;
1219 did_request_commit_ = false;
1220 did_request_animate_ = false;
1221 host_impl_->Animate(end_time);
1222 EXPECT_TRUE(did_request_redraw_);
1223 EXPECT_FALSE(did_request_animate_);
1224 EXPECT_TRUE(did_request_commit_);
1226 scoped_ptr<ScrollAndScaleSet> scroll_info =
1227 host_impl_->ProcessScrollDeltas();
1228 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1229 // Pushed to (0,0) via clamping against contents layer size.
1230 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1234 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1235 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1236 host_impl_->SetViewportSize(gfx::Size(50, 50));
1237 DrawFrame();
1239 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1240 DCHECK(scroll_layer);
1242 float min_page_scale = 0.5f;
1243 float max_page_scale = 4.f;
1244 base::TimeTicks start_time = base::TimeTicks() +
1245 base::TimeDelta::FromSeconds(1);
1246 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1247 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1248 base::TimeTicks end_time = start_time + duration;
1250 // Anchor zoom with unchanged page scale should not change scroll or scale.
1252 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1253 max_page_scale);
1254 scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
1256 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1257 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1258 gfx::Vector2d(),
1259 true,
1260 1.f,
1261 duration)));
1262 host_impl_->ActivateSyncTree();
1263 host_impl_->Animate(start_time);
1264 host_impl_->Animate(halfway_through_animation);
1265 EXPECT_TRUE(did_request_redraw_);
1266 host_impl_->Animate(end_time);
1267 EXPECT_TRUE(did_request_commit_);
1269 scoped_ptr<ScrollAndScaleSet> scroll_info =
1270 host_impl_->ProcessScrollDeltas();
1271 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1272 ExpectNone(*scroll_info, scroll_layer->id());
1276 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
1277 host_impl_->CreatePendingTree();
1278 CreateScrollAndContentsLayers(
1279 host_impl_->pending_tree(),
1280 gfx::Size(100, 100));
1281 host_impl_->ActivateSyncTree();
1282 DrawFrame();
1284 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1285 DCHECK(scroll_layer);
1287 float min_page_scale = 0.5f;
1288 float max_page_scale = 4.f;
1289 host_impl_->sync_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1290 max_page_scale);
1291 host_impl_->ActivateSyncTree();
1293 base::TimeTicks start_time = base::TimeTicks() +
1294 base::TimeDelta::FromSeconds(1);
1295 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1296 base::TimeTicks third_through_animation = start_time + duration / 3;
1297 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1298 base::TimeTicks end_time = start_time + duration;
1299 float target_scale = 2.f;
1301 scroll_layer->SetScrollOffset(gfx::ScrollOffset(50, 50));
1303 // Make sure TakePageScaleAnimation works properly.
1305 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1306 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1307 gfx::Vector2d(),
1308 false,
1309 target_scale,
1310 duration)));
1311 scoped_ptr<PendingPageScaleAnimation> psa =
1312 host_impl_->sync_tree()->TakePendingPageScaleAnimation();
1313 EXPECT_EQ(target_scale, psa->scale);
1314 EXPECT_EQ(duration, psa->duration);
1315 EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePendingPageScaleAnimation());
1317 // Recreate the PSA. Nothing should happen here since the tree containing the
1318 // PSA hasn't been activated yet.
1319 did_request_redraw_ = false;
1320 did_request_animate_ = false;
1321 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1322 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1323 gfx::Vector2d(),
1324 false,
1325 target_scale,
1326 duration)));
1327 host_impl_->Animate(halfway_through_animation);
1328 EXPECT_FALSE(did_request_animate_);
1329 EXPECT_FALSE(did_request_redraw_);
1331 // Activate the sync tree. This should cause the animation to become enabled.
1332 // It should also clear the pointer on the sync tree.
1333 host_impl_->ActivateSyncTree();
1334 EXPECT_EQ(nullptr,
1335 host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
1336 EXPECT_FALSE(did_request_redraw_);
1337 EXPECT_TRUE(did_request_animate_);
1339 // From here on, make sure the animation runs as normal.
1340 did_request_redraw_ = false;
1341 did_request_animate_ = false;
1342 host_impl_->Animate(start_time);
1343 EXPECT_TRUE(did_request_redraw_);
1344 EXPECT_TRUE(did_request_animate_);
1346 did_request_redraw_ = false;
1347 did_request_animate_ = false;
1348 host_impl_->Animate(third_through_animation);
1349 EXPECT_TRUE(did_request_redraw_);
1350 EXPECT_TRUE(did_request_animate_);
1352 // Another activation shouldn't have any effect on the animation.
1353 host_impl_->ActivateSyncTree();
1355 did_request_redraw_ = false;
1356 did_request_animate_ = false;
1357 host_impl_->Animate(halfway_through_animation);
1358 EXPECT_TRUE(did_request_redraw_);
1359 EXPECT_TRUE(did_request_animate_);
1361 did_request_redraw_ = false;
1362 did_request_animate_ = false;
1363 did_request_commit_ = false;
1364 host_impl_->Animate(end_time);
1365 EXPECT_TRUE(did_request_commit_);
1366 EXPECT_FALSE(did_request_animate_);
1368 scoped_ptr<ScrollAndScaleSet> scroll_info =
1369 host_impl_->ProcessScrollDeltas();
1370 EXPECT_EQ(scroll_info->page_scale_delta, target_scale);
1371 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1374 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1375 public:
1376 LayerTreeHostImplOverridePhysicalTime(
1377 const LayerTreeSettings& settings,
1378 LayerTreeHostImplClient* client,
1379 Proxy* proxy,
1380 SharedBitmapManager* manager,
1381 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1382 : LayerTreeHostImpl(settings,
1383 client,
1384 proxy,
1385 rendering_stats_instrumentation,
1386 manager,
1387 NULL,
1388 0) {}
1390 BeginFrameArgs CurrentBeginFrameArgs() const override {
1391 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
1392 fake_current_physical_time_);
1395 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1396 fake_current_physical_time_ = fake_now;
1399 private:
1400 base::TimeTicks fake_current_physical_time_;
1403 #define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST() \
1404 gfx::Size viewport_size(10, 10); \
1405 gfx::Size content_size(100, 100); \
1407 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = \
1408 new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_, \
1409 shared_bitmap_manager_.get(), \
1410 &stats_instrumentation_); \
1411 host_impl_ = make_scoped_ptr(host_impl_override_time); \
1412 host_impl_->InitializeRenderer(CreateOutputSurface()); \
1413 host_impl_->SetViewportSize(viewport_size); \
1415 scoped_ptr<LayerImpl> root = \
1416 LayerImpl::Create(host_impl_->active_tree(), 1); \
1417 root->SetBounds(viewport_size); \
1419 scoped_ptr<LayerImpl> scroll = \
1420 LayerImpl::Create(host_impl_->active_tree(), 2); \
1421 scroll->SetScrollClipLayer(root->id()); \
1422 scroll->SetScrollOffset(gfx::ScrollOffset()); \
1423 root->SetBounds(viewport_size); \
1424 scroll->SetBounds(content_size); \
1425 scroll->SetContentBounds(content_size); \
1426 scroll->SetIsContainerForFixedPositionLayers(true); \
1428 scoped_ptr<LayerImpl> contents = \
1429 LayerImpl::Create(host_impl_->active_tree(), 3); \
1430 contents->SetDrawsContent(true); \
1431 contents->SetBounds(content_size); \
1432 contents->SetContentBounds(content_size); \
1434 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = \
1435 SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4, \
1436 VERTICAL, 10, 0, false, true); \
1437 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); \
1439 scroll->AddChild(contents.Pass()); \
1440 root->AddChild(scroll.Pass()); \
1441 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1); \
1442 root->AddChild(scrollbar.Pass()); \
1444 host_impl_->active_tree()->SetRootLayer(root.Pass()); \
1445 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2, \
1446 Layer::INVALID_ID); \
1447 host_impl_->active_tree()->DidBecomeActive(); \
1448 DrawFrame();
1450 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1451 LayerTreeSettings settings;
1452 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1453 settings.scrollbar_fade_delay_ms = 20;
1454 settings.scrollbar_fade_duration_ms = 20;
1456 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1458 base::TimeTicks fake_now = gfx::FrameTime::Now();
1460 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1461 EXPECT_FALSE(did_request_redraw_);
1463 // If no scroll happened during a scroll gesture, it should have no effect.
1464 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1465 host_impl_->ScrollEnd();
1466 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1467 EXPECT_FALSE(did_request_redraw_);
1468 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1470 // After a scroll, a fade animation should be scheduled about 20ms from now.
1471 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1472 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1473 host_impl_->ScrollEnd();
1474 did_request_redraw_ = false;
1475 did_request_animate_ = false;
1476 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1477 requested_scrollbar_animation_delay_);
1478 EXPECT_FALSE(did_request_redraw_);
1479 EXPECT_FALSE(did_request_animate_);
1480 requested_scrollbar_animation_delay_ = base::TimeDelta();
1481 scrollbar_fade_start_.Run();
1482 host_impl_->Animate(fake_now);
1484 // After the fade begins, we should start getting redraws instead of a
1485 // scheduled animation.
1486 fake_now += base::TimeDelta::FromMilliseconds(25);
1487 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1488 EXPECT_TRUE(did_request_animate_);
1489 did_request_animate_ = false;
1491 // Setting the scroll offset outside a scroll should also cause the scrollbar
1492 // to appear and to schedule a fade.
1493 host_impl_->InnerViewportScrollLayer()->SetScrollOffset(
1494 gfx::ScrollOffset(5, 5));
1495 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1496 requested_scrollbar_animation_delay_);
1497 EXPECT_FALSE(did_request_redraw_);
1498 EXPECT_FALSE(did_request_animate_);
1499 requested_scrollbar_animation_delay_ = base::TimeDelta();
1501 // Unnecessarily Fade animation of solid color scrollbar is not triggered.
1502 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1503 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1504 host_impl_->ScrollEnd();
1505 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1508 TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) {
1509 LayerTreeSettings settings;
1510 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1511 settings.scrollbar_fade_delay_ms = 20;
1512 settings.scrollbar_fade_duration_ms = 20;
1513 settings.use_pinch_zoom_scrollbars = true;
1515 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1517 base::TimeTicks fake_now = gfx::FrameTime::Now();
1519 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
1521 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1522 EXPECT_FALSE(did_request_animate_);
1524 // If no scroll happened during a scroll gesture, it should have no effect.
1525 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1526 host_impl_->ScrollEnd();
1527 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1528 EXPECT_FALSE(did_request_animate_);
1529 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1531 // After a scroll, no fade animation should be scheduled.
1532 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1533 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1534 host_impl_->ScrollEnd();
1535 did_request_redraw_ = false;
1536 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1537 EXPECT_FALSE(did_request_animate_);
1538 requested_scrollbar_animation_delay_ = base::TimeDelta();
1540 // We should not see any draw requests.
1541 fake_now += base::TimeDelta::FromMilliseconds(25);
1542 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1543 EXPECT_FALSE(did_request_animate_);
1545 // Make page scale > min so that subsequent scrolls will trigger fades.
1546 host_impl_->SetPageScaleOnActiveTree(1.1f);
1548 // After a scroll, a fade animation should be scheduled about 20ms from now.
1549 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1550 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1551 host_impl_->ScrollEnd();
1552 did_request_redraw_ = false;
1553 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1554 requested_scrollbar_animation_delay_);
1555 EXPECT_FALSE(did_request_animate_);
1556 requested_scrollbar_animation_delay_ = base::TimeDelta();
1557 scrollbar_fade_start_.Run();
1559 // After the fade begins, we should start getting redraws instead of a
1560 // scheduled animation.
1561 fake_now += base::TimeDelta::FromMilliseconds(25);
1562 host_impl_->Animate(fake_now);
1563 EXPECT_TRUE(did_request_animate_);
1566 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1567 float device_scale_factor) {
1568 LayerTreeSettings settings;
1569 settings.scrollbar_fade_delay_ms = 500;
1570 settings.scrollbar_fade_duration_ms = 300;
1571 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1573 gfx::Size viewport_size(300, 200);
1574 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1575 gfx::ScaleSize(viewport_size, device_scale_factor));
1576 gfx::Size content_size(1000, 1000);
1578 CreateHostImpl(settings, CreateOutputSurface());
1579 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1580 host_impl_->SetViewportSize(device_viewport_size);
1582 scoped_ptr<LayerImpl> root =
1583 LayerImpl::Create(host_impl_->active_tree(), 1);
1584 root->SetBounds(viewport_size);
1586 scoped_ptr<LayerImpl> scroll =
1587 LayerImpl::Create(host_impl_->active_tree(), 2);
1588 scroll->SetScrollClipLayer(root->id());
1589 scroll->SetScrollOffset(gfx::ScrollOffset());
1590 scroll->SetBounds(content_size);
1591 scroll->SetContentBounds(content_size);
1592 scroll->SetIsContainerForFixedPositionLayers(true);
1594 scoped_ptr<LayerImpl> contents =
1595 LayerImpl::Create(host_impl_->active_tree(), 3);
1596 contents->SetDrawsContent(true);
1597 contents->SetBounds(content_size);
1598 contents->SetContentBounds(content_size);
1600 // The scrollbar is on the right side.
1601 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1602 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1603 scrollbar->SetDrawsContent(true);
1604 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1605 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1606 scrollbar->SetPosition(gfx::Point(285, 0));
1608 scroll->AddChild(contents.Pass());
1609 root->AddChild(scroll.Pass());
1610 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1611 root->AddChild(scrollbar.Pass());
1613 host_impl_->active_tree()->SetRootLayer(root.Pass());
1614 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
1615 Layer::INVALID_ID);
1616 host_impl_->active_tree()->DidBecomeActive();
1617 DrawFrame();
1619 LayerImpl* root_scroll =
1620 host_impl_->active_tree()->InnerViewportScrollLayer();
1621 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1622 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1623 static_cast<ScrollbarAnimationControllerThinning*>(
1624 root_scroll->scrollbar_animation_controller());
1625 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1627 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1628 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1630 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1631 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1633 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1634 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1636 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1637 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1638 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1640 did_request_redraw_ = false;
1641 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1642 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1643 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1644 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1645 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1646 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1647 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1650 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1651 SetupMouseMoveAtWithDeviceScale(1.f);
1654 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1655 SetupMouseMoveAtWithDeviceScale(2.f);
1658 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1659 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1660 host_impl_->SetViewportSize(gfx::Size(50, 50));
1661 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
1662 DrawFrame();
1664 CompositorFrameMetadata metadata =
1665 host_impl_->MakeCompositorFrameMetadata();
1666 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1667 EXPECT_EQ(1.f, metadata.page_scale_factor);
1668 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
1669 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1670 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1671 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1674 // Scrolling should update metadata immediately.
1675 EXPECT_EQ(InputHandler::ScrollStarted,
1676 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1677 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1679 CompositorFrameMetadata metadata =
1680 host_impl_->MakeCompositorFrameMetadata();
1681 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1683 host_impl_->ScrollEnd();
1685 CompositorFrameMetadata metadata =
1686 host_impl_->MakeCompositorFrameMetadata();
1687 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1690 // Page scale should update metadata correctly (shrinking only the viewport).
1691 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1692 host_impl_->PinchGestureBegin();
1693 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1694 host_impl_->PinchGestureEnd();
1695 host_impl_->ScrollEnd();
1697 CompositorFrameMetadata metadata =
1698 host_impl_->MakeCompositorFrameMetadata();
1699 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1700 EXPECT_EQ(2.f, metadata.page_scale_factor);
1701 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
1702 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1703 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1704 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1707 // Likewise if set from the main thread.
1708 host_impl_->ProcessScrollDeltas();
1709 host_impl_->active_tree()->PushPageScaleFromMainThread(4.f, 0.5f, 4.f);
1710 host_impl_->SetPageScaleOnActiveTree(4.f);
1712 CompositorFrameMetadata metadata =
1713 host_impl_->MakeCompositorFrameMetadata();
1714 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1715 EXPECT_EQ(4.f, metadata.page_scale_factor);
1716 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
1717 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1718 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1719 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1723 class DidDrawCheckLayer : public LayerImpl {
1724 public:
1725 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1726 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl, id));
1729 bool WillDraw(DrawMode draw_mode, ResourceProvider* provider) override {
1730 will_draw_called_ = true;
1731 if (will_draw_returns_false_)
1732 return false;
1733 return LayerImpl::WillDraw(draw_mode, provider);
1736 void AppendQuads(RenderPass* render_pass,
1737 const Occlusion& occlusion_in_content_space,
1738 AppendQuadsData* append_quads_data) override {
1739 append_quads_called_ = true;
1740 LayerImpl::AppendQuads(
1741 render_pass, occlusion_in_content_space, append_quads_data);
1744 void DidDraw(ResourceProvider* provider) override {
1745 did_draw_called_ = true;
1746 LayerImpl::DidDraw(provider);
1749 bool will_draw_called() const { return will_draw_called_; }
1750 bool append_quads_called() const { return append_quads_called_; }
1751 bool did_draw_called() const { return did_draw_called_; }
1753 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1755 void ClearDidDrawCheck() {
1756 will_draw_called_ = false;
1757 append_quads_called_ = false;
1758 did_draw_called_ = false;
1761 protected:
1762 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1763 : LayerImpl(tree_impl, id),
1764 will_draw_returns_false_(false),
1765 will_draw_called_(false),
1766 append_quads_called_(false),
1767 did_draw_called_(false) {
1768 SetBounds(gfx::Size(10, 10));
1769 SetContentBounds(gfx::Size(10, 10));
1770 SetDrawsContent(true);
1771 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1774 private:
1775 bool will_draw_returns_false_;
1776 bool will_draw_called_;
1777 bool append_quads_called_;
1778 bool did_draw_called_;
1781 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1782 // The root layer is always drawn, so run this test on a child layer that
1783 // will be masked out by the root layer's bounds.
1784 host_impl_->active_tree()->SetRootLayer(
1785 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1786 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1787 host_impl_->active_tree()->root_layer());
1789 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1790 DidDrawCheckLayer* layer =
1791 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1794 LayerTreeHostImpl::FrameData frame;
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->append_quads_called());
1801 EXPECT_TRUE(layer->did_draw_called());
1804 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
1807 LayerTreeHostImpl::FrameData frame;
1809 layer->set_will_draw_returns_false();
1810 layer->ClearDidDrawCheck();
1812 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1813 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1814 host_impl_->DidDrawAllLayers(frame);
1816 EXPECT_TRUE(layer->will_draw_called());
1817 EXPECT_FALSE(layer->append_quads_called());
1818 EXPECT_FALSE(layer->did_draw_called());
1822 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1823 // The root layer is always drawn, so run this test on a child layer that
1824 // will be masked out by the root layer's bounds.
1825 host_impl_->active_tree()->SetRootLayer(
1826 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1827 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1828 host_impl_->active_tree()->root_layer());
1829 root->SetMasksToBounds(true);
1831 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1832 DidDrawCheckLayer* layer =
1833 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1834 // Ensure visible_content_rect for layer is empty.
1835 layer->SetPosition(gfx::PointF(100.f, 100.f));
1836 layer->SetBounds(gfx::Size(10, 10));
1837 layer->SetContentBounds(gfx::Size(10, 10));
1839 LayerTreeHostImpl::FrameData frame;
1841 EXPECT_FALSE(layer->will_draw_called());
1842 EXPECT_FALSE(layer->did_draw_called());
1844 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1845 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1846 host_impl_->DidDrawAllLayers(frame);
1848 EXPECT_FALSE(layer->will_draw_called());
1849 EXPECT_FALSE(layer->did_draw_called());
1851 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1853 // Ensure visible_content_rect for layer is not empty
1854 layer->SetPosition(gfx::PointF());
1856 EXPECT_FALSE(layer->will_draw_called());
1857 EXPECT_FALSE(layer->did_draw_called());
1859 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1860 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1861 host_impl_->DidDrawAllLayers(frame);
1863 EXPECT_TRUE(layer->will_draw_called());
1864 EXPECT_TRUE(layer->did_draw_called());
1866 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1869 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1870 gfx::Size big_size(1000, 1000);
1871 host_impl_->SetViewportSize(big_size);
1873 host_impl_->active_tree()->SetRootLayer(
1874 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1875 DidDrawCheckLayer* root =
1876 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1878 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1879 DidDrawCheckLayer* occluded_layer =
1880 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1882 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1883 DidDrawCheckLayer* top_layer =
1884 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1885 // This layer covers the occluded_layer above. Make this layer large so it can
1886 // occlude.
1887 top_layer->SetBounds(big_size);
1888 top_layer->SetContentBounds(big_size);
1889 top_layer->SetContentsOpaque(true);
1891 LayerTreeHostImpl::FrameData frame;
1893 EXPECT_FALSE(occluded_layer->will_draw_called());
1894 EXPECT_FALSE(occluded_layer->did_draw_called());
1895 EXPECT_FALSE(top_layer->will_draw_called());
1896 EXPECT_FALSE(top_layer->did_draw_called());
1898 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1899 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1900 host_impl_->DidDrawAllLayers(frame);
1902 EXPECT_FALSE(occluded_layer->will_draw_called());
1903 EXPECT_FALSE(occluded_layer->did_draw_called());
1904 EXPECT_TRUE(top_layer->will_draw_called());
1905 EXPECT_TRUE(top_layer->did_draw_called());
1908 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1909 host_impl_->active_tree()->SetRootLayer(
1910 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1911 DidDrawCheckLayer* root =
1912 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1914 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1915 DidDrawCheckLayer* layer1 =
1916 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1918 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1919 DidDrawCheckLayer* layer2 =
1920 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1922 layer1->SetOpacity(0.3f);
1923 layer1->SetShouldFlattenTransform(true);
1925 EXPECT_FALSE(root->did_draw_called());
1926 EXPECT_FALSE(layer1->did_draw_called());
1927 EXPECT_FALSE(layer2->did_draw_called());
1929 LayerTreeHostImpl::FrameData frame;
1930 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
1931 host_impl_->active_tree()->root_layer());
1932 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1933 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1934 host_impl_->DidDrawAllLayers(frame);
1936 EXPECT_TRUE(root->did_draw_called());
1937 EXPECT_TRUE(layer1->did_draw_called());
1938 EXPECT_TRUE(layer2->did_draw_called());
1940 EXPECT_NE(root->render_surface(), layer1->render_surface());
1941 EXPECT_TRUE(!!layer1->render_surface());
1944 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1945 public:
1946 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1947 int id,
1948 bool tile_missing,
1949 bool had_incomplete_tile,
1950 bool animating,
1951 ResourceProvider* resource_provider) {
1952 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl,
1954 tile_missing,
1955 had_incomplete_tile,
1956 animating,
1957 resource_provider));
1960 void AppendQuads(RenderPass* render_pass,
1961 const Occlusion& occlusion_in_content_space,
1962 AppendQuadsData* append_quads_data) override {
1963 LayerImpl::AppendQuads(
1964 render_pass, occlusion_in_content_space, append_quads_data);
1965 if (had_incomplete_tile_)
1966 append_quads_data->num_incomplete_tiles++;
1967 if (tile_missing_)
1968 append_quads_data->num_missing_tiles++;
1971 private:
1972 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1973 int id,
1974 bool tile_missing,
1975 bool had_incomplete_tile,
1976 bool animating,
1977 ResourceProvider* resource_provider)
1978 : DidDrawCheckLayer(tree_impl, id),
1979 tile_missing_(tile_missing),
1980 had_incomplete_tile_(had_incomplete_tile) {
1981 if (animating)
1982 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1985 bool tile_missing_;
1986 bool had_incomplete_tile_;
1989 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsOnDefault) {
1990 host_impl_->active_tree()->SetRootLayer(
1991 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1992 DidDrawCheckLayer* root =
1993 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1995 bool tile_missing = false;
1996 bool had_incomplete_tile = false;
1997 bool is_animating = false;
1998 root->AddChild(
1999 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2001 tile_missing,
2002 had_incomplete_tile,
2003 is_animating,
2004 host_impl_->resource_provider()));
2006 LayerTreeHostImpl::FrameData frame;
2008 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2009 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2010 host_impl_->DidDrawAllLayers(frame);
2013 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) {
2014 host_impl_->active_tree()->SetRootLayer(
2015 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2016 DidDrawCheckLayer* root =
2017 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2018 bool tile_missing = false;
2019 bool had_incomplete_tile = false;
2020 bool is_animating = true;
2021 root->AddChild(
2022 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2024 tile_missing,
2025 had_incomplete_tile,
2026 is_animating,
2027 host_impl_->resource_provider()));
2029 LayerTreeHostImpl::FrameData frame;
2031 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2032 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2033 host_impl_->DidDrawAllLayers(frame);
2036 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithMissingTiles) {
2037 host_impl_->active_tree()->SetRootLayer(
2038 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2039 DidDrawCheckLayer* root =
2040 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2042 LayerTreeHostImpl::FrameData frame;
2043 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2044 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2045 host_impl_->DidDrawAllLayers(frame);
2046 host_impl_->SwapBuffers(frame);
2048 bool tile_missing = true;
2049 bool had_incomplete_tile = false;
2050 bool is_animating = false;
2051 root->AddChild(
2052 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2054 tile_missing,
2055 had_incomplete_tile,
2056 is_animating,
2057 host_impl_->resource_provider()));
2058 LayerTreeHostImpl::FrameData frame2;
2059 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
2060 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2061 host_impl_->DidDrawAllLayers(frame2);
2064 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithIncompleteTile) {
2065 host_impl_->active_tree()->SetRootLayer(
2066 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2067 DidDrawCheckLayer* root =
2068 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2070 LayerTreeHostImpl::FrameData frame;
2071 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2072 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2073 host_impl_->DidDrawAllLayers(frame);
2074 host_impl_->SwapBuffers(frame);
2076 bool tile_missing = false;
2077 bool had_incomplete_tile = true;
2078 bool is_animating = false;
2079 root->AddChild(
2080 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2082 tile_missing,
2083 had_incomplete_tile,
2084 is_animating,
2085 host_impl_->resource_provider()));
2086 LayerTreeHostImpl::FrameData frame2;
2087 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
2088 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2089 host_impl_->DidDrawAllLayers(frame2);
2092 TEST_F(LayerTreeHostImplTest,
2093 PrepareToDrawFailsWithAnimationAndMissingTilesUsesCheckerboard) {
2094 host_impl_->active_tree()->SetRootLayer(
2095 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
2096 DidDrawCheckLayer* root =
2097 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2099 LayerTreeHostImpl::FrameData frame;
2100 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2101 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2102 host_impl_->DidDrawAllLayers(frame);
2103 host_impl_->SwapBuffers(frame);
2105 bool tile_missing = true;
2106 bool had_incomplete_tile = false;
2107 bool is_animating = true;
2108 root->AddChild(
2109 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2111 tile_missing,
2112 had_incomplete_tile,
2113 is_animating,
2114 host_impl_->resource_provider()));
2115 LayerTreeHostImpl::FrameData frame2;
2116 EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS,
2117 host_impl_->PrepareToDraw(&frame2));
2118 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2119 host_impl_->DidDrawAllLayers(frame2);
2122 TEST_F(LayerTreeHostImplTest,
2123 PrepareToDrawSucceedsWithAnimationAndIncompleteTiles) {
2124 host_impl_->active_tree()->SetRootLayer(
2125 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
2126 DidDrawCheckLayer* root =
2127 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2129 LayerTreeHostImpl::FrameData frame;
2130 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2131 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2132 host_impl_->DidDrawAllLayers(frame);
2133 host_impl_->SwapBuffers(frame);
2135 bool tile_missing = false;
2136 bool had_incomplete_tile = true;
2137 bool is_animating = true;
2138 root->AddChild(
2139 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2141 tile_missing,
2142 had_incomplete_tile,
2143 is_animating,
2144 host_impl_->resource_provider()));
2145 LayerTreeHostImpl::FrameData frame2;
2146 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
2147 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2148 host_impl_->DidDrawAllLayers(frame2);
2151 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenHighResRequired) {
2152 host_impl_->active_tree()->SetRootLayer(
2153 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2154 DidDrawCheckLayer* root =
2155 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2157 LayerTreeHostImpl::FrameData frame;
2158 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2159 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2160 host_impl_->DidDrawAllLayers(frame);
2161 host_impl_->SwapBuffers(frame);
2163 bool tile_missing = false;
2164 bool had_incomplete_tile = false;
2165 bool is_animating = false;
2166 root->AddChild(
2167 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2169 tile_missing,
2170 had_incomplete_tile,
2171 is_animating,
2172 host_impl_->resource_provider()));
2173 host_impl_->SetRequiresHighResToDraw();
2174 LayerTreeHostImpl::FrameData frame2;
2175 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2));
2176 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2177 host_impl_->DidDrawAllLayers(frame2);
2180 TEST_F(LayerTreeHostImplTest,
2181 PrepareToDrawFailsWhenHighResRequiredAndIncompleteTiles) {
2182 host_impl_->active_tree()->SetRootLayer(
2183 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2184 DidDrawCheckLayer* root =
2185 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2187 LayerTreeHostImpl::FrameData frame;
2188 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2189 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2190 host_impl_->DidDrawAllLayers(frame);
2191 host_impl_->SwapBuffers(frame);
2193 bool tile_missing = false;
2194 bool had_incomplete_tile = true;
2195 bool is_animating = false;
2196 root->AddChild(
2197 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2199 tile_missing,
2200 had_incomplete_tile,
2201 is_animating,
2202 host_impl_->resource_provider()));
2203 host_impl_->SetRequiresHighResToDraw();
2204 LayerTreeHostImpl::FrameData frame2;
2205 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2206 host_impl_->PrepareToDraw(&frame2));
2207 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2208 host_impl_->DidDrawAllLayers(frame2);
2211 TEST_F(LayerTreeHostImplTest,
2212 PrepareToDrawFailsWhenHighResRequiredAndMissingTile) {
2213 host_impl_->active_tree()->SetRootLayer(
2214 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2215 DidDrawCheckLayer* root =
2216 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2218 LayerTreeHostImpl::FrameData frame;
2219 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2220 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2221 host_impl_->DidDrawAllLayers(frame);
2222 host_impl_->SwapBuffers(frame);
2224 bool tile_missing = true;
2225 bool had_incomplete_tile = false;
2226 bool is_animating = false;
2227 root->AddChild(
2228 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2230 tile_missing,
2231 had_incomplete_tile,
2232 is_animating,
2233 host_impl_->resource_provider()));
2234 host_impl_->SetRequiresHighResToDraw();
2235 LayerTreeHostImpl::FrameData frame2;
2236 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2237 host_impl_->PrepareToDraw(&frame2));
2238 host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now());
2239 host_impl_->DidDrawAllLayers(frame2);
2242 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2243 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2244 root->SetScrollClipLayer(Layer::INVALID_ID);
2245 host_impl_->active_tree()->SetRootLayer(root.Pass());
2246 DrawFrame();
2248 // Scroll event is ignored because layer is not scrollable.
2249 EXPECT_EQ(InputHandler::ScrollIgnored,
2250 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2251 EXPECT_FALSE(did_request_redraw_);
2252 EXPECT_FALSE(did_request_commit_);
2255 // TODO(bokan): Convert these tests to create inner and outer viewports.
2256 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2257 public:
2258 LayerTreeHostImplTopControlsTest()
2259 // Make the clip size the same as the layer (content) size so the layer is
2260 // non-scrollable.
2261 : layer_size_(10, 10),
2262 clip_size_(layer_size_),
2263 top_controls_height_(50) {
2264 settings_.calculate_top_controls_position = true;
2265 settings_.use_pinch_virtual_viewport = true;
2267 viewport_size_ = gfx::Size(clip_size_.width(),
2268 clip_size_.height() + top_controls_height_);
2271 bool CreateHostImpl(const LayerTreeSettings& settings,
2272 scoped_ptr<OutputSurface> output_surface) override {
2273 bool init =
2274 LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass());
2275 if (init && settings.calculate_top_controls_position) {
2276 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
2277 host_impl_->active_tree()->set_top_controls_delta(top_controls_height_);
2278 host_impl_->top_controls_manager()->SetTopControlsHeight(
2279 top_controls_height_);
2280 host_impl_->DidChangeTopControlsPosition();
2282 return init;
2285 void SetupTopControlsAndScrollLayer() {
2286 scoped_ptr<LayerImpl> root =
2287 LayerImpl::Create(host_impl_->active_tree(), 1);
2288 scoped_ptr<LayerImpl> root_clip =
2289 LayerImpl::Create(host_impl_->active_tree(), 2);
2290 root_clip->SetBounds(clip_size_);
2291 root->SetScrollClipLayer(root_clip->id());
2292 root->SetBounds(layer_size_);
2293 root->SetContentBounds(layer_size_);
2294 root->SetPosition(gfx::PointF());
2295 root->SetDrawsContent(false);
2296 root->SetIsContainerForFixedPositionLayers(true);
2297 int inner_viewport_scroll_layer_id = root->id();
2298 int page_scale_layer_id = root_clip->id();
2299 root_clip->AddChild(root.Pass());
2300 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2301 host_impl_->active_tree()->SetViewportLayersFromIds(
2302 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2303 Layer::INVALID_ID);
2304 // Set a viewport size that is large enough to contain both the top controls
2305 // and some content.
2306 host_impl_->SetViewportSize(viewport_size_);
2307 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2309 host_impl_->DidChangeTopControlsPosition();
2311 host_impl_->CreatePendingTree();
2312 root =
2313 LayerImpl::Create(host_impl_->sync_tree(), 1);
2314 root_clip =
2315 LayerImpl::Create(host_impl_->sync_tree(), 2);
2316 root_clip->SetBounds(clip_size_);
2317 root->SetScrollClipLayer(root_clip->id());
2318 root->SetBounds(layer_size_);
2319 root->SetContentBounds(layer_size_);
2320 root->SetPosition(gfx::PointF());
2321 root->SetDrawsContent(false);
2322 root->SetIsContainerForFixedPositionLayers(true);
2323 inner_viewport_scroll_layer_id = root->id();
2324 page_scale_layer_id = root_clip->id();
2325 root_clip->AddChild(root.Pass());
2326 host_impl_->sync_tree()->SetRootLayer(root_clip.Pass());
2327 host_impl_->sync_tree()->SetViewportLayersFromIds(
2328 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2329 Layer::INVALID_ID);
2330 // Set a viewport size that is large enough to contain both the top controls
2331 // and some content.
2332 host_impl_->SetViewportSize(viewport_size_);
2333 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2334 host_impl_->DidChangeTopControlsPosition();
2337 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2338 const gfx::Size& inner_viewport_size,
2339 const gfx::Size& outer_viewport_size,
2340 const gfx::Size& scroll_layer_size) {
2341 CreateHostImpl(settings_, CreateOutputSurface());
2342 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2343 host_impl_->DidChangeTopControlsPosition();
2345 scoped_ptr<LayerImpl> root =
2346 LayerImpl::Create(host_impl_->active_tree(), 1);
2347 scoped_ptr<LayerImpl> root_clip =
2348 LayerImpl::Create(host_impl_->active_tree(), 2);
2349 scoped_ptr<LayerImpl> page_scale =
2350 LayerImpl::Create(host_impl_->active_tree(), 3);
2352 scoped_ptr<LayerImpl> outer_scroll =
2353 LayerImpl::Create(host_impl_->active_tree(), 4);
2354 scoped_ptr<LayerImpl> outer_clip =
2355 LayerImpl::Create(host_impl_->active_tree(), 5);
2357 root_clip->SetBounds(inner_viewport_size);
2358 root->SetScrollClipLayer(root_clip->id());
2359 root->SetBounds(outer_viewport_size);
2360 root->SetContentBounds(outer_viewport_size);
2361 root->SetPosition(gfx::PointF());
2362 root->SetDrawsContent(false);
2363 root->SetIsContainerForFixedPositionLayers(true);
2365 outer_clip->SetBounds(outer_viewport_size);
2366 outer_scroll->SetScrollClipLayer(outer_clip->id());
2367 outer_scroll->SetBounds(scroll_layer_size);
2368 outer_scroll->SetContentBounds(scroll_layer_size);
2369 outer_scroll->SetPosition(gfx::PointF());
2370 outer_scroll->SetDrawsContent(false);
2371 outer_scroll->SetIsContainerForFixedPositionLayers(true);
2373 int inner_viewport_scroll_layer_id = root->id();
2374 int outer_viewport_scroll_layer_id = outer_scroll->id();
2375 int page_scale_layer_id = page_scale->id();
2377 outer_clip->AddChild(outer_scroll.Pass());
2378 root->AddChild(outer_clip.Pass());
2379 page_scale->AddChild(root.Pass());
2380 root_clip->AddChild(page_scale.Pass());
2382 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2383 host_impl_->active_tree()->SetViewportLayersFromIds(
2384 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2385 outer_viewport_scroll_layer_id);
2387 host_impl_->SetViewportSize(inner_viewport_size);
2388 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2389 EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds());
2392 protected:
2393 gfx::Size layer_size_;
2394 gfx::Size clip_size_;
2395 gfx::Size viewport_size_;
2396 float top_controls_height_;
2398 LayerTreeSettings settings_;
2399 }; // class LayerTreeHostImplTopControlsTest
2401 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2402 SetupTopControlsAndScrollLayerWithVirtualViewport(
2403 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2404 DrawFrame();
2406 EXPECT_EQ(InputHandler::ScrollStarted,
2407 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2409 // Make the test scroll delta a fractional amount, to verify that the
2410 // fixed container size delta is (1) non-zero, and (2) fractional, and
2411 // (3) matches the movement of the top controls.
2412 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2413 host_impl_->top_controls_manager()->ScrollBegin();
2414 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2415 host_impl_->top_controls_manager()->ScrollEnd();
2417 LayerImpl* inner_viewport_scroll_layer =
2418 host_impl_->active_tree()->InnerViewportScrollLayer();
2419 DCHECK(inner_viewport_scroll_layer);
2420 host_impl_->ScrollEnd();
2421 EXPECT_EQ(top_controls_scroll_delta,
2422 inner_viewport_scroll_layer->FixedContainerSizeDelta());
2425 // In this test, the outer viewport is initially unscrollable. We test that a
2426 // scroll initiated on the inner viewport, causing the top controls to show and
2427 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2428 TEST_F(LayerTreeHostImplTopControlsTest,
2429 TopControlsOuterViewportBecomesScrollable) {
2430 SetupTopControlsAndScrollLayerWithVirtualViewport(
2431 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2432 DrawFrame();
2434 LayerImpl *inner_scroll =
2435 host_impl_->active_tree()->InnerViewportScrollLayer();
2436 LayerImpl *inner_container =
2437 host_impl_->active_tree()->InnerViewportContainerLayer();
2438 LayerImpl *outer_scroll =
2439 host_impl_->active_tree()->OuterViewportScrollLayer();
2440 LayerImpl *outer_container =
2441 host_impl_->active_tree()->OuterViewportContainerLayer();
2443 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2444 outer_scroll->SetDrawsContent(true);
2445 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 1.f, 2.f);
2447 EXPECT_EQ(InputHandler::ScrollStarted,
2448 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2449 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 50.f));
2451 // The entire scroll delta should have been used to hide the top controls.
2452 // The viewport layers should be resized back to their full sizes.
2453 EXPECT_EQ(0.f,
2454 host_impl_->active_tree()->total_top_controls_content_offset());
2455 EXPECT_EQ(0.f, inner_scroll->TotalScrollOffset().y());
2456 EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height());
2457 EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height());
2459 // The inner viewport should be scrollable by 50px * page_scale.
2460 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 100.f));
2461 EXPECT_EQ(50.f, inner_scroll->TotalScrollOffset().y());
2462 EXPECT_EQ(0.f, outer_scroll->TotalScrollOffset().y());
2463 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset());
2465 host_impl_->ScrollEnd();
2467 EXPECT_EQ(InputHandler::ScrollStarted,
2468 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2469 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
2471 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2473 // The entire scroll delta should have been used to show the top controls.
2474 // The outer viewport should be resized to accomodate and scrolled to the
2475 // bottom of the document to keep the viewport in place.
2476 EXPECT_EQ(50.f,
2477 host_impl_->active_tree()->total_top_controls_content_offset());
2478 EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height());
2479 EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height());
2480 EXPECT_EQ(25.f, outer_scroll->TotalScrollOffset().y());
2481 EXPECT_EQ(25.f, inner_scroll->TotalScrollOffset().y());
2483 // Now when we continue scrolling, make sure the outer viewport gets scrolled
2484 // since it wasn't scrollable when the scroll began.
2485 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f));
2486 EXPECT_EQ(15.f, outer_scroll->TotalScrollOffset().y());
2487 EXPECT_EQ(25.f, inner_scroll->TotalScrollOffset().y());
2489 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f));
2490 EXPECT_EQ(0.f, outer_scroll->TotalScrollOffset().y());
2491 EXPECT_EQ(25.f, inner_scroll->TotalScrollOffset().y());
2493 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2494 host_impl_->ScrollEnd();
2496 EXPECT_EQ(0.f, outer_scroll->TotalScrollOffset().y());
2497 EXPECT_EQ(0.f, inner_scroll->TotalScrollOffset().y());
2500 // Test that the fixed position container delta is appropriately adjusted
2501 // by the top controls showing/hiding and page scale doesn't affect it.
2502 TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
2503 SetupTopControlsAndScrollLayerWithVirtualViewport(
2504 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
2505 DrawFrame();
2507 float page_scale = 1.5f;
2508 LayerImpl* outer_viewport_scroll_layer =
2509 host_impl_->active_tree()->OuterViewportScrollLayer();
2511 // Zoom in, since the fixed container is the outer viewport, the delta should
2512 // not be scaled.
2513 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
2515 EXPECT_EQ(InputHandler::ScrollStarted,
2516 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2518 // Scroll down, the top controls hiding should expand the viewport size so
2519 // the delta should be equal to the scroll distance.
2520 gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
2521 host_impl_->top_controls_manager()->ScrollBegin();
2522 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2523 EXPECT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
2524 host_impl_->top_controls_manager()->ContentTopOffset());
2525 EXPECT_VECTOR_EQ(top_controls_scroll_delta,
2526 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2527 host_impl_->ScrollEnd();
2529 // Scroll past the maximum extent. The delta shouldn't be greater than the
2530 // top controls height.
2531 host_impl_->top_controls_manager()->ScrollBegin();
2532 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2533 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2534 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2535 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2536 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_),
2537 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2538 host_impl_->ScrollEnd();
2540 // Scroll in the direction to make the top controls show.
2541 host_impl_->top_controls_manager()->ScrollBegin();
2542 host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta);
2543 EXPECT_EQ(top_controls_scroll_delta.y(),
2544 host_impl_->top_controls_manager()->ContentTopOffset());
2545 EXPECT_VECTOR_EQ(
2546 gfx::Vector2dF(0, top_controls_height_ - top_controls_scroll_delta.y()),
2547 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2548 host_impl_->top_controls_manager()->ScrollEnd();
2551 // Ensure setting the top controls position explicitly using the setters on the
2552 // TreeImpl correctly affects the top controls manager and viewport bounds.
2553 TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
2554 CreateHostImpl(settings_, CreateOutputSurface());
2555 SetupTopControlsAndScrollLayer();
2556 DrawFrame();
2558 host_impl_->active_tree()->set_top_controls_delta(0.f);
2559 host_impl_->active_tree()->set_top_controls_content_offset(30.f);
2560 EXPECT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
2561 EXPECT_EQ(-20.f, host_impl_->top_controls_manager()->ControlsTopOffset());
2563 host_impl_->active_tree()->set_top_controls_delta(-30.f);
2564 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2565 EXPECT_EQ(-50.f, host_impl_->top_controls_manager()->ControlsTopOffset());
2567 host_impl_->DidChangeTopControlsPosition();
2569 // Now that top controls have moved, expect the clip to resize.
2570 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2571 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2574 // Test that the top_controls delta and sent delta are appropriately
2575 // applied on sync tree activation. The total top controls offset shouldn't
2576 // change after the activation.
2577 TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
2578 CreateHostImpl(settings_, CreateOutputSurface());
2579 SetupTopControlsAndScrollLayer();
2580 DrawFrame();
2582 host_impl_->sync_tree()->set_top_controls_content_offset(15.f);
2584 host_impl_->active_tree()->set_top_controls_content_offset(20.f);
2585 host_impl_->active_tree()->set_top_controls_delta(-20.f);
2586 host_impl_->active_tree()->set_sent_top_controls_delta(-5.f);
2588 host_impl_->DidChangeTopControlsPosition();
2589 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2590 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2591 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2592 EXPECT_EQ(0.f,
2593 host_impl_->active_tree()->total_top_controls_content_offset());
2595 host_impl_->ActivateSyncTree();
2597 root_clip_ptr = host_impl_->active_tree()->root_layer();
2598 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2599 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2601 EXPECT_EQ(0.f, host_impl_->active_tree()->sent_top_controls_delta());
2602 EXPECT_EQ(-15.f, host_impl_->active_tree()->top_controls_delta());
2603 EXPECT_EQ(15.f, host_impl_->active_tree()->top_controls_content_offset());
2604 EXPECT_EQ(0.f,
2605 host_impl_->active_tree()->total_top_controls_content_offset());
2608 // Test that changing the top controls layout height is correctly applied to
2609 // the inner viewport container bounds. That is, the top controls layout
2610 // height is the amount that the inner viewport container was shrunk outside
2611 // the compositor to accommodate the top controls.
2612 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
2613 CreateHostImpl(settings_, CreateOutputSurface());
2614 SetupTopControlsAndScrollLayer();
2615 DrawFrame();
2617 host_impl_->sync_tree()->set_top_controls_content_offset(50.f);
2618 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2620 host_impl_->active_tree()->set_top_controls_content_offset(50.f);
2621 host_impl_->active_tree()->set_top_controls_delta(-50.f);
2623 host_impl_->DidChangeTopControlsPosition();
2624 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2625 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2626 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2628 host_impl_->sync_tree()->root_layer()->SetBounds(
2629 gfx::Size(root_clip_ptr->bounds().width(),
2630 root_clip_ptr->bounds().height() - 50.f));
2632 host_impl_->ActivateSyncTree();
2634 root_clip_ptr = host_impl_->active_tree()->root_layer();
2635 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2637 // The total bounds should remain unchanged since the bounds delta should
2638 // account for the difference between the layout height and the current
2639 // top controls offset.
2640 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2641 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), root_clip_ptr->bounds_delta());
2643 host_impl_->active_tree()->set_top_controls_delta(0.f);
2644 host_impl_->DidChangeTopControlsPosition();
2646 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset());
2647 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), root_clip_ptr->bounds_delta());
2648 EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f),
2649 root_clip_ptr->bounds());
2652 // Test that showing/hiding the top controls when the viewport is fully scrolled
2653 // doesn't incorrectly change the viewport offset due to clamping from changing
2654 // viewport bounds.
2655 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) {
2656 SetupTopControlsAndScrollLayerWithVirtualViewport(
2657 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2658 DrawFrame();
2660 EXPECT_EQ(top_controls_height_,
2661 host_impl_->active_tree()->total_top_controls_content_offset());
2663 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
2664 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
2666 // Scroll the viewports to max scroll offset.
2667 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
2668 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
2670 gfx::ScrollOffset viewport_offset =
2671 host_impl_->active_tree()->TotalScrollOffset();
2672 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset);
2674 // Hide the top controls by 25px.
2675 gfx::Vector2dF scroll_delta(0.f, 25.f);
2676 EXPECT_EQ(InputHandler::ScrollStarted,
2677 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2678 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2680 // scrolling down at the max extents no longer hides the top controls
2681 EXPECT_EQ(0.f,
2682 top_controls_height_ -
2683 host_impl_->active_tree()->total_top_controls_content_offset());
2685 // forcefully hide the top controls by 25px
2686 host_impl_->top_controls_manager()->ScrollBy(scroll_delta);
2687 host_impl_->ScrollEnd();
2689 EXPECT_EQ(scroll_delta.y(),
2690 top_controls_height_ -
2691 host_impl_->active_tree()->total_top_controls_content_offset());
2693 inner_scroll->ClampScrollToMaxScrollOffset();
2694 outer_scroll->ClampScrollToMaxScrollOffset();
2696 // We should still be fully scrolled.
2697 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
2698 host_impl_->active_tree()->TotalScrollOffset());
2700 viewport_offset = host_impl_->active_tree()->TotalScrollOffset();
2702 // Bring the top controls down by 25px.
2703 scroll_delta = gfx::Vector2dF(0.f, -25.f);
2704 EXPECT_EQ(InputHandler::ScrollStarted,
2705 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2706 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2707 host_impl_->ScrollEnd();
2709 // The viewport offset shouldn't have changed.
2710 EXPECT_EQ(viewport_offset,
2711 host_impl_->active_tree()->TotalScrollOffset());
2713 // Scroll the viewports to max scroll offset.
2714 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
2715 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
2716 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
2717 host_impl_->active_tree()->TotalScrollOffset());
2720 // Test that the top controls coming in and out maintains the same aspect ratio
2721 // between the inner and outer viewports.
2722 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
2723 SetupTopControlsAndScrollLayerWithVirtualViewport(
2724 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2725 DrawFrame();
2727 EXPECT_EQ(top_controls_height_,
2728 host_impl_->active_tree()->total_top_controls_content_offset());
2730 gfx::Vector2dF scroll_delta(0.f, 25.f);
2731 EXPECT_EQ(InputHandler::ScrollStarted,
2732 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2733 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2734 host_impl_->ScrollEnd();
2736 EXPECT_EQ(scroll_delta.y(),
2737 top_controls_height_ -
2738 host_impl_->active_tree()->total_top_controls_content_offset());
2740 // Top controls were hidden by 25px so the inner viewport should have expanded
2741 // by that much.
2742 LayerImpl* outer_container =
2743 host_impl_->active_tree()->OuterViewportContainerLayer();
2744 LayerImpl* inner_container =
2745 host_impl_->active_tree()->InnerViewportContainerLayer();
2746 EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling());
2748 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
2749 float aspect_ratio = inner_container->BoundsForScrolling().width() /
2750 inner_container->BoundsForScrolling().height();
2751 gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio));
2752 EXPECT_EQ(expected, outer_container->BoundsForScrolling());
2753 EXPECT_EQ(expected,
2754 host_impl_->InnerViewportScrollLayer()->BoundsForScrolling());
2757 // Test that scrolling the outer viewport affects the top controls.
2758 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
2759 SetupTopControlsAndScrollLayerWithVirtualViewport(
2760 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2761 DrawFrame();
2763 EXPECT_EQ(top_controls_height_,
2764 host_impl_->active_tree()->total_top_controls_content_offset());
2766 // Send a gesture scroll that will scroll the outer viewport, make sure the
2767 // top controls get scrolled.
2768 gfx::Vector2dF scroll_delta(0.f, 15.f);
2769 EXPECT_EQ(InputHandler::ScrollStarted,
2770 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2771 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2772 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
2773 host_impl_->CurrentlyScrollingLayer());
2774 host_impl_->ScrollEnd();
2776 EXPECT_EQ(scroll_delta.y(),
2777 top_controls_height_ -
2778 host_impl_->active_tree()->total_top_controls_content_offset());
2780 scroll_delta = gfx::Vector2dF(0.f, 50.f);
2781 EXPECT_EQ(InputHandler::ScrollStarted,
2782 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2783 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2785 EXPECT_EQ(0, host_impl_->active_tree()->total_top_controls_content_offset());
2786 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
2787 host_impl_->CurrentlyScrollingLayer());
2789 host_impl_->ScrollEnd();
2791 // Position the viewports such that the inner viewport will be scrolled.
2792 gfx::Vector2dF inner_viewport_offset(0.f, 25.f);
2793 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
2794 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset);
2796 scroll_delta = gfx::Vector2dF(0.f, -65.f);
2797 EXPECT_EQ(InputHandler::ScrollStarted,
2798 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2799 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2801 EXPECT_EQ(top_controls_height_,
2802 host_impl_->active_tree()->total_top_controls_content_offset());
2803 EXPECT_EQ(
2804 inner_viewport_offset.y() + (scroll_delta.y() + top_controls_height_),
2805 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
2807 host_impl_->ScrollEnd();
2810 TEST_F(LayerTreeHostImplTopControlsTest,
2811 ScrollNonScrollableRootWithTopControls) {
2812 CreateHostImpl(settings_, CreateOutputSurface());
2813 SetupTopControlsAndScrollLayer();
2814 DrawFrame();
2816 EXPECT_EQ(InputHandler::ScrollStarted,
2817 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2819 host_impl_->top_controls_manager()->ScrollBegin();
2820 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
2821 host_impl_->top_controls_manager()->ScrollEnd();
2822 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2823 // Now that top controls have moved, expect the clip to resize.
2824 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2825 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2827 host_impl_->ScrollEnd();
2829 EXPECT_EQ(InputHandler::ScrollStarted,
2830 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2832 float scroll_increment_y = -25.f;
2833 host_impl_->top_controls_manager()->ScrollBegin();
2834 host_impl_->top_controls_manager()->ScrollBy(
2835 gfx::Vector2dF(0.f, scroll_increment_y));
2836 EXPECT_EQ(-scroll_increment_y,
2837 host_impl_->top_controls_manager()->ContentTopOffset());
2838 // Now that top controls have moved, expect the clip to resize.
2839 EXPECT_EQ(gfx::Size(viewport_size_.width(),
2840 viewport_size_.height() + scroll_increment_y),
2841 root_clip_ptr->bounds());
2843 host_impl_->top_controls_manager()->ScrollBy(
2844 gfx::Vector2dF(0.f, scroll_increment_y));
2845 host_impl_->top_controls_manager()->ScrollEnd();
2846 EXPECT_EQ(-2 * scroll_increment_y,
2847 host_impl_->top_controls_manager()->ContentTopOffset());
2848 // Now that top controls have moved, expect the clip to resize.
2849 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2851 host_impl_->ScrollEnd();
2853 // Verify the layer is once-again non-scrollable.
2854 EXPECT_EQ(
2855 gfx::ScrollOffset(),
2856 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
2858 EXPECT_EQ(InputHandler::ScrollStarted,
2859 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2862 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
2863 // Test the configuration where a non-composited root layer is embedded in a
2864 // scrollable outer layer.
2865 gfx::Size surface_size(10, 10);
2866 gfx::Size contents_size(20, 20);
2868 scoped_ptr<LayerImpl> content_layer =
2869 LayerImpl::Create(host_impl_->active_tree(), 1);
2870 content_layer->SetDrawsContent(true);
2871 content_layer->SetPosition(gfx::PointF());
2872 content_layer->SetBounds(contents_size);
2873 content_layer->SetContentBounds(contents_size);
2874 content_layer->SetContentsScale(2.f, 2.f);
2876 scoped_ptr<LayerImpl> scroll_clip_layer =
2877 LayerImpl::Create(host_impl_->active_tree(), 3);
2878 scroll_clip_layer->SetBounds(surface_size);
2880 scoped_ptr<LayerImpl> scroll_layer =
2881 LayerImpl::Create(host_impl_->active_tree(), 2);
2882 scroll_layer->SetScrollClipLayer(3);
2883 scroll_layer->SetBounds(contents_size);
2884 scroll_layer->SetContentBounds(contents_size);
2885 scroll_layer->SetPosition(gfx::PointF());
2886 scroll_layer->AddChild(content_layer.Pass());
2887 scroll_clip_layer->AddChild(scroll_layer.Pass());
2889 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
2890 host_impl_->SetViewportSize(surface_size);
2891 DrawFrame();
2893 EXPECT_EQ(InputHandler::ScrollStarted,
2894 host_impl_->ScrollBegin(gfx::Point(5, 5),
2895 InputHandler::Wheel));
2896 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2897 host_impl_->ScrollEnd();
2898 EXPECT_TRUE(did_request_redraw_);
2899 EXPECT_TRUE(did_request_commit_);
2902 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
2903 gfx::Size surface_size(10, 10);
2904 gfx::Size contents_size(20, 20);
2905 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2906 root->SetBounds(surface_size);
2907 root->SetContentBounds(contents_size);
2908 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
2909 host_impl_->active_tree()->SetRootLayer(root.Pass());
2910 host_impl_->SetViewportSize(surface_size);
2911 DrawFrame();
2913 EXPECT_EQ(InputHandler::ScrollStarted,
2914 host_impl_->ScrollBegin(gfx::Point(5, 5),
2915 InputHandler::Wheel));
2916 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2917 host_impl_->ScrollEnd();
2918 EXPECT_TRUE(did_request_redraw_);
2919 EXPECT_TRUE(did_request_commit_);
2922 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
2923 gfx::Size surface_size(10, 10);
2924 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2925 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
2926 host_impl_->active_tree()->SetRootLayer(root.Pass());
2927 host_impl_->SetViewportSize(surface_size);
2928 DrawFrame();
2930 // Scroll event is ignored because the input coordinate is outside the layer
2931 // boundaries.
2932 EXPECT_EQ(InputHandler::ScrollIgnored,
2933 host_impl_->ScrollBegin(gfx::Point(15, 5),
2934 InputHandler::Wheel));
2935 EXPECT_FALSE(did_request_redraw_);
2936 EXPECT_FALSE(did_request_commit_);
2939 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
2940 gfx::Size surface_size(10, 10);
2941 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2942 scoped_ptr<LayerImpl> child =
2943 CreateScrollableLayer(2, surface_size, root.get());
2944 host_impl_->SetViewportSize(surface_size);
2946 gfx::Transform matrix;
2947 matrix.RotateAboutXAxis(180.0);
2948 child->SetTransform(matrix);
2949 child->SetDoubleSided(false);
2951 root->AddChild(child.Pass());
2952 host_impl_->active_tree()->SetRootLayer(root.Pass());
2953 DrawFrame();
2955 // Scroll event is ignored because the scrollable layer is not facing the
2956 // viewer and there is nothing scrollable behind it.
2957 EXPECT_EQ(InputHandler::ScrollIgnored,
2958 host_impl_->ScrollBegin(gfx::Point(5, 5),
2959 InputHandler::Wheel));
2960 EXPECT_FALSE(did_request_redraw_);
2961 EXPECT_FALSE(did_request_commit_);
2964 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
2965 gfx::Size surface_size(10, 10);
2966 scoped_ptr<LayerImpl> clip_layer =
2967 LayerImpl::Create(host_impl_->active_tree(), 3);
2968 scoped_ptr<LayerImpl> content_layer =
2969 CreateScrollableLayer(1, surface_size, clip_layer.get());
2970 content_layer->SetShouldScrollOnMainThread(true);
2971 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
2973 // Note: we can use the same clip layer for both since both calls to
2974 // CreateScrollableLayer() use the same surface size.
2975 scoped_ptr<LayerImpl> scroll_layer =
2976 CreateScrollableLayer(2, surface_size, clip_layer.get());
2977 scroll_layer->AddChild(content_layer.Pass());
2978 clip_layer->AddChild(scroll_layer.Pass());
2980 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
2981 host_impl_->SetViewportSize(surface_size);
2982 DrawFrame();
2984 // Scrolling fails because the content layer is asking to be scrolled on the
2985 // main thread.
2986 EXPECT_EQ(InputHandler::ScrollOnMainThread,
2987 host_impl_->ScrollBegin(gfx::Point(5, 5),
2988 InputHandler::Wheel));
2991 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
2992 gfx::Size surface_size(20, 20);
2993 gfx::Size viewport_size(10, 10);
2994 float page_scale = 2.f;
2995 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2996 scoped_ptr<LayerImpl> root_clip =
2997 LayerImpl::Create(host_impl_->active_tree(), 2);
2998 scoped_ptr<LayerImpl> root_scrolling =
2999 CreateScrollableLayer(3, surface_size, root_clip.get());
3000 EXPECT_EQ(viewport_size, root_clip->bounds());
3001 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3002 root_clip->AddChild(root_scrolling.Pass());
3003 root->AddChild(root_clip.Pass());
3004 host_impl_->active_tree()->SetRootLayer(root.Pass());
3005 // The behaviour in this test assumes the page scale is applied at a layer
3006 // above the clip layer.
3007 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
3008 Layer::INVALID_ID);
3009 host_impl_->active_tree()->DidBecomeActive();
3010 host_impl_->SetViewportSize(viewport_size);
3011 DrawFrame();
3013 LayerImpl* root_scroll =
3014 host_impl_->active_tree()->InnerViewportScrollLayer();
3015 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3017 gfx::Vector2d scroll_delta(0, 10);
3018 gfx::Vector2d expected_scroll_delta = scroll_delta;
3019 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3020 EXPECT_EQ(InputHandler::ScrollStarted,
3021 host_impl_->ScrollBegin(gfx::Point(5, 5),
3022 InputHandler::Wheel));
3023 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3024 host_impl_->ScrollEnd();
3026 // Set new page scale from main thread.
3027 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, page_scale,
3028 page_scale);
3030 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3031 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
3033 // The scroll range should also have been updated.
3034 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3036 // The page scale delta remains constant because the impl thread did not
3037 // scale.
3038 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3041 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
3042 gfx::Size surface_size(20, 20);
3043 gfx::Size viewport_size(10, 10);
3044 float page_scale = 2.f;
3045 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3046 scoped_ptr<LayerImpl> root_clip =
3047 LayerImpl::Create(host_impl_->active_tree(), 2);
3048 scoped_ptr<LayerImpl> root_scrolling =
3049 CreateScrollableLayer(3, surface_size, root_clip.get());
3050 EXPECT_EQ(viewport_size, root_clip->bounds());
3051 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3052 root_clip->AddChild(root_scrolling.Pass());
3053 root->AddChild(root_clip.Pass());
3054 host_impl_->active_tree()->SetRootLayer(root.Pass());
3055 // The behaviour in this test assumes the page scale is applied at a layer
3056 // above the clip layer.
3057 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
3058 Layer::INVALID_ID);
3059 host_impl_->active_tree()->DidBecomeActive();
3060 host_impl_->SetViewportSize(viewport_size);
3061 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, page_scale);
3062 DrawFrame();
3064 LayerImpl* root_scroll =
3065 host_impl_->active_tree()->InnerViewportScrollLayer();
3066 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3068 gfx::Vector2d scroll_delta(0, 10);
3069 gfx::Vector2d expected_scroll_delta = scroll_delta;
3070 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3071 EXPECT_EQ(InputHandler::ScrollStarted,
3072 host_impl_->ScrollBegin(gfx::Point(5, 5),
3073 InputHandler::Wheel));
3074 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3075 host_impl_->ScrollEnd();
3077 // Set new page scale on impl thread by pinching.
3078 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3079 host_impl_->PinchGestureBegin();
3080 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
3081 host_impl_->PinchGestureEnd();
3082 host_impl_->ScrollEnd();
3083 DrawOneFrame();
3085 // The scroll delta is not scaled because the main thread did not scale.
3086 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3087 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
3089 // The scroll range should also have been updated.
3090 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3092 // The page scale delta should match the new scale on the impl side.
3093 EXPECT_EQ(page_scale, host_impl_->active_tree()->current_page_scale_factor());
3096 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
3097 gfx::Size surface_size(10, 10);
3098 float default_page_scale = 1.f;
3099 gfx::Transform default_page_scale_matrix;
3100 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
3102 float new_page_scale = 2.f;
3103 gfx::Transform new_page_scale_matrix;
3104 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
3106 // Create a normal scrollable root layer and another scrollable child layer.
3107 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
3108 LayerImpl* root = host_impl_->active_tree()->root_layer();
3109 LayerImpl* child = scroll->children()[0];
3111 scoped_ptr<LayerImpl> scrollable_child_clip =
3112 LayerImpl::Create(host_impl_->active_tree(), 6);
3113 scoped_ptr<LayerImpl> scrollable_child =
3114 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
3115 scrollable_child_clip->AddChild(scrollable_child.Pass());
3116 child->AddChild(scrollable_child_clip.Pass());
3117 LayerImpl* grand_child = child->children()[0];
3119 // Set new page scale on impl thread by pinching.
3120 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3121 host_impl_->PinchGestureBegin();
3122 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
3123 host_impl_->PinchGestureEnd();
3124 host_impl_->ScrollEnd();
3125 DrawOneFrame();
3127 EXPECT_EQ(1.f, root->contents_scale_x());
3128 EXPECT_EQ(1.f, root->contents_scale_y());
3129 EXPECT_EQ(1.f, scroll->contents_scale_x());
3130 EXPECT_EQ(1.f, scroll->contents_scale_y());
3131 EXPECT_EQ(1.f, child->contents_scale_x());
3132 EXPECT_EQ(1.f, child->contents_scale_y());
3133 EXPECT_EQ(1.f, grand_child->contents_scale_x());
3134 EXPECT_EQ(1.f, grand_child->contents_scale_y());
3136 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3137 // the page scale delta on the root layer is applied hierarchically.
3138 LayerTreeHostImpl::FrameData frame;
3139 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3140 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3141 host_impl_->DidDrawAllLayers(frame);
3143 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
3144 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
3145 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
3146 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
3147 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
3148 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
3149 EXPECT_EQ(new_page_scale,
3150 grand_child->draw_transform().matrix().getDouble(0, 0));
3151 EXPECT_EQ(new_page_scale,
3152 grand_child->draw_transform().matrix().getDouble(1, 1));
3155 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
3156 gfx::Size surface_size(30, 30);
3157 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3158 root->SetBounds(gfx::Size(5, 5));
3159 scoped_ptr<LayerImpl> root_scrolling =
3160 LayerImpl::Create(host_impl_->active_tree(), 2);
3161 root_scrolling->SetBounds(surface_size);
3162 root_scrolling->SetContentBounds(surface_size);
3163 root_scrolling->SetScrollClipLayer(root->id());
3164 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3165 LayerImpl* root_scrolling_ptr = root_scrolling.get();
3166 root->AddChild(root_scrolling.Pass());
3167 int child_scroll_layer_id = 3;
3168 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
3169 child_scroll_layer_id, surface_size, root_scrolling_ptr);
3170 LayerImpl* child = child_scrolling.get();
3171 root_scrolling_ptr->AddChild(child_scrolling.Pass());
3172 host_impl_->active_tree()->SetRootLayer(root.Pass());
3173 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3174 Layer::INVALID_ID);
3175 host_impl_->active_tree()->DidBecomeActive();
3176 host_impl_->SetViewportSize(surface_size);
3177 DrawFrame();
3179 gfx::Vector2d scroll_delta(0, 10);
3180 gfx::Vector2d expected_scroll_delta(scroll_delta);
3181 gfx::ScrollOffset expected_max_scroll(child->MaxScrollOffset());
3182 EXPECT_EQ(InputHandler::ScrollStarted,
3183 host_impl_->ScrollBegin(gfx::Point(5, 5),
3184 InputHandler::Wheel));
3185 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3186 host_impl_->ScrollEnd();
3188 float page_scale = 2.f;
3189 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f,
3190 page_scale);
3192 DrawOneFrame();
3194 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3195 ExpectContains(
3196 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
3198 // The scroll range should not have changed.
3199 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
3201 // The page scale delta remains constant because the impl thread did not
3202 // scale.
3203 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3206 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
3207 // Scroll a child layer beyond its maximum scroll range and make sure the
3208 // parent layer is scrolled on the axis on which the child was unable to
3209 // scroll.
3210 gfx::Size surface_size(10, 10);
3211 gfx::Size content_size(20, 20);
3212 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3213 root->SetBounds(surface_size);
3215 scoped_ptr<LayerImpl> grand_child =
3216 CreateScrollableLayer(3, content_size, root.get());
3218 scoped_ptr<LayerImpl> child =
3219 CreateScrollableLayer(2, content_size, root.get());
3220 LayerImpl* grand_child_layer = grand_child.get();
3221 child->AddChild(grand_child.Pass());
3223 LayerImpl* child_layer = child.get();
3224 root->AddChild(child.Pass());
3225 host_impl_->active_tree()->SetRootLayer(root.Pass());
3226 host_impl_->active_tree()->DidBecomeActive();
3227 host_impl_->SetViewportSize(surface_size);
3228 grand_child_layer->SetScrollOffset(gfx::ScrollOffset(0, 5));
3229 child_layer->SetScrollOffset(gfx::ScrollOffset(3, 0));
3231 DrawFrame();
3233 gfx::Vector2d scroll_delta(-8, -7);
3234 EXPECT_EQ(InputHandler::ScrollStarted,
3235 host_impl_->ScrollBegin(gfx::Point(),
3236 InputHandler::Wheel));
3237 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3238 host_impl_->ScrollEnd();
3240 scoped_ptr<ScrollAndScaleSet> scroll_info =
3241 host_impl_->ProcessScrollDeltas();
3243 // The grand child should have scrolled up to its limit.
3244 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
3245 LayerImpl* grand_child = child->children()[0];
3246 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
3248 // The child should have only scrolled on the other axis.
3249 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
3253 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
3254 // Scroll a child layer beyond its maximum scroll range and make sure the
3255 // the scroll doesn't bubble up to the parent layer.
3256 gfx::Size surface_size(20, 20);
3257 gfx::Size viewport_size(10, 10);
3258 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3259 scoped_ptr<LayerImpl> root_scrolling =
3260 CreateScrollableLayer(2, surface_size, root.get());
3261 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3263 scoped_ptr<LayerImpl> grand_child =
3264 CreateScrollableLayer(4, surface_size, root.get());
3266 scoped_ptr<LayerImpl> child =
3267 CreateScrollableLayer(3, surface_size, root.get());
3268 LayerImpl* grand_child_layer = grand_child.get();
3269 child->AddChild(grand_child.Pass());
3271 LayerImpl* child_layer = child.get();
3272 root_scrolling->AddChild(child.Pass());
3273 root->AddChild(root_scrolling.Pass());
3274 EXPECT_EQ(viewport_size, root->bounds());
3275 host_impl_->active_tree()->SetRootLayer(root.Pass());
3276 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3277 Layer::INVALID_ID);
3278 host_impl_->active_tree()->DidBecomeActive();
3279 host_impl_->SetViewportSize(viewport_size);
3281 grand_child_layer->SetScrollOffset(gfx::ScrollOffset(0, 2));
3282 child_layer->SetScrollOffset(gfx::ScrollOffset(0, 3));
3284 DrawFrame();
3286 gfx::Vector2d scroll_delta(0, -10);
3287 EXPECT_EQ(InputHandler::ScrollStarted,
3288 host_impl_->ScrollBegin(gfx::Point(),
3289 InputHandler::NonBubblingGesture));
3290 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3291 host_impl_->ScrollEnd();
3293 scoped_ptr<ScrollAndScaleSet> scroll_info =
3294 host_impl_->ProcessScrollDeltas();
3296 // The grand child should have scrolled up to its limit.
3297 LayerImpl* child =
3298 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
3299 LayerImpl* grand_child = child->children()[0];
3300 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
3302 // The child should not have scrolled.
3303 ExpectNone(*scroll_info.get(), child->id());
3305 // The next time we scroll we should only scroll the parent.
3306 scroll_delta = gfx::Vector2d(0, -3);
3307 EXPECT_EQ(InputHandler::ScrollStarted,
3308 host_impl_->ScrollBegin(gfx::Point(5, 5),
3309 InputHandler::NonBubblingGesture));
3310 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3311 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3312 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
3313 host_impl_->ScrollEnd();
3315 scroll_info = host_impl_->ProcessScrollDeltas();
3317 // The child should have scrolled up to its limit.
3318 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
3320 // The grand child should not have scrolled.
3321 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
3323 // After scrolling the parent, another scroll on the opposite direction
3324 // should still scroll the child.
3325 scroll_delta = gfx::Vector2d(0, 7);
3326 EXPECT_EQ(InputHandler::ScrollStarted,
3327 host_impl_->ScrollBegin(gfx::Point(5, 5),
3328 InputHandler::NonBubblingGesture));
3329 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3330 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3331 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3332 host_impl_->ScrollEnd();
3334 scroll_info = host_impl_->ProcessScrollDeltas();
3336 // The grand child should have scrolled.
3337 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
3339 // The child should not have scrolled.
3340 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
3343 // Scrolling should be adjusted from viewport space.
3344 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 2.f, 2.f);
3345 host_impl_->SetPageScaleOnActiveTree(2.f);
3347 scroll_delta = gfx::Vector2d(0, -2);
3348 EXPECT_EQ(InputHandler::ScrollStarted,
3349 host_impl_->ScrollBegin(gfx::Point(1, 1),
3350 InputHandler::NonBubblingGesture));
3351 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
3352 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3353 host_impl_->ScrollEnd();
3355 scroll_info = host_impl_->ProcessScrollDeltas();
3357 // Should have scrolled by half the amount in layer space (5 - 2/2)
3358 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
3361 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
3362 // When we try to scroll a non-scrollable child layer, the scroll delta
3363 // should be applied to one of its ancestors if possible.
3364 gfx::Size surface_size(10, 10);
3365 gfx::Size content_size(20, 20);
3366 scoped_ptr<LayerImpl> root_clip =
3367 LayerImpl::Create(host_impl_->active_tree(), 3);
3368 scoped_ptr<LayerImpl> root =
3369 CreateScrollableLayer(1, content_size, root_clip.get());
3370 // Make 'root' the clip layer for child: since they have the same sizes the
3371 // child will have zero max_scroll_offset and scrolls will bubble.
3372 scoped_ptr<LayerImpl> child =
3373 CreateScrollableLayer(2, content_size, root.get());
3374 child->SetIsContainerForFixedPositionLayers(true);
3375 root->SetBounds(content_size);
3377 int root_scroll_id = root->id();
3378 root->AddChild(child.Pass());
3379 root_clip->AddChild(root.Pass());
3381 host_impl_->SetViewportSize(surface_size);
3382 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3383 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 2,
3384 Layer::INVALID_ID);
3385 host_impl_->active_tree()->DidBecomeActive();
3386 DrawFrame();
3388 gfx::Vector2d scroll_delta(0, 4);
3389 EXPECT_EQ(InputHandler::ScrollStarted,
3390 host_impl_->ScrollBegin(gfx::Point(5, 5),
3391 InputHandler::Wheel));
3392 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3393 host_impl_->ScrollEnd();
3395 scoped_ptr<ScrollAndScaleSet> scroll_info =
3396 host_impl_->ProcessScrollDeltas();
3398 // Only the root scroll should have scrolled.
3399 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
3400 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
3404 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
3405 gfx::Size surface_size(10, 10);
3406 scoped_ptr<LayerImpl> root_clip =
3407 LayerImpl::Create(host_impl_->active_tree(), 1);
3408 scoped_ptr<LayerImpl> root_scroll =
3409 CreateScrollableLayer(2, surface_size, root_clip.get());
3410 root_scroll->SetIsContainerForFixedPositionLayers(true);
3411 root_clip->AddChild(root_scroll.Pass());
3412 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3413 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3414 Layer::INVALID_ID);
3415 host_impl_->active_tree()->DidBecomeActive();
3416 host_impl_->SetViewportSize(surface_size);
3418 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3419 // synchronization.
3420 DrawFrame();
3421 host_impl_->active_tree()->DetachLayerTree();
3422 scoped_ptr<LayerImpl> root_clip2 =
3423 LayerImpl::Create(host_impl_->active_tree(), 3);
3424 scoped_ptr<LayerImpl> root_scroll2 =
3425 CreateScrollableLayer(4, surface_size, root_clip2.get());
3426 root_scroll2->SetIsContainerForFixedPositionLayers(true);
3427 root_clip2->AddChild(root_scroll2.Pass());
3428 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
3429 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 4,
3430 Layer::INVALID_ID);
3431 host_impl_->active_tree()->DidBecomeActive();
3433 // Scrolling should still work even though we did not draw yet.
3434 EXPECT_EQ(InputHandler::ScrollStarted,
3435 host_impl_->ScrollBegin(gfx::Point(5, 5),
3436 InputHandler::Wheel));
3439 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
3440 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3442 // Rotate the root layer 90 degrees counter-clockwise about its center.
3443 gfx::Transform rotate_transform;
3444 rotate_transform.Rotate(-90.0);
3445 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
3447 gfx::Size surface_size(50, 50);
3448 host_impl_->SetViewportSize(surface_size);
3449 DrawFrame();
3451 // Scroll to the right in screen coordinates with a gesture.
3452 gfx::Vector2d gesture_scroll_delta(10, 0);
3453 EXPECT_EQ(InputHandler::ScrollStarted,
3454 host_impl_->ScrollBegin(gfx::Point(),
3455 InputHandler::Gesture));
3456 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3457 host_impl_->ScrollEnd();
3459 // The layer should have scrolled down in its local coordinates.
3460 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3461 ExpectContains(*scroll_info.get(),
3462 scroll_layer->id(),
3463 gfx::Vector2d(0, gesture_scroll_delta.x()));
3465 // Reset and scroll down with the wheel.
3466 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3467 gfx::Vector2d wheel_scroll_delta(0, 10);
3468 EXPECT_EQ(InputHandler::ScrollStarted,
3469 host_impl_->ScrollBegin(gfx::Point(),
3470 InputHandler::Wheel));
3471 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3472 host_impl_->ScrollEnd();
3474 // The layer should have scrolled down in its local coordinates.
3475 scroll_info = host_impl_->ProcessScrollDeltas();
3476 ExpectContains(*scroll_info.get(),
3477 scroll_layer->id(),
3478 wheel_scroll_delta);
3481 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
3482 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3483 int child_clip_layer_id = 6;
3484 int child_layer_id = 7;
3485 float child_layer_angle = -20.f;
3487 // Create a child layer that is rotated to a non-axis-aligned angle.
3488 scoped_ptr<LayerImpl> clip_layer =
3489 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
3490 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
3491 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
3492 gfx::Transform rotate_transform;
3493 rotate_transform.Translate(-50.0, -50.0);
3494 rotate_transform.Rotate(child_layer_angle);
3495 rotate_transform.Translate(50.0, 50.0);
3496 clip_layer->SetTransform(rotate_transform);
3498 // Only allow vertical scrolling.
3499 clip_layer->SetBounds(
3500 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
3501 // The rotation depends on the layer's transform origin, and the child layer
3502 // is a different size than the clip, so make sure the clip layer's origin
3503 // lines up over the child.
3504 clip_layer->SetTransformOrigin(gfx::Point3F(
3505 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
3506 LayerImpl* child_ptr = child.get();
3507 clip_layer->AddChild(child.Pass());
3508 scroll_layer->AddChild(clip_layer.Pass());
3510 gfx::Size surface_size(50, 50);
3511 host_impl_->SetViewportSize(surface_size);
3512 DrawFrame();
3514 // Scroll down in screen coordinates with a gesture.
3515 gfx::Vector2d gesture_scroll_delta(0, 10);
3516 EXPECT_EQ(InputHandler::ScrollStarted,
3517 host_impl_->ScrollBegin(gfx::Point(1, 1),
3518 InputHandler::Gesture));
3519 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3520 host_impl_->ScrollEnd();
3522 // The child layer should have scrolled down in its local coordinates an
3523 // amount proportional to the angle between it and the input scroll delta.
3524 gfx::Vector2d expected_scroll_delta(
3526 gesture_scroll_delta.y() *
3527 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
3528 scoped_ptr<ScrollAndScaleSet> scroll_info =
3529 host_impl_->ProcessScrollDeltas();
3530 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
3532 // The root scroll layer should not have scrolled, because the input delta
3533 // was close to the layer's axis of movement.
3534 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
3537 // Now reset and scroll the same amount horizontally.
3538 child_ptr->SetScrollDelta(gfx::Vector2dF());
3539 gfx::Vector2d gesture_scroll_delta(10, 0);
3540 EXPECT_EQ(InputHandler::ScrollStarted,
3541 host_impl_->ScrollBegin(gfx::Point(1, 1),
3542 InputHandler::Gesture));
3543 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3544 host_impl_->ScrollEnd();
3546 // The child layer should have scrolled down in its local coordinates an
3547 // amount proportional to the angle between it and the input scroll delta.
3548 gfx::Vector2d expected_scroll_delta(
3550 -gesture_scroll_delta.x() *
3551 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
3552 scoped_ptr<ScrollAndScaleSet> scroll_info =
3553 host_impl_->ProcessScrollDeltas();
3554 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
3556 // The root scroll layer should have scrolled more, since the input scroll
3557 // delta was mostly orthogonal to the child layer's vertical scroll axis.
3558 gfx::Vector2d expected_root_scroll_delta(
3559 gesture_scroll_delta.x() *
3560 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
3562 ExpectContains(*scroll_info.get(),
3563 scroll_layer->id(),
3564 expected_root_scroll_delta);
3568 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
3569 LayerImpl* scroll_layer =
3570 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3572 // Scale the layer to twice its normal size.
3573 int scale = 2;
3574 gfx::Transform scale_transform;
3575 scale_transform.Scale(scale, scale);
3576 scroll_layer->SetTransform(scale_transform);
3578 gfx::Size surface_size(50, 50);
3579 host_impl_->SetViewportSize(surface_size);
3580 DrawFrame();
3582 // Scroll down in screen coordinates with a gesture.
3583 gfx::Vector2d scroll_delta(0, 10);
3584 EXPECT_EQ(InputHandler::ScrollStarted,
3585 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3586 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3587 host_impl_->ScrollEnd();
3589 // The layer should have scrolled down in its local coordinates, but half the
3590 // amount.
3591 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3592 ExpectContains(*scroll_info.get(),
3593 scroll_layer->id(),
3594 gfx::Vector2d(0, scroll_delta.y() / scale));
3596 // Reset and scroll down with the wheel.
3597 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3598 gfx::Vector2d wheel_scroll_delta(0, 10);
3599 EXPECT_EQ(InputHandler::ScrollStarted,
3600 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3601 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3602 host_impl_->ScrollEnd();
3604 // It should apply the scale factor to the scroll delta for the wheel event.
3605 scroll_info = host_impl_->ProcessScrollDeltas();
3606 ExpectContains(*scroll_info.get(),
3607 scroll_layer->id(),
3608 wheel_scroll_delta);
3611 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
3612 int width = 332;
3613 int height = 20;
3614 int scale = 3;
3615 SetupScrollAndContentsLayers(gfx::Size(width, height));
3616 host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
3617 gfx::Size(width * scale - 1, height * scale));
3618 host_impl_->SetDeviceScaleFactor(scale);
3619 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
3621 LayerImpl* inner_viewport_scroll_layer =
3622 host_impl_->active_tree()->InnerViewportScrollLayer();
3623 EXPECT_EQ(gfx::ScrollOffset(0, 0),
3624 inner_viewport_scroll_layer->MaxScrollOffset());
3627 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
3628 public:
3629 TestScrollOffsetDelegate()
3630 : page_scale_factor_(0.f),
3631 min_page_scale_factor_(-1.f),
3632 max_page_scale_factor_(-1.f) {}
3634 ~TestScrollOffsetDelegate() override {}
3636 gfx::ScrollOffset GetTotalScrollOffset() override {
3637 return getter_return_value_;
3640 bool IsExternalFlingActive() const override { return false; }
3642 void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
3643 const gfx::ScrollOffset& max_scroll_offset,
3644 const gfx::SizeF& scrollable_size,
3645 float page_scale_factor,
3646 float min_page_scale_factor,
3647 float max_page_scale_factor) override {
3648 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
3649 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
3650 last_set_scroll_offset_ = total_scroll_offset;
3651 max_scroll_offset_ = max_scroll_offset;
3652 scrollable_size_ = scrollable_size;
3653 page_scale_factor_ = page_scale_factor;
3654 min_page_scale_factor_ = min_page_scale_factor;
3655 max_page_scale_factor_ = max_page_scale_factor;
3658 gfx::ScrollOffset last_set_scroll_offset() {
3659 return last_set_scroll_offset_;
3662 void set_getter_return_value(const gfx::ScrollOffset& value) {
3663 getter_return_value_ = value;
3666 gfx::ScrollOffset max_scroll_offset() const {
3667 return max_scroll_offset_;
3670 gfx::SizeF scrollable_size() const {
3671 return scrollable_size_;
3674 float page_scale_factor() const {
3675 return page_scale_factor_;
3678 float min_page_scale_factor() const {
3679 return min_page_scale_factor_;
3682 float max_page_scale_factor() const {
3683 return max_page_scale_factor_;
3686 private:
3687 gfx::ScrollOffset last_set_scroll_offset_;
3688 gfx::ScrollOffset getter_return_value_;
3689 gfx::ScrollOffset max_scroll_offset_;
3690 gfx::SizeF scrollable_size_;
3691 float page_scale_factor_;
3692 float min_page_scale_factor_;
3693 float max_page_scale_factor_;
3696 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
3697 TestScrollOffsetDelegate scroll_delegate;
3698 host_impl_->SetViewportSize(gfx::Size(10, 20));
3699 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3700 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3701 clip_layer->SetBounds(gfx::Size(10, 20));
3703 // Setting the delegate results in the current scroll offset being set.
3704 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
3705 scroll_layer->SetScrollOffset(gfx::ScrollOffset());
3706 scroll_layer->SetScrollDelta(initial_scroll_delta);
3707 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3708 EXPECT_EQ(initial_scroll_delta.ToString(),
3709 scroll_delegate.last_set_scroll_offset().ToString());
3711 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3712 // page_scale_factor and {min|max}_page_scale_factor being set.
3713 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
3714 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset());
3715 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3716 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
3717 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
3719 // Updating page scale immediately updates the delegate.
3720 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 0.5f, 4.f);
3721 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
3722 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3723 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3724 host_impl_->SetPageScaleOnActiveTree(2.f * 1.5f);
3725 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
3726 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3727 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3728 host_impl_->SetPageScaleOnActiveTree(2.f);
3729 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
3730 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3731 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3732 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3734 // The pinch gesture doesn't put the delegate into a state where the scroll
3735 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3736 // delegate).
3737 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3738 host_impl_->PinchGestureBegin();
3739 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
3740 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
3741 host_impl_->PinchGestureEnd();
3742 host_impl_->ScrollEnd();
3744 // Scrolling should be relative to the offset as returned by the delegate.
3745 gfx::Vector2dF scroll_delta(0.f, 10.f);
3746 gfx::ScrollOffset current_offset(7.f, 8.f);
3748 scroll_delegate.set_getter_return_value(current_offset);
3749 EXPECT_EQ(InputHandler::ScrollStarted,
3750 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3752 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3753 EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
3754 scroll_delegate.last_set_scroll_offset());
3756 current_offset = gfx::ScrollOffset(42.f, 41.f);
3757 scroll_delegate.set_getter_return_value(current_offset);
3758 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3759 EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
3760 scroll_delegate.last_set_scroll_offset());
3761 host_impl_->ScrollEnd();
3762 scroll_delegate.set_getter_return_value(gfx::ScrollOffset());
3764 // Forces a full tree synchronization and ensures that the scroll delegate
3765 // sees the correct size of the new tree.
3766 gfx::Size new_size(42, 24);
3767 host_impl_->CreatePendingTree();
3768 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
3769 host_impl_->ActivateSyncTree();
3770 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
3772 // Un-setting the delegate should propagate the delegate's current offset to
3773 // the root scrollable layer.
3774 current_offset = gfx::ScrollOffset(13.f, 12.f);
3775 scroll_delegate.set_getter_return_value(current_offset);
3776 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3778 EXPECT_EQ(current_offset.ToString(),
3779 scroll_layer->TotalScrollOffset().ToString());
3782 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
3783 const gfx::Transform target_space_transform =
3784 layer->draw_properties().target_space_transform;
3785 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
3786 gfx::Point translated_point;
3787 target_space_transform.TransformPoint(&translated_point);
3788 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
3789 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
3792 TEST_F(LayerTreeHostImplTest,
3793 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
3794 TestScrollOffsetDelegate scroll_delegate;
3795 host_impl_->SetViewportSize(gfx::Size(10, 20));
3796 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3797 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3798 clip_layer->SetBounds(gfx::Size(10, 20));
3799 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3801 // Draw first frame to clear any pending draws and check scroll.
3802 DrawFrame();
3803 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
3804 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
3806 // Set external scroll delta on delegate and notify LayerTreeHost.
3807 gfx::ScrollOffset scroll_offset(10.f, 10.f);
3808 scroll_delegate.set_getter_return_value(scroll_offset);
3809 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
3811 // Check scroll delta reflected in layer.
3812 LayerTreeHostImpl::FrameData frame;
3813 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3814 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3815 host_impl_->DidDrawAllLayers(frame);
3816 EXPECT_FALSE(frame.has_no_damage);
3817 CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset));
3819 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3822 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
3823 InputHandlerScrollResult scroll_result;
3824 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3825 host_impl_->SetViewportSize(gfx::Size(50, 50));
3826 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
3827 DrawFrame();
3828 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3830 // In-bounds scrolling does not affect overscroll.
3831 EXPECT_EQ(InputHandler::ScrollStarted,
3832 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3833 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3834 EXPECT_TRUE(scroll_result.did_scroll);
3835 EXPECT_FALSE(scroll_result.did_overscroll_root);
3836 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
3837 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3839 // Overscroll events are reflected immediately.
3840 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
3841 EXPECT_TRUE(scroll_result.did_scroll);
3842 EXPECT_TRUE(scroll_result.did_overscroll_root);
3843 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
3844 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3845 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3846 host_impl_->accumulated_root_overscroll());
3848 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
3849 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
3850 EXPECT_TRUE(scroll_result.did_scroll);
3851 EXPECT_FALSE(scroll_result.did_overscroll_root);
3852 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
3853 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3854 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3855 host_impl_->accumulated_root_overscroll());
3857 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
3858 EXPECT_FALSE(scroll_result.did_scroll);
3859 EXPECT_TRUE(scroll_result.did_overscroll_root);
3860 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
3861 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3862 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3863 host_impl_->accumulated_root_overscroll());
3865 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
3866 EXPECT_TRUE(scroll_result.did_scroll);
3867 EXPECT_FALSE(scroll_result.did_overscroll_root);
3868 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
3869 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3870 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3871 host_impl_->accumulated_root_overscroll());
3873 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
3874 EXPECT_TRUE(scroll_result.did_scroll);
3875 EXPECT_TRUE(scroll_result.did_overscroll_root);
3876 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
3877 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
3878 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3879 host_impl_->accumulated_root_overscroll());
3881 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
3882 EXPECT_TRUE(scroll_result.did_scroll);
3883 EXPECT_TRUE(scroll_result.did_overscroll_root);
3884 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
3885 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
3886 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3887 host_impl_->accumulated_root_overscroll());
3889 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
3890 EXPECT_TRUE(scroll_result.did_scroll);
3891 EXPECT_TRUE(scroll_result.did_overscroll_root);
3892 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
3893 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3894 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3895 host_impl_->accumulated_root_overscroll());
3897 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
3898 // as no scroll occurs.
3899 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3900 EXPECT_FALSE(scroll_result.did_scroll);
3901 EXPECT_TRUE(scroll_result.did_overscroll_root);
3902 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
3903 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
3904 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3905 host_impl_->accumulated_root_overscroll());
3907 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3908 EXPECT_FALSE(scroll_result.did_scroll);
3909 EXPECT_TRUE(scroll_result.did_overscroll_root);
3910 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
3911 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
3912 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3913 host_impl_->accumulated_root_overscroll());
3915 // Overscroll resets on valid scroll.
3916 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3917 EXPECT_TRUE(scroll_result.did_scroll);
3918 EXPECT_FALSE(scroll_result.did_overscroll_root);
3919 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
3920 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3921 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3922 host_impl_->accumulated_root_overscroll());
3924 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3925 EXPECT_TRUE(scroll_result.did_scroll);
3926 EXPECT_TRUE(scroll_result.did_overscroll_root);
3927 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
3928 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3929 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
3930 host_impl_->accumulated_root_overscroll());
3932 host_impl_->ScrollEnd();
3936 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
3937 // Scroll child layers beyond their maximum scroll range and make sure root
3938 // overscroll does not accumulate.
3939 gfx::Size surface_size(10, 10);
3940 scoped_ptr<LayerImpl> root_clip =
3941 LayerImpl::Create(host_impl_->active_tree(), 4);
3942 scoped_ptr<LayerImpl> root =
3943 CreateScrollableLayer(1, surface_size, root_clip.get());
3945 scoped_ptr<LayerImpl> grand_child =
3946 CreateScrollableLayer(3, surface_size, root_clip.get());
3948 scoped_ptr<LayerImpl> child =
3949 CreateScrollableLayer(2, surface_size, root_clip.get());
3950 LayerImpl* grand_child_layer = grand_child.get();
3951 child->AddChild(grand_child.Pass());
3953 LayerImpl* child_layer = child.get();
3954 root->AddChild(child.Pass());
3955 root_clip->AddChild(root.Pass());
3956 child_layer->SetScrollOffset(gfx::ScrollOffset(0, 3));
3957 grand_child_layer->SetScrollOffset(gfx::ScrollOffset(0, 2));
3958 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3959 host_impl_->active_tree()->DidBecomeActive();
3960 host_impl_->SetViewportSize(surface_size);
3961 DrawFrame();
3963 gfx::Vector2d scroll_delta(0, -10);
3964 EXPECT_EQ(InputHandler::ScrollStarted,
3965 host_impl_->ScrollBegin(gfx::Point(),
3966 InputHandler::NonBubblingGesture));
3967 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3968 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3969 host_impl_->ScrollEnd();
3971 // The next time we scroll we should only scroll the parent, but overscroll
3972 // should still not reach the root layer.
3973 scroll_delta = gfx::Vector2d(0, -30);
3974 EXPECT_EQ(InputHandler::ScrollStarted,
3975 host_impl_->ScrollBegin(gfx::Point(5, 5),
3976 InputHandler::NonBubblingGesture));
3977 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3978 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3979 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3980 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
3981 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3982 host_impl_->ScrollEnd();
3984 // After scrolling the parent, another scroll on the opposite direction
3985 // should scroll the child.
3986 scroll_delta = gfx::Vector2d(0, 70);
3987 EXPECT_EQ(InputHandler::ScrollStarted,
3988 host_impl_->ScrollBegin(gfx::Point(5, 5),
3989 InputHandler::NonBubblingGesture));
3990 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3991 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3992 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3993 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3994 host_impl_->ScrollEnd();
3998 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
3999 // When we try to scroll a non-scrollable child layer, the scroll delta
4000 // should be applied to one of its ancestors if possible. Overscroll should
4001 // be reflected only when it has bubbled up to the root scrolling layer.
4002 gfx::Size surface_size(10, 10);
4003 gfx::Size content_size(20, 20);
4004 scoped_ptr<LayerImpl> root_clip =
4005 LayerImpl::Create(host_impl_->active_tree(), 3);
4006 scoped_ptr<LayerImpl> root =
4007 CreateScrollableLayer(1, content_size, root_clip.get());
4008 root->SetIsContainerForFixedPositionLayers(true);
4009 scoped_ptr<LayerImpl> child =
4010 CreateScrollableLayer(2, content_size, root_clip.get());
4012 child->SetScrollClipLayer(Layer::INVALID_ID);
4013 root->AddChild(child.Pass());
4014 root_clip->AddChild(root.Pass());
4016 host_impl_->SetViewportSize(surface_size);
4017 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4018 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4019 Layer::INVALID_ID);
4020 host_impl_->active_tree()->DidBecomeActive();
4021 DrawFrame();
4023 gfx::Vector2d scroll_delta(0, 8);
4024 EXPECT_EQ(InputHandler::ScrollStarted,
4025 host_impl_->ScrollBegin(gfx::Point(5, 5),
4026 InputHandler::Wheel));
4027 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4028 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4029 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4030 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
4031 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4032 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
4033 host_impl_->ScrollEnd();
4037 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
4038 LayerTreeSettings settings;
4039 CreateHostImpl(settings, CreateOutputSurface());
4041 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
4042 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4043 clip_layer->SetBounds(gfx::Size(50, 50));
4044 host_impl_->SetViewportSize(gfx::Size(50, 50));
4045 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4046 DrawFrame();
4047 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4049 // Even though the layer can't scroll the overscroll still happens.
4050 EXPECT_EQ(InputHandler::ScrollStarted,
4051 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
4052 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4053 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4056 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
4057 gfx::Size surface_size(980, 1439);
4058 gfx::Size content_size(980, 1438);
4059 float device_scale_factor = 1.5f;
4060 scoped_ptr<LayerImpl> root_clip =
4061 LayerImpl::Create(host_impl_->active_tree(), 3);
4062 scoped_ptr<LayerImpl> root =
4063 CreateScrollableLayer(1, content_size, root_clip.get());
4064 root->SetIsContainerForFixedPositionLayers(true);
4065 scoped_ptr<LayerImpl> child =
4066 CreateScrollableLayer(2, content_size, root_clip.get());
4067 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
4068 host_impl_->active_tree()->PushPageScaleFromMainThread(0.326531f, 0.326531f,
4069 5.f);
4070 host_impl_->SetPageScaleOnActiveTree(0.326531f);
4071 child->SetScrollClipLayer(Layer::INVALID_ID);
4072 root->AddChild(child.Pass());
4073 root_clip->AddChild(root.Pass());
4075 host_impl_->SetViewportSize(surface_size);
4076 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4077 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4078 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4079 Layer::INVALID_ID);
4080 host_impl_->active_tree()->DidBecomeActive();
4081 DrawFrame();
4083 // Horizontal & Vertical GlowEffect should not be applied when
4084 // content size is less then view port size. For Example Horizontal &
4085 // vertical GlowEffect should not be applied in about:blank page.
4086 EXPECT_EQ(InputHandler::ScrollStarted,
4087 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
4088 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
4089 EXPECT_EQ(gfx::Vector2dF().ToString(),
4090 host_impl_->accumulated_root_overscroll().ToString());
4092 host_impl_->ScrollEnd();
4096 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
4097 gfx::Size surface_size(100, 100);
4098 gfx::Size content_size(200, 200);
4099 scoped_ptr<LayerImpl> root_clip =
4100 LayerImpl::Create(host_impl_->active_tree(), 3);
4101 scoped_ptr<LayerImpl> root =
4102 CreateScrollableLayer(1, content_size, root_clip.get());
4103 root->SetIsContainerForFixedPositionLayers(true);
4104 scoped_ptr<LayerImpl> child =
4105 CreateScrollableLayer(2, content_size, root_clip.get());
4107 child->SetScrollClipLayer(Layer::INVALID_ID);
4108 root->AddChild(child.Pass());
4109 root_clip->AddChild(root.Pass());
4111 host_impl_->SetViewportSize(surface_size);
4112 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4113 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4114 Layer::INVALID_ID);
4115 host_impl_->active_tree()->DidBecomeActive();
4116 DrawFrame();
4118 // Edge glow effect should be applicable only upon reaching Edges
4119 // of the content. unnecessary glow effect calls shouldn't be
4120 // called while scrolling up without reaching the edge of the content.
4121 EXPECT_EQ(InputHandler::ScrollStarted,
4122 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
4123 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4124 EXPECT_EQ(gfx::Vector2dF().ToString(),
4125 host_impl_->accumulated_root_overscroll().ToString());
4126 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
4127 EXPECT_EQ(gfx::Vector2dF().ToString(),
4128 host_impl_->accumulated_root_overscroll().ToString());
4129 host_impl_->ScrollEnd();
4130 // unusedrootDelta should be subtracted from applied delta so that
4131 // unwanted glow effect calls are not called.
4132 EXPECT_EQ(InputHandler::ScrollStarted,
4133 host_impl_->ScrollBegin(gfx::Point(0, 0),
4134 InputHandler::NonBubblingGesture));
4135 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
4136 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4137 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4138 host_impl_->accumulated_root_overscroll().ToString());
4140 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
4141 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4142 host_impl_->accumulated_root_overscroll().ToString());
4143 host_impl_->ScrollEnd();
4144 // TestCase to check kEpsilon, which prevents minute values to trigger
4145 // gloweffect without reaching edge.
4146 EXPECT_EQ(InputHandler::ScrollStarted,
4147 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
4148 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
4149 EXPECT_EQ(gfx::Vector2dF().ToString(),
4150 host_impl_->accumulated_root_overscroll().ToString());
4151 host_impl_->ScrollEnd();
4155 class BlendStateCheckLayer : public LayerImpl {
4156 public:
4157 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
4158 int id,
4159 ResourceProvider* resource_provider) {
4160 return make_scoped_ptr(
4161 new BlendStateCheckLayer(tree_impl, id, resource_provider));
4164 void AppendQuads(RenderPass* render_pass,
4165 const Occlusion& occlusion_in_content_space,
4166 AppendQuadsData* append_quads_data) override {
4167 quads_appended_ = true;
4169 gfx::Rect opaque_rect;
4170 if (contents_opaque())
4171 opaque_rect = quad_rect_;
4172 else
4173 opaque_rect = opaque_content_rect_;
4174 gfx::Rect visible_quad_rect = quad_rect_;
4176 SharedQuadState* shared_quad_state =
4177 render_pass->CreateAndAppendSharedQuadState();
4178 PopulateSharedQuadState(shared_quad_state);
4180 TileDrawQuad* test_blending_draw_quad =
4181 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
4182 test_blending_draw_quad->SetNew(shared_quad_state,
4183 quad_rect_,
4184 opaque_rect,
4185 visible_quad_rect,
4186 resource_id_,
4187 gfx::RectF(0.f, 0.f, 1.f, 1.f),
4188 gfx::Size(1, 1),
4189 false);
4190 test_blending_draw_quad->visible_rect = quad_visible_rect_;
4191 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
4192 EXPECT_EQ(has_render_surface_, !!render_surface());
4195 void SetExpectation(bool blend, bool has_render_surface) {
4196 blend_ = blend;
4197 has_render_surface_ = has_render_surface;
4198 quads_appended_ = false;
4201 bool quads_appended() const { return quads_appended_; }
4203 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
4204 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
4205 void SetOpaqueContentRect(const gfx::Rect& rect) {
4206 opaque_content_rect_ = rect;
4209 private:
4210 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
4211 int id,
4212 ResourceProvider* resource_provider)
4213 : LayerImpl(tree_impl, id),
4214 blend_(false),
4215 has_render_surface_(false),
4216 quads_appended_(false),
4217 quad_rect_(5, 5, 5, 5),
4218 quad_visible_rect_(5, 5, 5, 5),
4219 resource_id_(resource_provider->CreateResource(
4220 gfx::Size(1, 1),
4221 GL_CLAMP_TO_EDGE,
4222 ResourceProvider::TextureHintImmutable,
4223 RGBA_8888)) {
4224 resource_provider->AllocateForTesting(resource_id_);
4225 SetBounds(gfx::Size(10, 10));
4226 SetContentBounds(gfx::Size(10, 10));
4227 SetDrawsContent(true);
4230 bool blend_;
4231 bool has_render_surface_;
4232 bool quads_appended_;
4233 gfx::Rect quad_rect_;
4234 gfx::Rect opaque_content_rect_;
4235 gfx::Rect quad_visible_rect_;
4236 ResourceProvider::ResourceId resource_id_;
4239 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
4241 scoped_ptr<LayerImpl> root =
4242 LayerImpl::Create(host_impl_->active_tree(), 1);
4243 root->SetBounds(gfx::Size(10, 10));
4244 root->SetContentBounds(root->bounds());
4245 root->SetDrawsContent(false);
4246 host_impl_->active_tree()->SetRootLayer(root.Pass());
4248 LayerImpl* root = host_impl_->active_tree()->root_layer();
4250 root->AddChild(
4251 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4253 host_impl_->resource_provider()));
4254 BlendStateCheckLayer* layer1 =
4255 static_cast<BlendStateCheckLayer*>(root->children()[0]);
4256 layer1->SetPosition(gfx::PointF(2.f, 2.f));
4258 LayerTreeHostImpl::FrameData frame;
4260 // Opaque layer, drawn without blending.
4261 layer1->SetContentsOpaque(true);
4262 layer1->SetExpectation(false, false);
4263 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4264 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4265 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4266 EXPECT_TRUE(layer1->quads_appended());
4267 host_impl_->DidDrawAllLayers(frame);
4269 // Layer with translucent content and painting, so drawn with blending.
4270 layer1->SetContentsOpaque(false);
4271 layer1->SetExpectation(true, false);
4272 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4273 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4274 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4275 EXPECT_TRUE(layer1->quads_appended());
4276 host_impl_->DidDrawAllLayers(frame);
4278 // Layer with translucent opacity, drawn with blending.
4279 layer1->SetContentsOpaque(true);
4280 layer1->SetOpacity(0.5f);
4281 layer1->SetExpectation(true, false);
4282 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4283 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4284 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4285 EXPECT_TRUE(layer1->quads_appended());
4286 host_impl_->DidDrawAllLayers(frame);
4288 // Layer with translucent opacity and painting, drawn with blending.
4289 layer1->SetContentsOpaque(true);
4290 layer1->SetOpacity(0.5f);
4291 layer1->SetExpectation(true, false);
4292 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4293 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4294 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4295 EXPECT_TRUE(layer1->quads_appended());
4296 host_impl_->DidDrawAllLayers(frame);
4298 layer1->AddChild(
4299 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4301 host_impl_->resource_provider()));
4302 BlendStateCheckLayer* layer2 =
4303 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
4304 layer2->SetPosition(gfx::PointF(4.f, 4.f));
4306 // 2 opaque layers, drawn without blending.
4307 layer1->SetContentsOpaque(true);
4308 layer1->SetOpacity(1.f);
4309 layer1->SetExpectation(false, false);
4310 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4311 layer2->SetContentsOpaque(true);
4312 layer2->SetOpacity(1.f);
4313 layer2->SetExpectation(false, false);
4314 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4315 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4316 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4317 EXPECT_TRUE(layer1->quads_appended());
4318 EXPECT_TRUE(layer2->quads_appended());
4319 host_impl_->DidDrawAllLayers(frame);
4321 // Parent layer with translucent content, drawn with blending.
4322 // Child layer with opaque content, drawn without blending.
4323 layer1->SetContentsOpaque(false);
4324 layer1->SetExpectation(true, false);
4325 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4326 layer2->SetExpectation(false, false);
4327 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4328 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4329 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4330 EXPECT_TRUE(layer1->quads_appended());
4331 EXPECT_TRUE(layer2->quads_appended());
4332 host_impl_->DidDrawAllLayers(frame);
4334 // Parent layer with translucent content but opaque painting, drawn without
4335 // blending.
4336 // Child layer with opaque content, drawn without blending.
4337 layer1->SetContentsOpaque(true);
4338 layer1->SetExpectation(false, false);
4339 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4340 layer2->SetExpectation(false, false);
4341 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4342 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4343 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4344 EXPECT_TRUE(layer1->quads_appended());
4345 EXPECT_TRUE(layer2->quads_appended());
4346 host_impl_->DidDrawAllLayers(frame);
4348 // Parent layer with translucent opacity and opaque content. Since it has a
4349 // drawing child, it's drawn to a render surface which carries the opacity,
4350 // so it's itself drawn without blending.
4351 // Child layer with opaque content, drawn without blending (parent surface
4352 // carries the inherited opacity).
4353 layer1->SetContentsOpaque(true);
4354 layer1->SetOpacity(0.5f);
4355 layer1->SetExpectation(false, true);
4356 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4357 layer2->SetExpectation(false, false);
4358 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4359 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
4360 host_impl_->active_tree()->root_layer());
4361 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4362 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4363 EXPECT_TRUE(layer1->quads_appended());
4364 EXPECT_TRUE(layer2->quads_appended());
4365 host_impl_->DidDrawAllLayers(frame);
4367 // Draw again, but with child non-opaque, to make sure
4368 // layer1 not culled.
4369 layer1->SetContentsOpaque(true);
4370 layer1->SetOpacity(1.f);
4371 layer1->SetExpectation(false, false);
4372 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4373 layer2->SetContentsOpaque(true);
4374 layer2->SetOpacity(0.5f);
4375 layer2->SetExpectation(true, false);
4376 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4377 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4378 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4379 EXPECT_TRUE(layer1->quads_appended());
4380 EXPECT_TRUE(layer2->quads_appended());
4381 host_impl_->DidDrawAllLayers(frame);
4383 // A second way of making the child non-opaque.
4384 layer1->SetContentsOpaque(true);
4385 layer1->SetOpacity(1.f);
4386 layer1->SetExpectation(false, false);
4387 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4388 layer2->SetContentsOpaque(false);
4389 layer2->SetOpacity(1.f);
4390 layer2->SetExpectation(true, false);
4391 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4392 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4393 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4394 EXPECT_TRUE(layer1->quads_appended());
4395 EXPECT_TRUE(layer2->quads_appended());
4396 host_impl_->DidDrawAllLayers(frame);
4398 // And when the layer says its not opaque but is painted opaque, it is not
4399 // blended.
4400 layer1->SetContentsOpaque(true);
4401 layer1->SetOpacity(1.f);
4402 layer1->SetExpectation(false, false);
4403 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4404 layer2->SetContentsOpaque(true);
4405 layer2->SetOpacity(1.f);
4406 layer2->SetExpectation(false, false);
4407 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4408 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4409 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4410 EXPECT_TRUE(layer1->quads_appended());
4411 EXPECT_TRUE(layer2->quads_appended());
4412 host_impl_->DidDrawAllLayers(frame);
4414 // Layer with partially opaque contents, drawn with blending.
4415 layer1->SetContentsOpaque(false);
4416 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4417 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
4418 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4419 layer1->SetExpectation(true, false);
4420 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4421 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4422 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4423 EXPECT_TRUE(layer1->quads_appended());
4424 host_impl_->DidDrawAllLayers(frame);
4426 // Layer with partially opaque contents partially culled, drawn with blending.
4427 layer1->SetContentsOpaque(false);
4428 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4429 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
4430 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4431 layer1->SetExpectation(true, false);
4432 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4433 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4434 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4435 EXPECT_TRUE(layer1->quads_appended());
4436 host_impl_->DidDrawAllLayers(frame);
4438 // Layer with partially opaque contents culled, drawn with blending.
4439 layer1->SetContentsOpaque(false);
4440 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4441 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
4442 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4443 layer1->SetExpectation(true, false);
4444 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4445 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4446 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4447 EXPECT_TRUE(layer1->quads_appended());
4448 host_impl_->DidDrawAllLayers(frame);
4450 // Layer with partially opaque contents and translucent contents culled, drawn
4451 // without blending.
4452 layer1->SetContentsOpaque(false);
4453 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4454 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
4455 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4456 layer1->SetExpectation(false, false);
4457 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4458 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4459 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4460 EXPECT_TRUE(layer1->quads_appended());
4461 host_impl_->DidDrawAllLayers(frame);
4464 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
4465 protected:
4466 LayerTreeHostImplViewportCoveredTest() :
4467 gutter_quad_material_(DrawQuad::SOLID_COLOR),
4468 child_(NULL),
4469 did_activate_pending_tree_(false) {}
4471 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
4472 if (always_draw) {
4473 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
4475 return FakeOutputSurface::Create3d();
4478 void SetupActiveTreeLayers() {
4479 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
4480 host_impl_->active_tree()->SetRootLayer(
4481 LayerImpl::Create(host_impl_->active_tree(), 1));
4482 host_impl_->active_tree()->root_layer()->AddChild(
4483 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4485 host_impl_->resource_provider()));
4486 child_ = static_cast<BlendStateCheckLayer*>(
4487 host_impl_->active_tree()->root_layer()->children()[0]);
4488 child_->SetExpectation(false, false);
4489 child_->SetContentsOpaque(true);
4492 // Expect no gutter rects.
4493 void TestLayerCoversFullViewport() {
4494 gfx::Rect layer_rect(viewport_size_);
4495 child_->SetPosition(layer_rect.origin());
4496 child_->SetBounds(layer_rect.size());
4497 child_->SetContentBounds(layer_rect.size());
4498 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4499 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4501 LayerTreeHostImpl::FrameData frame;
4502 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4503 ASSERT_EQ(1u, frame.render_passes.size());
4505 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
4506 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4507 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4509 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4510 host_impl_->DidDrawAllLayers(frame);
4513 // Expect fullscreen gutter rect.
4514 void TestEmptyLayer() {
4515 gfx::Rect layer_rect(0, 0, 0, 0);
4516 child_->SetPosition(layer_rect.origin());
4517 child_->SetBounds(layer_rect.size());
4518 child_->SetContentBounds(layer_rect.size());
4519 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4520 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4522 LayerTreeHostImpl::FrameData frame;
4523 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4524 ASSERT_EQ(1u, frame.render_passes.size());
4526 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
4527 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4528 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4530 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4531 host_impl_->DidDrawAllLayers(frame);
4534 // Expect four surrounding gutter rects.
4535 void TestLayerInMiddleOfViewport() {
4536 gfx::Rect layer_rect(500, 500, 200, 200);
4537 child_->SetPosition(layer_rect.origin());
4538 child_->SetBounds(layer_rect.size());
4539 child_->SetContentBounds(layer_rect.size());
4540 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4541 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4543 LayerTreeHostImpl::FrameData frame;
4544 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4545 ASSERT_EQ(1u, frame.render_passes.size());
4547 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
4548 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
4549 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4551 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4552 host_impl_->DidDrawAllLayers(frame);
4555 // Expect no gutter rects.
4556 void TestLayerIsLargerThanViewport() {
4557 gfx::Rect layer_rect(viewport_size_.width() + 10,
4558 viewport_size_.height() + 10);
4559 child_->SetPosition(layer_rect.origin());
4560 child_->SetBounds(layer_rect.size());
4561 child_->SetContentBounds(layer_rect.size());
4562 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4563 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4565 LayerTreeHostImpl::FrameData frame;
4566 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4567 ASSERT_EQ(1u, frame.render_passes.size());
4569 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
4570 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4571 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4573 host_impl_->DidDrawAllLayers(frame);
4576 void DidActivateSyncTree() override { did_activate_pending_tree_ = true; }
4578 void set_gutter_quad_material(DrawQuad::Material material) {
4579 gutter_quad_material_ = material;
4581 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
4582 gutter_texture_size_ = gutter_texture_size;
4585 protected:
4586 size_t CountGutterQuads(const QuadList& quad_list) {
4587 size_t num_gutter_quads = 0;
4588 for (const auto& quad : quad_list) {
4589 num_gutter_quads += (quad->material == gutter_quad_material_) ? 1 : 0;
4591 return num_gutter_quads;
4594 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
4595 LayerTestCommon::VerifyQuadsExactlyCoverRect(
4596 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
4599 // Make sure that the texture coordinates match their expectations.
4600 void ValidateTextureDrawQuads(const QuadList& quad_list) {
4601 for (const auto& quad : quad_list) {
4602 if (quad->material != DrawQuad::TEXTURE_CONTENT)
4603 continue;
4604 const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
4605 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
4606 gutter_texture_size_, host_impl_->device_scale_factor());
4607 EXPECT_EQ(texture_quad->uv_top_left.x(),
4608 texture_quad->rect.x() / gutter_texture_size_pixels.width());
4609 EXPECT_EQ(texture_quad->uv_top_left.y(),
4610 texture_quad->rect.y() / gutter_texture_size_pixels.height());
4611 EXPECT_EQ(
4612 texture_quad->uv_bottom_right.x(),
4613 texture_quad->rect.right() / gutter_texture_size_pixels.width());
4614 EXPECT_EQ(
4615 texture_quad->uv_bottom_right.y(),
4616 texture_quad->rect.bottom() / gutter_texture_size_pixels.height());
4620 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
4621 return gfx::ToRoundedSize(
4622 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
4625 DrawQuad::Material gutter_quad_material_;
4626 gfx::Size gutter_texture_size_;
4627 gfx::Size viewport_size_;
4628 BlendStateCheckLayer* child_;
4629 bool did_activate_pending_tree_;
4632 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
4633 viewport_size_ = gfx::Size(1000, 1000);
4635 bool always_draw = false;
4636 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4638 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4639 SetupActiveTreeLayers();
4640 TestLayerCoversFullViewport();
4641 TestEmptyLayer();
4642 TestLayerInMiddleOfViewport();
4643 TestLayerIsLargerThanViewport();
4646 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
4647 viewport_size_ = gfx::Size(1000, 1000);
4649 bool always_draw = false;
4650 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4652 host_impl_->SetDeviceScaleFactor(2.f);
4653 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4654 SetupActiveTreeLayers();
4655 TestLayerCoversFullViewport();
4656 TestEmptyLayer();
4657 TestLayerInMiddleOfViewport();
4658 TestLayerIsLargerThanViewport();
4661 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
4662 viewport_size_ = gfx::Size(1000, 1000);
4664 bool always_draw = false;
4665 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4667 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4668 SetupActiveTreeLayers();
4670 // Specify an overhang bitmap to use.
4671 bool is_opaque = false;
4672 UIResourceBitmap ui_resource_bitmap(gfx::Size(2, 2), is_opaque);
4673 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
4674 UIResourceId ui_resource_id = 12345;
4675 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
4676 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
4677 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
4678 set_gutter_texture_size(gfx::Size(32, 32));
4680 TestLayerCoversFullViewport();
4681 TestEmptyLayer();
4682 TestLayerInMiddleOfViewport();
4683 TestLayerIsLargerThanViewport();
4685 // Change the resource size.
4686 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
4687 set_gutter_texture_size(gfx::Size(128, 16));
4689 TestLayerCoversFullViewport();
4690 TestEmptyLayer();
4691 TestLayerInMiddleOfViewport();
4692 TestLayerIsLargerThanViewport();
4694 // Change the device scale factor
4695 host_impl_->SetDeviceScaleFactor(2.f);
4696 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4698 TestLayerCoversFullViewport();
4699 TestEmptyLayer();
4700 TestLayerInMiddleOfViewport();
4701 TestLayerIsLargerThanViewport();
4704 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
4705 viewport_size_ = gfx::Size(1000, 1000);
4707 bool always_draw = true;
4708 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4710 // Pending tree to force active_tree size invalid. Not used otherwise.
4711 host_impl_->CreatePendingTree();
4712 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4713 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4715 SetupActiveTreeLayers();
4716 TestEmptyLayer();
4717 TestLayerInMiddleOfViewport();
4718 TestLayerIsLargerThanViewport();
4721 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
4722 viewport_size_ = gfx::Size(1000, 1000);
4724 bool always_draw = true;
4725 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4727 // Set larger viewport and activate it to active tree.
4728 host_impl_->CreatePendingTree();
4729 gfx::Size larger_viewport(viewport_size_.width() + 100,
4730 viewport_size_.height() + 100);
4731 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
4732 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4733 host_impl_->ActivateSyncTree();
4734 EXPECT_TRUE(did_activate_pending_tree_);
4735 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
4737 // Shrink pending tree viewport without activating.
4738 host_impl_->CreatePendingTree();
4739 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4740 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4742 SetupActiveTreeLayers();
4743 TestEmptyLayer();
4744 TestLayerInMiddleOfViewport();
4745 TestLayerIsLargerThanViewport();
4748 class FakeDrawableLayerImpl: public LayerImpl {
4749 public:
4750 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4751 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl, id));
4753 protected:
4754 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
4755 : LayerImpl(tree_impl, id) {}
4758 // Only reshape when we know we are going to draw. Otherwise, the reshape
4759 // can leave the window at the wrong size if we never draw and the proper
4760 // viewport size is never set.
4761 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
4762 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4763 scoped_ptr<OutputSurface> output_surface(
4764 FakeOutputSurface::Create3d(provider));
4765 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4767 scoped_ptr<LayerImpl> root =
4768 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4769 root->SetBounds(gfx::Size(10, 10));
4770 root->SetContentBounds(gfx::Size(10, 10));
4771 root->SetDrawsContent(true);
4772 host_impl_->active_tree()->SetRootLayer(root.Pass());
4773 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
4774 provider->TestContext3d()->clear_reshape_called();
4776 LayerTreeHostImpl::FrameData frame;
4777 host_impl_->SetViewportSize(gfx::Size(10, 10));
4778 host_impl_->SetDeviceScaleFactor(1.f);
4779 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4780 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4781 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4782 EXPECT_EQ(provider->TestContext3d()->width(), 10);
4783 EXPECT_EQ(provider->TestContext3d()->height(), 10);
4784 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4785 host_impl_->DidDrawAllLayers(frame);
4786 provider->TestContext3d()->clear_reshape_called();
4788 host_impl_->SetViewportSize(gfx::Size(20, 30));
4789 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4790 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4791 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4792 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4793 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4794 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4795 host_impl_->DidDrawAllLayers(frame);
4796 provider->TestContext3d()->clear_reshape_called();
4798 host_impl_->SetDeviceScaleFactor(2.f);
4799 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4800 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4801 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4802 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4803 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4804 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
4805 host_impl_->DidDrawAllLayers(frame);
4806 provider->TestContext3d()->clear_reshape_called();
4809 // Make sure damage tracking propagates all the way to the graphics context,
4810 // where it should request to swap only the sub-buffer that is damaged.
4811 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
4812 scoped_refptr<TestContextProvider> context_provider(
4813 TestContextProvider::Create());
4814 context_provider->BindToCurrentThread();
4815 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
4817 scoped_ptr<FakeOutputSurface> output_surface(
4818 FakeOutputSurface::Create3d(context_provider));
4819 FakeOutputSurface* fake_output_surface = output_surface.get();
4821 // This test creates its own LayerTreeHostImpl, so
4822 // that we can force partial swap enabled.
4823 LayerTreeSettings settings;
4824 settings.renderer_settings.partial_swap_enabled = true;
4825 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4826 new TestSharedBitmapManager());
4827 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
4828 LayerTreeHostImpl::Create(settings,
4829 this,
4830 &proxy_,
4831 &stats_instrumentation_,
4832 shared_bitmap_manager.get(),
4833 NULL,
4835 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
4836 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
4838 scoped_ptr<LayerImpl> root =
4839 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
4840 scoped_ptr<LayerImpl> child =
4841 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
4842 child->SetPosition(gfx::PointF(12.f, 13.f));
4843 child->SetBounds(gfx::Size(14, 15));
4844 child->SetContentBounds(gfx::Size(14, 15));
4845 child->SetDrawsContent(true);
4846 root->SetBounds(gfx::Size(500, 500));
4847 root->SetContentBounds(gfx::Size(500, 500));
4848 root->SetDrawsContent(true);
4849 root->AddChild(child.Pass());
4850 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
4852 LayerTreeHostImpl::FrameData frame;
4854 // First frame, the entire screen should get swapped.
4855 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4856 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4857 layer_tree_host_impl->DidDrawAllLayers(frame);
4858 layer_tree_host_impl->SwapBuffers(frame);
4859 gfx::Rect expected_swap_rect(0, 0, 500, 500);
4860 EXPECT_EQ(expected_swap_rect.ToString(),
4861 fake_output_surface->last_swap_rect().ToString());
4863 // Second frame, only the damaged area should get swapped. Damage should be
4864 // the union of old and new child rects.
4865 // expected damage rect: gfx::Rect(26, 28);
4866 // expected swap rect: vertically flipped, with origin at bottom left corner.
4867 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
4868 gfx::PointF());
4869 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4870 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4871 host_impl_->DidDrawAllLayers(frame);
4872 layer_tree_host_impl->SwapBuffers(frame);
4874 // Make sure that partial swap is constrained to the viewport dimensions
4875 // expected damage rect: gfx::Rect(500, 500);
4876 // expected swap rect: flipped damage rect, but also clamped to viewport
4877 expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
4878 EXPECT_EQ(expected_swap_rect.ToString(),
4879 fake_output_surface->last_swap_rect().ToString());
4881 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
4882 // This will damage everything.
4883 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
4884 SK_ColorBLACK);
4885 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4886 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4887 host_impl_->DidDrawAllLayers(frame);
4888 layer_tree_host_impl->SwapBuffers(frame);
4890 expected_swap_rect = gfx::Rect(0, 0, 10, 10);
4891 EXPECT_EQ(expected_swap_rect.ToString(),
4892 fake_output_surface->last_swap_rect().ToString());
4895 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
4896 scoped_ptr<LayerImpl> root =
4897 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4898 scoped_ptr<LayerImpl> child =
4899 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
4900 child->SetBounds(gfx::Size(10, 10));
4901 child->SetContentBounds(gfx::Size(10, 10));
4902 child->SetDrawsContent(true);
4903 root->SetBounds(gfx::Size(10, 10));
4904 root->SetContentBounds(gfx::Size(10, 10));
4905 root->SetDrawsContent(true);
4906 root->SetForceRenderSurface(true);
4907 root->AddChild(child.Pass());
4909 host_impl_->active_tree()->SetRootLayer(root.Pass());
4911 LayerTreeHostImpl::FrameData frame;
4913 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4914 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
4915 EXPECT_EQ(1u, frame.render_passes.size());
4916 host_impl_->DidDrawAllLayers(frame);
4919 class FakeLayerWithQuads : public LayerImpl {
4920 public:
4921 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4922 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl, id));
4925 void AppendQuads(RenderPass* render_pass,
4926 const Occlusion& occlusion_in_content_space,
4927 AppendQuadsData* append_quads_data) override {
4928 SharedQuadState* shared_quad_state =
4929 render_pass->CreateAndAppendSharedQuadState();
4930 PopulateSharedQuadState(shared_quad_state);
4932 SkColor gray = SkColorSetRGB(100, 100, 100);
4933 gfx::Rect quad_rect(content_bounds());
4934 gfx::Rect visible_quad_rect(quad_rect);
4935 SolidColorDrawQuad* my_quad =
4936 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4937 my_quad->SetNew(
4938 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
4941 private:
4942 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
4943 : LayerImpl(tree_impl, id) {}
4946 class MockContext : public TestWebGraphicsContext3D {
4947 public:
4948 MOCK_METHOD1(useProgram, void(GLuint program));
4949 MOCK_METHOD5(uniform4f, void(GLint location,
4950 GLfloat x,
4951 GLfloat y,
4952 GLfloat z,
4953 GLfloat w));
4954 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
4955 GLsizei count,
4956 GLboolean transpose,
4957 const GLfloat* value));
4958 MOCK_METHOD4(drawElements, void(GLenum mode,
4959 GLsizei count,
4960 GLenum type,
4961 GLintptr offset));
4962 MOCK_METHOD1(enable, void(GLenum cap));
4963 MOCK_METHOD1(disable, void(GLenum cap));
4964 MOCK_METHOD4(scissor, void(GLint x,
4965 GLint y,
4966 GLsizei width,
4967 GLsizei height));
4970 class MockContextHarness {
4971 private:
4972 MockContext* context_;
4974 public:
4975 explicit MockContextHarness(MockContext* context)
4976 : context_(context) {
4977 context_->set_have_post_sub_buffer(true);
4979 // Catch "uninteresting" calls
4980 EXPECT_CALL(*context_, useProgram(_))
4981 .Times(0);
4983 EXPECT_CALL(*context_, drawElements(_, _, _, _))
4984 .Times(0);
4986 // These are not asserted
4987 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
4988 .WillRepeatedly(Return());
4990 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
4991 .WillRepeatedly(Return());
4993 // Any un-sanctioned calls to enable() are OK
4994 EXPECT_CALL(*context_, enable(_))
4995 .WillRepeatedly(Return());
4997 // Any un-sanctioned calls to disable() are OK
4998 EXPECT_CALL(*context_, disable(_))
4999 .WillRepeatedly(Return());
5002 void MustDrawSolidQuad() {
5003 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
5004 .WillOnce(Return())
5005 .RetiresOnSaturation();
5007 EXPECT_CALL(*context_, useProgram(_))
5008 .WillOnce(Return())
5009 .RetiresOnSaturation();
5012 void MustSetScissor(int x, int y, int width, int height) {
5013 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5014 .WillRepeatedly(Return());
5016 EXPECT_CALL(*context_, scissor(x, y, width, height))
5017 .Times(AtLeast(1))
5018 .WillRepeatedly(Return());
5021 void MustSetNoScissor() {
5022 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
5023 .WillRepeatedly(Return());
5025 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5026 .Times(0);
5028 EXPECT_CALL(*context_, scissor(_, _, _, _))
5029 .Times(0);
5033 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
5034 scoped_ptr<MockContext> mock_context_owned(new MockContext);
5035 MockContext* mock_context = mock_context_owned.get();
5036 MockContextHarness harness(mock_context);
5038 // Run test case
5039 LayerTreeSettings settings = DefaultSettings();
5040 settings.renderer_settings.partial_swap_enabled = false;
5041 CreateHostImpl(settings,
5042 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5043 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5045 // Without partial swap, and no clipping, no scissor is set.
5046 harness.MustDrawSolidQuad();
5047 harness.MustSetNoScissor();
5049 LayerTreeHostImpl::FrameData frame;
5050 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5051 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5052 host_impl_->DidDrawAllLayers(frame);
5054 Mock::VerifyAndClearExpectations(&mock_context);
5056 // Without partial swap, but a layer does clip its subtree, one scissor is
5057 // set.
5058 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
5059 harness.MustDrawSolidQuad();
5060 harness.MustSetScissor(0, 0, 10, 10);
5062 LayerTreeHostImpl::FrameData frame;
5063 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5064 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5065 host_impl_->DidDrawAllLayers(frame);
5067 Mock::VerifyAndClearExpectations(&mock_context);
5070 TEST_F(LayerTreeHostImplTest, PartialSwap) {
5071 scoped_ptr<MockContext> context_owned(new MockContext);
5072 MockContext* mock_context = context_owned.get();
5073 MockContextHarness harness(mock_context);
5075 LayerTreeSettings settings = DefaultSettings();
5076 settings.renderer_settings.partial_swap_enabled = true;
5077 CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass()));
5078 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5080 // The first frame is not a partially-swapped one.
5081 harness.MustSetScissor(0, 0, 10, 10);
5082 harness.MustDrawSolidQuad();
5084 LayerTreeHostImpl::FrameData frame;
5085 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5086 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5087 host_impl_->DidDrawAllLayers(frame);
5089 Mock::VerifyAndClearExpectations(&mock_context);
5091 // Damage a portion of the frame.
5092 host_impl_->active_tree()->root_layer()->SetUpdateRect(
5093 gfx::Rect(0, 0, 2, 3));
5095 // The second frame will be partially-swapped (the y coordinates are flipped).
5096 harness.MustSetScissor(0, 7, 2, 3);
5097 harness.MustDrawSolidQuad();
5099 LayerTreeHostImpl::FrameData frame;
5100 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5101 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5102 host_impl_->DidDrawAllLayers(frame);
5104 Mock::VerifyAndClearExpectations(&mock_context);
5107 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
5108 bool partial_swap,
5109 LayerTreeHostImplClient* client,
5110 Proxy* proxy,
5111 SharedBitmapManager* manager,
5112 RenderingStatsInstrumentation* stats_instrumentation) {
5113 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5114 scoped_ptr<OutputSurface> output_surface(
5115 FakeOutputSurface::Create3d(provider));
5116 provider->BindToCurrentThread();
5117 provider->TestContext3d()->set_have_post_sub_buffer(true);
5119 LayerTreeSettings settings;
5120 settings.renderer_settings.partial_swap_enabled = partial_swap;
5121 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
5122 settings, client, proxy, stats_instrumentation, manager, NULL, 0);
5123 my_host_impl->InitializeRenderer(output_surface.Pass());
5124 my_host_impl->SetViewportSize(gfx::Size(100, 100));
5127 Layers are created as follows:
5129 +--------------------+
5130 | 1 |
5131 | +-----------+ |
5132 | | 2 | |
5133 | | +-------------------+
5134 | | | 3 |
5135 | | +-------------------+
5136 | | | |
5137 | +-----------+ |
5140 +--------------------+
5142 Layers 1, 2 have render surfaces
5144 scoped_ptr<LayerImpl> root =
5145 LayerImpl::Create(my_host_impl->active_tree(), 1);
5146 scoped_ptr<LayerImpl> child =
5147 LayerImpl::Create(my_host_impl->active_tree(), 2);
5148 scoped_ptr<LayerImpl> grand_child =
5149 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
5151 gfx::Rect root_rect(0, 0, 100, 100);
5152 gfx::Rect child_rect(10, 10, 50, 50);
5153 gfx::Rect grand_child_rect(5, 5, 150, 150);
5155 root->CreateRenderSurface();
5156 root->SetPosition(root_rect.origin());
5157 root->SetBounds(root_rect.size());
5158 root->SetContentBounds(root->bounds());
5159 root->draw_properties().visible_content_rect = root_rect;
5160 root->SetDrawsContent(false);
5161 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
5163 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
5164 child->SetOpacity(0.5f);
5165 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
5166 child->SetContentBounds(child->bounds());
5167 child->draw_properties().visible_content_rect = child_rect;
5168 child->SetDrawsContent(false);
5169 child->SetForceRenderSurface(true);
5171 grand_child->SetPosition(grand_child_rect.origin());
5172 grand_child->SetBounds(grand_child_rect.size());
5173 grand_child->SetContentBounds(grand_child->bounds());
5174 grand_child->draw_properties().visible_content_rect = grand_child_rect;
5175 grand_child->SetDrawsContent(true);
5177 child->AddChild(grand_child.Pass());
5178 root->AddChild(child.Pass());
5180 my_host_impl->active_tree()->SetRootLayer(root.Pass());
5181 return my_host_impl.Pass();
5184 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
5185 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
5186 new TestSharedBitmapManager());
5187 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5188 SetupLayersForOpacity(true,
5189 this,
5190 &proxy_,
5191 shared_bitmap_manager.get(),
5192 &stats_instrumentation_);
5194 LayerTreeHostImpl::FrameData frame;
5195 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5197 // Verify all quads have been computed
5198 ASSERT_EQ(2U, frame.render_passes.size());
5199 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5200 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5201 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5202 frame.render_passes[0]->quad_list.front()->material);
5203 EXPECT_EQ(DrawQuad::RENDER_PASS,
5204 frame.render_passes[1]->quad_list.front()->material);
5206 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5207 my_host_impl->DidDrawAllLayers(frame);
5211 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
5212 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
5213 new TestSharedBitmapManager());
5214 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5215 SetupLayersForOpacity(false,
5216 this,
5217 &proxy_,
5218 shared_bitmap_manager.get(),
5219 &stats_instrumentation_);
5221 LayerTreeHostImpl::FrameData frame;
5222 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5224 // Verify all quads have been computed
5225 ASSERT_EQ(2U, frame.render_passes.size());
5226 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5227 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5228 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5229 frame.render_passes[0]->quad_list.front()->material);
5230 EXPECT_EQ(DrawQuad::RENDER_PASS,
5231 frame.render_passes[1]->quad_list.front()->material);
5233 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5234 my_host_impl->DidDrawAllLayers(frame);
5238 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
5239 scoped_ptr<TestWebGraphicsContext3D> context =
5240 TestWebGraphicsContext3D::Create();
5241 TestWebGraphicsContext3D* context3d = context.get();
5242 scoped_ptr<OutputSurface> output_surface(
5243 FakeOutputSurface::Create3d(context.Pass()));
5244 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5246 scoped_ptr<LayerImpl> root_layer =
5247 LayerImpl::Create(host_impl_->active_tree(), 1);
5248 root_layer->SetBounds(gfx::Size(10, 10));
5250 scoped_refptr<VideoFrame> softwareFrame =
5251 media::VideoFrame::CreateColorFrame(
5252 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5253 FakeVideoFrameProvider provider;
5254 provider.set_frame(softwareFrame);
5255 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
5256 host_impl_->active_tree(), 4, &provider, media::VIDEO_ROTATION_0);
5257 video_layer->SetBounds(gfx::Size(10, 10));
5258 video_layer->SetContentBounds(gfx::Size(10, 10));
5259 video_layer->SetDrawsContent(true);
5260 root_layer->AddChild(video_layer.Pass());
5262 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
5263 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
5264 io_surface_layer->SetBounds(gfx::Size(10, 10));
5265 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
5266 io_surface_layer->SetDrawsContent(true);
5267 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5268 root_layer->AddChild(io_surface_layer.Pass());
5270 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
5272 EXPECT_EQ(0u, context3d->NumTextures());
5274 LayerTreeHostImpl::FrameData frame;
5275 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5276 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5277 host_impl_->DidDrawAllLayers(frame);
5278 host_impl_->SwapBuffers(frame);
5280 EXPECT_GT(context3d->NumTextures(), 0u);
5282 // Kill the layer tree.
5283 host_impl_->active_tree()->SetRootLayer(
5284 LayerImpl::Create(host_impl_->active_tree(), 100));
5285 // There should be no textures left in use after.
5286 EXPECT_EQ(0u, context3d->NumTextures());
5289 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
5290 public:
5291 MOCK_METHOD1(useProgram, void(GLuint program));
5292 MOCK_METHOD4(drawElements, void(GLenum mode,
5293 GLsizei count,
5294 GLenum type,
5295 GLintptr offset));
5298 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
5299 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
5300 new MockDrawQuadsToFillScreenContext);
5301 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
5303 // Run test case
5304 LayerTreeSettings settings = DefaultSettings();
5305 settings.renderer_settings.partial_swap_enabled = false;
5306 CreateHostImpl(settings,
5307 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5308 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5309 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
5311 // Verify one quad is drawn when transparent background set is not set.
5312 host_impl_->active_tree()->set_has_transparent_background(false);
5313 EXPECT_CALL(*mock_context, useProgram(_))
5314 .Times(1);
5315 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
5316 .Times(1);
5317 LayerTreeHostImpl::FrameData frame;
5318 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5319 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5320 host_impl_->DidDrawAllLayers(frame);
5321 Mock::VerifyAndClearExpectations(&mock_context);
5323 // Verify no quads are drawn when transparent background is set.
5324 host_impl_->active_tree()->set_has_transparent_background(true);
5325 host_impl_->SetFullRootLayerDamage();
5326 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5327 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5328 host_impl_->DidDrawAllLayers(frame);
5329 Mock::VerifyAndClearExpectations(&mock_context);
5332 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
5333 set_reduce_memory_result(false);
5335 // If changing the memory limit wouldn't result in changing what was
5336 // committed, then no commit should be requested.
5337 set_reduce_memory_result(false);
5338 host_impl_->set_max_memory_needed_bytes(
5339 host_impl_->memory_allocation_limit_bytes() - 1);
5340 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5341 host_impl_->memory_allocation_limit_bytes() - 1));
5342 EXPECT_FALSE(did_request_commit_);
5343 did_request_commit_ = false;
5345 // If changing the memory limit would result in changing what was
5346 // committed, then a commit should be requested, even though nothing was
5347 // evicted.
5348 set_reduce_memory_result(false);
5349 host_impl_->set_max_memory_needed_bytes(
5350 host_impl_->memory_allocation_limit_bytes());
5351 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5352 host_impl_->memory_allocation_limit_bytes() - 1));
5353 EXPECT_TRUE(did_request_commit_);
5354 did_request_commit_ = false;
5356 // Especially if changing the memory limit caused evictions, we need
5357 // to re-commit.
5358 set_reduce_memory_result(true);
5359 host_impl_->set_max_memory_needed_bytes(1);
5360 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5361 host_impl_->memory_allocation_limit_bytes() - 1));
5362 EXPECT_TRUE(did_request_commit_);
5363 did_request_commit_ = false;
5365 // But if we set it to the same value that it was before, we shouldn't
5366 // re-commit.
5367 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5368 host_impl_->memory_allocation_limit_bytes()));
5369 EXPECT_FALSE(did_request_commit_);
5372 class LayerTreeHostImplTestWithDelegatingRenderer
5373 : public LayerTreeHostImplTest {
5374 protected:
5375 scoped_ptr<OutputSurface> CreateOutputSurface() override {
5376 return FakeOutputSurface::CreateDelegating3d();
5379 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
5380 bool expect_to_draw = !expected_damage.IsEmpty();
5382 LayerTreeHostImpl::FrameData frame;
5383 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5385 if (!expect_to_draw) {
5386 // With no damage, we don't draw, and no quads are created.
5387 ASSERT_EQ(0u, frame.render_passes.size());
5388 } else {
5389 ASSERT_EQ(1u, frame.render_passes.size());
5391 // Verify the damage rect for the root render pass.
5392 const RenderPass* root_render_pass = frame.render_passes.back();
5393 EXPECT_EQ(expected_damage, root_render_pass->damage_rect);
5395 // Verify the root and child layers' quads are generated and not being
5396 // culled.
5397 ASSERT_EQ(2u, root_render_pass->quad_list.size());
5399 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
5400 gfx::RectF expected_child_visible_rect(child->content_bounds());
5401 EXPECT_EQ(expected_child_visible_rect,
5402 root_render_pass->quad_list.front()->visible_rect);
5404 LayerImpl* root = host_impl_->active_tree()->root_layer();
5405 gfx::RectF expected_root_visible_rect(root->content_bounds());
5406 EXPECT_EQ(expected_root_visible_rect,
5407 root_render_pass->quad_list.ElementAt(1)->visible_rect);
5410 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5411 host_impl_->DidDrawAllLayers(frame);
5412 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
5416 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
5417 scoped_ptr<SolidColorLayerImpl> root =
5418 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5419 root->SetPosition(gfx::PointF());
5420 root->SetBounds(gfx::Size(10, 10));
5421 root->SetContentBounds(gfx::Size(10, 10));
5422 root->SetDrawsContent(true);
5424 // Child layer is in the bottom right corner.
5425 scoped_ptr<SolidColorLayerImpl> child =
5426 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
5427 child->SetPosition(gfx::PointF(9.f, 9.f));
5428 child->SetBounds(gfx::Size(1, 1));
5429 child->SetContentBounds(gfx::Size(1, 1));
5430 child->SetDrawsContent(true);
5431 root->AddChild(child.Pass());
5433 host_impl_->active_tree()->SetRootLayer(root.Pass());
5435 // Draw a frame. In the first frame, the entire viewport should be damaged.
5436 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
5437 DrawFrameAndTestDamage(full_frame_damage);
5439 // The second frame has damage that doesn't touch the child layer. Its quads
5440 // should still be generated.
5441 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
5442 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
5443 DrawFrameAndTestDamage(small_damage);
5445 // The third frame should have no damage, so no quads should be generated.
5446 gfx::Rect no_damage;
5447 DrawFrameAndTestDamage(no_damage);
5450 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5451 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5452 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
5453 LayerTreeSettings settings;
5454 CreateHostImpl(settings, CreateOutputSurface());
5455 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
5458 class FakeMaskLayerImpl : public LayerImpl {
5459 public:
5460 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
5461 int id) {
5462 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
5465 void GetContentsResourceId(ResourceProvider::ResourceId* resource_id,
5466 gfx::Size* resource_size) const override {
5467 *resource_id = 0;
5470 private:
5471 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
5472 : LayerImpl(tree_impl, id) {}
5475 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
5476 LayerTreeSettings settings;
5477 settings.layer_transforms_should_scale_layer_contents = true;
5478 CreateHostImpl(settings, CreateOutputSurface());
5480 // Root
5481 // |
5482 // +-- Scaling Layer (adds a 2x scale)
5483 // |
5484 // +-- Content Layer
5485 // +--Mask
5486 scoped_ptr<LayerImpl> scoped_root =
5487 LayerImpl::Create(host_impl_->active_tree(), 1);
5488 LayerImpl* root = scoped_root.get();
5489 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5491 scoped_ptr<LayerImpl> scoped_scaling_layer =
5492 LayerImpl::Create(host_impl_->active_tree(), 2);
5493 LayerImpl* scaling_layer = scoped_scaling_layer.get();
5494 root->AddChild(scoped_scaling_layer.Pass());
5496 scoped_ptr<LayerImpl> scoped_content_layer =
5497 LayerImpl::Create(host_impl_->active_tree(), 3);
5498 LayerImpl* content_layer = scoped_content_layer.get();
5499 scaling_layer->AddChild(scoped_content_layer.Pass());
5501 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5502 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5503 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5504 content_layer->SetMaskLayer(scoped_mask_layer.Pass());
5506 gfx::Size root_size(100, 100);
5507 root->SetBounds(root_size);
5508 root->SetContentBounds(root_size);
5509 root->SetPosition(gfx::PointF());
5511 gfx::Size scaling_layer_size(50, 50);
5512 scaling_layer->SetBounds(scaling_layer_size);
5513 scaling_layer->SetContentBounds(scaling_layer_size);
5514 scaling_layer->SetPosition(gfx::PointF());
5515 gfx::Transform scale;
5516 scale.Scale(2.f, 2.f);
5517 scaling_layer->SetTransform(scale);
5519 content_layer->SetBounds(scaling_layer_size);
5520 content_layer->SetContentBounds(scaling_layer_size);
5521 content_layer->SetPosition(gfx::PointF());
5522 content_layer->SetDrawsContent(true);
5524 mask_layer->SetBounds(scaling_layer_size);
5525 mask_layer->SetContentBounds(scaling_layer_size);
5526 mask_layer->SetPosition(gfx::PointF());
5527 mask_layer->SetDrawsContent(true);
5530 // Check that the tree scaling is correctly taken into account for the mask,
5531 // that should fully map onto the quad.
5532 float device_scale_factor = 1.f;
5533 host_impl_->SetViewportSize(root_size);
5534 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5536 LayerTreeHostImpl::FrameData frame;
5537 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5539 ASSERT_EQ(1u, frame.render_passes.size());
5540 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5541 ASSERT_EQ(DrawQuad::RENDER_PASS,
5542 frame.render_passes[0]->quad_list.front()->material);
5543 const RenderPassDrawQuad* render_pass_quad =
5544 RenderPassDrawQuad::MaterialCast(
5545 frame.render_passes[0]->quad_list.front());
5546 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5547 render_pass_quad->rect.ToString());
5548 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5549 render_pass_quad->MaskUVRect().ToString());
5550 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5551 render_pass_quad->mask_uv_scale.ToString());
5553 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5554 host_impl_->DidDrawAllLayers(frame);
5558 // Applying a DSF should change the render surface size, but won't affect
5559 // which part of the mask is used.
5560 device_scale_factor = 2.f;
5561 gfx::Size device_viewport =
5562 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5563 host_impl_->SetViewportSize(device_viewport);
5564 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5565 host_impl_->active_tree()->set_needs_update_draw_properties();
5567 LayerTreeHostImpl::FrameData frame;
5568 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5570 ASSERT_EQ(1u, frame.render_passes.size());
5571 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5572 ASSERT_EQ(DrawQuad::RENDER_PASS,
5573 frame.render_passes[0]->quad_list.front()->material);
5574 const RenderPassDrawQuad* render_pass_quad =
5575 RenderPassDrawQuad::MaterialCast(
5576 frame.render_passes[0]->quad_list.front());
5577 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
5578 render_pass_quad->rect.ToString());
5579 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5580 render_pass_quad->MaskUVRect().ToString());
5581 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5582 render_pass_quad->mask_uv_scale.ToString());
5584 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5585 host_impl_->DidDrawAllLayers(frame);
5589 // Applying an equivalent content scale on the content layer and the mask
5590 // should still result in the same part of the mask being used.
5591 gfx::Size content_bounds =
5592 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
5593 device_scale_factor));
5594 content_layer->SetContentBounds(content_bounds);
5595 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5596 mask_layer->SetContentBounds(content_bounds);
5597 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5598 host_impl_->active_tree()->set_needs_update_draw_properties();
5600 LayerTreeHostImpl::FrameData frame;
5601 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5603 ASSERT_EQ(1u, frame.render_passes.size());
5604 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5605 ASSERT_EQ(DrawQuad::RENDER_PASS,
5606 frame.render_passes[0]->quad_list.front()->material);
5607 const RenderPassDrawQuad* render_pass_quad =
5608 RenderPassDrawQuad::MaterialCast(
5609 frame.render_passes[0]->quad_list.front());
5610 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
5611 render_pass_quad->rect.ToString());
5612 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5613 render_pass_quad->MaskUVRect().ToString());
5614 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5615 render_pass_quad->mask_uv_scale.ToString());
5617 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5618 host_impl_->DidDrawAllLayers(frame);
5622 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
5623 // The mask layer has bounds 100x100 but is attached to a layer with bounds
5624 // 50x50.
5626 scoped_ptr<LayerImpl> scoped_root =
5627 LayerImpl::Create(host_impl_->active_tree(), 1);
5628 LayerImpl* root = scoped_root.get();
5629 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5631 scoped_ptr<LayerImpl> scoped_content_layer =
5632 LayerImpl::Create(host_impl_->active_tree(), 3);
5633 LayerImpl* content_layer = scoped_content_layer.get();
5634 root->AddChild(scoped_content_layer.Pass());
5636 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5637 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5638 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5639 content_layer->SetMaskLayer(scoped_mask_layer.Pass());
5641 gfx::Size root_size(100, 100);
5642 root->SetBounds(root_size);
5643 root->SetContentBounds(root_size);
5644 root->SetPosition(gfx::PointF());
5646 gfx::Size layer_size(50, 50);
5647 content_layer->SetBounds(layer_size);
5648 content_layer->SetContentBounds(layer_size);
5649 content_layer->SetPosition(gfx::PointF());
5650 content_layer->SetDrawsContent(true);
5652 gfx::Size mask_size(100, 100);
5653 mask_layer->SetBounds(mask_size);
5654 mask_layer->SetContentBounds(mask_size);
5655 mask_layer->SetPosition(gfx::PointF());
5656 mask_layer->SetDrawsContent(true);
5658 // Check that the mask fills the surface.
5659 float device_scale_factor = 1.f;
5660 host_impl_->SetViewportSize(root_size);
5661 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5663 LayerTreeHostImpl::FrameData frame;
5664 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5666 ASSERT_EQ(1u, frame.render_passes.size());
5667 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5668 ASSERT_EQ(DrawQuad::RENDER_PASS,
5669 frame.render_passes[0]->quad_list.front()->material);
5670 const RenderPassDrawQuad* render_pass_quad =
5671 RenderPassDrawQuad::MaterialCast(
5672 frame.render_passes[0]->quad_list.front());
5673 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5674 render_pass_quad->rect.ToString());
5675 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5676 render_pass_quad->MaskUVRect().ToString());
5677 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5678 render_pass_quad->mask_uv_scale.ToString());
5680 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5681 host_impl_->DidDrawAllLayers(frame);
5684 // Applying a DSF should change the render surface size, but won't affect
5685 // which part of the mask is used.
5686 device_scale_factor = 2.f;
5687 gfx::Size device_viewport =
5688 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5689 host_impl_->SetViewportSize(device_viewport);
5690 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5691 host_impl_->active_tree()->set_needs_update_draw_properties();
5693 LayerTreeHostImpl::FrameData frame;
5694 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5696 ASSERT_EQ(1u, frame.render_passes.size());
5697 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5698 ASSERT_EQ(DrawQuad::RENDER_PASS,
5699 frame.render_passes[0]->quad_list.front()->material);
5700 const RenderPassDrawQuad* render_pass_quad =
5701 RenderPassDrawQuad::MaterialCast(
5702 frame.render_passes[0]->quad_list.front());
5703 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5704 render_pass_quad->rect.ToString());
5705 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5706 render_pass_quad->MaskUVRect().ToString());
5707 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5708 render_pass_quad->mask_uv_scale.ToString());
5710 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5711 host_impl_->DidDrawAllLayers(frame);
5714 // Applying an equivalent content scale on the content layer and the mask
5715 // should still result in the same part of the mask being used.
5716 gfx::Size layer_size_large =
5717 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5718 content_layer->SetContentBounds(layer_size_large);
5719 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5720 gfx::Size mask_size_large =
5721 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5722 mask_layer->SetContentBounds(mask_size_large);
5723 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5724 host_impl_->active_tree()->set_needs_update_draw_properties();
5726 LayerTreeHostImpl::FrameData frame;
5727 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5729 ASSERT_EQ(1u, frame.render_passes.size());
5730 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5731 ASSERT_EQ(DrawQuad::RENDER_PASS,
5732 frame.render_passes[0]->quad_list.front()->material);
5733 const RenderPassDrawQuad* render_pass_quad =
5734 RenderPassDrawQuad::MaterialCast(
5735 frame.render_passes[0]->quad_list.front());
5736 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5737 render_pass_quad->rect.ToString());
5738 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5739 render_pass_quad->MaskUVRect().ToString());
5740 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5741 render_pass_quad->mask_uv_scale.ToString());
5743 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5744 host_impl_->DidDrawAllLayers(frame);
5747 // Applying a different contents scale to the mask layer means it will have
5748 // a larger texture, but it should use the same tex coords to cover the
5749 // layer it masks.
5750 mask_layer->SetContentBounds(mask_size);
5751 mask_layer->SetContentsScale(1.f, 1.f);
5752 host_impl_->active_tree()->set_needs_update_draw_properties();
5754 LayerTreeHostImpl::FrameData frame;
5755 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5757 ASSERT_EQ(1u, frame.render_passes.size());
5758 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5759 ASSERT_EQ(DrawQuad::RENDER_PASS,
5760 frame.render_passes[0]->quad_list.front()->material);
5761 const RenderPassDrawQuad* render_pass_quad =
5762 RenderPassDrawQuad::MaterialCast(
5763 frame.render_passes[0]->quad_list.front());
5764 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5765 render_pass_quad->rect.ToString());
5766 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5767 render_pass_quad->MaskUVRect().ToString());
5768 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5769 render_pass_quad->mask_uv_scale.ToString());
5771 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5772 host_impl_->DidDrawAllLayers(frame);
5776 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
5777 // The replica's mask layer has bounds 100x100 but the replica is of a
5778 // layer with bounds 50x50.
5780 scoped_ptr<LayerImpl> scoped_root =
5781 LayerImpl::Create(host_impl_->active_tree(), 1);
5782 LayerImpl* root = scoped_root.get();
5783 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5785 scoped_ptr<LayerImpl> scoped_content_layer =
5786 LayerImpl::Create(host_impl_->active_tree(), 3);
5787 LayerImpl* content_layer = scoped_content_layer.get();
5788 root->AddChild(scoped_content_layer.Pass());
5790 scoped_ptr<LayerImpl> scoped_replica_layer =
5791 LayerImpl::Create(host_impl_->active_tree(), 2);
5792 LayerImpl* replica_layer = scoped_replica_layer.get();
5793 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5795 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5796 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5797 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5798 replica_layer->SetMaskLayer(scoped_mask_layer.Pass());
5800 gfx::Size root_size(100, 100);
5801 root->SetBounds(root_size);
5802 root->SetContentBounds(root_size);
5803 root->SetPosition(gfx::PointF());
5805 gfx::Size layer_size(50, 50);
5806 content_layer->SetBounds(layer_size);
5807 content_layer->SetContentBounds(layer_size);
5808 content_layer->SetPosition(gfx::PointF());
5809 content_layer->SetDrawsContent(true);
5811 gfx::Size mask_size(100, 100);
5812 mask_layer->SetBounds(mask_size);
5813 mask_layer->SetContentBounds(mask_size);
5814 mask_layer->SetPosition(gfx::PointF());
5815 mask_layer->SetDrawsContent(true);
5817 // Check that the mask fills the surface.
5818 float device_scale_factor = 1.f;
5819 host_impl_->SetViewportSize(root_size);
5820 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5822 LayerTreeHostImpl::FrameData frame;
5823 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5825 ASSERT_EQ(1u, frame.render_passes.size());
5826 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5827 ASSERT_EQ(DrawQuad::RENDER_PASS,
5828 frame.render_passes[0]->quad_list.ElementAt(1)->material);
5829 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
5830 frame.render_passes[0]->quad_list.ElementAt(1));
5831 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5832 replica_quad->rect.ToString());
5833 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5834 replica_quad->MaskUVRect().ToString());
5835 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5836 replica_quad->mask_uv_scale.ToString());
5838 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5839 host_impl_->DidDrawAllLayers(frame);
5842 // Applying a DSF should change the render surface size, but won't affect
5843 // which part of the mask is used.
5844 device_scale_factor = 2.f;
5845 gfx::Size device_viewport =
5846 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5847 host_impl_->SetViewportSize(device_viewport);
5848 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5849 host_impl_->active_tree()->set_needs_update_draw_properties();
5851 LayerTreeHostImpl::FrameData frame;
5852 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5854 ASSERT_EQ(1u, frame.render_passes.size());
5855 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5856 ASSERT_EQ(DrawQuad::RENDER_PASS,
5857 frame.render_passes[0]->quad_list.ElementAt(1)->material);
5858 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
5859 frame.render_passes[0]->quad_list.ElementAt(1));
5860 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5861 replica_quad->rect.ToString());
5862 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5863 replica_quad->MaskUVRect().ToString());
5864 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5865 replica_quad->mask_uv_scale.ToString());
5867 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5868 host_impl_->DidDrawAllLayers(frame);
5871 // Applying an equivalent content scale on the content layer and the mask
5872 // should still result in the same part of the mask being used.
5873 gfx::Size layer_size_large =
5874 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5875 content_layer->SetContentBounds(layer_size_large);
5876 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5877 gfx::Size mask_size_large =
5878 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5879 mask_layer->SetContentBounds(mask_size_large);
5880 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5881 host_impl_->active_tree()->set_needs_update_draw_properties();
5883 LayerTreeHostImpl::FrameData frame;
5884 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5886 ASSERT_EQ(1u, frame.render_passes.size());
5887 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5888 ASSERT_EQ(DrawQuad::RENDER_PASS,
5889 frame.render_passes[0]->quad_list.ElementAt(1)->material);
5890 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
5891 frame.render_passes[0]->quad_list.ElementAt(1));
5892 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5893 replica_quad->rect.ToString());
5894 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5895 replica_quad->MaskUVRect().ToString());
5896 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5897 replica_quad->mask_uv_scale.ToString());
5899 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5900 host_impl_->DidDrawAllLayers(frame);
5903 // Applying a different contents scale to the mask layer means it will have
5904 // a larger texture, but it should use the same tex coords to cover the
5905 // layer it masks.
5906 mask_layer->SetContentBounds(mask_size);
5907 mask_layer->SetContentsScale(1.f, 1.f);
5908 host_impl_->active_tree()->set_needs_update_draw_properties();
5910 LayerTreeHostImpl::FrameData frame;
5911 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5913 ASSERT_EQ(1u, frame.render_passes.size());
5914 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5915 ASSERT_EQ(DrawQuad::RENDER_PASS,
5916 frame.render_passes[0]->quad_list.ElementAt(1)->material);
5917 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
5918 frame.render_passes[0]->quad_list.ElementAt(1));
5919 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5920 replica_quad->rect.ToString());
5921 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5922 replica_quad->MaskUVRect().ToString());
5923 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(),
5924 replica_quad->mask_uv_scale.ToString());
5926 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5927 host_impl_->DidDrawAllLayers(frame);
5931 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
5932 // The replica is of a layer with bounds 50x50, but it has a child that causes
5933 // the surface bounds to be larger.
5935 scoped_ptr<LayerImpl> scoped_root =
5936 LayerImpl::Create(host_impl_->active_tree(), 1);
5937 LayerImpl* root = scoped_root.get();
5938 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5940 scoped_ptr<LayerImpl> scoped_content_layer =
5941 LayerImpl::Create(host_impl_->active_tree(), 2);
5942 LayerImpl* content_layer = scoped_content_layer.get();
5943 root->AddChild(scoped_content_layer.Pass());
5945 scoped_ptr<LayerImpl> scoped_content_child_layer =
5946 LayerImpl::Create(host_impl_->active_tree(), 3);
5947 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5948 content_layer->AddChild(scoped_content_child_layer.Pass());
5950 scoped_ptr<LayerImpl> scoped_replica_layer =
5951 LayerImpl::Create(host_impl_->active_tree(), 4);
5952 LayerImpl* replica_layer = scoped_replica_layer.get();
5953 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5955 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5956 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
5957 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5958 replica_layer->SetMaskLayer(scoped_mask_layer.Pass());
5960 gfx::Size root_size(100, 100);
5961 root->SetBounds(root_size);
5962 root->SetContentBounds(root_size);
5963 root->SetPosition(gfx::PointF());
5965 gfx::Size layer_size(50, 50);
5966 content_layer->SetBounds(layer_size);
5967 content_layer->SetContentBounds(layer_size);
5968 content_layer->SetPosition(gfx::PointF());
5969 content_layer->SetDrawsContent(true);
5971 gfx::Size child_size(50, 50);
5972 content_child_layer->SetBounds(child_size);
5973 content_child_layer->SetContentBounds(child_size);
5974 content_child_layer->SetPosition(gfx::Point(50, 0));
5975 content_child_layer->SetDrawsContent(true);
5977 gfx::Size mask_size(50, 50);
5978 mask_layer->SetBounds(mask_size);
5979 mask_layer->SetContentBounds(mask_size);
5980 mask_layer->SetPosition(gfx::PointF());
5981 mask_layer->SetDrawsContent(true);
5983 float device_scale_factor = 1.f;
5984 host_impl_->SetViewportSize(root_size);
5985 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5987 LayerTreeHostImpl::FrameData frame;
5988 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5990 ASSERT_EQ(1u, frame.render_passes.size());
5991 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5993 // The surface is 100x50.
5994 ASSERT_EQ(DrawQuad::RENDER_PASS,
5995 frame.render_passes[0]->quad_list.front()->material);
5996 const RenderPassDrawQuad* render_pass_quad =
5997 RenderPassDrawQuad::MaterialCast(
5998 frame.render_passes[0]->quad_list.front());
5999 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
6000 render_pass_quad->rect.ToString());
6002 // The mask covers the owning layer only.
6003 ASSERT_EQ(DrawQuad::RENDER_PASS,
6004 frame.render_passes[0]->quad_list.ElementAt(1)->material);
6005 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
6006 frame.render_passes[0]->quad_list.ElementAt(1));
6007 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
6008 replica_quad->rect.ToString());
6009 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
6010 replica_quad->MaskUVRect().ToString());
6011 EXPECT_EQ(gfx::Vector2dF(2.f, 1.f).ToString(),
6012 replica_quad->mask_uv_scale.ToString());
6014 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6015 host_impl_->DidDrawAllLayers(frame);
6018 // Move the child to (-50, 0) instead. Now the mask should be moved to still
6019 // cover the layer being replicated.
6020 content_child_layer->SetPosition(gfx::Point(-50, 0));
6022 LayerTreeHostImpl::FrameData frame;
6023 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6025 ASSERT_EQ(1u, frame.render_passes.size());
6026 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
6028 // The surface is 100x50 with its origin at (-50, 0).
6029 ASSERT_EQ(DrawQuad::RENDER_PASS,
6030 frame.render_passes[0]->quad_list.front()->material);
6031 const RenderPassDrawQuad* render_pass_quad =
6032 RenderPassDrawQuad::MaterialCast(
6033 frame.render_passes[0]->quad_list.front());
6034 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
6035 render_pass_quad->rect.ToString());
6037 // The mask covers the owning layer only.
6038 ASSERT_EQ(DrawQuad::RENDER_PASS,
6039 frame.render_passes[0]->quad_list.ElementAt(1)->material);
6040 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast(
6041 frame.render_passes[0]->quad_list.ElementAt(1));
6042 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
6043 replica_quad->rect.ToString());
6044 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
6045 replica_quad->MaskUVRect().ToString());
6046 EXPECT_EQ(gfx::Vector2dF(2.f, 1.f).ToString(),
6047 replica_quad->mask_uv_scale.ToString());
6049 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6050 host_impl_->DidDrawAllLayers(frame);
6054 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
6055 // The masked layer has bounds 50x50, but it has a child that causes
6056 // the surface bounds to be larger. It also has a parent that clips the
6057 // masked layer and its surface.
6059 scoped_ptr<LayerImpl> scoped_root =
6060 LayerImpl::Create(host_impl_->active_tree(), 1);
6061 LayerImpl* root = scoped_root.get();
6062 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
6064 scoped_ptr<LayerImpl> scoped_clipping_layer =
6065 LayerImpl::Create(host_impl_->active_tree(), 2);
6066 LayerImpl* clipping_layer = scoped_clipping_layer.get();
6067 root->AddChild(scoped_clipping_layer.Pass());
6069 scoped_ptr<LayerImpl> scoped_content_layer =
6070 LayerImpl::Create(host_impl_->active_tree(), 3);
6071 LayerImpl* content_layer = scoped_content_layer.get();
6072 clipping_layer->AddChild(scoped_content_layer.Pass());
6074 scoped_ptr<LayerImpl> scoped_content_child_layer =
6075 LayerImpl::Create(host_impl_->active_tree(), 4);
6076 LayerImpl* content_child_layer = scoped_content_child_layer.get();
6077 content_layer->AddChild(scoped_content_child_layer.Pass());
6079 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
6080 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
6081 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
6082 content_layer->SetMaskLayer(scoped_mask_layer.Pass());
6084 gfx::Size root_size(100, 100);
6085 root->SetBounds(root_size);
6086 root->SetContentBounds(root_size);
6087 root->SetPosition(gfx::PointF());
6089 gfx::Rect clipping_rect(20, 10, 10, 20);
6090 clipping_layer->SetBounds(clipping_rect.size());
6091 clipping_layer->SetContentBounds(clipping_rect.size());
6092 clipping_layer->SetPosition(clipping_rect.origin());
6093 clipping_layer->SetMasksToBounds(true);
6095 gfx::Size layer_size(50, 50);
6096 content_layer->SetBounds(layer_size);
6097 content_layer->SetContentBounds(layer_size);
6098 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
6099 content_layer->SetDrawsContent(true);
6101 gfx::Size child_size(50, 50);
6102 content_child_layer->SetBounds(child_size);
6103 content_child_layer->SetContentBounds(child_size);
6104 content_child_layer->SetPosition(gfx::Point(50, 0));
6105 content_child_layer->SetDrawsContent(true);
6107 gfx::Size mask_size(100, 100);
6108 mask_layer->SetBounds(mask_size);
6109 mask_layer->SetContentBounds(mask_size);
6110 mask_layer->SetPosition(gfx::PointF());
6111 mask_layer->SetDrawsContent(true);
6113 float device_scale_factor = 1.f;
6114 host_impl_->SetViewportSize(root_size);
6115 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6117 LayerTreeHostImpl::FrameData frame;
6118 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6120 ASSERT_EQ(1u, frame.render_passes.size());
6121 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
6123 // The surface is clipped to 10x20.
6124 ASSERT_EQ(DrawQuad::RENDER_PASS,
6125 frame.render_passes[0]->quad_list.front()->material);
6126 const RenderPassDrawQuad* render_pass_quad =
6127 RenderPassDrawQuad::MaterialCast(
6128 frame.render_passes[0]->quad_list.front());
6129 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
6130 render_pass_quad->rect.ToString());
6131 // The masked layer is 50x50, but the surface size is 10x20. So the texture
6132 // coords in the mask are scaled by 10/50 and 20/50.
6133 // The surface is clipped to (20,10) so the mask texture coords are offset
6134 // by 20/50 and 10/50
6135 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f)
6136 .ToString(),
6137 render_pass_quad->MaskUVRect().ToString());
6138 EXPECT_EQ(gfx::Vector2dF(10.f / 50.f, 20.f / 50.f).ToString(),
6139 render_pass_quad->mask_uv_scale.ToString());
6141 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6142 host_impl_->DidDrawAllLayers(frame);
6146 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
6147 public:
6148 using GLRenderer::ShouldAntialiasQuad;
6151 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
6152 // Due to precision issues (especially on Android), sometimes far
6153 // away quads can end up thinking they need AA.
6154 float device_scale_factor = 4.f / 3.f;
6155 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6156 gfx::Size root_size(2000, 1000);
6157 gfx::Size device_viewport_size =
6158 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
6159 host_impl_->SetViewportSize(device_viewport_size);
6161 host_impl_->CreatePendingTree();
6162 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f,
6163 16.f);
6165 scoped_ptr<LayerImpl> scoped_root =
6166 LayerImpl::Create(host_impl_->pending_tree(), 1);
6167 LayerImpl* root = scoped_root.get();
6169 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
6171 scoped_ptr<LayerImpl> scoped_scrolling_layer =
6172 LayerImpl::Create(host_impl_->pending_tree(), 2);
6173 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
6174 root->AddChild(scoped_scrolling_layer.Pass());
6176 gfx::Size content_layer_bounds(100000, 100);
6177 gfx::Size pile_tile_size(3000, 3000);
6178 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
6179 pile_tile_size, content_layer_bounds));
6181 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
6182 FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(),
6183 3, pile);
6184 LayerImpl* content_layer = scoped_content_layer.get();
6185 scrolling_layer->AddChild(scoped_content_layer.Pass());
6186 content_layer->SetBounds(content_layer_bounds);
6187 content_layer->SetDrawsContent(true);
6189 root->SetBounds(root_size);
6191 gfx::ScrollOffset scroll_offset(100000, 0);
6192 scrolling_layer->SetScrollClipLayer(root->id());
6193 scrolling_layer->SetScrollOffset(scroll_offset);
6195 host_impl_->ActivateSyncTree();
6197 host_impl_->active_tree()->UpdateDrawProperties();
6198 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
6200 LayerTreeHostImpl::FrameData frame;
6201 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6203 ASSERT_EQ(1u, frame.render_passes.size());
6204 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
6205 const DrawQuad* quad = frame.render_passes[0]->quad_list.front();
6207 bool antialiased =
6208 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6209 quad->quadTransform(), quad, false);
6210 EXPECT_FALSE(antialiased);
6212 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6213 host_impl_->DidDrawAllLayers(frame);
6217 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
6218 public:
6219 CompositorFrameMetadataTest()
6220 : swap_buffers_complete_(0) {}
6222 void DidSwapBuffersCompleteOnImplThread() override {
6223 swap_buffers_complete_++;
6226 int swap_buffers_complete_;
6229 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
6230 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
6232 LayerTreeHostImpl::FrameData frame;
6233 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6234 host_impl_->DrawLayers(&frame, base::TimeTicks());
6235 host_impl_->DidDrawAllLayers(frame);
6237 CompositorFrameAck ack;
6238 host_impl_->ReclaimResources(&ack);
6239 host_impl_->DidSwapBuffersComplete();
6240 EXPECT_EQ(swap_buffers_complete_, 1);
6243 class CountingSoftwareDevice : public SoftwareOutputDevice {
6244 public:
6245 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6247 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
6248 ++frames_began_;
6249 return SoftwareOutputDevice::BeginPaint(damage_rect);
6251 void EndPaint(SoftwareFrameData* frame_data) override {
6252 ++frames_ended_;
6253 SoftwareOutputDevice::EndPaint(frame_data);
6256 int frames_began_, frames_ended_;
6259 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
6260 // No main thread evictions in resourceless software mode.
6261 set_reduce_memory_result(false);
6262 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
6263 bool delegated_rendering = false;
6264 FakeOutputSurface* output_surface =
6265 FakeOutputSurface::CreateDeferredGL(
6266 scoped_ptr<SoftwareOutputDevice>(software_device),
6267 delegated_rendering).release();
6268 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6269 scoped_ptr<OutputSurface>(output_surface)));
6270 host_impl_->SetViewportSize(gfx::Size(50, 50));
6272 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6274 const gfx::Transform external_transform;
6275 const gfx::Rect external_viewport;
6276 const gfx::Rect external_clip;
6277 const bool resourceless_software_draw = true;
6278 host_impl_->SetExternalDrawConstraints(external_transform,
6279 external_viewport,
6280 external_clip,
6281 external_viewport,
6282 external_transform,
6283 resourceless_software_draw);
6285 EXPECT_EQ(0, software_device->frames_began_);
6286 EXPECT_EQ(0, software_device->frames_ended_);
6288 DrawFrame();
6290 EXPECT_EQ(1, software_device->frames_began_);
6291 EXPECT_EQ(1, software_device->frames_ended_);
6293 // Call other API methods that are likely to hit NULL pointer in this mode.
6294 EXPECT_TRUE(host_impl_->AsValue().get());
6295 EXPECT_TRUE(host_impl_->ActivationStateAsValue().get());
6298 TEST_F(LayerTreeHostImplTest,
6299 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
6300 set_reduce_memory_result(false);
6301 bool delegated_rendering = false;
6302 FakeOutputSurface* output_surface =
6303 FakeOutputSurface::CreateDeferredGL(
6304 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
6305 delegated_rendering).release();
6306 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6307 scoped_ptr<OutputSurface>(output_surface)));
6309 const gfx::Transform external_transform;
6310 const gfx::Rect external_viewport;
6311 const gfx::Rect external_clip;
6312 const bool resourceless_software_draw = true;
6313 host_impl_->SetExternalDrawConstraints(external_transform,
6314 external_viewport,
6315 external_clip,
6316 external_viewport,
6317 external_transform,
6318 resourceless_software_draw);
6320 // SolidColorLayerImpl will be drawn.
6321 scoped_ptr<SolidColorLayerImpl> root_layer =
6322 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6324 // VideoLayerImpl will not be drawn.
6325 FakeVideoFrameProvider provider;
6326 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
6327 host_impl_->active_tree(), 2, &provider, media::VIDEO_ROTATION_0);
6328 video_layer->SetBounds(gfx::Size(10, 10));
6329 video_layer->SetContentBounds(gfx::Size(10, 10));
6330 video_layer->SetDrawsContent(true);
6331 root_layer->AddChild(video_layer.Pass());
6332 SetupRootLayerImpl(root_layer.Pass());
6334 LayerTreeHostImpl::FrameData frame;
6335 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6336 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6337 host_impl_->DidDrawAllLayers(frame);
6339 EXPECT_EQ(1u, frame.will_draw_layers.size());
6340 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
6343 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
6344 protected:
6345 void SetUp() override {
6346 LayerTreeHostImplTest::SetUp();
6348 set_reduce_memory_result(false);
6350 bool delegated_rendering = false;
6351 scoped_ptr<FakeOutputSurface> output_surface(
6352 FakeOutputSurface::CreateDeferredGL(
6353 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
6354 delegated_rendering));
6355 output_surface_ = output_surface.get();
6357 EXPECT_TRUE(CreateHostImpl(DefaultSettings(), output_surface.Pass()));
6359 scoped_ptr<SolidColorLayerImpl> root_layer =
6360 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6361 SetupRootLayerImpl(root_layer.Pass());
6363 onscreen_context_provider_ = TestContextProvider::Create();
6366 void UpdateRendererCapabilitiesOnImplThread() override {
6367 did_update_renderer_capabilities_ = true;
6370 FakeOutputSurface* output_surface_;
6371 scoped_refptr<TestContextProvider> onscreen_context_provider_;
6372 bool did_update_renderer_capabilities_;
6376 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
6377 // Software draw.
6378 DrawFrame();
6380 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6382 // DeferredInitialize and hardware draw.
6383 did_update_renderer_capabilities_ = false;
6384 EXPECT_TRUE(
6385 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
6386 EXPECT_EQ(onscreen_context_provider_.get(),
6387 host_impl_->output_surface()->context_provider());
6388 EXPECT_TRUE(did_update_renderer_capabilities_);
6390 // Defer intialized GL draw.
6391 DrawFrame();
6393 // Revert back to software.
6394 did_update_renderer_capabilities_ = false;
6395 output_surface_->ReleaseGL();
6396 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6397 EXPECT_TRUE(did_update_renderer_capabilities_);
6399 // Software draw again.
6400 DrawFrame();
6403 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails) {
6404 // Software draw.
6405 DrawFrame();
6407 // Fail initialization of the onscreen context before the OutputSurface binds
6408 // it to the thread.
6409 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
6411 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6413 // DeferredInitialize fails.
6414 did_update_renderer_capabilities_ = false;
6415 EXPECT_FALSE(
6416 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
6417 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
6418 EXPECT_FALSE(did_update_renderer_capabilities_);
6420 // Software draw again.
6421 DrawFrame();
6424 // Checks that we have a non-0 default allocation if we pass a context that
6425 // doesn't support memory management extensions.
6426 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
6427 LayerTreeSettings settings;
6428 host_impl_ = LayerTreeHostImpl::Create(settings,
6429 this,
6430 &proxy_,
6431 &stats_instrumentation_,
6432 shared_bitmap_manager_.get(),
6433 gpu_memory_buffer_manager_.get(),
6436 scoped_ptr<OutputSurface> output_surface(
6437 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6438 host_impl_->InitializeRenderer(output_surface.Pass());
6439 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
6442 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
6443 ManagedMemoryPolicy policy1(
6444 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
6445 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
6446 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
6447 int allow_nice_to_have_cutoff_value =
6448 ManagedMemoryPolicy::PriorityCutoffToValue(
6449 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
6450 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
6451 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
6453 // GPU rasterization should be disabled by default on the tree(s)
6454 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
6455 EXPECT_TRUE(host_impl_->pending_tree() == NULL);
6457 host_impl_->SetVisible(true);
6458 host_impl_->SetMemoryPolicy(policy1);
6459 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
6460 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
6462 host_impl_->SetVisible(false);
6463 EXPECT_EQ(0u, current_limit_bytes_);
6464 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
6466 host_impl_->SetVisible(true);
6467 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
6468 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
6470 // Now enable GPU rasterization and test if we get nice to have cutoff,
6471 // when visible.
6472 LayerTreeSettings settings;
6473 settings.gpu_rasterization_enabled = true;
6474 host_impl_ = LayerTreeHostImpl::Create(
6475 settings, this, &proxy_, &stats_instrumentation_, NULL, NULL, 0);
6476 host_impl_->SetUseGpuRasterization(true);
6477 host_impl_->SetVisible(true);
6478 host_impl_->SetMemoryPolicy(policy1);
6479 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
6480 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
6482 host_impl_->SetVisible(false);
6483 EXPECT_EQ(0u, current_limit_bytes_);
6484 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
6487 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
6488 ASSERT_TRUE(host_impl_->active_tree());
6490 // RequiresHighResToDraw is set when new output surface is used.
6491 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6493 host_impl_->ResetRequiresHighResToDraw();
6495 host_impl_->SetVisible(false);
6496 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6497 host_impl_->SetVisible(true);
6498 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6499 host_impl_->SetVisible(false);
6500 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6502 host_impl_->ResetRequiresHighResToDraw();
6504 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6505 host_impl_->SetVisible(true);
6506 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6509 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
6510 ASSERT_TRUE(host_impl_->active_tree());
6511 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
6513 // RequiresHighResToDraw is set when new output surface is used.
6514 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6516 host_impl_->ResetRequiresHighResToDraw();
6518 host_impl_->SetUseGpuRasterization(false);
6519 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6520 host_impl_->SetUseGpuRasterization(true);
6521 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6522 host_impl_->SetUseGpuRasterization(false);
6523 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6525 host_impl_->ResetRequiresHighResToDraw();
6527 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6528 host_impl_->SetUseGpuRasterization(true);
6529 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6532 class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest {
6533 public:
6534 void SetUp() override {
6535 LayerTreeSettings settings;
6536 settings.impl_side_painting = true;
6538 fake_host_impl_ = new FakeLayerTreeHostImpl(
6539 settings, &proxy_, shared_bitmap_manager_.get());
6540 host_impl_.reset(fake_host_impl_);
6541 host_impl_->InitializeRenderer(CreateOutputSurface());
6542 host_impl_->SetViewportSize(gfx::Size(10, 10));
6545 FakeLayerTreeHostImpl* fake_host_impl_;
6548 TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) {
6549 fake_host_impl_->DidModifyTilePriorities();
6550 EXPECT_TRUE(fake_host_impl_->prepare_tiles_needed());
6551 fake_host_impl_->SetVisible(false);
6552 EXPECT_FALSE(fake_host_impl_->prepare_tiles_needed());
6555 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
6556 scoped_ptr<TestWebGraphicsContext3D> context =
6557 TestWebGraphicsContext3D::Create();
6558 TestWebGraphicsContext3D* context3d = context.get();
6559 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
6560 CreateHostImpl(DefaultSettings(), output_surface.Pass());
6562 EXPECT_EQ(0u, context3d->NumTextures());
6564 UIResourceId ui_resource_id = 1;
6565 bool is_opaque = false;
6566 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
6567 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6568 EXPECT_EQ(1u, context3d->NumTextures());
6569 ResourceProvider::ResourceId id1 =
6570 host_impl_->ResourceIdForUIResource(ui_resource_id);
6571 EXPECT_NE(0u, id1);
6573 // Multiple requests with the same id is allowed. The previous texture is
6574 // deleted.
6575 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6576 EXPECT_EQ(1u, context3d->NumTextures());
6577 ResourceProvider::ResourceId id2 =
6578 host_impl_->ResourceIdForUIResource(ui_resource_id);
6579 EXPECT_NE(0u, id2);
6580 EXPECT_NE(id1, id2);
6582 // Deleting invalid UIResourceId is allowed and does not change state.
6583 host_impl_->DeleteUIResource(-1);
6584 EXPECT_EQ(1u, context3d->NumTextures());
6586 // Should return zero for invalid UIResourceId. Number of textures should
6587 // not change.
6588 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
6589 EXPECT_EQ(1u, context3d->NumTextures());
6591 host_impl_->DeleteUIResource(ui_resource_id);
6592 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
6593 EXPECT_EQ(0u, context3d->NumTextures());
6595 // Should not change state for multiple deletion on one UIResourceId
6596 host_impl_->DeleteUIResource(ui_resource_id);
6597 EXPECT_EQ(0u, context3d->NumTextures());
6600 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
6601 scoped_ptr<TestWebGraphicsContext3D> context =
6602 TestWebGraphicsContext3D::Create();
6603 TestWebGraphicsContext3D* context3d = context.get();
6604 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6606 EXPECT_EQ(0u, context3d->NumTextures());
6608 gfx::Size size(4, 4);
6609 // SkImageInfo has no support for ETC1. The |info| below contains the right
6610 // total pixel size for the bitmap but not the right height and width. The
6611 // correct width/height are passed directly to UIResourceBitmap.
6612 SkImageInfo info =
6613 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
6614 skia::RefPtr<SkPixelRef> pixel_ref =
6615 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
6616 pixel_ref->setImmutable();
6617 UIResourceBitmap bitmap(pixel_ref, size);
6618 UIResourceId ui_resource_id = 1;
6619 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6620 EXPECT_EQ(1u, context3d->NumTextures());
6621 ResourceProvider::ResourceId id1 =
6622 host_impl_->ResourceIdForUIResource(ui_resource_id);
6623 EXPECT_NE(0u, id1);
6626 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
6629 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
6630 scoped_refptr<TestContextProvider> context_provider =
6631 TestContextProvider::Create();
6633 CreateHostImpl(DefaultSettings(),
6634 FakeOutputSurface::Create3d(context_provider));
6636 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
6638 ScopedPtrVector<CopyOutputRequest> requests;
6639 requests.push_back(CopyOutputRequest::CreateRequest(
6640 base::Bind(&ShutdownReleasesContext_Callback)));
6642 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
6644 LayerTreeHostImpl::FrameData frame;
6645 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6646 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6647 host_impl_->DidDrawAllLayers(frame);
6649 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6650 // texture in a texture mailbox.
6651 EXPECT_FALSE(context_provider->HasOneRef());
6652 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
6654 host_impl_ = nullptr;
6656 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6657 // released, and the texture deleted.
6658 EXPECT_TRUE(context_provider->HasOneRef());
6659 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
6662 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
6663 // When flinging via touch, only the child should scroll (we should not
6664 // bubble).
6665 gfx::Size surface_size(10, 10);
6666 gfx::Size content_size(20, 20);
6667 scoped_ptr<LayerImpl> root_clip =
6668 LayerImpl::Create(host_impl_->active_tree(), 3);
6669 scoped_ptr<LayerImpl> root =
6670 CreateScrollableLayer(1, content_size, root_clip.get());
6671 root->SetIsContainerForFixedPositionLayers(true);
6672 scoped_ptr<LayerImpl> child =
6673 CreateScrollableLayer(2, content_size, root_clip.get());
6675 root->AddChild(child.Pass());
6676 int root_id = root->id();
6677 root_clip->AddChild(root.Pass());
6679 host_impl_->SetViewportSize(surface_size);
6680 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6681 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
6682 Layer::INVALID_ID);
6683 host_impl_->active_tree()->DidBecomeActive();
6684 DrawFrame();
6686 EXPECT_EQ(InputHandler::ScrollStarted,
6687 host_impl_->ScrollBegin(gfx::Point(),
6688 InputHandler::Gesture));
6690 EXPECT_EQ(InputHandler::ScrollStarted,
6691 host_impl_->FlingScrollBegin());
6693 gfx::Vector2d scroll_delta(0, 100);
6694 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6695 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6697 host_impl_->ScrollEnd();
6699 scoped_ptr<ScrollAndScaleSet> scroll_info =
6700 host_impl_->ProcessScrollDeltas();
6702 // Only the child should have scrolled.
6703 ASSERT_EQ(1u, scroll_info->scrolls.size());
6704 ExpectNone(*scroll_info.get(), root_id);
6708 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
6709 // Scroll a child layer beyond its maximum scroll range and make sure the
6710 // the scroll doesn't bubble up to the parent layer.
6711 gfx::Size surface_size(10, 10);
6712 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
6713 scoped_ptr<LayerImpl> root_scrolling =
6714 CreateScrollableLayer(2, surface_size, root.get());
6716 scoped_ptr<LayerImpl> grand_child =
6717 CreateScrollableLayer(4, surface_size, root.get());
6718 grand_child->SetScrollOffset(gfx::ScrollOffset(0, 2));
6720 scoped_ptr<LayerImpl> child =
6721 CreateScrollableLayer(3, surface_size, root.get());
6722 child->SetScrollOffset(gfx::ScrollOffset(0, 4));
6723 child->AddChild(grand_child.Pass());
6725 root_scrolling->AddChild(child.Pass());
6726 root->AddChild(root_scrolling.Pass());
6727 host_impl_->active_tree()->SetRootLayer(root.Pass());
6728 host_impl_->active_tree()->DidBecomeActive();
6729 host_impl_->SetViewportSize(surface_size);
6730 DrawFrame();
6732 scoped_ptr<ScrollAndScaleSet> scroll_info;
6733 LayerImpl* child =
6734 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6735 LayerImpl* grand_child = child->children()[0];
6737 gfx::Vector2d scroll_delta(0, -2);
6738 EXPECT_EQ(InputHandler::ScrollStarted,
6739 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6740 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6742 // The grand child should have scrolled up to its limit.
6743 scroll_info = host_impl_->ProcessScrollDeltas();
6744 ASSERT_EQ(1u, scroll_info->scrolls.size());
6745 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6746 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6748 // The child should have received the bubbled delta, but the locked
6749 // scrolling layer should remain set as the grand child.
6750 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6751 scroll_info = host_impl_->ProcessScrollDeltas();
6752 ASSERT_EQ(2u, scroll_info->scrolls.size());
6753 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6754 ExpectContains(*scroll_info, child->id(), scroll_delta);
6755 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6757 // The first |ScrollBy| after the fling should re-lock the scrolling
6758 // layer to the first layer that scrolled, which is the child.
6759 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6760 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6761 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6763 // The child should have scrolled up to its limit.
6764 scroll_info = host_impl_->ProcessScrollDeltas();
6765 ASSERT_EQ(2u, scroll_info->scrolls.size());
6766 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6767 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
6769 // As the locked layer is at it's limit, no further scrolling can occur.
6770 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6771 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6772 host_impl_->ScrollEnd();
6776 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6777 // When flinging via wheel, the root should eventually scroll (we should
6778 // bubble).
6779 gfx::Size surface_size(10, 10);
6780 gfx::Size content_size(20, 20);
6781 scoped_ptr<LayerImpl> root_clip =
6782 LayerImpl::Create(host_impl_->active_tree(), 3);
6783 scoped_ptr<LayerImpl> root_scroll =
6784 CreateScrollableLayer(1, content_size, root_clip.get());
6785 int root_scroll_id = root_scroll->id();
6786 scoped_ptr<LayerImpl> child =
6787 CreateScrollableLayer(2, content_size, root_clip.get());
6789 root_scroll->AddChild(child.Pass());
6790 root_clip->AddChild(root_scroll.Pass());
6792 host_impl_->SetViewportSize(surface_size);
6793 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6794 host_impl_->active_tree()->DidBecomeActive();
6795 DrawFrame();
6797 EXPECT_EQ(InputHandler::ScrollStarted,
6798 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6800 EXPECT_EQ(InputHandler::ScrollStarted,
6801 host_impl_->FlingScrollBegin());
6803 gfx::Vector2d scroll_delta(0, 100);
6804 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6805 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6807 host_impl_->ScrollEnd();
6809 scoped_ptr<ScrollAndScaleSet> scroll_info =
6810 host_impl_->ProcessScrollDeltas();
6812 // The root should have scrolled.
6813 ASSERT_EQ(2u, scroll_info->scrolls.size());
6814 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
6818 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6819 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6820 // we should return ScrollUnknown.
6821 gfx::Size content_size(100, 100);
6822 SetupScrollAndContentsLayers(content_size);
6824 int scroll_layer_id = 2;
6825 LayerImpl* scroll_layer =
6826 host_impl_->active_tree()->LayerById(scroll_layer_id);
6827 scroll_layer->SetDrawsContent(true);
6829 int page_scale_layer_id = 5;
6830 LayerImpl* page_scale_layer =
6831 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6833 int occluder_layer_id = 6;
6834 scoped_ptr<LayerImpl> occluder_layer =
6835 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6836 occluder_layer->SetDrawsContent(true);
6837 occluder_layer->SetBounds(content_size);
6838 occluder_layer->SetContentBounds(content_size);
6839 occluder_layer->SetPosition(gfx::PointF());
6841 // The parent of the occluder is *above* the scroller.
6842 page_scale_layer->AddChild(occluder_layer.Pass());
6844 DrawFrame();
6846 EXPECT_EQ(InputHandler::ScrollUnknown,
6847 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6850 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6851 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6852 // is not the first scroller we encounter when walking up from the layer, we
6853 // should also return ScrollUnknown.
6854 gfx::Size content_size(100, 100);
6855 SetupScrollAndContentsLayers(content_size);
6857 int scroll_layer_id = 2;
6858 LayerImpl* scroll_layer =
6859 host_impl_->active_tree()->LayerById(scroll_layer_id);
6860 scroll_layer->SetDrawsContent(true);
6862 int occluder_layer_id = 6;
6863 scoped_ptr<LayerImpl> occluder_layer =
6864 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6865 occluder_layer->SetDrawsContent(true);
6866 occluder_layer->SetBounds(content_size);
6867 occluder_layer->SetContentBounds(content_size);
6868 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6870 int child_scroll_clip_layer_id = 7;
6871 scoped_ptr<LayerImpl> child_scroll_clip =
6872 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6874 int child_scroll_layer_id = 8;
6875 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6876 child_scroll_layer_id, content_size, child_scroll_clip.get());
6878 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6880 child_scroll->AddChild(occluder_layer.Pass());
6881 scroll_layer->AddChild(child_scroll.Pass());
6883 DrawFrame();
6885 EXPECT_EQ(InputHandler::ScrollUnknown,
6886 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6889 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) {
6890 gfx::Size content_size(100, 100);
6891 SetupScrollAndContentsLayers(content_size);
6893 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6895 int scroll_layer_id = 2;
6896 LayerImpl* scroll_layer =
6897 host_impl_->active_tree()->LayerById(scroll_layer_id);
6899 int child_scroll_layer_id = 7;
6900 scoped_ptr<LayerImpl> child_scroll =
6901 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6902 child_scroll->SetDrawsContent(false);
6904 scroll_layer->AddChild(child_scroll.Pass());
6906 DrawFrame();
6908 // We should not have scrolled |child_scroll| even though we technically "hit"
6909 // it. The reason for this is that if the scrolling the scroll would not move
6910 // any layer that is a drawn RSLL member, then we can ignore the hit.
6912 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6913 // overscrolling the inner viewport.
6914 EXPECT_EQ(InputHandler::ScrollStarted,
6915 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6917 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6920 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6921 // This test case is very similar to the one above with one key difference:
6922 // the invisible scroller has a scroll child that is indeed draw contents.
6923 // If we attempt to initiate a gesture scroll off of the visible scroll child
6924 // we should still start the scroll child.
6925 gfx::Size content_size(100, 100);
6926 SetupScrollAndContentsLayers(content_size);
6928 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6930 int scroll_layer_id = 2;
6931 LayerImpl* scroll_layer =
6932 host_impl_->active_tree()->LayerById(scroll_layer_id);
6934 int scroll_child_id = 6;
6935 scoped_ptr<LayerImpl> scroll_child =
6936 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6937 scroll_child->SetDrawsContent(true);
6938 scroll_child->SetBounds(content_size);
6939 scroll_child->SetContentBounds(content_size);
6940 // Move the scroll child so it's not hit by our test point.
6941 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6943 int invisible_scroll_layer_id = 7;
6944 scoped_ptr<LayerImpl> invisible_scroll =
6945 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6946 invisible_scroll->SetDrawsContent(false);
6948 int container_id = 8;
6949 scoped_ptr<LayerImpl> container =
6950 LayerImpl::Create(host_impl_->active_tree(), container_id);
6952 scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
6953 scroll_children->insert(scroll_child.get());
6954 invisible_scroll->SetScrollChildren(scroll_children.release());
6956 scroll_child->SetScrollParent(invisible_scroll.get());
6958 container->AddChild(invisible_scroll.Pass());
6959 container->AddChild(scroll_child.Pass());
6961 scroll_layer->AddChild(container.Pass());
6963 DrawFrame();
6965 // We should not have scrolled |child_scroll| even though we technically "hit"
6966 // it. The reason for this is that if the scrolling the scroll would not move
6967 // any layer that is a drawn RSLL member, then we can ignore the hit.
6969 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6970 // overscrolling the inner viewport.
6971 EXPECT_EQ(InputHandler::ScrollStarted,
6972 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6974 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6977 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6978 // to CompositorFrameMetadata after SwapBuffers();
6979 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6980 scoped_ptr<SolidColorLayerImpl> root =
6981 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6982 root->SetPosition(gfx::PointF());
6983 root->SetBounds(gfx::Size(10, 10));
6984 root->SetContentBounds(gfx::Size(10, 10));
6985 root->SetDrawsContent(true);
6987 host_impl_->active_tree()->SetRootLayer(root.Pass());
6989 FakeOutputSurface* fake_output_surface =
6990 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6992 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6993 fake_output_surface->last_sent_frame().metadata.latency_info;
6994 EXPECT_TRUE(metadata_latency_before.empty());
6996 ui::LatencyInfo latency_info;
6997 latency_info.AddLatencyNumber(
6998 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6999 scoped_ptr<SwapPromise> swap_promise(
7000 new LatencyInfoSwapPromise(latency_info));
7001 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
7002 host_impl_->SetNeedsRedraw();
7004 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
7005 LayerTreeHostImpl::FrameData frame;
7006 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
7007 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
7008 host_impl_->DidDrawAllLayers(frame);
7009 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
7011 const std::vector<ui::LatencyInfo>& metadata_latency_after =
7012 fake_output_surface->last_sent_frame().metadata.latency_info;
7013 EXPECT_EQ(1u, metadata_latency_after.size());
7014 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
7015 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
7018 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
7019 int root_layer_id = 1;
7020 scoped_ptr<SolidColorLayerImpl> root =
7021 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
7022 root->SetPosition(gfx::PointF());
7023 root->SetBounds(gfx::Size(10, 10));
7024 root->SetContentBounds(gfx::Size(10, 10));
7025 root->SetDrawsContent(true);
7027 host_impl_->active_tree()->SetRootLayer(root.Pass());
7029 // Ensure the default frame selection bounds are empty.
7030 FakeOutputSurface* fake_output_surface =
7031 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
7032 const ViewportSelectionBound& selection_start_before =
7033 fake_output_surface->last_sent_frame().metadata.selection_start;
7034 const ViewportSelectionBound& selection_end_before =
7035 fake_output_surface->last_sent_frame().metadata.selection_end;
7036 EXPECT_EQ(ViewportSelectionBound(), selection_start_before);
7037 EXPECT_EQ(ViewportSelectionBound(), selection_end_before);
7039 // Plumb the layer-local selection bounds.
7040 gfx::PointF selection_top(5, 0);
7041 gfx::PointF selection_bottom(5, 5);
7042 LayerSelectionBound start, end;
7043 start.type = SELECTION_BOUND_CENTER;
7044 start.layer_id = root_layer_id;
7045 start.edge_bottom = selection_bottom;
7046 start.edge_top = selection_top;
7047 end = start;
7048 host_impl_->active_tree()->RegisterSelection(start, end);
7050 // Trigger a draw-swap sequence.
7051 host_impl_->SetNeedsRedraw();
7053 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
7054 LayerTreeHostImpl::FrameData frame;
7055 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
7056 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
7057 host_impl_->DidDrawAllLayers(frame);
7058 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
7060 // Ensure the selection bounds have propagated to the frame metadata.
7061 const ViewportSelectionBound& selection_start_after =
7062 fake_output_surface->last_sent_frame().metadata.selection_start;
7063 const ViewportSelectionBound& selection_end_after =
7064 fake_output_surface->last_sent_frame().metadata.selection_end;
7065 EXPECT_EQ(start.type, selection_start_after.type);
7066 EXPECT_EQ(end.type, selection_end_after.type);
7067 EXPECT_EQ(selection_bottom, selection_start_after.edge_bottom);
7068 EXPECT_EQ(selection_top, selection_start_after.edge_top);
7069 EXPECT_TRUE(selection_start_after.visible);
7070 EXPECT_TRUE(selection_start_after.visible);
7073 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
7074 public:
7075 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
7076 LayerTreeHostImpl* layer_tree_host_impl,
7077 int* set_needs_commit_count,
7078 int* set_needs_redraw_count,
7079 int* forward_to_main_count)
7080 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
7081 set_needs_commit_count_(set_needs_commit_count),
7082 set_needs_redraw_count_(set_needs_redraw_count),
7083 forward_to_main_count_(forward_to_main_count) {}
7085 ~SimpleSwapPromiseMonitor() override {}
7087 void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
7089 void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; }
7091 void OnForwardScrollUpdateToMainThreadOnImpl() override {
7092 (*forward_to_main_count_)++;
7095 private:
7096 int* set_needs_commit_count_;
7097 int* set_needs_redraw_count_;
7098 int* forward_to_main_count_;
7101 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
7102 int set_needs_commit_count = 0;
7103 int set_needs_redraw_count = 0;
7104 int forward_to_main_count = 0;
7107 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7108 new SimpleSwapPromiseMonitor(NULL,
7109 host_impl_.get(),
7110 &set_needs_commit_count,
7111 &set_needs_redraw_count,
7112 &forward_to_main_count));
7113 host_impl_->SetNeedsRedraw();
7114 EXPECT_EQ(0, set_needs_commit_count);
7115 EXPECT_EQ(1, set_needs_redraw_count);
7116 EXPECT_EQ(0, forward_to_main_count);
7119 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
7120 // monitored.
7121 host_impl_->SetNeedsRedraw();
7122 EXPECT_EQ(0, set_needs_commit_count);
7123 EXPECT_EQ(1, set_needs_redraw_count);
7124 EXPECT_EQ(0, forward_to_main_count);
7127 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7128 new SimpleSwapPromiseMonitor(NULL,
7129 host_impl_.get(),
7130 &set_needs_commit_count,
7131 &set_needs_redraw_count,
7132 &forward_to_main_count));
7133 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
7134 EXPECT_EQ(0, set_needs_commit_count);
7135 EXPECT_EQ(2, set_needs_redraw_count);
7136 EXPECT_EQ(0, forward_to_main_count);
7140 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7141 new SimpleSwapPromiseMonitor(NULL,
7142 host_impl_.get(),
7143 &set_needs_commit_count,
7144 &set_needs_redraw_count,
7145 &forward_to_main_count));
7146 // Empty damage rect won't signal the monitor.
7147 host_impl_->SetNeedsRedrawRect(gfx::Rect());
7148 EXPECT_EQ(0, set_needs_commit_count);
7149 EXPECT_EQ(2, set_needs_redraw_count);
7150 EXPECT_EQ(0, forward_to_main_count);
7154 set_needs_commit_count = 0;
7155 set_needs_redraw_count = 0;
7156 forward_to_main_count = 0;
7157 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7158 new SimpleSwapPromiseMonitor(NULL,
7159 host_impl_.get(),
7160 &set_needs_commit_count,
7161 &set_needs_redraw_count,
7162 &forward_to_main_count));
7163 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
7165 // Scrolling normally should not trigger any forwarding.
7166 EXPECT_EQ(InputHandler::ScrollStarted,
7167 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7168 EXPECT_TRUE(
7169 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
7170 host_impl_->ScrollEnd();
7172 EXPECT_EQ(0, set_needs_commit_count);
7173 EXPECT_EQ(1, set_needs_redraw_count);
7174 EXPECT_EQ(0, forward_to_main_count);
7176 // Scrolling with a scroll handler should defer the swap to the main
7177 // thread.
7178 scroll_layer->SetHaveScrollEventHandlers(true);
7179 EXPECT_EQ(InputHandler::ScrollStarted,
7180 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7181 EXPECT_TRUE(
7182 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
7183 host_impl_->ScrollEnd();
7185 EXPECT_EQ(0, set_needs_commit_count);
7186 EXPECT_EQ(2, set_needs_redraw_count);
7187 EXPECT_EQ(1, forward_to_main_count);
7191 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
7192 public:
7193 void SetUp() override {
7194 LayerTreeSettings settings = DefaultSettings();
7195 settings.calculate_top_controls_position = true;
7196 CreateHostImpl(settings, CreateOutputSurface());
7197 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
7198 host_impl_->active_tree()->set_top_controls_delta(top_controls_height_);
7199 host_impl_->top_controls_manager()->SetTopControlsHeight(
7200 top_controls_height_);
7203 protected:
7204 static const int top_controls_height_;
7207 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
7209 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
7210 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7211 ->SetScrollOffset(gfx::ScrollOffset(0, 10));
7212 host_impl_->Animate(base::TimeTicks());
7213 EXPECT_FALSE(did_request_redraw_);
7216 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsHeightIsCommitted) {
7217 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7218 EXPECT_FALSE(did_request_redraw_);
7219 host_impl_->CreatePendingTree();
7220 host_impl_->sync_tree()->set_top_controls_height(100);
7221 host_impl_->ActivateSyncTree();
7222 EXPECT_EQ(100, host_impl_->top_controls_manager()->top_controls_height());
7225 TEST_F(LayerTreeHostImplWithTopControlsTest,
7226 TopControlsStayFullyVisibleOnHeightChange) {
7227 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7228 EXPECT_EQ(0.f, host_impl_->ControlsTopOffset());
7230 host_impl_->CreatePendingTree();
7231 host_impl_->sync_tree()->set_top_controls_height(0);
7232 host_impl_->ActivateSyncTree();
7233 EXPECT_EQ(0.f, host_impl_->ControlsTopOffset());
7235 host_impl_->CreatePendingTree();
7236 host_impl_->sync_tree()->set_top_controls_height(50);
7237 host_impl_->ActivateSyncTree();
7238 EXPECT_EQ(0.f, host_impl_->ControlsTopOffset());
7241 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
7242 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7243 ->SetScrollOffset(gfx::ScrollOffset(0, 10));
7244 host_impl_->DidChangeTopControlsPosition();
7245 EXPECT_TRUE(did_request_animate_);
7246 EXPECT_TRUE(did_request_redraw_);
7249 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
7250 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7251 host_impl_->SetViewportSize(gfx::Size(100, 100));
7252 host_impl_->top_controls_manager()->UpdateTopControlsState(
7253 BOTH, SHOWN, false);
7254 DrawFrame();
7256 EXPECT_EQ(InputHandler::ScrollStarted,
7257 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7258 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7259 EXPECT_EQ(gfx::Vector2dF().ToString(),
7260 scroll_layer->TotalScrollOffset().ToString());
7262 // Scroll just the top controls and verify that the scroll succeeds.
7263 const float residue = 10;
7264 float offset = top_controls_height_ - residue;
7265 EXPECT_TRUE(
7266 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7267 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7268 EXPECT_EQ(gfx::Vector2dF().ToString(),
7269 scroll_layer->TotalScrollOffset().ToString());
7271 // Scroll across the boundary
7272 const float content_scroll = 20;
7273 offset = residue + content_scroll;
7274 EXPECT_TRUE(
7275 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7276 EXPECT_EQ(-top_controls_height_,
7277 host_impl_->top_controls_manager()->ControlsTopOffset());
7278 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
7279 scroll_layer->TotalScrollOffset().ToString());
7281 // Now scroll back to the top of the content
7282 offset = -content_scroll;
7283 EXPECT_TRUE(
7284 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7285 EXPECT_EQ(-top_controls_height_,
7286 host_impl_->top_controls_manager()->ControlsTopOffset());
7287 EXPECT_EQ(gfx::Vector2dF().ToString(),
7288 scroll_layer->TotalScrollOffset().ToString());
7290 // And scroll the top controls completely into view
7291 offset = -top_controls_height_;
7292 EXPECT_TRUE(
7293 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7294 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7295 EXPECT_EQ(gfx::Vector2dF().ToString(),
7296 scroll_layer->TotalScrollOffset().ToString());
7298 // And attempt to scroll past the end
7299 EXPECT_FALSE(
7300 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7301 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7302 EXPECT_EQ(gfx::Vector2dF().ToString(),
7303 scroll_layer->TotalScrollOffset().ToString());
7305 host_impl_->ScrollEnd();
7308 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
7309 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7310 host_impl_->SetViewportSize(gfx::Size(100, 200));
7311 host_impl_->top_controls_manager()->UpdateTopControlsState(
7312 BOTH, SHOWN, false);
7313 DrawFrame();
7315 EXPECT_EQ(InputHandler::ScrollStarted,
7316 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7317 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7318 EXPECT_EQ(gfx::Vector2dF().ToString(),
7319 scroll_layer->TotalScrollOffset().ToString());
7321 // Scroll the top controls partially.
7322 const float residue = 35;
7323 float offset = top_controls_height_ - residue;
7324 EXPECT_TRUE(
7325 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7326 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7327 EXPECT_EQ(gfx::Vector2dF().ToString(),
7328 scroll_layer->TotalScrollOffset().ToString());
7330 did_request_redraw_ = false;
7331 did_request_animate_ = false;
7332 did_request_commit_ = false;
7334 // End the scroll while the controls are still offset from their limit.
7335 host_impl_->ScrollEnd();
7336 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7337 EXPECT_TRUE(did_request_animate_);
7338 EXPECT_TRUE(did_request_redraw_);
7339 EXPECT_FALSE(did_request_commit_);
7341 // The top controls should properly animate until finished, despite the scroll
7342 // offset being at the origin.
7343 base::TimeTicks animation_time = gfx::FrameTime::Now();
7344 while (did_request_animate_) {
7345 did_request_redraw_ = false;
7346 did_request_animate_ = false;
7347 did_request_commit_ = false;
7349 float old_offset =
7350 host_impl_->top_controls_manager()->ControlsTopOffset();
7352 animation_time += base::TimeDelta::FromMilliseconds(5);
7353 host_impl_->Animate(animation_time);
7354 EXPECT_EQ(gfx::Vector2dF().ToString(),
7355 scroll_layer->TotalScrollOffset().ToString());
7357 float new_offset =
7358 host_impl_->top_controls_manager()->ControlsTopOffset();
7360 // No commit is needed as the controls are animating the content offset,
7361 // not the scroll offset.
7362 EXPECT_FALSE(did_request_commit_);
7364 if (new_offset != old_offset)
7365 EXPECT_TRUE(did_request_redraw_);
7367 if (new_offset != 0) {
7368 EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
7369 EXPECT_TRUE(did_request_animate_);
7372 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7375 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
7376 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7377 host_impl_->SetViewportSize(gfx::Size(100, 100));
7378 host_impl_->top_controls_manager()->UpdateTopControlsState(
7379 BOTH, SHOWN, false);
7380 float initial_scroll_offset = 50;
7381 scroll_layer->SetScrollOffset(gfx::ScrollOffset(0, initial_scroll_offset));
7382 DrawFrame();
7384 EXPECT_EQ(InputHandler::ScrollStarted,
7385 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7386 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7387 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7388 scroll_layer->TotalScrollOffset().ToString());
7390 // Scroll the top controls partially.
7391 const float residue = 15;
7392 float offset = top_controls_height_ - residue;
7393 EXPECT_TRUE(
7394 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7395 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7396 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7397 scroll_layer->TotalScrollOffset().ToString());
7399 did_request_redraw_ = false;
7400 did_request_animate_ = false;
7401 did_request_commit_ = false;
7403 // End the scroll while the controls are still offset from the limit.
7404 host_impl_->ScrollEnd();
7405 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7406 EXPECT_TRUE(did_request_animate_);
7407 EXPECT_TRUE(did_request_redraw_);
7408 EXPECT_FALSE(did_request_commit_);
7410 // Animate the top controls to the limit.
7411 base::TimeTicks animation_time = gfx::FrameTime::Now();
7412 while (did_request_animate_) {
7413 did_request_redraw_ = false;
7414 did_request_animate_ = false;
7415 did_request_commit_ = false;
7417 float old_offset =
7418 host_impl_->top_controls_manager()->ControlsTopOffset();
7420 animation_time += base::TimeDelta::FromMilliseconds(5);
7421 host_impl_->Animate(animation_time);
7423 float new_offset =
7424 host_impl_->top_controls_manager()->ControlsTopOffset();
7426 if (new_offset != old_offset) {
7427 EXPECT_TRUE(did_request_redraw_);
7428 EXPECT_TRUE(did_request_commit_);
7431 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7434 TEST_F(LayerTreeHostImplWithTopControlsTest,
7435 TopControlsScrollDeltaInOverScroll) {
7436 // test varifies that the overscroll delta should not have accumulated in
7437 // the top controls if we do a hide and show without releasing finger.
7439 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7440 host_impl_->SetViewportSize(gfx::Size(100, 100));
7441 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7442 false);
7443 DrawFrame();
7445 EXPECT_EQ(InputHandler::ScrollStarted,
7446 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7447 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7449 float offset = 50;
7450 EXPECT_TRUE(
7451 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7452 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7453 EXPECT_EQ(gfx::Vector2dF().ToString(),
7454 scroll_layer->TotalScrollOffset().ToString());
7456 EXPECT_TRUE(
7457 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7458 EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
7459 scroll_layer->TotalScrollOffset().ToString());
7461 EXPECT_TRUE(
7462 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7464 // Should have fully scrolled
7465 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer->MaxScrollOffset().y()).ToString(),
7466 scroll_layer->TotalScrollOffset().ToString());
7468 float overscrollamount = 10;
7470 // Overscroll the content
7471 EXPECT_FALSE(
7472 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount))
7473 .did_scroll);
7474 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
7475 scroll_layer->TotalScrollOffset().ToString());
7476 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount).ToString(),
7477 host_impl_->accumulated_root_overscroll().ToString());
7479 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset))
7480 .did_scroll);
7481 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7482 scroll_layer->TotalScrollOffset().ToString());
7483 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7485 EXPECT_TRUE(
7486 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset)).did_scroll);
7487 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7488 scroll_layer->TotalScrollOffset().ToString());
7490 // Top controls should be fully visible
7491 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7493 host_impl_->ScrollEnd();
7496 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
7497 public:
7498 void SetupVirtualViewportLayers(const gfx::Size& content_size,
7499 const gfx::Size& outer_viewport,
7500 const gfx::Size& inner_viewport) {
7501 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
7502 const int kOuterViewportClipLayerId = 6;
7503 const int kOuterViewportScrollLayerId = 7;
7504 const int kInnerViewportScrollLayerId = 2;
7505 const int kInnerViewportClipLayerId = 4;
7506 const int kPageScaleLayerId = 5;
7508 scoped_ptr<LayerImpl> inner_scroll =
7509 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
7510 inner_scroll->SetIsContainerForFixedPositionLayers(true);
7511 inner_scroll->SetScrollOffset(gfx::ScrollOffset());
7513 scoped_ptr<LayerImpl> inner_clip =
7514 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
7515 inner_clip->SetBounds(inner_viewport);
7517 scoped_ptr<LayerImpl> page_scale =
7518 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
7520 inner_scroll->SetScrollClipLayer(inner_clip->id());
7521 inner_scroll->SetBounds(outer_viewport);
7522 inner_scroll->SetContentBounds(outer_viewport);
7523 inner_scroll->SetPosition(gfx::PointF());
7525 scoped_ptr<LayerImpl> outer_clip =
7526 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
7527 outer_clip->SetBounds(outer_viewport);
7528 outer_clip->SetIsContainerForFixedPositionLayers(true);
7530 scoped_ptr<LayerImpl> outer_scroll =
7531 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
7532 outer_scroll->SetScrollClipLayer(outer_clip->id());
7533 outer_scroll->SetScrollOffset(gfx::ScrollOffset());
7534 outer_scroll->SetBounds(content_size);
7535 outer_scroll->SetContentBounds(content_size);
7536 outer_scroll->SetPosition(gfx::PointF());
7538 scoped_ptr<LayerImpl> contents =
7539 LayerImpl::Create(layer_tree_impl, 8);
7540 contents->SetDrawsContent(true);
7541 contents->SetBounds(content_size);
7542 contents->SetContentBounds(content_size);
7543 contents->SetPosition(gfx::PointF());
7545 outer_scroll->AddChild(contents.Pass());
7546 outer_clip->AddChild(outer_scroll.Pass());
7547 inner_scroll->AddChild(outer_clip.Pass());
7548 page_scale->AddChild(inner_scroll.Pass());
7549 inner_clip->AddChild(page_scale.Pass());
7551 layer_tree_impl->SetRootLayer(inner_clip.Pass());
7552 layer_tree_impl->SetViewportLayersFromIds(
7553 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
7554 kOuterViewportScrollLayerId);
7556 host_impl_->active_tree()->DidBecomeActive();
7560 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
7561 gfx::Size content_size = gfx::Size(100, 160);
7562 gfx::Size outer_viewport = gfx::Size(50, 80);
7563 gfx::Size inner_viewport = gfx::Size(25, 40);
7565 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7567 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7568 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7569 DrawFrame();
7571 gfx::Vector2dF inner_expected;
7572 gfx::Vector2dF outer_expected;
7573 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7574 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7576 // Make sure the fling goes to the outer viewport first
7577 EXPECT_EQ(InputHandler::ScrollStarted,
7578 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7579 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
7581 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7582 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7583 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7585 host_impl_->ScrollEnd();
7587 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7588 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7590 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7591 EXPECT_EQ(InputHandler::ScrollStarted,
7592 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7593 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
7595 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7596 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7598 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7599 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7601 host_impl_->ScrollEnd();
7603 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7604 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7608 TEST_F(LayerTreeHostImplVirtualViewportTest,
7609 DiagonalScrollBubblesPerfectlyToInner) {
7610 gfx::Size content_size = gfx::Size(100, 160);
7611 gfx::Size outer_viewport = gfx::Size(50, 80);
7612 gfx::Size inner_viewport = gfx::Size(25, 40);
7614 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7616 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7617 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7618 DrawFrame();
7620 gfx::Vector2dF inner_expected;
7621 gfx::Vector2dF outer_expected;
7622 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7623 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7625 // Make sure the scroll goes to the outer viewport first.
7626 EXPECT_EQ(InputHandler::ScrollStarted,
7627 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7628 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
7630 // Scroll near the edge of the outer viewport.
7631 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7632 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7633 outer_expected += scroll_delta;
7635 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7636 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7638 // Now diagonal scroll across the outer viewport boundary in a single event.
7639 // The entirety of the scroll should be consumed, as bubbling between inner
7640 // and outer viewport layers is perfect.
7641 host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2));
7642 outer_expected += scroll_delta;
7643 inner_expected += scroll_delta;
7644 host_impl_->ScrollEnd();
7646 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
7647 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
7651 TEST_F(LayerTreeHostImplVirtualViewportTest,
7652 TouchFlingCanLockToViewportLayerAfterBubbling) {
7653 gfx::Size content_size = gfx::Size(100, 160);
7654 gfx::Size outer_viewport = gfx::Size(50, 80);
7655 gfx::Size inner_viewport = gfx::Size(25, 40);
7657 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7659 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7660 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7662 scoped_ptr<LayerImpl> child =
7663 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7664 LayerImpl* child_scroll = child.get();
7665 outer_scroll->children()[0]->AddChild(child.Pass());
7667 DrawFrame();
7669 scoped_ptr<ScrollAndScaleSet> scroll_info;
7671 gfx::Vector2d scroll_delta(0, inner_viewport.height());
7672 EXPECT_EQ(InputHandler::ScrollStarted,
7673 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
7674 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7676 // The child should have scrolled up to its limit.
7677 scroll_info = host_impl_->ProcessScrollDeltas();
7678 ASSERT_EQ(1u, scroll_info->scrolls.size());
7679 ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
7680 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7682 // The first |ScrollBy| after the fling should re-lock the scrolling
7683 // layer to the first layer that scrolled, the inner viewport scroll layer.
7684 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
7685 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7686 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7688 // The inner viewport should have scrolled up to its limit.
7689 scroll_info = host_impl_->ProcessScrollDeltas();
7690 ASSERT_EQ(2u, scroll_info->scrolls.size());
7691 ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
7692 ExpectContains(*scroll_info, inner_scroll->id(), scroll_delta);
7694 // As the locked layer is at its limit, no further scrolling can occur.
7695 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7696 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7697 host_impl_->ScrollEnd();
7701 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
7702 public:
7703 void SetUp() override {
7704 LayerTreeSettings settings = DefaultSettings();
7705 settings.max_memory_for_prepaint_percentage = 50;
7706 CreateHostImpl(settings, CreateOutputSurface());
7710 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
7711 // Set up a memory policy and percentages which could cause
7712 // 32-bit integer overflows.
7713 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
7715 // Verify implicit limits are calculated correctly with no overflows
7716 host_impl_->SetMemoryPolicy(mem_policy);
7717 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
7718 300u * 1024u * 1024u);
7719 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
7720 150u * 1024u * 1024u);
7723 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
7724 const gfx::Size layer_size(100, 100);
7725 gfx::Transform external_transform;
7726 const gfx::Rect external_viewport(layer_size);
7727 const gfx::Rect external_clip(layer_size);
7728 const bool resourceless_software_draw = false;
7729 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
7731 host_impl_->SetExternalDrawConstraints(external_transform,
7732 external_viewport,
7733 external_clip,
7734 external_viewport,
7735 external_transform,
7736 resourceless_software_draw);
7737 DrawFrame();
7738 EXPECT_TRANSFORMATION_MATRIX_EQ(
7739 external_transform, layer->draw_properties().target_space_transform);
7741 external_transform.Translate(20, 20);
7742 host_impl_->SetExternalDrawConstraints(external_transform,
7743 external_viewport,
7744 external_clip,
7745 external_viewport,
7746 external_transform,
7747 resourceless_software_draw);
7748 DrawFrame();
7749 EXPECT_TRANSFORMATION_MATRIX_EQ(
7750 external_transform, layer->draw_properties().target_space_transform);
7753 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
7754 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7755 DrawFrame();
7757 base::TimeTicks start_time =
7758 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7760 EXPECT_EQ(InputHandler::ScrollStarted,
7761 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7763 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
7765 host_impl_->Animate(start_time);
7766 host_impl_->UpdateAnimationState(true);
7768 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->TotalScrollOffset());
7770 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
7771 host_impl_->UpdateAnimationState(true);
7773 float y = scrolling_layer->TotalScrollOffset().y();
7774 EXPECT_TRUE(y > 1 && y < 49);
7776 // Update target.
7777 EXPECT_EQ(InputHandler::ScrollStarted,
7778 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7780 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
7781 host_impl_->UpdateAnimationState(true);
7783 y = scrolling_layer->TotalScrollOffset().y();
7784 EXPECT_TRUE(y > 50 && y < 100);
7785 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
7787 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
7788 host_impl_->UpdateAnimationState(true);
7790 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7791 scrolling_layer->TotalScrollOffset());
7792 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
7795 TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairs) {
7796 host_impl_->CreatePendingTree();
7797 host_impl_->pending_tree()->SetRootLayer(
7798 PictureLayerImpl::Create(host_impl_->pending_tree(), 10, false));
7800 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
7801 LayerImpl* pending_layer = pending_tree->root_layer();
7803 std::vector<PictureLayerImpl::Pair> layer_pairs;
7804 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
7805 EXPECT_EQ(1u, layer_pairs.size());
7806 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7807 EXPECT_EQ(nullptr, layer_pairs[0].active);
7809 host_impl_->ActivateSyncTree();
7811 LayerTreeImpl* active_tree = host_impl_->active_tree();
7812 LayerImpl* active_layer = active_tree->root_layer();
7813 EXPECT_NE(active_tree, pending_tree);
7814 EXPECT_NE(active_layer, pending_layer);
7815 EXPECT_NE(nullptr, active_tree);
7816 EXPECT_NE(nullptr, active_layer);
7818 host_impl_->CreatePendingTree();
7820 layer_pairs.clear();
7821 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
7822 EXPECT_EQ(1u, layer_pairs.size());
7823 EXPECT_EQ(active_layer, layer_pairs[0].active);
7824 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7826 // Activate, the active layer has no twin now.
7827 host_impl_->ActivateSyncTree();
7829 layer_pairs.clear();
7830 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
7831 EXPECT_EQ(1u, layer_pairs.size());
7832 EXPECT_EQ(active_layer, layer_pairs[0].active);
7833 EXPECT_EQ(nullptr, layer_pairs[0].pending);
7835 // Create another layer in the pending tree that's not in the active tree. We
7836 // should get two pairs.
7837 host_impl_->CreatePendingTree();
7838 host_impl_->pending_tree()->root_layer()->AddChild(
7839 PictureLayerImpl::Create(host_impl_->pending_tree(), 11, false));
7841 LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[0];
7843 layer_pairs.clear();
7844 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
7845 EXPECT_EQ(2u, layer_pairs.size());
7847 // The pair ordering is flaky, so make it consistent.
7848 if (layer_pairs[0].active != active_layer)
7849 std::swap(layer_pairs[0], layer_pairs[1]);
7851 EXPECT_EQ(active_layer, layer_pairs[0].active);
7852 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7853 EXPECT_EQ(new_pending_layer, layer_pairs[1].pending);
7854 EXPECT_EQ(nullptr, layer_pairs[1].active);
7857 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
7858 host_impl_->CreatePendingTree();
7859 host_impl_->ActivateSyncTree();
7860 host_impl_->CreatePendingTree();
7862 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
7864 scoped_ptr<FakePictureLayerImpl> pending_layer =
7865 FakePictureLayerImpl::Create(pending_tree, 10);
7866 pending_layer->DoPostCommitInitializationIfNeeded();
7867 FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
7868 pending_tree->SetRootLayer(pending_layer.Pass());
7869 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
7871 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
7872 pending_tree->DidBecomeActive();
7873 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7875 scoped_ptr<FakePictureLayerImpl> mask_layer =
7876 FakePictureLayerImpl::Create(pending_tree, 11);
7877 mask_layer->DoPostCommitInitializationIfNeeded();
7878 FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
7879 raw_pending_layer->SetMaskLayer(mask_layer.Pass());
7880 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
7882 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7883 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
7884 pending_tree->DidBecomeActive();
7885 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7886 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7888 scoped_ptr<FakePictureLayerImpl> replica_layer =
7889 FakePictureLayerImpl::Create(pending_tree, 12);
7890 scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
7891 FakePictureLayerImpl::Create(pending_tree, 13);
7892 replica_mask_layer->DoPostCommitInitializationIfNeeded();
7893 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
7894 replica_layer->SetMaskLayer(replica_mask_layer.Pass());
7895 raw_pending_layer->SetReplicaLayer(replica_layer.Pass());
7896 ASSERT_EQ(raw_replica_mask_layer,
7897 raw_pending_layer->replica_layer()->mask_layer());
7899 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7900 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7901 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
7902 pending_tree->DidBecomeActive();
7903 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
7904 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
7905 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
7908 TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
7909 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
7910 host_impl_->SetViewportSize(gfx::Size(50, 50));
7911 DrawFrame();
7913 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
7915 float min_page_scale = 1.f, max_page_scale = 4.f;
7916 float page_scale_factor = 1.f;
7918 // The scroll deltas should have the page scale factor applied.
7920 host_impl_->active_tree()->PushPageScaleFromMainThread(
7921 page_scale_factor, min_page_scale, max_page_scale);
7922 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
7923 scroll_layer->SetScrollDelta(gfx::Vector2d());
7925 float page_scale_delta = 2.f;
7926 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
7927 host_impl_->PinchGestureBegin();
7928 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
7929 host_impl_->PinchGestureEnd();
7930 host_impl_->ScrollEnd();
7932 gfx::Vector2dF scroll_delta(0, 5);
7933 EXPECT_EQ(InputHandler::ScrollStarted,
7934 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
7935 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
7937 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7938 host_impl_->ScrollEnd();
7939 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5), scroll_layer->TotalScrollOffset());
7943 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
7944 public:
7945 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7946 void DidLoseOutputSurfaceOnImplThread() override { num_lost_surfaces_++; }
7948 protected:
7949 int num_lost_surfaces_;
7952 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
7953 // Really we just need at least one client notification each time
7954 // we go from having a valid output surface to not having a valid output
7955 // surface.
7956 EXPECT_EQ(0, num_lost_surfaces_);
7957 host_impl_->DidLoseOutputSurface();
7958 EXPECT_EQ(1, num_lost_surfaces_);
7959 host_impl_->DidLoseOutputSurface();
7960 EXPECT_LE(1, num_lost_surfaces_);
7963 } // namespace
7964 } // namespace cc