Route selection bounds updates through the compositor
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blobdc7b106ca0d110a06b3e8a303730f9f40af2eacb
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host_impl.h"
7 #include <cmath>
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/containers/hash_tables.h"
12 #include "base/containers/scoped_ptr_hash_map.h"
13 #include "cc/animation/scrollbar_animation_controller_thinning.h"
14 #include "cc/base/latency_info_swap_promise.h"
15 #include "cc/base/math_util.h"
16 #include "cc/input/top_controls_manager.h"
17 #include "cc/layers/append_quads_data.h"
18 #include "cc/layers/delegated_renderer_layer_impl.h"
19 #include "cc/layers/heads_up_display_layer_impl.h"
20 #include "cc/layers/io_surface_layer_impl.h"
21 #include "cc/layers/layer_impl.h"
22 #include "cc/layers/painted_scrollbar_layer_impl.h"
23 #include "cc/layers/render_surface_impl.h"
24 #include "cc/layers/solid_color_layer_impl.h"
25 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
26 #include "cc/layers/texture_layer_impl.h"
27 #include "cc/layers/tiled_layer_impl.h"
28 #include "cc/layers/video_layer_impl.h"
29 #include "cc/output/begin_frame_args.h"
30 #include "cc/output/compositor_frame_ack.h"
31 #include "cc/output/compositor_frame_metadata.h"
32 #include "cc/output/copy_output_request.h"
33 #include "cc/output/copy_output_result.h"
34 #include "cc/output/gl_renderer.h"
35 #include "cc/quads/render_pass_draw_quad.h"
36 #include "cc/quads/solid_color_draw_quad.h"
37 #include "cc/quads/texture_draw_quad.h"
38 #include "cc/quads/tile_draw_quad.h"
39 #include "cc/resources/layer_tiling_data.h"
40 #include "cc/test/animation_test_common.h"
41 #include "cc/test/fake_layer_tree_host_impl.h"
42 #include "cc/test/fake_output_surface.h"
43 #include "cc/test/fake_output_surface_client.h"
44 #include "cc/test/fake_picture_layer_impl.h"
45 #include "cc/test/fake_picture_pile_impl.h"
46 #include "cc/test/fake_proxy.h"
47 #include "cc/test/fake_rendering_stats_instrumentation.h"
48 #include "cc/test/fake_video_frame_provider.h"
49 #include "cc/test/geometry_test_utils.h"
50 #include "cc/test/layer_test_common.h"
51 #include "cc/test/render_pass_test_common.h"
52 #include "cc/test/test_shared_bitmap_manager.h"
53 #include "cc/test/test_web_graphics_context_3d.h"
54 #include "cc/trees/layer_tree_impl.h"
55 #include "cc/trees/single_thread_proxy.h"
56 #include "media/base/media.h"
57 #include "testing/gmock/include/gmock/gmock.h"
58 #include "testing/gtest/include/gtest/gtest.h"
59 #include "third_party/skia/include/core/SkMallocPixelRef.h"
60 #include "ui/gfx/frame_time.h"
61 #include "ui/gfx/rect_conversions.h"
62 #include "ui/gfx/size_conversions.h"
63 #include "ui/gfx/vector2d_conversions.h"
65 using ::testing::Mock;
66 using ::testing::Return;
67 using ::testing::AnyNumber;
68 using ::testing::AtLeast;
69 using ::testing::_;
70 using media::VideoFrame;
72 namespace cc {
73 namespace {
75 class LayerTreeHostImplTest : public testing::Test,
76 public LayerTreeHostImplClient {
77 public:
78 LayerTreeHostImplTest()
79 : proxy_(base::MessageLoopProxy::current()),
80 always_impl_thread_(&proxy_),
81 always_main_thread_blocked_(&proxy_),
82 shared_bitmap_manager_(new TestSharedBitmapManager()),
83 on_can_draw_state_changed_called_(false),
84 did_notify_ready_to_activate_(false),
85 did_request_commit_(false),
86 did_request_redraw_(false),
87 did_request_animate_(false),
88 did_request_manage_tiles_(false),
89 did_upload_visible_tile_(false),
90 reduce_memory_result_(true),
91 current_limit_bytes_(0),
92 current_priority_cutoff_value_(0) {
93 media::InitializeMediaLibraryForTesting();
96 LayerTreeSettings DefaultSettings() {
97 LayerTreeSettings settings;
98 settings.minimum_occlusion_tracking_size = gfx::Size();
99 settings.impl_side_painting = true;
100 settings.texture_id_allocation_chunk_size = 1;
101 settings.report_overscroll_only_for_scrollable_axes = true;
102 return settings;
105 virtual void SetUp() OVERRIDE {
106 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
109 virtual void TearDown() OVERRIDE {}
111 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {}
112 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
113 virtual void CommitVSyncParameters(base::TimeTicks timebase,
114 base::TimeDelta interval) OVERRIDE {}
115 virtual void SetEstimatedParentDrawTime(base::TimeDelta draw_time) OVERRIDE {}
116 virtual void SetMaxSwapsPendingOnImplThread(int max) OVERRIDE {}
117 virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
118 virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {}
119 virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {}
120 virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
121 on_can_draw_state_changed_called_ = true;
123 virtual void NotifyReadyToActivate() OVERRIDE {
124 did_notify_ready_to_activate_ = true;
125 host_impl_->ActivateSyncTree();
127 virtual void SetNeedsRedrawOnImplThread() OVERRIDE {
128 did_request_redraw_ = true;
130 virtual void SetNeedsRedrawRectOnImplThread(
131 const gfx::Rect& damage_rect) OVERRIDE {
132 did_request_redraw_ = true;
134 virtual void SetNeedsAnimateOnImplThread() OVERRIDE {
135 did_request_animate_ = true;
137 virtual void SetNeedsManageTilesOnImplThread() OVERRIDE {
138 did_request_manage_tiles_ = true;
140 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {
141 did_upload_visible_tile_ = true;
143 virtual void SetNeedsCommitOnImplThread() OVERRIDE {
144 did_request_commit_ = true;
146 virtual void PostAnimationEventsToMainThreadOnImplThread(
147 scoped_ptr<AnimationEventsVector> events) OVERRIDE {}
148 virtual bool ReduceContentsTextureMemoryOnImplThread(
149 size_t limit_bytes, int priority_cutoff) OVERRIDE {
150 current_limit_bytes_ = limit_bytes;
151 current_priority_cutoff_value_ = priority_cutoff;
152 return reduce_memory_result_;
154 virtual bool IsInsideDraw() OVERRIDE { return false; }
155 virtual void RenewTreePriority() OVERRIDE {}
156 virtual void PostDelayedScrollbarFadeOnImplThread(
157 const base::Closure& start_fade,
158 base::TimeDelta delay) OVERRIDE {
159 scrollbar_fade_start_ = start_fade;
160 requested_scrollbar_animation_delay_ = delay;
162 virtual void DidActivateSyncTree() OVERRIDE {}
163 virtual void DidManageTiles() OVERRIDE {}
165 void set_reduce_memory_result(bool reduce_memory_result) {
166 reduce_memory_result_ = reduce_memory_result;
169 bool CreateHostImpl(const LayerTreeSettings& settings,
170 scoped_ptr<OutputSurface> output_surface) {
171 host_impl_ = LayerTreeHostImpl::Create(settings,
172 this,
173 &proxy_,
174 &stats_instrumentation_,
175 shared_bitmap_manager_.get(),
177 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
178 host_impl_->SetViewportSize(gfx::Size(10, 10));
179 return init;
182 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
183 root->SetPosition(gfx::PointF());
184 root->SetBounds(gfx::Size(10, 10));
185 root->SetContentBounds(gfx::Size(10, 10));
186 root->SetDrawsContent(true);
187 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
188 host_impl_->active_tree()->SetRootLayer(root.Pass());
191 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
192 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
193 for (size_t i = 0; i < layer->children().size(); ++i)
194 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
197 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
198 int id,
199 const gfx::Vector2d& scroll_delta) {
200 int times_encountered = 0;
202 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
203 if (scroll_info.scrolls[i].layer_id != id)
204 continue;
205 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
206 times_encountered++;
209 ASSERT_EQ(1, times_encountered);
212 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
213 int times_encountered = 0;
215 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
216 if (scroll_info.scrolls[i].layer_id != id)
217 continue;
218 times_encountered++;
221 ASSERT_EQ(0, times_encountered);
224 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
225 const gfx::Size& content_size) {
226 const int kInnerViewportScrollLayerId = 2;
227 const int kInnerViewportClipLayerId = 4;
228 const int kPageScaleLayerId = 5;
229 scoped_ptr<LayerImpl> root =
230 LayerImpl::Create(layer_tree_impl, 1);
231 root->SetBounds(content_size);
232 root->SetContentBounds(content_size);
233 root->SetPosition(gfx::PointF());
235 scoped_ptr<LayerImpl> scroll =
236 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
237 LayerImpl* scroll_layer = scroll.get();
238 scroll->SetIsContainerForFixedPositionLayers(true);
239 scroll->SetScrollOffset(gfx::Vector2d());
241 scoped_ptr<LayerImpl> clip =
242 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
243 clip->SetBounds(
244 gfx::Size(content_size.width() / 2, content_size.height() / 2));
246 scoped_ptr<LayerImpl> page_scale =
247 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
249 scroll->SetScrollClipLayer(clip->id());
250 scroll->SetBounds(content_size);
251 scroll->SetContentBounds(content_size);
252 scroll->SetPosition(gfx::PointF());
253 scroll->SetIsContainerForFixedPositionLayers(true);
255 scoped_ptr<LayerImpl> contents =
256 LayerImpl::Create(layer_tree_impl, 3);
257 contents->SetDrawsContent(true);
258 contents->SetBounds(content_size);
259 contents->SetContentBounds(content_size);
260 contents->SetPosition(gfx::PointF());
262 scroll->AddChild(contents.Pass());
263 page_scale->AddChild(scroll.Pass());
264 clip->AddChild(page_scale.Pass());
265 root->AddChild(clip.Pass());
267 layer_tree_impl->SetRootLayer(root.Pass());
268 layer_tree_impl->SetViewportLayersFromIds(
269 kPageScaleLayerId, kInnerViewportScrollLayerId, Layer::INVALID_ID);
271 return scroll_layer;
274 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
275 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
276 host_impl_->active_tree(), content_size);
277 host_impl_->active_tree()->DidBecomeActive();
278 return scroll_layer;
281 // TODO(wjmaclean) Add clip-layer pointer to parameters.
282 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
283 const gfx::Size& size,
284 LayerImpl* clip_layer) {
285 DCHECK(clip_layer);
286 DCHECK(id != clip_layer->id());
287 scoped_ptr<LayerImpl> layer =
288 LayerImpl::Create(host_impl_->active_tree(), id);
289 layer->SetScrollClipLayer(clip_layer->id());
290 layer->SetDrawsContent(true);
291 layer->SetBounds(size);
292 layer->SetContentBounds(size);
293 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
294 return layer.Pass();
297 void DrawFrame() {
298 LayerTreeHostImpl::FrameData frame;
299 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
300 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
301 host_impl_->DidDrawAllLayers(frame);
304 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
305 void pinch_zoom_pan_viewport_test(float device_scale_factor);
306 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
307 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
308 float device_scale_factor);
310 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
311 // Note: It is not possible to disable the renderer once it has been set,
312 // so we do not need to test that disabling the renderer notifies us
313 // that can_draw changed.
314 EXPECT_FALSE(host_impl_->CanDraw());
315 on_can_draw_state_changed_called_ = false;
317 // Set up the root layer, which allows us to draw.
318 SetupScrollAndContentsLayers(gfx::Size(100, 100));
319 EXPECT_TRUE(host_impl_->CanDraw());
320 EXPECT_TRUE(on_can_draw_state_changed_called_);
321 on_can_draw_state_changed_called_ = false;
323 // Toggle the root layer to make sure it toggles can_draw
324 host_impl_->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
325 EXPECT_FALSE(host_impl_->CanDraw());
326 EXPECT_TRUE(on_can_draw_state_changed_called_);
327 on_can_draw_state_changed_called_ = false;
329 SetupScrollAndContentsLayers(gfx::Size(100, 100));
330 EXPECT_TRUE(host_impl_->CanDraw());
331 EXPECT_TRUE(on_can_draw_state_changed_called_);
332 on_can_draw_state_changed_called_ = false;
334 // Toggle the device viewport size to make sure it toggles can_draw.
335 host_impl_->SetViewportSize(gfx::Size());
336 if (always_draw) {
337 EXPECT_TRUE(host_impl_->CanDraw());
338 } else {
339 EXPECT_FALSE(host_impl_->CanDraw());
341 EXPECT_TRUE(on_can_draw_state_changed_called_);
342 on_can_draw_state_changed_called_ = false;
344 host_impl_->SetViewportSize(gfx::Size(100, 100));
345 EXPECT_TRUE(host_impl_->CanDraw());
346 EXPECT_TRUE(on_can_draw_state_changed_called_);
347 on_can_draw_state_changed_called_ = false;
349 // Toggle contents textures purged without causing any evictions,
350 // and make sure that it does not change can_draw.
351 set_reduce_memory_result(false);
352 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
353 host_impl_->memory_allocation_limit_bytes() - 1));
354 EXPECT_TRUE(host_impl_->CanDraw());
355 EXPECT_FALSE(on_can_draw_state_changed_called_);
356 on_can_draw_state_changed_called_ = false;
358 // Toggle contents textures purged to make sure it toggles can_draw.
359 set_reduce_memory_result(true);
360 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
361 host_impl_->memory_allocation_limit_bytes() - 1));
362 if (always_draw) {
363 EXPECT_TRUE(host_impl_->CanDraw());
364 } else {
365 EXPECT_FALSE(host_impl_->CanDraw());
367 EXPECT_TRUE(on_can_draw_state_changed_called_);
368 on_can_draw_state_changed_called_ = false;
370 host_impl_->active_tree()->ResetContentsTexturesPurged();
371 EXPECT_TRUE(host_impl_->CanDraw());
372 EXPECT_TRUE(on_can_draw_state_changed_called_);
373 on_can_draw_state_changed_called_ = false;
376 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
378 protected:
379 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
380 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
383 void DrawOneFrame() {
384 LayerTreeHostImpl::FrameData frame_data;
385 host_impl_->PrepareToDraw(&frame_data);
386 host_impl_->DidDrawAllLayers(frame_data);
389 FakeProxy proxy_;
390 DebugScopedSetImplThread always_impl_thread_;
391 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
393 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
394 scoped_ptr<LayerTreeHostImpl> host_impl_;
395 FakeRenderingStatsInstrumentation stats_instrumentation_;
396 bool on_can_draw_state_changed_called_;
397 bool did_notify_ready_to_activate_;
398 bool did_request_commit_;
399 bool did_request_redraw_;
400 bool did_request_animate_;
401 bool did_request_manage_tiles_;
402 bool did_upload_visible_tile_;
403 bool reduce_memory_result_;
404 base::Closure scrollbar_fade_start_;
405 base::TimeDelta requested_scrollbar_animation_delay_;
406 size_t current_limit_bytes_;
407 int current_priority_cutoff_value_;
410 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
411 bool always_draw = false;
412 CheckNotifyCalledIfCanDrawChanged(always_draw);
415 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
416 scoped_ptr<FakeOutputSurface> output_surface(
417 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
418 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
420 bool always_draw = true;
421 CheckNotifyCalledIfCanDrawChanged(always_draw);
424 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
425 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
427 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
428 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
431 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
433 scoped_ptr<LayerImpl> root =
434 LayerImpl::Create(host_impl_->active_tree(), 1);
435 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
436 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
437 root->children()[1]->AddChild(
438 LayerImpl::Create(host_impl_->active_tree(), 4));
439 root->children()[1]->AddChild(
440 LayerImpl::Create(host_impl_->active_tree(), 5));
441 root->children()[1]->children()[0]->AddChild(
442 LayerImpl::Create(host_impl_->active_tree(), 6));
443 host_impl_->active_tree()->SetRootLayer(root.Pass());
445 LayerImpl* root = host_impl_->active_tree()->root_layer();
447 ExpectClearedScrollDeltasRecursive(root);
449 scoped_ptr<ScrollAndScaleSet> scroll_info;
451 scroll_info = host_impl_->ProcessScrollDeltas();
452 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
453 ExpectClearedScrollDeltasRecursive(root);
455 scroll_info = host_impl_->ProcessScrollDeltas();
456 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
457 ExpectClearedScrollDeltasRecursive(root);
460 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
461 gfx::Vector2d scroll_offset(20, 30);
462 gfx::Vector2d scroll_delta(11, -15);
464 scoped_ptr<LayerImpl> root_clip =
465 LayerImpl::Create(host_impl_->active_tree(), 2);
466 scoped_ptr<LayerImpl> root =
467 LayerImpl::Create(host_impl_->active_tree(), 1);
468 root_clip->SetBounds(gfx::Size(10, 10));
469 LayerImpl* root_layer = root.get();
470 root_clip->AddChild(root.Pass());
471 root_layer->SetBounds(gfx::Size(110, 110));
472 root_layer->SetScrollClipLayer(root_clip->id());
473 root_layer->SetScrollOffset(scroll_offset);
474 root_layer->ScrollBy(scroll_delta);
475 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
477 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
479 scoped_ptr<ScrollAndScaleSet> scroll_info;
481 scroll_info = host_impl_->ProcessScrollDeltas();
482 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
483 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta);
484 ExpectContains(*scroll_info, root->id(), scroll_delta);
486 gfx::Vector2d scroll_delta2(-5, 27);
487 root->ScrollBy(scroll_delta2);
488 scroll_info = host_impl_->ProcessScrollDeltas();
489 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
490 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
491 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
493 root->ScrollBy(gfx::Vector2d());
494 scroll_info = host_impl_->ProcessScrollDeltas();
495 EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
498 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
499 SetupScrollAndContentsLayers(gfx::Size(100, 100));
500 host_impl_->SetViewportSize(gfx::Size(50, 50));
501 DrawFrame();
503 EXPECT_EQ(InputHandler::ScrollStarted,
504 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
505 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
506 InputHandler::Wheel));
507 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
508 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
509 InputHandler::Wheel));
510 host_impl_->ScrollEnd();
511 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
512 InputHandler::Wheel));
513 EXPECT_TRUE(did_request_redraw_);
514 EXPECT_TRUE(did_request_commit_);
517 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
518 // We should not crash when trying to scroll an empty layer tree.
519 EXPECT_EQ(InputHandler::ScrollIgnored,
520 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
523 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
524 scoped_ptr<TestWebGraphicsContext3D> context_owned =
525 TestWebGraphicsContext3D::Create();
526 context_owned->set_context_lost(true);
528 scoped_ptr<FakeOutputSurface> output_surface(FakeOutputSurface::Create3d(
529 context_owned.Pass()));
531 // Initialization will fail.
532 EXPECT_FALSE(CreateHostImpl(DefaultSettings(),
533 output_surface.PassAs<OutputSurface>()));
535 SetupScrollAndContentsLayers(gfx::Size(100, 100));
537 // We should not crash when trying to scroll after the renderer initialization
538 // fails.
539 EXPECT_EQ(InputHandler::ScrollStarted,
540 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
543 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
544 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
545 host_impl_->SetViewportSize(gfx::Size(50, 50));
546 DrawFrame();
548 // We should not crash if the tree is replaced while we are scrolling.
549 EXPECT_EQ(InputHandler::ScrollStarted,
550 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
551 host_impl_->active_tree()->DetachLayerTree();
553 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
555 // We should still be scrolling, because the scrolled layer also exists in the
556 // new tree.
557 gfx::Vector2d scroll_delta(0, 10);
558 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
559 host_impl_->ScrollEnd();
560 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
561 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
564 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
565 SetupScrollAndContentsLayers(gfx::Size(100, 100));
566 host_impl_->SetViewportSize(gfx::Size(50, 50));
567 DrawFrame();
569 // We should be able to scroll even if the root layer loses its render surface
570 // after the most recent render.
571 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
572 host_impl_->active_tree()->set_needs_update_draw_properties();
574 EXPECT_EQ(InputHandler::ScrollStarted,
575 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
578 TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
579 SetupScrollAndContentsLayers(gfx::Size(100, 100));
580 host_impl_->SetViewportSize(gfx::Size(50, 50));
581 DrawFrame();
582 LayerImpl* root = host_impl_->active_tree()->root_layer();
584 root->SetHaveWheelEventHandlers(true);
586 // With registered event handlers, wheel scrolls have to go to the main
587 // thread.
588 EXPECT_EQ(InputHandler::ScrollOnMainThread,
589 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
591 // But gesture scrolls can still be handled.
592 EXPECT_EQ(InputHandler::ScrollStarted,
593 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
596 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
597 SetupScrollAndContentsLayers(gfx::Size(100, 100));
598 host_impl_->SetViewportSize(gfx::Size(50, 50));
599 DrawFrame();
601 // Ignore the fling since no layer is being scrolled
602 EXPECT_EQ(InputHandler::ScrollIgnored,
603 host_impl_->FlingScrollBegin());
605 // Start scrolling a layer
606 EXPECT_EQ(InputHandler::ScrollStarted,
607 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
609 // Now the fling should go ahead since we've started scrolling a layer
610 EXPECT_EQ(InputHandler::ScrollStarted,
611 host_impl_->FlingScrollBegin());
614 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
615 SetupScrollAndContentsLayers(gfx::Size(100, 100));
616 host_impl_->SetViewportSize(gfx::Size(50, 50));
617 DrawFrame();
619 // Ignore the fling since no layer is being scrolled
620 EXPECT_EQ(InputHandler::ScrollIgnored,
621 host_impl_->FlingScrollBegin());
623 // Start scrolling a layer
624 EXPECT_EQ(InputHandler::ScrollStarted,
625 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
627 // Now the fling should go ahead since we've started scrolling a layer
628 EXPECT_EQ(InputHandler::ScrollStarted,
629 host_impl_->FlingScrollBegin());
632 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
633 SetupScrollAndContentsLayers(gfx::Size(100, 100));
634 host_impl_->SetViewportSize(gfx::Size(50, 50));
635 DrawFrame();
636 LayerImpl* root = host_impl_->active_tree()->root_layer();
638 root->SetShouldScrollOnMainThread(true);
640 // Start scrolling a layer
641 EXPECT_EQ(InputHandler::ScrollOnMainThread,
642 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
644 // The fling should be ignored since there's no layer being scrolled impl-side
645 EXPECT_EQ(InputHandler::ScrollIgnored,
646 host_impl_->FlingScrollBegin());
649 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
650 SetupScrollAndContentsLayers(gfx::Size(100, 100));
651 host_impl_->SetViewportSize(gfx::Size(50, 50));
652 DrawFrame();
653 LayerImpl* root = host_impl_->active_tree()->root_layer();
655 root->SetShouldScrollOnMainThread(true);
657 EXPECT_EQ(InputHandler::ScrollOnMainThread,
658 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
659 EXPECT_EQ(InputHandler::ScrollOnMainThread,
660 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
663 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
664 SetupScrollAndContentsLayers(gfx::Size(200, 200));
665 host_impl_->SetViewportSize(gfx::Size(100, 100));
667 LayerImpl* root = host_impl_->active_tree()->root_layer();
668 root->SetContentsScale(2.f, 2.f);
669 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
671 DrawFrame();
673 // All scroll types inside the non-fast scrollable region should fail.
674 EXPECT_EQ(InputHandler::ScrollOnMainThread,
675 host_impl_->ScrollBegin(gfx::Point(25, 25),
676 InputHandler::Wheel));
677 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
678 InputHandler::Wheel));
679 EXPECT_EQ(InputHandler::ScrollOnMainThread,
680 host_impl_->ScrollBegin(gfx::Point(25, 25),
681 InputHandler::Gesture));
682 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
683 InputHandler::Gesture));
685 // All scroll types outside this region should succeed.
686 EXPECT_EQ(InputHandler::ScrollStarted,
687 host_impl_->ScrollBegin(gfx::Point(75, 75),
688 InputHandler::Wheel));
689 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
690 InputHandler::Gesture));
691 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
692 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
693 InputHandler::Gesture));
694 host_impl_->ScrollEnd();
695 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
696 InputHandler::Gesture));
697 EXPECT_EQ(InputHandler::ScrollStarted,
698 host_impl_->ScrollBegin(gfx::Point(75, 75),
699 InputHandler::Gesture));
700 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
701 InputHandler::Gesture));
702 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
703 host_impl_->ScrollEnd();
704 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
705 InputHandler::Gesture));
708 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
709 SetupScrollAndContentsLayers(gfx::Size(200, 200));
710 host_impl_->SetViewportSize(gfx::Size(100, 100));
712 LayerImpl* root = host_impl_->active_tree()->root_layer();
713 root->SetContentsScale(2.f, 2.f);
714 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
715 root->SetPosition(gfx::PointF(-25.f, 0.f));
717 DrawFrame();
719 // This point would fall into the non-fast scrollable region except that we've
720 // moved the layer down by 25 pixels.
721 EXPECT_EQ(InputHandler::ScrollStarted,
722 host_impl_->ScrollBegin(gfx::Point(40, 10),
723 InputHandler::Wheel));
724 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
725 InputHandler::Wheel));
726 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
727 host_impl_->ScrollEnd();
729 // This point is still inside the non-fast region.
730 EXPECT_EQ(InputHandler::ScrollOnMainThread,
731 host_impl_->ScrollBegin(gfx::Point(10, 10),
732 InputHandler::Wheel));
735 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
736 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
737 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
738 host_impl_->SetViewportSize(gfx::Size(50, 50));
739 DrawFrame();
741 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
742 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
743 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
744 host_impl_->ScrollEnd();
745 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
748 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
749 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
750 scroll_layer->SetHaveScrollEventHandlers(true);
751 host_impl_->SetViewportSize(gfx::Size(50, 50));
752 DrawFrame();
754 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
755 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
756 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
757 host_impl_->ScrollEnd();
758 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
761 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
762 SetupScrollAndContentsLayers(gfx::Size(200, 200));
763 host_impl_->SetViewportSize(gfx::Size(100, 100));
765 DrawFrame();
767 EXPECT_EQ(InputHandler::ScrollStarted,
768 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
770 // Trying to scroll to the left/top will not succeed.
771 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
772 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
773 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
775 // Scrolling to the right/bottom will succeed.
776 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
777 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
778 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
780 // Scrolling to left/top will now succeed.
781 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
782 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
783 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
785 // Scrolling diagonally against an edge will succeed.
786 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
787 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
788 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
790 // Trying to scroll more than the available space will also succeed.
791 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
794 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
795 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
796 host_impl_->SetViewportSize(gfx::Size(100, 1000));
798 DrawFrame();
800 EXPECT_EQ(InputHandler::ScrollStarted,
801 host_impl_->ScrollBegin(gfx::Point(),
802 InputHandler::Wheel));
804 // Trying to scroll without a vertical scrollbar will fail.
805 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
806 gfx::Point(), SCROLL_FORWARD));
807 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
808 gfx::Point(), SCROLL_BACKWARD));
810 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
811 PaintedScrollbarLayerImpl::Create(
812 host_impl_->active_tree(),
814 VERTICAL));
815 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
816 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
817 vertical_scrollbar.get());
819 // Trying to scroll with a vertical scrollbar will succeed.
820 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
821 gfx::Point(), SCROLL_FORWARD));
822 EXPECT_FLOAT_EQ(875.f,
823 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
824 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
825 gfx::Point(), SCROLL_BACKWARD));
828 // The user-scrollability breaks for zoomed-in pages. So disable this.
829 // http://crbug.com/322223
830 TEST_F(LayerTreeHostImplTest, DISABLED_ScrollWithUserUnscrollableLayers) {
831 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
832 host_impl_->SetViewportSize(gfx::Size(100, 100));
834 gfx::Size overflow_size(400, 400);
835 ASSERT_EQ(1u, scroll_layer->children().size());
836 LayerImpl* overflow = scroll_layer->children()[0];
837 overflow->SetBounds(overflow_size);
838 overflow->SetContentBounds(overflow_size);
839 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
840 overflow->SetScrollOffset(gfx::Vector2d());
841 overflow->SetPosition(gfx::PointF());
843 DrawFrame();
844 gfx::Point scroll_position(10, 10);
846 EXPECT_EQ(InputHandler::ScrollStarted,
847 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
848 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
849 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->TotalScrollOffset());
851 gfx::Vector2dF scroll_delta(10, 10);
852 host_impl_->ScrollBy(scroll_position, scroll_delta);
853 host_impl_->ScrollEnd();
854 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
855 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
857 overflow->set_user_scrollable_horizontal(false);
859 EXPECT_EQ(InputHandler::ScrollStarted,
860 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
861 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
862 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
864 host_impl_->ScrollBy(scroll_position, scroll_delta);
865 host_impl_->ScrollEnd();
866 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
867 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
869 overflow->set_user_scrollable_vertical(false);
871 EXPECT_EQ(InputHandler::ScrollStarted,
872 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
873 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
874 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
876 host_impl_->ScrollBy(scroll_position, scroll_delta);
877 host_impl_->ScrollEnd();
878 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->TotalScrollOffset());
879 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
882 TEST_F(LayerTreeHostImplTest,
883 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
884 SetupScrollAndContentsLayers(gfx::Size(100, 100));
885 host_impl_->SetViewportSize(gfx::Size(50, 50));
886 DrawFrame();
888 // We should be able to hit test for touch event handlers even if the root
889 // layer loses its render surface after the most recent render.
890 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
891 host_impl_->active_tree()->set_needs_update_draw_properties();
893 EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
896 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
897 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
898 host_impl_->SetViewportSize(gfx::Size(50, 50));
899 DrawFrame();
901 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
902 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
903 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
905 float min_page_scale = 1.f, max_page_scale = 4.f;
906 float page_scale_factor = 1.f;
908 // The impl-based pinch zoom should adjust the max scroll position.
910 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
911 page_scale_factor, min_page_scale, max_page_scale);
912 host_impl_->active_tree()->SetPageScaleDelta(1.f);
913 scroll_layer->SetScrollDelta(gfx::Vector2d());
915 float page_scale_delta = 2.f;
916 gfx::Vector2dF expected_container_size_delta(
917 container_layer->bounds().width(), container_layer->bounds().height());
918 expected_container_size_delta.Scale((1.f - page_scale_delta) /
919 (page_scale_factor * page_scale_delta));
921 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
922 host_impl_->PinchGestureBegin();
923 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
924 // While the gesture is still active, the scroll layer should have a
925 // container size delta = container->bounds() * ((1.f -
926 // page_scale_delta)/())
927 EXPECT_EQ(expected_container_size_delta,
928 scroll_layer->FixedContainerSizeDelta());
929 host_impl_->PinchGestureEnd();
930 host_impl_->ScrollEnd();
931 EXPECT_FALSE(did_request_animate_);
932 EXPECT_TRUE(did_request_redraw_);
933 EXPECT_TRUE(did_request_commit_);
934 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
936 scoped_ptr<ScrollAndScaleSet> scroll_info =
937 host_impl_->ProcessScrollDeltas();
938 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
940 EXPECT_EQ(gfx::Vector2d(75, 75).ToString(),
941 scroll_layer->MaxScrollOffset().ToString());
944 // Scrolling after a pinch gesture should always be in local space. The
945 // scroll deltas do not have the page scale factor applied.
947 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
948 page_scale_factor, min_page_scale, max_page_scale);
949 host_impl_->active_tree()->SetPageScaleDelta(1.f);
950 scroll_layer->SetScrollDelta(gfx::Vector2d());
952 float page_scale_delta = 2.f;
953 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
954 host_impl_->PinchGestureBegin();
955 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
956 host_impl_->PinchGestureEnd();
957 host_impl_->ScrollEnd();
959 gfx::Vector2d scroll_delta(0, 10);
960 EXPECT_EQ(InputHandler::ScrollStarted,
961 host_impl_->ScrollBegin(gfx::Point(5, 5),
962 InputHandler::Wheel));
963 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
964 host_impl_->ScrollEnd();
966 scoped_ptr<ScrollAndScaleSet> scroll_info =
967 host_impl_->ProcessScrollDeltas();
968 ExpectContains(*scroll_info.get(),
969 scroll_layer->id(),
970 scroll_delta);
974 TEST_F(LayerTreeHostImplTest, MasksToBoundsDoesntClobberInnerContainerSize) {
975 SetupScrollAndContentsLayers(gfx::Size(100, 100));
976 host_impl_->SetViewportSize(gfx::Size(50, 50));
977 DrawFrame();
979 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
980 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
981 DCHECK(scroll_layer);
983 float min_page_scale = 1.f;
984 float max_page_scale = 4.f;
985 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
986 min_page_scale,
987 max_page_scale);
989 // If the container's masks_to_bounds is false, the viewport size should
990 // overwrite the inner viewport container layer's size.
992 EXPECT_EQ(gfx::Size(50, 50),
993 container_layer->bounds());
994 container_layer->SetMasksToBounds(false);
996 container_layer->SetBounds(gfx::Size(30, 25));
997 EXPECT_EQ(gfx::Size(30, 25),
998 container_layer->bounds());
1000 // This should cause a reset of the inner viewport container layer's bounds.
1001 host_impl_->DidChangeTopControlsPosition();
1003 EXPECT_EQ(gfx::Size(50, 50),
1004 container_layer->bounds());
1007 host_impl_->SetViewportSize(gfx::Size(50, 50));
1008 container_layer->SetBounds(gfx::Size(50, 50));
1010 // If the container's masks_to_bounds is true, the viewport size should
1011 // *NOT* overwrite the inner viewport container layer's size.
1013 EXPECT_EQ(gfx::Size(50, 50),
1014 container_layer->bounds());
1015 container_layer->SetMasksToBounds(true);
1017 container_layer->SetBounds(gfx::Size(30, 25));
1018 EXPECT_EQ(gfx::Size(30, 25),
1019 container_layer->bounds());
1021 // This should cause a reset of the inner viewport container layer's bounds.
1022 host_impl_->DidChangeTopControlsPosition();
1024 EXPECT_EQ(gfx::Size(30, 25),
1025 container_layer->bounds());
1029 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1030 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1031 host_impl_->SetViewportSize(gfx::Size(50, 50));
1032 DrawFrame();
1034 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1035 DCHECK(scroll_layer);
1037 float min_page_scale = 1.f;
1038 float max_page_scale = 4.f;
1040 // Basic pinch zoom in gesture
1042 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1043 min_page_scale,
1044 max_page_scale);
1045 scroll_layer->SetScrollDelta(gfx::Vector2d());
1047 float page_scale_delta = 2.f;
1048 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1049 host_impl_->PinchGestureBegin();
1050 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1051 host_impl_->PinchGestureEnd();
1052 host_impl_->ScrollEnd();
1053 EXPECT_FALSE(did_request_animate_);
1054 EXPECT_TRUE(did_request_redraw_);
1055 EXPECT_TRUE(did_request_commit_);
1057 scoped_ptr<ScrollAndScaleSet> scroll_info =
1058 host_impl_->ProcessScrollDeltas();
1059 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1062 // Zoom-in clamping
1064 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1065 min_page_scale,
1066 max_page_scale);
1067 scroll_layer->SetScrollDelta(gfx::Vector2d());
1068 float page_scale_delta = 10.f;
1070 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1071 host_impl_->PinchGestureBegin();
1072 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1073 host_impl_->PinchGestureEnd();
1074 host_impl_->ScrollEnd();
1076 scoped_ptr<ScrollAndScaleSet> scroll_info =
1077 host_impl_->ProcessScrollDeltas();
1078 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1081 // Zoom-out clamping
1083 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1084 min_page_scale,
1085 max_page_scale);
1086 scroll_layer->SetScrollDelta(gfx::Vector2d());
1087 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1089 float page_scale_delta = 0.1f;
1090 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1091 host_impl_->PinchGestureBegin();
1092 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1093 host_impl_->PinchGestureEnd();
1094 host_impl_->ScrollEnd();
1096 scoped_ptr<ScrollAndScaleSet> scroll_info =
1097 host_impl_->ProcessScrollDeltas();
1098 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1100 EXPECT_TRUE(scroll_info->scrolls.empty());
1103 // Two-finger panning should not happen based on pinch events only
1105 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1106 min_page_scale,
1107 max_page_scale);
1108 scroll_layer->SetScrollDelta(gfx::Vector2d());
1109 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1111 float page_scale_delta = 1.f;
1112 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1113 host_impl_->PinchGestureBegin();
1114 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1115 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1116 host_impl_->PinchGestureEnd();
1117 host_impl_->ScrollEnd();
1119 scoped_ptr<ScrollAndScaleSet> scroll_info =
1120 host_impl_->ProcessScrollDeltas();
1121 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1122 EXPECT_TRUE(scroll_info->scrolls.empty());
1125 // Two-finger panning should work with interleaved scroll events
1127 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1128 min_page_scale,
1129 max_page_scale);
1130 scroll_layer->SetScrollDelta(gfx::Vector2d());
1131 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1133 float page_scale_delta = 1.f;
1134 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1135 host_impl_->PinchGestureBegin();
1136 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1137 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1138 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1139 host_impl_->PinchGestureEnd();
1140 host_impl_->ScrollEnd();
1142 scoped_ptr<ScrollAndScaleSet> scroll_info =
1143 host_impl_->ProcessScrollDeltas();
1144 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1145 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1148 // Two-finger panning should work when starting fully zoomed out.
1150 host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
1151 0.5f,
1152 4.f);
1153 scroll_layer->SetScrollDelta(gfx::Vector2d());
1154 scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
1156 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
1157 host_impl_->PinchGestureBegin();
1158 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1159 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1160 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1161 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1162 host_impl_->PinchGestureEnd();
1163 host_impl_->ScrollEnd();
1165 scoped_ptr<ScrollAndScaleSet> scroll_info =
1166 host_impl_->ProcessScrollDeltas();
1167 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1168 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1172 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1173 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1174 host_impl_->SetViewportSize(gfx::Size(50, 50));
1175 DrawFrame();
1177 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1178 DCHECK(scroll_layer);
1180 float min_page_scale = 0.5f;
1181 float max_page_scale = 4.f;
1182 base::TimeTicks start_time = base::TimeTicks() +
1183 base::TimeDelta::FromSeconds(1);
1184 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1185 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1186 base::TimeTicks end_time = start_time + duration;
1188 // Non-anchor zoom-in
1190 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1191 min_page_scale,
1192 max_page_scale);
1193 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1195 did_request_redraw_ = false;
1196 did_request_animate_ = false;
1197 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), false, 2.f, duration);
1198 EXPECT_FALSE(did_request_redraw_);
1199 EXPECT_TRUE(did_request_animate_);
1201 did_request_redraw_ = false;
1202 did_request_animate_ = false;
1203 host_impl_->Animate(start_time);
1204 EXPECT_TRUE(did_request_redraw_);
1205 EXPECT_TRUE(did_request_animate_);
1207 did_request_redraw_ = false;
1208 did_request_animate_ = false;
1209 host_impl_->Animate(halfway_through_animation);
1210 EXPECT_TRUE(did_request_redraw_);
1211 EXPECT_TRUE(did_request_animate_);
1213 did_request_redraw_ = false;
1214 did_request_animate_ = false;
1215 did_request_commit_ = false;
1216 host_impl_->Animate(end_time);
1217 EXPECT_TRUE(did_request_commit_);
1218 EXPECT_FALSE(did_request_animate_);
1220 scoped_ptr<ScrollAndScaleSet> scroll_info =
1221 host_impl_->ProcessScrollDeltas();
1222 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1223 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1226 // Anchor zoom-out
1228 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1229 min_page_scale,
1230 max_page_scale);
1231 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1233 did_request_redraw_ = false;
1234 did_request_animate_ = false;
1235 host_impl_->StartPageScaleAnimation(
1236 gfx::Vector2d(25, 25), true, min_page_scale, duration);
1237 EXPECT_FALSE(did_request_redraw_);
1238 EXPECT_TRUE(did_request_animate_);
1240 did_request_redraw_ = false;
1241 did_request_animate_ = false;
1242 host_impl_->Animate(start_time);
1243 EXPECT_TRUE(did_request_redraw_);
1244 EXPECT_TRUE(did_request_animate_);
1246 did_request_redraw_ = false;
1247 did_request_commit_ = false;
1248 did_request_animate_ = false;
1249 host_impl_->Animate(end_time);
1250 EXPECT_TRUE(did_request_redraw_);
1251 EXPECT_FALSE(did_request_animate_);
1252 EXPECT_TRUE(did_request_commit_);
1254 scoped_ptr<ScrollAndScaleSet> scroll_info =
1255 host_impl_->ProcessScrollDeltas();
1256 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1257 // Pushed to (0,0) via clamping against contents layer size.
1258 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1262 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1263 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1264 host_impl_->SetViewportSize(gfx::Size(50, 50));
1265 DrawFrame();
1267 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1268 DCHECK(scroll_layer);
1270 float min_page_scale = 0.5f;
1271 float max_page_scale = 4.f;
1272 base::TimeTicks start_time = base::TimeTicks() +
1273 base::TimeDelta::FromSeconds(1);
1274 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1275 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1276 base::TimeTicks end_time = start_time + duration;
1278 // Anchor zoom with unchanged page scale should not change scroll or scale.
1280 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1281 min_page_scale,
1282 max_page_scale);
1283 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1285 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), true, 1.f, duration);
1286 host_impl_->Animate(start_time);
1287 host_impl_->Animate(halfway_through_animation);
1288 EXPECT_TRUE(did_request_redraw_);
1289 host_impl_->Animate(end_time);
1290 EXPECT_TRUE(did_request_commit_);
1292 scoped_ptr<ScrollAndScaleSet> scroll_info =
1293 host_impl_->ProcessScrollDeltas();
1294 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1295 ExpectNone(*scroll_info, scroll_layer->id());
1299 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1300 public:
1301 LayerTreeHostImplOverridePhysicalTime(
1302 const LayerTreeSettings& settings,
1303 LayerTreeHostImplClient* client,
1304 Proxy* proxy,
1305 SharedBitmapManager* manager,
1306 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1307 : LayerTreeHostImpl(settings,
1308 client,
1309 proxy,
1310 rendering_stats_instrumentation,
1311 manager,
1312 0) {}
1314 virtual base::TimeTicks CurrentFrameTimeTicks() OVERRIDE {
1315 return fake_current_physical_time_;
1318 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1319 fake_current_physical_time_ = fake_now;
1322 private:
1323 base::TimeTicks fake_current_physical_time_;
1326 #define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST() \
1327 gfx::Size viewport_size(10, 10); \
1328 gfx::Size content_size(100, 100); \
1330 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = \
1331 new LayerTreeHostImplOverridePhysicalTime(settings, \
1332 this, \
1333 &proxy_, \
1334 shared_bitmap_manager_.get(), \
1335 &stats_instrumentation_); \
1336 host_impl_ = make_scoped_ptr(host_impl_override_time); \
1337 host_impl_->InitializeRenderer(CreateOutputSurface()); \
1338 host_impl_->SetViewportSize(viewport_size); \
1340 scoped_ptr<LayerImpl> root = \
1341 LayerImpl::Create(host_impl_->active_tree(), 1); \
1342 root->SetBounds(viewport_size); \
1344 scoped_ptr<LayerImpl> scroll = \
1345 LayerImpl::Create(host_impl_->active_tree(), 2); \
1346 scroll->SetScrollClipLayer(root->id()); \
1347 scroll->SetScrollOffset(gfx::Vector2d()); \
1348 root->SetBounds(viewport_size); \
1349 scroll->SetBounds(content_size); \
1350 scroll->SetContentBounds(content_size); \
1351 scroll->SetIsContainerForFixedPositionLayers(true); \
1353 scoped_ptr<LayerImpl> contents = \
1354 LayerImpl::Create(host_impl_->active_tree(), 3); \
1355 contents->SetDrawsContent(true); \
1356 contents->SetBounds(content_size); \
1357 contents->SetContentBounds(content_size); \
1359 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = \
1360 SolidColorScrollbarLayerImpl::Create( \
1361 host_impl_->active_tree(), 4, VERTICAL, 10, 0, false, true); \
1362 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); \
1364 scroll->AddChild(contents.Pass()); \
1365 root->AddChild(scroll.Pass()); \
1366 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1); \
1367 root->AddChild(scrollbar.PassAs<LayerImpl>()); \
1369 host_impl_->active_tree()->SetRootLayer(root.Pass()); \
1370 host_impl_->active_tree()->SetViewportLayersFromIds( \
1371 1, 2, Layer::INVALID_ID); \
1372 host_impl_->active_tree()->DidBecomeActive(); \
1373 DrawFrame();
1375 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1376 LayerTreeSettings settings;
1377 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1378 settings.scrollbar_fade_delay_ms = 20;
1379 settings.scrollbar_fade_duration_ms = 20;
1381 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1383 base::TimeTicks fake_now = gfx::FrameTime::Now();
1385 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1386 EXPECT_FALSE(did_request_redraw_);
1388 // If no scroll happened during a scroll gesture, it should have no effect.
1389 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1390 host_impl_->ScrollEnd();
1391 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1392 EXPECT_FALSE(did_request_redraw_);
1393 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1395 // After a scroll, a fade animation should be scheduled about 20ms from now.
1396 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1397 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1398 host_impl_->ScrollEnd();
1399 did_request_redraw_ = false;
1400 did_request_animate_ = false;
1401 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1402 requested_scrollbar_animation_delay_);
1403 EXPECT_FALSE(did_request_redraw_);
1404 EXPECT_FALSE(did_request_animate_);
1405 requested_scrollbar_animation_delay_ = base::TimeDelta();
1406 scrollbar_fade_start_.Run();
1407 host_impl_->Animate(fake_now);
1409 // After the fade begins, we should start getting redraws instead of a
1410 // scheduled animation.
1411 fake_now += base::TimeDelta::FromMilliseconds(25);
1412 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1413 EXPECT_TRUE(did_request_animate_);
1414 did_request_animate_ = false;
1416 // Setting the scroll offset outside a scroll should also cause the scrollbar
1417 // to appear and to schedule a fade.
1418 host_impl_->InnerViewportScrollLayer()->SetScrollOffset(gfx::Vector2d(5, 5));
1419 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1420 requested_scrollbar_animation_delay_);
1421 EXPECT_FALSE(did_request_redraw_);
1422 EXPECT_FALSE(did_request_animate_);
1423 requested_scrollbar_animation_delay_ = base::TimeDelta();
1426 TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) {
1427 LayerTreeSettings settings;
1428 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1429 settings.scrollbar_fade_delay_ms = 20;
1430 settings.scrollbar_fade_duration_ms = 20;
1431 settings.use_pinch_zoom_scrollbars = true;
1433 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1435 base::TimeTicks fake_now = gfx::FrameTime::Now();
1437 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
1439 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1440 EXPECT_FALSE(did_request_animate_);
1442 // If no scroll happened during a scroll gesture, it should have no effect.
1443 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1444 host_impl_->ScrollEnd();
1445 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1446 EXPECT_FALSE(did_request_animate_);
1447 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1449 // After a scroll, no fade animation should be scheduled.
1450 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1451 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1452 host_impl_->ScrollEnd();
1453 did_request_redraw_ = false;
1454 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1455 EXPECT_FALSE(did_request_animate_);
1456 requested_scrollbar_animation_delay_ = base::TimeDelta();
1458 // We should not see any draw requests.
1459 fake_now += base::TimeDelta::FromMilliseconds(25);
1460 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1461 EXPECT_FALSE(did_request_animate_);
1463 // Make page scale > min so that subsequent scrolls will trigger fades.
1464 host_impl_->active_tree()->SetPageScaleDelta(1.1f);
1466 // After a scroll, a fade animation should be scheduled about 20ms from now.
1467 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1468 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1469 host_impl_->ScrollEnd();
1470 did_request_redraw_ = false;
1471 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1472 requested_scrollbar_animation_delay_);
1473 EXPECT_FALSE(did_request_animate_);
1474 requested_scrollbar_animation_delay_ = base::TimeDelta();
1475 scrollbar_fade_start_.Run();
1477 // After the fade begins, we should start getting redraws instead of a
1478 // scheduled animation.
1479 fake_now += base::TimeDelta::FromMilliseconds(25);
1480 host_impl_->Animate(fake_now);
1481 EXPECT_TRUE(did_request_animate_);
1484 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1485 float device_scale_factor) {
1486 LayerTreeSettings settings;
1487 settings.scrollbar_fade_delay_ms = 500;
1488 settings.scrollbar_fade_duration_ms = 300;
1489 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1491 gfx::Size viewport_size(300, 200);
1492 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1493 gfx::ScaleSize(viewport_size, device_scale_factor));
1494 gfx::Size content_size(1000, 1000);
1496 CreateHostImpl(settings, CreateOutputSurface());
1497 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1498 host_impl_->SetViewportSize(device_viewport_size);
1500 scoped_ptr<LayerImpl> root =
1501 LayerImpl::Create(host_impl_->active_tree(), 1);
1502 root->SetBounds(viewport_size);
1504 scoped_ptr<LayerImpl> scroll =
1505 LayerImpl::Create(host_impl_->active_tree(), 2);
1506 scroll->SetScrollClipLayer(root->id());
1507 scroll->SetScrollOffset(gfx::Vector2d());
1508 scroll->SetBounds(content_size);
1509 scroll->SetContentBounds(content_size);
1510 scroll->SetIsContainerForFixedPositionLayers(true);
1512 scoped_ptr<LayerImpl> contents =
1513 LayerImpl::Create(host_impl_->active_tree(), 3);
1514 contents->SetDrawsContent(true);
1515 contents->SetBounds(content_size);
1516 contents->SetContentBounds(content_size);
1518 // The scrollbar is on the right side.
1519 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1520 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1521 scrollbar->SetDrawsContent(true);
1522 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1523 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1524 scrollbar->SetPosition(gfx::Point(285, 0));
1526 scroll->AddChild(contents.Pass());
1527 root->AddChild(scroll.Pass());
1528 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1529 root->AddChild(scrollbar.PassAs<LayerImpl>());
1531 host_impl_->active_tree()->SetRootLayer(root.Pass());
1532 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
1533 host_impl_->active_tree()->DidBecomeActive();
1534 DrawFrame();
1536 LayerImpl* root_scroll =
1537 host_impl_->active_tree()->InnerViewportScrollLayer();
1538 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1539 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1540 static_cast<ScrollbarAnimationControllerThinning*>(
1541 root_scroll->scrollbar_animation_controller());
1542 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1544 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1545 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1547 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1548 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1550 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1551 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1553 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1554 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1555 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1557 did_request_redraw_ = false;
1558 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1559 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1560 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1561 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1562 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1563 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1564 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1567 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1568 SetupMouseMoveAtWithDeviceScale(1.f);
1571 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1572 SetupMouseMoveAtWithDeviceScale(2.f);
1575 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1576 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1577 host_impl_->SetViewportSize(gfx::Size(50, 50));
1578 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
1579 DrawFrame();
1581 CompositorFrameMetadata metadata =
1582 host_impl_->MakeCompositorFrameMetadata();
1583 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1584 EXPECT_EQ(1.f, metadata.page_scale_factor);
1585 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.viewport_size);
1586 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1587 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1588 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1591 // Scrolling should update metadata immediately.
1592 EXPECT_EQ(InputHandler::ScrollStarted,
1593 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1594 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1596 CompositorFrameMetadata metadata =
1597 host_impl_->MakeCompositorFrameMetadata();
1598 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1600 host_impl_->ScrollEnd();
1602 CompositorFrameMetadata metadata =
1603 host_impl_->MakeCompositorFrameMetadata();
1604 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1607 // Page scale should update metadata correctly (shrinking only the viewport).
1608 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1609 host_impl_->PinchGestureBegin();
1610 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1611 host_impl_->PinchGestureEnd();
1612 host_impl_->ScrollEnd();
1614 CompositorFrameMetadata metadata =
1615 host_impl_->MakeCompositorFrameMetadata();
1616 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1617 EXPECT_EQ(2.f, metadata.page_scale_factor);
1618 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.viewport_size);
1619 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1620 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1621 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1624 // Likewise if set from the main thread.
1625 host_impl_->ProcessScrollDeltas();
1626 host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
1627 host_impl_->active_tree()->SetPageScaleDelta(1.f);
1629 CompositorFrameMetadata metadata =
1630 host_impl_->MakeCompositorFrameMetadata();
1631 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1632 EXPECT_EQ(4.f, metadata.page_scale_factor);
1633 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.viewport_size);
1634 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1635 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1636 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1640 class DidDrawCheckLayer : public LayerImpl {
1641 public:
1642 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1643 return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(tree_impl, id));
1646 virtual bool WillDraw(DrawMode draw_mode, ResourceProvider* provider)
1647 OVERRIDE {
1648 will_draw_called_ = true;
1649 if (will_draw_returns_false_)
1650 return false;
1651 return LayerImpl::WillDraw(draw_mode, provider);
1654 virtual void AppendQuads(RenderPass* render_pass,
1655 const OcclusionTracker<LayerImpl>& occlusion_tracker,
1656 AppendQuadsData* append_quads_data) OVERRIDE {
1657 append_quads_called_ = true;
1658 LayerImpl::AppendQuads(render_pass, occlusion_tracker, append_quads_data);
1661 virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
1662 did_draw_called_ = true;
1663 LayerImpl::DidDraw(provider);
1666 bool will_draw_called() const { return will_draw_called_; }
1667 bool append_quads_called() const { return append_quads_called_; }
1668 bool did_draw_called() const { return did_draw_called_; }
1670 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1672 void ClearDidDrawCheck() {
1673 will_draw_called_ = false;
1674 append_quads_called_ = false;
1675 did_draw_called_ = false;
1678 protected:
1679 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1680 : LayerImpl(tree_impl, id),
1681 will_draw_returns_false_(false),
1682 will_draw_called_(false),
1683 append_quads_called_(false),
1684 did_draw_called_(false) {
1685 SetBounds(gfx::Size(10, 10));
1686 SetContentBounds(gfx::Size(10, 10));
1687 SetDrawsContent(true);
1688 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1691 private:
1692 bool will_draw_returns_false_;
1693 bool will_draw_called_;
1694 bool append_quads_called_;
1695 bool did_draw_called_;
1698 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1699 // The root layer is always drawn, so run this test on a child layer that
1700 // will be masked out by the root layer's bounds.
1701 host_impl_->active_tree()->SetRootLayer(
1702 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1703 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1704 host_impl_->active_tree()->root_layer());
1706 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1707 DidDrawCheckLayer* layer =
1708 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1711 LayerTreeHostImpl::FrameData frame;
1712 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1713 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1714 host_impl_->DidDrawAllLayers(frame);
1716 EXPECT_TRUE(layer->will_draw_called());
1717 EXPECT_TRUE(layer->append_quads_called());
1718 EXPECT_TRUE(layer->did_draw_called());
1721 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
1724 LayerTreeHostImpl::FrameData frame;
1726 layer->set_will_draw_returns_false();
1727 layer->ClearDidDrawCheck();
1729 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1730 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1731 host_impl_->DidDrawAllLayers(frame);
1733 EXPECT_TRUE(layer->will_draw_called());
1734 EXPECT_FALSE(layer->append_quads_called());
1735 EXPECT_FALSE(layer->did_draw_called());
1739 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1740 // The root layer is always drawn, so run this test on a child layer that
1741 // will be masked out by the root layer's bounds.
1742 host_impl_->active_tree()->SetRootLayer(
1743 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1744 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1745 host_impl_->active_tree()->root_layer());
1746 root->SetMasksToBounds(true);
1748 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1749 DidDrawCheckLayer* layer =
1750 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1751 // Ensure visible_content_rect for layer is empty.
1752 layer->SetPosition(gfx::PointF(100.f, 100.f));
1753 layer->SetBounds(gfx::Size(10, 10));
1754 layer->SetContentBounds(gfx::Size(10, 10));
1756 LayerTreeHostImpl::FrameData frame;
1758 EXPECT_FALSE(layer->will_draw_called());
1759 EXPECT_FALSE(layer->did_draw_called());
1761 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1762 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1763 host_impl_->DidDrawAllLayers(frame);
1765 EXPECT_FALSE(layer->will_draw_called());
1766 EXPECT_FALSE(layer->did_draw_called());
1768 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1770 // Ensure visible_content_rect for layer is not empty
1771 layer->SetPosition(gfx::PointF());
1773 EXPECT_FALSE(layer->will_draw_called());
1774 EXPECT_FALSE(layer->did_draw_called());
1776 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1777 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1778 host_impl_->DidDrawAllLayers(frame);
1780 EXPECT_TRUE(layer->will_draw_called());
1781 EXPECT_TRUE(layer->did_draw_called());
1783 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1786 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1787 gfx::Size big_size(1000, 1000);
1788 host_impl_->SetViewportSize(big_size);
1790 host_impl_->active_tree()->SetRootLayer(
1791 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1792 DidDrawCheckLayer* root =
1793 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1795 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1796 DidDrawCheckLayer* occluded_layer =
1797 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1799 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1800 DidDrawCheckLayer* top_layer =
1801 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1802 // This layer covers the occluded_layer above. Make this layer large so it can
1803 // occlude.
1804 top_layer->SetBounds(big_size);
1805 top_layer->SetContentBounds(big_size);
1806 top_layer->SetContentsOpaque(true);
1808 LayerTreeHostImpl::FrameData frame;
1810 EXPECT_FALSE(occluded_layer->will_draw_called());
1811 EXPECT_FALSE(occluded_layer->did_draw_called());
1812 EXPECT_FALSE(top_layer->will_draw_called());
1813 EXPECT_FALSE(top_layer->did_draw_called());
1815 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1816 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1817 host_impl_->DidDrawAllLayers(frame);
1819 EXPECT_FALSE(occluded_layer->will_draw_called());
1820 EXPECT_FALSE(occluded_layer->did_draw_called());
1821 EXPECT_TRUE(top_layer->will_draw_called());
1822 EXPECT_TRUE(top_layer->did_draw_called());
1825 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1826 host_impl_->active_tree()->SetRootLayer(
1827 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1828 DidDrawCheckLayer* root =
1829 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1831 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1832 DidDrawCheckLayer* layer1 =
1833 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1835 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1836 DidDrawCheckLayer* layer2 =
1837 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1839 layer1->SetOpacity(0.3f);
1840 layer1->SetShouldFlattenTransform(true);
1842 EXPECT_FALSE(root->did_draw_called());
1843 EXPECT_FALSE(layer1->did_draw_called());
1844 EXPECT_FALSE(layer2->did_draw_called());
1846 LayerTreeHostImpl::FrameData frame;
1847 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1848 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1849 host_impl_->DidDrawAllLayers(frame);
1851 EXPECT_TRUE(root->did_draw_called());
1852 EXPECT_TRUE(layer1->did_draw_called());
1853 EXPECT_TRUE(layer2->did_draw_called());
1855 EXPECT_NE(root->render_surface(), layer1->render_surface());
1856 EXPECT_TRUE(!!layer1->render_surface());
1859 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1860 public:
1861 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1862 int id,
1863 bool tile_missing,
1864 bool had_incomplete_tile,
1865 bool animating,
1866 ResourceProvider* resource_provider) {
1867 return scoped_ptr<LayerImpl>(
1868 new MissingTextureAnimatingLayer(tree_impl,
1870 tile_missing,
1871 had_incomplete_tile,
1872 animating,
1873 resource_provider));
1876 virtual void AppendQuads(RenderPass* render_pass,
1877 const OcclusionTracker<LayerImpl>& occlusion_tracker,
1878 AppendQuadsData* append_quads_data) OVERRIDE {
1879 LayerImpl::AppendQuads(render_pass, occlusion_tracker, append_quads_data);
1880 if (had_incomplete_tile_)
1881 append_quads_data->had_incomplete_tile = true;
1882 if (tile_missing_)
1883 append_quads_data->num_missing_tiles++;
1886 private:
1887 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1888 int id,
1889 bool tile_missing,
1890 bool had_incomplete_tile,
1891 bool animating,
1892 ResourceProvider* resource_provider)
1893 : DidDrawCheckLayer(tree_impl, id),
1894 tile_missing_(tile_missing),
1895 had_incomplete_tile_(had_incomplete_tile) {
1896 if (animating)
1897 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1900 bool tile_missing_;
1901 bool had_incomplete_tile_;
1904 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsOnDefault) {
1905 host_impl_->active_tree()->SetRootLayer(
1906 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1907 DidDrawCheckLayer* root =
1908 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1910 bool tile_missing = false;
1911 bool had_incomplete_tile = false;
1912 bool is_animating = false;
1913 root->AddChild(
1914 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1916 tile_missing,
1917 had_incomplete_tile,
1918 is_animating,
1919 host_impl_->resource_provider()));
1921 LayerTreeHostImpl::FrameData frame;
1923 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1924 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1925 host_impl_->DidDrawAllLayers(frame);
1928 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) {
1929 host_impl_->active_tree()->SetRootLayer(
1930 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1931 DidDrawCheckLayer* root =
1932 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1933 bool tile_missing = false;
1934 bool had_incomplete_tile = false;
1935 bool is_animating = true;
1936 root->AddChild(
1937 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1939 tile_missing,
1940 had_incomplete_tile,
1941 is_animating,
1942 host_impl_->resource_provider()));
1944 LayerTreeHostImpl::FrameData frame;
1946 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1947 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1948 host_impl_->DidDrawAllLayers(frame);
1951 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithMissingTiles) {
1952 host_impl_->active_tree()->SetRootLayer(
1953 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1954 DidDrawCheckLayer* root =
1955 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1957 bool tile_missing = true;
1958 bool had_incomplete_tile = false;
1959 bool is_animating = false;
1960 root->AddChild(
1961 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1963 tile_missing,
1964 had_incomplete_tile,
1965 is_animating,
1966 host_impl_->resource_provider()));
1967 LayerTreeHostImpl::FrameData frame;
1968 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1969 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1970 host_impl_->DidDrawAllLayers(frame);
1973 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithIncompleteTile) {
1974 host_impl_->active_tree()->SetRootLayer(
1975 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1976 DidDrawCheckLayer* root =
1977 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1979 bool tile_missing = false;
1980 bool had_incomplete_tile = true;
1981 bool is_animating = false;
1982 root->AddChild(
1983 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1985 tile_missing,
1986 had_incomplete_tile,
1987 is_animating,
1988 host_impl_->resource_provider()));
1989 LayerTreeHostImpl::FrameData frame;
1990 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1991 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1992 host_impl_->DidDrawAllLayers(frame);
1995 TEST_F(LayerTreeHostImplTest,
1996 PrepareToDrawFailsWithAnimationAndMissingTilesUsesCheckerboard) {
1997 host_impl_->active_tree()->SetRootLayer(
1998 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
1999 DidDrawCheckLayer* root =
2000 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2001 bool tile_missing = true;
2002 bool had_incomplete_tile = false;
2003 bool is_animating = true;
2004 root->AddChild(
2005 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2007 tile_missing,
2008 had_incomplete_tile,
2009 is_animating,
2010 host_impl_->resource_provider()));
2011 LayerTreeHostImpl::FrameData frame;
2012 EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS,
2013 host_impl_->PrepareToDraw(&frame));
2014 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2015 host_impl_->DidDrawAllLayers(frame);
2018 TEST_F(LayerTreeHostImplTest,
2019 PrepareToDrawSucceedsWithAnimationAndIncompleteTiles) {
2020 host_impl_->active_tree()->SetRootLayer(
2021 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
2022 DidDrawCheckLayer* root =
2023 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2024 bool tile_missing = false;
2025 bool had_incomplete_tile = true;
2026 bool is_animating = true;
2027 root->AddChild(
2028 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2030 tile_missing,
2031 had_incomplete_tile,
2032 is_animating,
2033 host_impl_->resource_provider()));
2034 LayerTreeHostImpl::FrameData frame;
2035 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2036 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2037 host_impl_->DidDrawAllLayers(frame);
2040 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenHighResRequired) {
2041 host_impl_->active_tree()->SetRootLayer(
2042 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2043 DidDrawCheckLayer* root =
2044 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2045 bool tile_missing = false;
2046 bool had_incomplete_tile = false;
2047 bool is_animating = false;
2048 root->AddChild(
2049 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2051 tile_missing,
2052 had_incomplete_tile,
2053 is_animating,
2054 host_impl_->resource_provider()));
2055 host_impl_->active_tree()->SetRequiresHighResToDraw();
2056 LayerTreeHostImpl::FrameData frame;
2057 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2058 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2059 host_impl_->DidDrawAllLayers(frame);
2062 TEST_F(LayerTreeHostImplTest,
2063 PrepareToDrawFailsWhenHighResRequiredAndIncompleteTiles) {
2064 host_impl_->active_tree()->SetRootLayer(
2065 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2066 DidDrawCheckLayer* root =
2067 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2068 bool tile_missing = false;
2069 bool had_incomplete_tile = true;
2070 bool is_animating = false;
2071 root->AddChild(
2072 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2074 tile_missing,
2075 had_incomplete_tile,
2076 is_animating,
2077 host_impl_->resource_provider()));
2078 host_impl_->active_tree()->SetRequiresHighResToDraw();
2079 LayerTreeHostImpl::FrameData frame;
2080 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2081 host_impl_->PrepareToDraw(&frame));
2082 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2083 host_impl_->DidDrawAllLayers(frame);
2086 TEST_F(LayerTreeHostImplTest,
2087 PrepareToDrawSucceedsWhenHighResRequiredAndMissingTile) {
2088 host_impl_->active_tree()->SetRootLayer(
2089 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2090 DidDrawCheckLayer* root =
2091 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2092 bool tile_missing = true;
2093 bool had_incomplete_tile = false;
2094 bool is_animating = false;
2095 root->AddChild(
2096 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2098 tile_missing,
2099 had_incomplete_tile,
2100 is_animating,
2101 host_impl_->resource_provider()));
2102 host_impl_->active_tree()->SetRequiresHighResToDraw();
2103 LayerTreeHostImpl::FrameData frame;
2104 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2105 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2106 host_impl_->DidDrawAllLayers(frame);
2109 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2110 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2111 root->SetScrollClipLayer(Layer::INVALID_ID);
2112 host_impl_->active_tree()->SetRootLayer(root.Pass());
2113 DrawFrame();
2115 // Scroll event is ignored because layer is not scrollable.
2116 EXPECT_EQ(InputHandler::ScrollIgnored,
2117 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2118 EXPECT_FALSE(did_request_redraw_);
2119 EXPECT_FALSE(did_request_commit_);
2122 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2123 public:
2124 LayerTreeHostImplTopControlsTest()
2125 // Make the clip size the same as the layer (content) size so the layer is
2126 // non-scrollable.
2127 : layer_size_(10, 10),
2128 clip_size_(layer_size_) {
2129 settings_.calculate_top_controls_position = true;
2130 settings_.top_controls_height = 50;
2132 viewport_size_ =
2133 gfx::Size(clip_size_.width(),
2134 clip_size_.height() + settings_.top_controls_height);
2137 void SetupTopControlsAndScrollLayer() {
2138 CreateHostImpl(settings_, CreateOutputSurface());
2140 scoped_ptr<LayerImpl> root =
2141 LayerImpl::Create(host_impl_->active_tree(), 1);
2142 scoped_ptr<LayerImpl> root_clip =
2143 LayerImpl::Create(host_impl_->active_tree(), 2);
2144 root_clip->SetBounds(clip_size_);
2145 root->SetScrollClipLayer(root_clip->id());
2146 root->SetBounds(layer_size_);
2147 root->SetContentBounds(layer_size_);
2148 root->SetPosition(gfx::PointF());
2149 root->SetDrawsContent(false);
2150 root->SetIsContainerForFixedPositionLayers(true);
2151 int inner_viewport_scroll_layer_id = root->id();
2152 int page_scale_layer_id = root_clip->id();
2153 root_clip->AddChild(root.Pass());
2154 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2155 host_impl_->active_tree()->SetViewportLayersFromIds(
2156 page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
2157 // Set a viewport size that is large enough to contain both the top controls
2158 // and some content.
2159 host_impl_->SetViewportSize(viewport_size_);
2160 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2161 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2164 protected:
2165 gfx::Size layer_size_;
2166 gfx::Size clip_size_;
2167 gfx::Size viewport_size_;
2169 LayerTreeSettings settings_;
2170 }; // class LayerTreeHostImplTopControlsTest
2172 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2173 SetupTopControlsAndScrollLayer();
2174 DrawFrame();
2176 EXPECT_EQ(InputHandler::ScrollStarted,
2177 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2179 // Make the test scroll delta a fractional amount, to verify that the
2180 // fixed container size delta is (1) non-zero, and (2) fractional, and
2181 // (3) matches the movement of the top controls.
2182 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2183 host_impl_->top_controls_manager()->ScrollBegin();
2184 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2185 host_impl_->top_controls_manager()->ScrollEnd();
2187 LayerImpl* inner_viewport_scroll_layer =
2188 host_impl_->active_tree()->InnerViewportScrollLayer();
2189 DCHECK(inner_viewport_scroll_layer);
2190 host_impl_->ScrollEnd();
2191 EXPECT_EQ(top_controls_scroll_delta,
2192 inner_viewport_scroll_layer->FixedContainerSizeDelta());
2195 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsWithPageScale) {
2196 SetupTopControlsAndScrollLayer();
2197 DrawFrame();
2199 EXPECT_EQ(InputHandler::ScrollStarted,
2200 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2202 float page_scale = 1.5f;
2203 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale, 1.f, 2.f);
2205 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.f);
2206 gfx::Vector2dF expected_container_size_delta =
2207 ScaleVector2d(top_controls_scroll_delta, 1.f / page_scale);
2208 host_impl_->top_controls_manager()->ScrollBegin();
2209 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2210 host_impl_->top_controls_manager()->ScrollEnd();
2212 LayerImpl* inner_viewport_scroll_layer =
2213 host_impl_->active_tree()->InnerViewportScrollLayer();
2214 DCHECK(inner_viewport_scroll_layer);
2215 host_impl_->ScrollEnd();
2217 // Use a tolerance that requires the container size delta to be within 0.01
2218 // pixels.
2219 double tolerance = 0.0001;
2220 EXPECT_LT(
2221 (expected_container_size_delta -
2222 inner_viewport_scroll_layer->FixedContainerSizeDelta()).LengthSquared(),
2223 tolerance);
2226 TEST_F(LayerTreeHostImplTopControlsTest,
2227 ScrollNonScrollableRootWithTopControls) {
2228 SetupTopControlsAndScrollLayer();
2229 DrawFrame();
2231 EXPECT_EQ(InputHandler::ScrollStarted,
2232 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2234 host_impl_->top_controls_manager()->ScrollBegin();
2235 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
2236 host_impl_->top_controls_manager()->ScrollEnd();
2237 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->content_top_offset());
2238 // Now that top controls have moved, expect the clip to resize.
2239 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2240 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2242 host_impl_->ScrollEnd();
2244 EXPECT_EQ(InputHandler::ScrollStarted,
2245 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2247 float scroll_increment_y = -25.f;
2248 host_impl_->top_controls_manager()->ScrollBegin();
2249 host_impl_->top_controls_manager()->ScrollBy(
2250 gfx::Vector2dF(0.f, scroll_increment_y));
2251 EXPECT_EQ(-scroll_increment_y,
2252 host_impl_->top_controls_manager()->content_top_offset());
2253 // Now that top controls have moved, expect the clip to resize.
2254 EXPECT_EQ(gfx::Size(viewport_size_.width(),
2255 viewport_size_.height() + scroll_increment_y),
2256 root_clip_ptr->bounds());
2258 host_impl_->top_controls_manager()->ScrollBy(
2259 gfx::Vector2dF(0.f, scroll_increment_y));
2260 host_impl_->top_controls_manager()->ScrollEnd();
2261 EXPECT_EQ(-2 * scroll_increment_y,
2262 host_impl_->top_controls_manager()->content_top_offset());
2263 // Now that top controls have moved, expect the clip to resize.
2264 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2266 host_impl_->ScrollEnd();
2268 // Verify the layer is once-again non-scrollable.
2269 EXPECT_EQ(
2270 gfx::Vector2d(),
2271 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
2273 EXPECT_EQ(InputHandler::ScrollStarted,
2274 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2277 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
2278 // Test the configuration where a non-composited root layer is embedded in a
2279 // scrollable outer layer.
2280 gfx::Size surface_size(10, 10);
2281 gfx::Size contents_size(20, 20);
2283 scoped_ptr<LayerImpl> content_layer =
2284 LayerImpl::Create(host_impl_->active_tree(), 1);
2285 content_layer->SetDrawsContent(true);
2286 content_layer->SetPosition(gfx::PointF());
2287 content_layer->SetBounds(contents_size);
2288 content_layer->SetContentBounds(contents_size);
2289 content_layer->SetContentsScale(2.f, 2.f);
2291 scoped_ptr<LayerImpl> scroll_clip_layer =
2292 LayerImpl::Create(host_impl_->active_tree(), 3);
2293 scroll_clip_layer->SetBounds(surface_size);
2295 scoped_ptr<LayerImpl> scroll_layer =
2296 LayerImpl::Create(host_impl_->active_tree(), 2);
2297 scroll_layer->SetScrollClipLayer(3);
2298 scroll_layer->SetBounds(contents_size);
2299 scroll_layer->SetContentBounds(contents_size);
2300 scroll_layer->SetPosition(gfx::PointF());
2301 scroll_layer->AddChild(content_layer.Pass());
2302 scroll_clip_layer->AddChild(scroll_layer.Pass());
2304 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
2305 host_impl_->SetViewportSize(surface_size);
2306 DrawFrame();
2308 EXPECT_EQ(InputHandler::ScrollStarted,
2309 host_impl_->ScrollBegin(gfx::Point(5, 5),
2310 InputHandler::Wheel));
2311 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2312 host_impl_->ScrollEnd();
2313 EXPECT_TRUE(did_request_redraw_);
2314 EXPECT_TRUE(did_request_commit_);
2317 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
2318 gfx::Size surface_size(10, 10);
2319 gfx::Size contents_size(20, 20);
2320 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2321 root->SetBounds(surface_size);
2322 root->SetContentBounds(contents_size);
2323 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
2324 host_impl_->active_tree()->SetRootLayer(root.Pass());
2325 host_impl_->SetViewportSize(surface_size);
2326 DrawFrame();
2328 EXPECT_EQ(InputHandler::ScrollStarted,
2329 host_impl_->ScrollBegin(gfx::Point(5, 5),
2330 InputHandler::Wheel));
2331 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2332 host_impl_->ScrollEnd();
2333 EXPECT_TRUE(did_request_redraw_);
2334 EXPECT_TRUE(did_request_commit_);
2337 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
2338 gfx::Size surface_size(10, 10);
2339 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2340 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
2341 host_impl_->active_tree()->SetRootLayer(root.Pass());
2342 host_impl_->SetViewportSize(surface_size);
2343 DrawFrame();
2345 // Scroll event is ignored because the input coordinate is outside the layer
2346 // boundaries.
2347 EXPECT_EQ(InputHandler::ScrollIgnored,
2348 host_impl_->ScrollBegin(gfx::Point(15, 5),
2349 InputHandler::Wheel));
2350 EXPECT_FALSE(did_request_redraw_);
2351 EXPECT_FALSE(did_request_commit_);
2354 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
2355 gfx::Size surface_size(10, 10);
2356 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2357 scoped_ptr<LayerImpl> child =
2358 CreateScrollableLayer(2, surface_size, root.get());
2359 host_impl_->SetViewportSize(surface_size);
2361 gfx::Transform matrix;
2362 matrix.RotateAboutXAxis(180.0);
2363 child->SetTransform(matrix);
2364 child->SetDoubleSided(false);
2366 root->AddChild(child.Pass());
2367 host_impl_->active_tree()->SetRootLayer(root.Pass());
2368 DrawFrame();
2370 // Scroll event is ignored because the scrollable layer is not facing the
2371 // viewer and there is nothing scrollable behind it.
2372 EXPECT_EQ(InputHandler::ScrollIgnored,
2373 host_impl_->ScrollBegin(gfx::Point(5, 5),
2374 InputHandler::Wheel));
2375 EXPECT_FALSE(did_request_redraw_);
2376 EXPECT_FALSE(did_request_commit_);
2379 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
2380 gfx::Size surface_size(10, 10);
2381 scoped_ptr<LayerImpl> clip_layer =
2382 LayerImpl::Create(host_impl_->active_tree(), 3);
2383 scoped_ptr<LayerImpl> content_layer =
2384 CreateScrollableLayer(1, surface_size, clip_layer.get());
2385 content_layer->SetShouldScrollOnMainThread(true);
2386 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
2388 // Note: we can use the same clip layer for both since both calls to
2389 // CreateScrollableLayer() use the same surface size.
2390 scoped_ptr<LayerImpl> scroll_layer =
2391 CreateScrollableLayer(2, surface_size, clip_layer.get());
2392 scroll_layer->AddChild(content_layer.Pass());
2393 clip_layer->AddChild(scroll_layer.Pass());
2395 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
2396 host_impl_->SetViewportSize(surface_size);
2397 DrawFrame();
2399 // Scrolling fails because the content layer is asking to be scrolled on the
2400 // main thread.
2401 EXPECT_EQ(InputHandler::ScrollOnMainThread,
2402 host_impl_->ScrollBegin(gfx::Point(5, 5),
2403 InputHandler::Wheel));
2406 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
2407 gfx::Size surface_size(20, 20);
2408 gfx::Size viewport_size(10, 10);
2409 float page_scale = 2.f;
2410 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2411 scoped_ptr<LayerImpl> root_clip =
2412 LayerImpl::Create(host_impl_->active_tree(), 2);
2413 scoped_ptr<LayerImpl> root_scrolling =
2414 CreateScrollableLayer(3, surface_size, root_clip.get());
2415 EXPECT_EQ(viewport_size, root_clip->bounds());
2416 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2417 root_clip->AddChild(root_scrolling.Pass());
2418 root->AddChild(root_clip.Pass());
2419 host_impl_->active_tree()->SetRootLayer(root.Pass());
2420 // The behaviour in this test assumes the page scale is applied at a layer
2421 // above the clip layer.
2422 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2423 host_impl_->active_tree()->DidBecomeActive();
2424 host_impl_->SetViewportSize(viewport_size);
2425 DrawFrame();
2427 LayerImpl* root_scroll =
2428 host_impl_->active_tree()->InnerViewportScrollLayer();
2429 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2431 gfx::Vector2d scroll_delta(0, 10);
2432 gfx::Vector2d expected_scroll_delta = scroll_delta;
2433 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2434 EXPECT_EQ(InputHandler::ScrollStarted,
2435 host_impl_->ScrollBegin(gfx::Point(5, 5),
2436 InputHandler::Wheel));
2437 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2438 host_impl_->ScrollEnd();
2440 // Set new page scale from main thread.
2441 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2442 page_scale,
2443 page_scale);
2445 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2446 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2448 // The scroll range should also have been updated.
2449 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2451 // The page scale delta remains constant because the impl thread did not
2452 // scale.
2453 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2456 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
2457 gfx::Size surface_size(20, 20);
2458 gfx::Size viewport_size(10, 10);
2459 float page_scale = 2.f;
2460 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2461 scoped_ptr<LayerImpl> root_clip =
2462 LayerImpl::Create(host_impl_->active_tree(), 2);
2463 scoped_ptr<LayerImpl> root_scrolling =
2464 CreateScrollableLayer(3, surface_size, root_clip.get());
2465 EXPECT_EQ(viewport_size, root_clip->bounds());
2466 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2467 root_clip->AddChild(root_scrolling.Pass());
2468 root->AddChild(root_clip.Pass());
2469 host_impl_->active_tree()->SetRootLayer(root.Pass());
2470 // The behaviour in this test assumes the page scale is applied at a layer
2471 // above the clip layer.
2472 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2473 host_impl_->active_tree()->DidBecomeActive();
2474 host_impl_->SetViewportSize(viewport_size);
2475 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
2476 DrawFrame();
2478 LayerImpl* root_scroll =
2479 host_impl_->active_tree()->InnerViewportScrollLayer();
2480 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2482 gfx::Vector2d scroll_delta(0, 10);
2483 gfx::Vector2d expected_scroll_delta = scroll_delta;
2484 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2485 EXPECT_EQ(InputHandler::ScrollStarted,
2486 host_impl_->ScrollBegin(gfx::Point(5, 5),
2487 InputHandler::Wheel));
2488 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2489 host_impl_->ScrollEnd();
2491 // Set new page scale on impl thread by pinching.
2492 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2493 host_impl_->PinchGestureBegin();
2494 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
2495 host_impl_->PinchGestureEnd();
2496 host_impl_->ScrollEnd();
2497 DrawOneFrame();
2499 // The scroll delta is not scaled because the main thread did not scale.
2500 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2501 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2503 // The scroll range should also have been updated.
2504 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2506 // The page scale delta should match the new scale on the impl side.
2507 EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
2510 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
2511 gfx::Size surface_size(10, 10);
2512 float default_page_scale = 1.f;
2513 gfx::Transform default_page_scale_matrix;
2514 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
2516 float new_page_scale = 2.f;
2517 gfx::Transform new_page_scale_matrix;
2518 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
2520 // Create a normal scrollable root layer and another scrollable child layer.
2521 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
2522 LayerImpl* root = host_impl_->active_tree()->root_layer();
2523 LayerImpl* child = scroll->children()[0];
2525 scoped_ptr<LayerImpl> scrollable_child_clip =
2526 LayerImpl::Create(host_impl_->active_tree(), 6);
2527 scoped_ptr<LayerImpl> scrollable_child =
2528 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
2529 scrollable_child_clip->AddChild(scrollable_child.Pass());
2530 child->AddChild(scrollable_child_clip.Pass());
2531 LayerImpl* grand_child = child->children()[0];
2533 // Set new page scale on impl thread by pinching.
2534 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2535 host_impl_->PinchGestureBegin();
2536 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
2537 host_impl_->PinchGestureEnd();
2538 host_impl_->ScrollEnd();
2539 DrawOneFrame();
2541 EXPECT_EQ(1.f, root->contents_scale_x());
2542 EXPECT_EQ(1.f, root->contents_scale_y());
2543 EXPECT_EQ(1.f, scroll->contents_scale_x());
2544 EXPECT_EQ(1.f, scroll->contents_scale_y());
2545 EXPECT_EQ(1.f, child->contents_scale_x());
2546 EXPECT_EQ(1.f, child->contents_scale_y());
2547 EXPECT_EQ(1.f, grand_child->contents_scale_x());
2548 EXPECT_EQ(1.f, grand_child->contents_scale_y());
2550 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
2551 // the page scale delta on the root layer is applied hierarchically.
2552 LayerTreeHostImpl::FrameData frame;
2553 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2554 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2555 host_impl_->DidDrawAllLayers(frame);
2557 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
2558 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
2559 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
2560 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
2561 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
2562 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
2563 EXPECT_EQ(new_page_scale,
2564 grand_child->draw_transform().matrix().getDouble(0, 0));
2565 EXPECT_EQ(new_page_scale,
2566 grand_child->draw_transform().matrix().getDouble(1, 1));
2569 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
2570 gfx::Size surface_size(30, 30);
2571 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2572 root->SetBounds(gfx::Size(5, 5));
2573 scoped_ptr<LayerImpl> root_scrolling =
2574 LayerImpl::Create(host_impl_->active_tree(), 2);
2575 root_scrolling->SetBounds(surface_size);
2576 root_scrolling->SetContentBounds(surface_size);
2577 root_scrolling->SetScrollClipLayer(root->id());
2578 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2579 LayerImpl* root_scrolling_ptr = root_scrolling.get();
2580 root->AddChild(root_scrolling.Pass());
2581 int child_scroll_layer_id = 3;
2582 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
2583 child_scroll_layer_id, surface_size, root_scrolling_ptr);
2584 LayerImpl* child = child_scrolling.get();
2585 root_scrolling_ptr->AddChild(child_scrolling.Pass());
2586 host_impl_->active_tree()->SetRootLayer(root.Pass());
2587 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2588 host_impl_->active_tree()->DidBecomeActive();
2589 host_impl_->SetViewportSize(surface_size);
2590 DrawFrame();
2592 gfx::Vector2d scroll_delta(0, 10);
2593 gfx::Vector2d expected_scroll_delta(scroll_delta);
2594 gfx::Vector2d expected_max_scroll(child->MaxScrollOffset());
2595 EXPECT_EQ(InputHandler::ScrollStarted,
2596 host_impl_->ScrollBegin(gfx::Point(5, 5),
2597 InputHandler::Wheel));
2598 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2599 host_impl_->ScrollEnd();
2601 float page_scale = 2.f;
2602 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2603 1.f,
2604 page_scale);
2606 DrawOneFrame();
2608 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2609 ExpectContains(
2610 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
2612 // The scroll range should not have changed.
2613 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
2615 // The page scale delta remains constant because the impl thread did not
2616 // scale.
2617 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2620 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
2621 // Scroll a child layer beyond its maximum scroll range and make sure the
2622 // parent layer is scrolled on the axis on which the child was unable to
2623 // scroll.
2624 gfx::Size surface_size(10, 10);
2625 gfx::Size content_size(20, 20);
2626 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2627 root->SetBounds(surface_size);
2629 scoped_ptr<LayerImpl> grand_child =
2630 CreateScrollableLayer(3, content_size, root.get());
2632 scoped_ptr<LayerImpl> child =
2633 CreateScrollableLayer(2, content_size, root.get());
2634 LayerImpl* grand_child_layer = grand_child.get();
2635 child->AddChild(grand_child.Pass());
2637 LayerImpl* child_layer = child.get();
2638 root->AddChild(child.Pass());
2639 host_impl_->active_tree()->SetRootLayer(root.Pass());
2640 host_impl_->active_tree()->DidBecomeActive();
2641 host_impl_->SetViewportSize(surface_size);
2642 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 5));
2643 child_layer->SetScrollOffset(gfx::Vector2d(3, 0));
2645 DrawFrame();
2647 gfx::Vector2d scroll_delta(-8, -7);
2648 EXPECT_EQ(InputHandler::ScrollStarted,
2649 host_impl_->ScrollBegin(gfx::Point(),
2650 InputHandler::Wheel));
2651 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2652 host_impl_->ScrollEnd();
2654 scoped_ptr<ScrollAndScaleSet> scroll_info =
2655 host_impl_->ProcessScrollDeltas();
2657 // The grand child should have scrolled up to its limit.
2658 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2659 LayerImpl* grand_child = child->children()[0];
2660 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
2662 // The child should have only scrolled on the other axis.
2663 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
2667 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
2668 // Scroll a child layer beyond its maximum scroll range and make sure the
2669 // the scroll doesn't bubble up to the parent layer.
2670 gfx::Size surface_size(20, 20);
2671 gfx::Size viewport_size(10, 10);
2672 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2673 scoped_ptr<LayerImpl> root_scrolling =
2674 CreateScrollableLayer(2, surface_size, root.get());
2675 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2677 scoped_ptr<LayerImpl> grand_child =
2678 CreateScrollableLayer(4, surface_size, root.get());
2680 scoped_ptr<LayerImpl> child =
2681 CreateScrollableLayer(3, surface_size, root.get());
2682 LayerImpl* grand_child_layer = grand_child.get();
2683 child->AddChild(grand_child.Pass());
2685 LayerImpl* child_layer = child.get();
2686 root_scrolling->AddChild(child.Pass());
2687 root->AddChild(root_scrolling.Pass());
2688 EXPECT_EQ(viewport_size, root->bounds());
2689 host_impl_->active_tree()->SetRootLayer(root.Pass());
2690 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2691 host_impl_->active_tree()->DidBecomeActive();
2692 host_impl_->SetViewportSize(viewport_size);
2694 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
2695 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
2697 DrawFrame();
2699 gfx::Vector2d scroll_delta(0, -10);
2700 EXPECT_EQ(InputHandler::ScrollStarted,
2701 host_impl_->ScrollBegin(gfx::Point(),
2702 InputHandler::NonBubblingGesture));
2703 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2704 host_impl_->ScrollEnd();
2706 scoped_ptr<ScrollAndScaleSet> scroll_info =
2707 host_impl_->ProcessScrollDeltas();
2709 // The grand child should have scrolled up to its limit.
2710 LayerImpl* child =
2711 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
2712 LayerImpl* grand_child = child->children()[0];
2713 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2715 // The child should not have scrolled.
2716 ExpectNone(*scroll_info.get(), child->id());
2718 // The next time we scroll we should only scroll the parent.
2719 scroll_delta = gfx::Vector2d(0, -3);
2720 EXPECT_EQ(InputHandler::ScrollStarted,
2721 host_impl_->ScrollBegin(gfx::Point(5, 5),
2722 InputHandler::NonBubblingGesture));
2723 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2724 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2725 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
2726 host_impl_->ScrollEnd();
2728 scroll_info = host_impl_->ProcessScrollDeltas();
2730 // The child should have scrolled up to its limit.
2731 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2733 // The grand child should not have scrolled.
2734 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2736 // After scrolling the parent, another scroll on the opposite direction
2737 // should still scroll the child.
2738 scroll_delta = gfx::Vector2d(0, 7);
2739 EXPECT_EQ(InputHandler::ScrollStarted,
2740 host_impl_->ScrollBegin(gfx::Point(5, 5),
2741 InputHandler::NonBubblingGesture));
2742 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2743 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2744 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2745 host_impl_->ScrollEnd();
2747 scroll_info = host_impl_->ProcessScrollDeltas();
2749 // The grand child should have scrolled.
2750 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
2752 // The child should not have scrolled.
2753 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2756 // Scrolling should be adjusted from viewport space.
2757 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
2758 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2760 scroll_delta = gfx::Vector2d(0, -2);
2761 EXPECT_EQ(InputHandler::ScrollStarted,
2762 host_impl_->ScrollBegin(gfx::Point(1, 1),
2763 InputHandler::NonBubblingGesture));
2764 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
2765 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2766 host_impl_->ScrollEnd();
2768 scroll_info = host_impl_->ProcessScrollDeltas();
2770 // Should have scrolled by half the amount in layer space (5 - 2/2)
2771 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
2774 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
2775 // When we try to scroll a non-scrollable child layer, the scroll delta
2776 // should be applied to one of its ancestors if possible.
2777 gfx::Size surface_size(10, 10);
2778 gfx::Size content_size(20, 20);
2779 scoped_ptr<LayerImpl> root_clip =
2780 LayerImpl::Create(host_impl_->active_tree(), 3);
2781 scoped_ptr<LayerImpl> root =
2782 CreateScrollableLayer(1, content_size, root_clip.get());
2783 // Make 'root' the clip layer for child: since they have the same sizes the
2784 // child will have zero max_scroll_offset and scrolls will bubble.
2785 scoped_ptr<LayerImpl> child =
2786 CreateScrollableLayer(2, content_size, root.get());
2787 child->SetIsContainerForFixedPositionLayers(true);
2788 root->SetBounds(content_size);
2790 int root_scroll_id = root->id();
2791 root->AddChild(child.Pass());
2792 root_clip->AddChild(root.Pass());
2794 host_impl_->SetViewportSize(surface_size);
2795 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2796 host_impl_->active_tree()->SetViewportLayersFromIds(3, 2, Layer::INVALID_ID);
2797 host_impl_->active_tree()->DidBecomeActive();
2798 DrawFrame();
2800 gfx::Vector2d scroll_delta(0, 4);
2801 EXPECT_EQ(InputHandler::ScrollStarted,
2802 host_impl_->ScrollBegin(gfx::Point(5, 5),
2803 InputHandler::Wheel));
2804 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2805 host_impl_->ScrollEnd();
2807 scoped_ptr<ScrollAndScaleSet> scroll_info =
2808 host_impl_->ProcessScrollDeltas();
2810 // Only the root scroll should have scrolled.
2811 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
2812 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
2816 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
2817 gfx::Size surface_size(10, 10);
2818 scoped_ptr<LayerImpl> root_clip =
2819 LayerImpl::Create(host_impl_->active_tree(), 1);
2820 scoped_ptr<LayerImpl> root_scroll =
2821 CreateScrollableLayer(2, surface_size, root_clip.get());
2822 root_scroll->SetIsContainerForFixedPositionLayers(true);
2823 root_clip->AddChild(root_scroll.Pass());
2824 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2825 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2826 host_impl_->active_tree()->DidBecomeActive();
2827 host_impl_->SetViewportSize(surface_size);
2829 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
2830 // synchronization.
2831 DrawFrame();
2832 host_impl_->active_tree()->DetachLayerTree();
2833 scoped_ptr<LayerImpl> root_clip2 =
2834 LayerImpl::Create(host_impl_->active_tree(), 3);
2835 scoped_ptr<LayerImpl> root_scroll2 =
2836 CreateScrollableLayer(4, surface_size, root_clip2.get());
2837 root_scroll2->SetIsContainerForFixedPositionLayers(true);
2838 root_clip2->AddChild(root_scroll2.Pass());
2839 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
2840 host_impl_->active_tree()->SetViewportLayersFromIds(3, 4, Layer::INVALID_ID);
2841 host_impl_->active_tree()->DidBecomeActive();
2843 // Scrolling should still work even though we did not draw yet.
2844 EXPECT_EQ(InputHandler::ScrollStarted,
2845 host_impl_->ScrollBegin(gfx::Point(5, 5),
2846 InputHandler::Wheel));
2849 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
2850 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2852 // Rotate the root layer 90 degrees counter-clockwise about its center.
2853 gfx::Transform rotate_transform;
2854 rotate_transform.Rotate(-90.0);
2855 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
2857 gfx::Size surface_size(50, 50);
2858 host_impl_->SetViewportSize(surface_size);
2859 DrawFrame();
2861 // Scroll to the right in screen coordinates with a gesture.
2862 gfx::Vector2d gesture_scroll_delta(10, 0);
2863 EXPECT_EQ(InputHandler::ScrollStarted,
2864 host_impl_->ScrollBegin(gfx::Point(),
2865 InputHandler::Gesture));
2866 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2867 host_impl_->ScrollEnd();
2869 // The layer should have scrolled down in its local coordinates.
2870 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2871 ExpectContains(*scroll_info.get(),
2872 scroll_layer->id(),
2873 gfx::Vector2d(0, gesture_scroll_delta.x()));
2875 // Reset and scroll down with the wheel.
2876 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2877 gfx::Vector2d wheel_scroll_delta(0, 10);
2878 EXPECT_EQ(InputHandler::ScrollStarted,
2879 host_impl_->ScrollBegin(gfx::Point(),
2880 InputHandler::Wheel));
2881 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2882 host_impl_->ScrollEnd();
2884 // The layer should have scrolled down in its local coordinates.
2885 scroll_info = host_impl_->ProcessScrollDeltas();
2886 ExpectContains(*scroll_info.get(),
2887 scroll_layer->id(),
2888 wheel_scroll_delta);
2891 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
2892 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2893 int child_clip_layer_id = 6;
2894 int child_layer_id = 7;
2895 float child_layer_angle = -20.f;
2897 // Create a child layer that is rotated to a non-axis-aligned angle.
2898 scoped_ptr<LayerImpl> clip_layer =
2899 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
2900 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
2901 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
2902 gfx::Transform rotate_transform;
2903 rotate_transform.Translate(-50.0, -50.0);
2904 rotate_transform.Rotate(child_layer_angle);
2905 rotate_transform.Translate(50.0, 50.0);
2906 clip_layer->SetTransform(rotate_transform);
2908 // Only allow vertical scrolling.
2909 clip_layer->SetBounds(
2910 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
2911 // The rotation depends on the layer's transform origin, and the child layer
2912 // is a different size than the clip, so make sure the clip layer's origin
2913 // lines up over the child.
2914 clip_layer->SetTransformOrigin(gfx::Point3F(
2915 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
2916 LayerImpl* child_ptr = child.get();
2917 clip_layer->AddChild(child.Pass());
2918 scroll_layer->AddChild(clip_layer.Pass());
2920 gfx::Size surface_size(50, 50);
2921 host_impl_->SetViewportSize(surface_size);
2922 DrawFrame();
2924 // Scroll down in screen coordinates with a gesture.
2925 gfx::Vector2d gesture_scroll_delta(0, 10);
2926 EXPECT_EQ(InputHandler::ScrollStarted,
2927 host_impl_->ScrollBegin(gfx::Point(1, 1),
2928 InputHandler::Gesture));
2929 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2930 host_impl_->ScrollEnd();
2932 // The child layer should have scrolled down in its local coordinates an
2933 // amount proportional to the angle between it and the input scroll delta.
2934 gfx::Vector2d expected_scroll_delta(
2936 gesture_scroll_delta.y() *
2937 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
2938 scoped_ptr<ScrollAndScaleSet> scroll_info =
2939 host_impl_->ProcessScrollDeltas();
2940 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2942 // The root scroll layer should not have scrolled, because the input delta
2943 // was close to the layer's axis of movement.
2944 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
2947 // Now reset and scroll the same amount horizontally.
2948 child_ptr->SetScrollDelta(gfx::Vector2dF());
2949 gfx::Vector2d gesture_scroll_delta(10, 0);
2950 EXPECT_EQ(InputHandler::ScrollStarted,
2951 host_impl_->ScrollBegin(gfx::Point(1, 1),
2952 InputHandler::Gesture));
2953 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2954 host_impl_->ScrollEnd();
2956 // The child layer should have scrolled down in its local coordinates an
2957 // amount proportional to the angle between it and the input scroll delta.
2958 gfx::Vector2d expected_scroll_delta(
2960 -gesture_scroll_delta.x() *
2961 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
2962 scoped_ptr<ScrollAndScaleSet> scroll_info =
2963 host_impl_->ProcessScrollDeltas();
2964 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2966 // The root scroll layer should have scrolled more, since the input scroll
2967 // delta was mostly orthogonal to the child layer's vertical scroll axis.
2968 gfx::Vector2d expected_root_scroll_delta(
2969 gesture_scroll_delta.x() *
2970 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
2972 ExpectContains(*scroll_info.get(),
2973 scroll_layer->id(),
2974 expected_root_scroll_delta);
2978 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
2979 LayerImpl* scroll_layer =
2980 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2982 // Scale the layer to twice its normal size.
2983 int scale = 2;
2984 gfx::Transform scale_transform;
2985 scale_transform.Scale(scale, scale);
2986 scroll_layer->SetTransform(scale_transform);
2988 gfx::Size surface_size(50, 50);
2989 host_impl_->SetViewportSize(surface_size);
2990 DrawFrame();
2992 // Scroll down in screen coordinates with a gesture.
2993 gfx::Vector2d scroll_delta(0, 10);
2994 EXPECT_EQ(InputHandler::ScrollStarted,
2995 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2996 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2997 host_impl_->ScrollEnd();
2999 // The layer should have scrolled down in its local coordinates, but half the
3000 // amount.
3001 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3002 ExpectContains(*scroll_info.get(),
3003 scroll_layer->id(),
3004 gfx::Vector2d(0, scroll_delta.y() / scale));
3006 // Reset and scroll down with the wheel.
3007 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3008 gfx::Vector2d wheel_scroll_delta(0, 10);
3009 EXPECT_EQ(InputHandler::ScrollStarted,
3010 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3011 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3012 host_impl_->ScrollEnd();
3014 // The scale should not have been applied to the scroll delta.
3015 scroll_info = host_impl_->ProcessScrollDeltas();
3016 ExpectContains(*scroll_info.get(),
3017 scroll_layer->id(),
3018 wheel_scroll_delta);
3021 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
3022 public:
3023 TestScrollOffsetDelegate()
3024 : page_scale_factor_(0.f),
3025 min_page_scale_factor_(-1.f),
3026 max_page_scale_factor_(-1.f) {}
3028 virtual ~TestScrollOffsetDelegate() {}
3030 virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
3031 return getter_return_value_;
3034 virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
3036 virtual void UpdateRootLayerState(const gfx::Vector2dF& total_scroll_offset,
3037 const gfx::Vector2dF& max_scroll_offset,
3038 const gfx::SizeF& scrollable_size,
3039 float page_scale_factor,
3040 float min_page_scale_factor,
3041 float max_page_scale_factor) OVERRIDE {
3042 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
3043 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
3044 last_set_scroll_offset_ = total_scroll_offset;
3045 max_scroll_offset_ = max_scroll_offset;
3046 scrollable_size_ = scrollable_size;
3047 page_scale_factor_ = page_scale_factor;
3048 min_page_scale_factor_ = min_page_scale_factor;
3049 max_page_scale_factor_ = max_page_scale_factor;
3052 gfx::Vector2dF last_set_scroll_offset() {
3053 return last_set_scroll_offset_;
3056 void set_getter_return_value(const gfx::Vector2dF& value) {
3057 getter_return_value_ = value;
3060 gfx::Vector2dF max_scroll_offset() const {
3061 return max_scroll_offset_;
3064 gfx::SizeF scrollable_size() const {
3065 return scrollable_size_;
3068 float page_scale_factor() const {
3069 return page_scale_factor_;
3072 float min_page_scale_factor() const {
3073 return min_page_scale_factor_;
3076 float max_page_scale_factor() const {
3077 return max_page_scale_factor_;
3080 private:
3081 gfx::Vector2dF last_set_scroll_offset_;
3082 gfx::Vector2dF getter_return_value_;
3083 gfx::Vector2dF max_scroll_offset_;
3084 gfx::SizeF scrollable_size_;
3085 float page_scale_factor_;
3086 float min_page_scale_factor_;
3087 float max_page_scale_factor_;
3090 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
3091 TestScrollOffsetDelegate scroll_delegate;
3092 host_impl_->SetViewportSize(gfx::Size(10, 20));
3093 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3094 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3095 clip_layer->SetBounds(gfx::Size(10, 20));
3097 // Setting the delegate results in the current scroll offset being set.
3098 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
3099 scroll_layer->SetScrollOffset(gfx::Vector2d());
3100 scroll_layer->SetScrollDelta(initial_scroll_delta);
3101 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3102 EXPECT_EQ(initial_scroll_delta.ToString(),
3103 scroll_delegate.last_set_scroll_offset().ToString());
3105 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3106 // page_scale_factor and {min|max}_page_scale_factor being set.
3107 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
3108 EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
3109 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3110 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
3111 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
3113 // Updating page scale immediately updates the delegate.
3114 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
3115 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
3116 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3117 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3118 host_impl_->active_tree()->SetPageScaleDelta(1.5f);
3119 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
3120 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3121 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3122 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3123 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3124 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3125 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3126 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3128 // The pinch gesture doesn't put the delegate into a state where the scroll
3129 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3130 // delegate).
3131 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3132 host_impl_->PinchGestureBegin();
3133 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
3134 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
3135 host_impl_->PinchGestureEnd();
3136 host_impl_->ScrollEnd();
3138 // Scrolling should be relative to the offset as returned by the delegate.
3139 gfx::Vector2dF scroll_delta(0.f, 10.f);
3140 gfx::Vector2dF current_offset(7.f, 8.f);
3142 scroll_delegate.set_getter_return_value(current_offset);
3143 EXPECT_EQ(InputHandler::ScrollStarted,
3144 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3146 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3147 EXPECT_EQ(current_offset + scroll_delta,
3148 scroll_delegate.last_set_scroll_offset());
3150 current_offset = gfx::Vector2dF(42.f, 41.f);
3151 scroll_delegate.set_getter_return_value(current_offset);
3152 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3153 EXPECT_EQ(current_offset + scroll_delta,
3154 scroll_delegate.last_set_scroll_offset());
3155 host_impl_->ScrollEnd();
3156 scroll_delegate.set_getter_return_value(gfx::Vector2dF());
3158 // Forces a full tree synchronization and ensures that the scroll delegate
3159 // sees the correct size of the new tree.
3160 gfx::Size new_size(42, 24);
3161 host_impl_->CreatePendingTree();
3162 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
3163 host_impl_->ActivateSyncTree();
3164 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
3166 // Un-setting the delegate should propagate the delegate's current offset to
3167 // the root scrollable layer.
3168 current_offset = gfx::Vector2dF(13.f, 12.f);
3169 scroll_delegate.set_getter_return_value(current_offset);
3170 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3172 EXPECT_EQ(current_offset.ToString(),
3173 scroll_layer->TotalScrollOffset().ToString());
3176 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
3177 const gfx::Transform target_space_transform =
3178 layer->draw_properties().target_space_transform;
3179 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
3180 gfx::Point translated_point;
3181 target_space_transform.TransformPoint(&translated_point);
3182 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
3183 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
3186 TEST_F(LayerTreeHostImplTest,
3187 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
3188 TestScrollOffsetDelegate scroll_delegate;
3189 host_impl_->SetViewportSize(gfx::Size(10, 20));
3190 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3191 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3192 clip_layer->SetBounds(gfx::Size(10, 20));
3193 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3195 // Draw first frame to clear any pending draws and check scroll.
3196 DrawFrame();
3197 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
3198 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
3200 // Set external scroll delta on delegate and notify LayerTreeHost.
3201 gfx::Vector2dF scroll_delta(10.f, 10.f);
3202 scroll_delegate.set_getter_return_value(scroll_delta);
3203 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
3205 // Check scroll delta reflected in layer.
3206 DrawFrame();
3207 CheckLayerScrollDelta(scroll_layer, scroll_delta);
3209 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3212 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
3213 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3214 host_impl_->SetViewportSize(gfx::Size(50, 50));
3215 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3216 DrawFrame();
3217 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3219 // In-bounds scrolling does not affect overscroll.
3220 EXPECT_EQ(InputHandler::ScrollStarted,
3221 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3222 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3223 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3225 // Overscroll events are reflected immediately.
3226 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
3227 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3229 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
3230 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
3231 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3232 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
3233 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3234 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
3235 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3236 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
3237 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
3238 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
3239 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
3240 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
3241 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3243 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
3244 // as no scroll occurs.
3245 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3246 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
3247 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3248 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
3249 // Overscroll resets on valid scroll.
3250 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3251 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3252 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3253 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3254 host_impl_->ScrollEnd();
3258 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
3259 // Scroll child layers beyond their maximum scroll range and make sure root
3260 // overscroll does not accumulate.
3261 gfx::Size surface_size(10, 10);
3262 scoped_ptr<LayerImpl> root_clip =
3263 LayerImpl::Create(host_impl_->active_tree(), 4);
3264 scoped_ptr<LayerImpl> root =
3265 CreateScrollableLayer(1, surface_size, root_clip.get());
3267 scoped_ptr<LayerImpl> grand_child =
3268 CreateScrollableLayer(3, surface_size, root_clip.get());
3270 scoped_ptr<LayerImpl> child =
3271 CreateScrollableLayer(2, surface_size, root_clip.get());
3272 LayerImpl* grand_child_layer = grand_child.get();
3273 child->AddChild(grand_child.Pass());
3275 LayerImpl* child_layer = child.get();
3276 root->AddChild(child.Pass());
3277 root_clip->AddChild(root.Pass());
3278 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
3279 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
3280 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3281 host_impl_->active_tree()->DidBecomeActive();
3282 host_impl_->SetViewportSize(surface_size);
3283 DrawFrame();
3285 gfx::Vector2d scroll_delta(0, -10);
3286 EXPECT_EQ(InputHandler::ScrollStarted,
3287 host_impl_->ScrollBegin(gfx::Point(),
3288 InputHandler::NonBubblingGesture));
3289 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3290 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3291 host_impl_->ScrollEnd();
3293 // The next time we scroll we should only scroll the parent, but overscroll
3294 // should still not reach the root layer.
3295 scroll_delta = gfx::Vector2d(0, -30);
3296 EXPECT_EQ(InputHandler::ScrollStarted,
3297 host_impl_->ScrollBegin(gfx::Point(5, 5),
3298 InputHandler::NonBubblingGesture));
3299 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3300 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3301 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3302 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
3303 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3304 host_impl_->ScrollEnd();
3306 // After scrolling the parent, another scroll on the opposite direction
3307 // should scroll the child.
3308 scroll_delta = gfx::Vector2d(0, 70);
3309 EXPECT_EQ(InputHandler::ScrollStarted,
3310 host_impl_->ScrollBegin(gfx::Point(5, 5),
3311 InputHandler::NonBubblingGesture));
3312 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3313 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3314 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3315 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3316 host_impl_->ScrollEnd();
3320 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
3321 // When we try to scroll a non-scrollable child layer, the scroll delta
3322 // should be applied to one of its ancestors if possible. Overscroll should
3323 // be reflected only when it has bubbled up to the root scrolling layer.
3324 gfx::Size surface_size(10, 10);
3325 gfx::Size content_size(20, 20);
3326 scoped_ptr<LayerImpl> root_clip =
3327 LayerImpl::Create(host_impl_->active_tree(), 3);
3328 scoped_ptr<LayerImpl> root =
3329 CreateScrollableLayer(1, content_size, root_clip.get());
3330 root->SetIsContainerForFixedPositionLayers(true);
3331 scoped_ptr<LayerImpl> child =
3332 CreateScrollableLayer(2, content_size, root_clip.get());
3334 child->SetScrollClipLayer(Layer::INVALID_ID);
3335 root->AddChild(child.Pass());
3336 root_clip->AddChild(root.Pass());
3338 host_impl_->SetViewportSize(surface_size);
3339 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3340 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3341 host_impl_->active_tree()->DidBecomeActive();
3342 DrawFrame();
3344 gfx::Vector2d scroll_delta(0, 8);
3345 EXPECT_EQ(InputHandler::ScrollStarted,
3346 host_impl_->ScrollBegin(gfx::Point(5, 5),
3347 InputHandler::Wheel));
3348 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3349 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3350 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3351 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
3352 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3353 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
3354 host_impl_->ScrollEnd();
3358 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
3359 LayerTreeSettings settings;
3360 CreateHostImpl(settings, CreateOutputSurface());
3362 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
3363 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3364 clip_layer->SetBounds(gfx::Size(50, 50));
3365 host_impl_->SetViewportSize(gfx::Size(50, 50));
3366 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3367 DrawFrame();
3368 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3370 // Even though the layer can't scroll the overscroll still happens.
3371 EXPECT_EQ(InputHandler::ScrollStarted,
3372 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3373 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3374 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3377 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
3378 gfx::Size surface_size(980, 1439);
3379 gfx::Size content_size(980, 1438);
3380 float device_scale_factor = 1.5f;
3381 scoped_ptr<LayerImpl> root_clip =
3382 LayerImpl::Create(host_impl_->active_tree(), 3);
3383 scoped_ptr<LayerImpl> root =
3384 CreateScrollableLayer(1, content_size, root_clip.get());
3385 root->SetIsContainerForFixedPositionLayers(true);
3386 scoped_ptr<LayerImpl> child =
3387 CreateScrollableLayer(2, content_size, root_clip.get());
3388 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
3389 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
3390 0.326531f, 0.326531f, 5.f);
3391 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3392 child->SetScrollClipLayer(Layer::INVALID_ID);
3393 root->AddChild(child.Pass());
3394 root_clip->AddChild(root.Pass());
3396 host_impl_->SetViewportSize(surface_size);
3397 host_impl_->SetDeviceScaleFactor(device_scale_factor);
3398 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3399 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3400 host_impl_->active_tree()->DidBecomeActive();
3401 DrawFrame();
3403 // Horizontal & Vertical GlowEffect should not be applied when
3404 // content size is less then view port size. For Example Horizontal &
3405 // vertical GlowEffect should not be applied in about:blank page.
3406 EXPECT_EQ(InputHandler::ScrollStarted,
3407 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3408 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
3409 EXPECT_EQ(gfx::Vector2dF().ToString(),
3410 host_impl_->accumulated_root_overscroll().ToString());
3412 host_impl_->ScrollEnd();
3416 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
3417 gfx::Size surface_size(100, 100);
3418 gfx::Size content_size(200, 200);
3419 scoped_ptr<LayerImpl> root_clip =
3420 LayerImpl::Create(host_impl_->active_tree(), 3);
3421 scoped_ptr<LayerImpl> root =
3422 CreateScrollableLayer(1, content_size, root_clip.get());
3423 root->SetIsContainerForFixedPositionLayers(true);
3424 scoped_ptr<LayerImpl> child =
3425 CreateScrollableLayer(2, content_size, root_clip.get());
3427 child->SetScrollClipLayer(Layer::INVALID_ID);
3428 root->AddChild(child.Pass());
3429 root_clip->AddChild(root.Pass());
3431 host_impl_->SetViewportSize(surface_size);
3432 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3433 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3434 host_impl_->active_tree()->DidBecomeActive();
3435 DrawFrame();
3437 // Edge glow effect should be applicable only upon reaching Edges
3438 // of the content. unnecessary glow effect calls shouldn't be
3439 // called while scrolling up without reaching the edge of the content.
3440 EXPECT_EQ(InputHandler::ScrollStarted,
3441 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3442 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
3443 EXPECT_EQ(gfx::Vector2dF().ToString(),
3444 host_impl_->accumulated_root_overscroll().ToString());
3445 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
3446 EXPECT_EQ(gfx::Vector2dF().ToString(),
3447 host_impl_->accumulated_root_overscroll().ToString());
3448 host_impl_->ScrollEnd();
3449 // unusedrootDelta should be subtracted from applied delta so that
3450 // unwanted glow effect calls are not called.
3451 EXPECT_EQ(InputHandler::ScrollStarted,
3452 host_impl_->ScrollBegin(gfx::Point(0, 0),
3453 InputHandler::NonBubblingGesture));
3454 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
3455 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
3456 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3457 host_impl_->accumulated_root_overscroll().ToString());
3459 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
3460 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3461 host_impl_->accumulated_root_overscroll().ToString());
3462 host_impl_->ScrollEnd();
3463 // TestCase to check kEpsilon, which prevents minute values to trigger
3464 // gloweffect without reaching edge.
3465 EXPECT_EQ(InputHandler::ScrollStarted,
3466 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3467 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
3468 EXPECT_EQ(gfx::Vector2dF().ToString(),
3469 host_impl_->accumulated_root_overscroll().ToString());
3470 host_impl_->ScrollEnd();
3474 class BlendStateCheckLayer : public LayerImpl {
3475 public:
3476 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
3477 int id,
3478 ResourceProvider* resource_provider) {
3479 return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(tree_impl,
3481 resource_provider));
3484 virtual void AppendQuads(RenderPass* render_pass,
3485 const OcclusionTracker<LayerImpl>& occlusion_tracker,
3486 AppendQuadsData* append_quads_data) OVERRIDE {
3487 quads_appended_ = true;
3489 gfx::Rect opaque_rect;
3490 if (contents_opaque())
3491 opaque_rect = quad_rect_;
3492 else
3493 opaque_rect = opaque_content_rect_;
3494 gfx::Rect visible_quad_rect = quad_rect_;
3496 SharedQuadState* shared_quad_state =
3497 render_pass->CreateAndAppendSharedQuadState();
3498 PopulateSharedQuadState(shared_quad_state);
3500 scoped_ptr<TileDrawQuad> test_blending_draw_quad = TileDrawQuad::Create();
3501 test_blending_draw_quad->SetNew(shared_quad_state,
3502 quad_rect_,
3503 opaque_rect,
3504 visible_quad_rect,
3505 resource_id_,
3506 gfx::RectF(0.f, 0.f, 1.f, 1.f),
3507 gfx::Size(1, 1),
3508 false);
3509 test_blending_draw_quad->visible_rect = quad_visible_rect_;
3510 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
3511 EXPECT_EQ(has_render_surface_, !!render_surface());
3512 render_pass->AppendDrawQuad(test_blending_draw_quad.PassAs<DrawQuad>());
3515 void SetExpectation(bool blend, bool has_render_surface) {
3516 blend_ = blend;
3517 has_render_surface_ = has_render_surface;
3518 quads_appended_ = false;
3521 bool quads_appended() const { return quads_appended_; }
3523 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
3524 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
3525 void SetOpaqueContentRect(const gfx::Rect& rect) {
3526 opaque_content_rect_ = rect;
3529 private:
3530 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
3531 int id,
3532 ResourceProvider* resource_provider)
3533 : LayerImpl(tree_impl, id),
3534 blend_(false),
3535 has_render_surface_(false),
3536 quads_appended_(false),
3537 quad_rect_(5, 5, 5, 5),
3538 quad_visible_rect_(5, 5, 5, 5),
3539 resource_id_(resource_provider->CreateResource(
3540 gfx::Size(1, 1),
3541 GL_CLAMP_TO_EDGE,
3542 ResourceProvider::TextureUsageAny,
3543 RGBA_8888)) {
3544 resource_provider->AllocateForTesting(resource_id_);
3545 SetBounds(gfx::Size(10, 10));
3546 SetContentBounds(gfx::Size(10, 10));
3547 SetDrawsContent(true);
3550 bool blend_;
3551 bool has_render_surface_;
3552 bool quads_appended_;
3553 gfx::Rect quad_rect_;
3554 gfx::Rect opaque_content_rect_;
3555 gfx::Rect quad_visible_rect_;
3556 ResourceProvider::ResourceId resource_id_;
3559 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
3561 scoped_ptr<LayerImpl> root =
3562 LayerImpl::Create(host_impl_->active_tree(), 1);
3563 root->SetBounds(gfx::Size(10, 10));
3564 root->SetContentBounds(root->bounds());
3565 root->SetDrawsContent(false);
3566 host_impl_->active_tree()->SetRootLayer(root.Pass());
3568 LayerImpl* root = host_impl_->active_tree()->root_layer();
3570 root->AddChild(
3571 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3573 host_impl_->resource_provider()));
3574 BlendStateCheckLayer* layer1 =
3575 static_cast<BlendStateCheckLayer*>(root->children()[0]);
3576 layer1->SetPosition(gfx::PointF(2.f, 2.f));
3578 LayerTreeHostImpl::FrameData frame;
3580 // Opaque layer, drawn without blending.
3581 layer1->SetContentsOpaque(true);
3582 layer1->SetExpectation(false, false);
3583 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3584 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3585 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3586 EXPECT_TRUE(layer1->quads_appended());
3587 host_impl_->DidDrawAllLayers(frame);
3589 // Layer with translucent content and painting, so drawn with blending.
3590 layer1->SetContentsOpaque(false);
3591 layer1->SetExpectation(true, false);
3592 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3593 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3594 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3595 EXPECT_TRUE(layer1->quads_appended());
3596 host_impl_->DidDrawAllLayers(frame);
3598 // Layer with translucent opacity, drawn with blending.
3599 layer1->SetContentsOpaque(true);
3600 layer1->SetOpacity(0.5f);
3601 layer1->SetExpectation(true, false);
3602 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3603 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3604 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3605 EXPECT_TRUE(layer1->quads_appended());
3606 host_impl_->DidDrawAllLayers(frame);
3608 // Layer with translucent opacity and painting, drawn with blending.
3609 layer1->SetContentsOpaque(true);
3610 layer1->SetOpacity(0.5f);
3611 layer1->SetExpectation(true, false);
3612 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3613 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3614 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3615 EXPECT_TRUE(layer1->quads_appended());
3616 host_impl_->DidDrawAllLayers(frame);
3618 layer1->AddChild(
3619 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3621 host_impl_->resource_provider()));
3622 BlendStateCheckLayer* layer2 =
3623 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
3624 layer2->SetPosition(gfx::PointF(4.f, 4.f));
3626 // 2 opaque layers, drawn without blending.
3627 layer1->SetContentsOpaque(true);
3628 layer1->SetOpacity(1.f);
3629 layer1->SetExpectation(false, false);
3630 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3631 layer2->SetContentsOpaque(true);
3632 layer2->SetOpacity(1.f);
3633 layer2->SetExpectation(false, false);
3634 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3635 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3636 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3637 EXPECT_TRUE(layer1->quads_appended());
3638 EXPECT_TRUE(layer2->quads_appended());
3639 host_impl_->DidDrawAllLayers(frame);
3641 // Parent layer with translucent content, drawn with blending.
3642 // Child layer with opaque content, drawn without blending.
3643 layer1->SetContentsOpaque(false);
3644 layer1->SetExpectation(true, false);
3645 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3646 layer2->SetExpectation(false, false);
3647 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3648 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3649 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3650 EXPECT_TRUE(layer1->quads_appended());
3651 EXPECT_TRUE(layer2->quads_appended());
3652 host_impl_->DidDrawAllLayers(frame);
3654 // Parent layer with translucent content but opaque painting, drawn without
3655 // blending.
3656 // Child layer with opaque content, drawn without blending.
3657 layer1->SetContentsOpaque(true);
3658 layer1->SetExpectation(false, false);
3659 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3660 layer2->SetExpectation(false, false);
3661 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3662 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3663 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3664 EXPECT_TRUE(layer1->quads_appended());
3665 EXPECT_TRUE(layer2->quads_appended());
3666 host_impl_->DidDrawAllLayers(frame);
3668 // Parent layer with translucent opacity and opaque content. Since it has a
3669 // drawing child, it's drawn to a render surface which carries the opacity,
3670 // so it's itself drawn without blending.
3671 // Child layer with opaque content, drawn without blending (parent surface
3672 // carries the inherited opacity).
3673 layer1->SetContentsOpaque(true);
3674 layer1->SetOpacity(0.5f);
3675 layer1->SetExpectation(false, true);
3676 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3677 layer2->SetExpectation(false, false);
3678 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3679 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3680 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3681 EXPECT_TRUE(layer1->quads_appended());
3682 EXPECT_TRUE(layer2->quads_appended());
3683 host_impl_->DidDrawAllLayers(frame);
3685 // Draw again, but with child non-opaque, to make sure
3686 // layer1 not culled.
3687 layer1->SetContentsOpaque(true);
3688 layer1->SetOpacity(1.f);
3689 layer1->SetExpectation(false, false);
3690 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3691 layer2->SetContentsOpaque(true);
3692 layer2->SetOpacity(0.5f);
3693 layer2->SetExpectation(true, false);
3694 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3695 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3696 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3697 EXPECT_TRUE(layer1->quads_appended());
3698 EXPECT_TRUE(layer2->quads_appended());
3699 host_impl_->DidDrawAllLayers(frame);
3701 // A second way of making the child non-opaque.
3702 layer1->SetContentsOpaque(true);
3703 layer1->SetOpacity(1.f);
3704 layer1->SetExpectation(false, false);
3705 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3706 layer2->SetContentsOpaque(false);
3707 layer2->SetOpacity(1.f);
3708 layer2->SetExpectation(true, false);
3709 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3710 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3711 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3712 EXPECT_TRUE(layer1->quads_appended());
3713 EXPECT_TRUE(layer2->quads_appended());
3714 host_impl_->DidDrawAllLayers(frame);
3716 // And when the layer says its not opaque but is painted opaque, it is not
3717 // blended.
3718 layer1->SetContentsOpaque(true);
3719 layer1->SetOpacity(1.f);
3720 layer1->SetExpectation(false, false);
3721 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3722 layer2->SetContentsOpaque(true);
3723 layer2->SetOpacity(1.f);
3724 layer2->SetExpectation(false, false);
3725 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3726 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3727 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3728 EXPECT_TRUE(layer1->quads_appended());
3729 EXPECT_TRUE(layer2->quads_appended());
3730 host_impl_->DidDrawAllLayers(frame);
3732 // Layer with partially opaque contents, drawn with blending.
3733 layer1->SetContentsOpaque(false);
3734 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3735 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
3736 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3737 layer1->SetExpectation(true, false);
3738 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3739 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3740 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3741 EXPECT_TRUE(layer1->quads_appended());
3742 host_impl_->DidDrawAllLayers(frame);
3744 // Layer with partially opaque contents partially culled, drawn with blending.
3745 layer1->SetContentsOpaque(false);
3746 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3747 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
3748 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3749 layer1->SetExpectation(true, false);
3750 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3751 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3752 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3753 EXPECT_TRUE(layer1->quads_appended());
3754 host_impl_->DidDrawAllLayers(frame);
3756 // Layer with partially opaque contents culled, drawn with blending.
3757 layer1->SetContentsOpaque(false);
3758 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3759 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
3760 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3761 layer1->SetExpectation(true, false);
3762 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3763 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3764 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3765 EXPECT_TRUE(layer1->quads_appended());
3766 host_impl_->DidDrawAllLayers(frame);
3768 // Layer with partially opaque contents and translucent contents culled, drawn
3769 // without blending.
3770 layer1->SetContentsOpaque(false);
3771 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3772 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
3773 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3774 layer1->SetExpectation(false, false);
3775 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3776 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3777 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3778 EXPECT_TRUE(layer1->quads_appended());
3779 host_impl_->DidDrawAllLayers(frame);
3782 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
3783 protected:
3784 LayerTreeHostImplViewportCoveredTest() :
3785 gutter_quad_material_(DrawQuad::SOLID_COLOR),
3786 child_(NULL),
3787 did_activate_pending_tree_(false) {}
3789 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
3790 if (always_draw) {
3791 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
3792 .PassAs<OutputSurface>();
3794 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
3797 void SetupActiveTreeLayers() {
3798 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
3799 host_impl_->active_tree()->SetRootLayer(
3800 LayerImpl::Create(host_impl_->active_tree(), 1));
3801 host_impl_->active_tree()->root_layer()->AddChild(
3802 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3804 host_impl_->resource_provider()));
3805 child_ = static_cast<BlendStateCheckLayer*>(
3806 host_impl_->active_tree()->root_layer()->children()[0]);
3807 child_->SetExpectation(false, false);
3808 child_->SetContentsOpaque(true);
3811 // Expect no gutter rects.
3812 void TestLayerCoversFullViewport() {
3813 gfx::Rect layer_rect(viewport_size_);
3814 child_->SetPosition(layer_rect.origin());
3815 child_->SetBounds(layer_rect.size());
3816 child_->SetContentBounds(layer_rect.size());
3817 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3818 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3820 LayerTreeHostImpl::FrameData frame;
3821 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3822 ASSERT_EQ(1u, frame.render_passes.size());
3824 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3825 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3826 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3828 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3829 host_impl_->DidDrawAllLayers(frame);
3832 // Expect fullscreen gutter rect.
3833 void TestEmptyLayer() {
3834 gfx::Rect layer_rect(0, 0, 0, 0);
3835 child_->SetPosition(layer_rect.origin());
3836 child_->SetBounds(layer_rect.size());
3837 child_->SetContentBounds(layer_rect.size());
3838 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3839 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3841 LayerTreeHostImpl::FrameData frame;
3842 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3843 ASSERT_EQ(1u, frame.render_passes.size());
3845 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
3846 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3847 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3849 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3850 host_impl_->DidDrawAllLayers(frame);
3853 // Expect four surrounding gutter rects.
3854 void TestLayerInMiddleOfViewport() {
3855 gfx::Rect layer_rect(500, 500, 200, 200);
3856 child_->SetPosition(layer_rect.origin());
3857 child_->SetBounds(layer_rect.size());
3858 child_->SetContentBounds(layer_rect.size());
3859 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3860 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3862 LayerTreeHostImpl::FrameData frame;
3863 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3864 ASSERT_EQ(1u, frame.render_passes.size());
3866 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
3867 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
3868 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3870 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3871 host_impl_->DidDrawAllLayers(frame);
3874 // Expect no gutter rects.
3875 void TestLayerIsLargerThanViewport() {
3876 gfx::Rect layer_rect(viewport_size_.width() + 10,
3877 viewport_size_.height() + 10);
3878 child_->SetPosition(layer_rect.origin());
3879 child_->SetBounds(layer_rect.size());
3880 child_->SetContentBounds(layer_rect.size());
3881 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3882 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3884 LayerTreeHostImpl::FrameData frame;
3885 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3886 ASSERT_EQ(1u, frame.render_passes.size());
3888 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3889 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3890 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3892 host_impl_->DidDrawAllLayers(frame);
3895 virtual void DidActivateSyncTree() OVERRIDE {
3896 did_activate_pending_tree_ = true;
3899 void set_gutter_quad_material(DrawQuad::Material material) {
3900 gutter_quad_material_ = material;
3902 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
3903 gutter_texture_size_ = gutter_texture_size;
3906 protected:
3907 size_t CountGutterQuads(const QuadList& quad_list) {
3908 size_t num_gutter_quads = 0;
3909 for (size_t i = 0; i < quad_list.size(); ++i) {
3910 num_gutter_quads += (quad_list[i]->material ==
3911 gutter_quad_material_) ? 1 : 0;
3913 return num_gutter_quads;
3916 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
3917 LayerTestCommon::VerifyQuadsExactlyCoverRect(
3918 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
3921 // Make sure that the texture coordinates match their expectations.
3922 void ValidateTextureDrawQuads(const QuadList& quad_list) {
3923 for (size_t i = 0; i < quad_list.size(); ++i) {
3924 if (quad_list[i]->material != DrawQuad::TEXTURE_CONTENT)
3925 continue;
3926 const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(quad_list[i]);
3927 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
3928 gutter_texture_size_, host_impl_->device_scale_factor());
3929 EXPECT_EQ(quad->uv_top_left.x(),
3930 quad->rect.x() / gutter_texture_size_pixels.width());
3931 EXPECT_EQ(quad->uv_top_left.y(),
3932 quad->rect.y() / gutter_texture_size_pixels.height());
3933 EXPECT_EQ(quad->uv_bottom_right.x(),
3934 quad->rect.right() / gutter_texture_size_pixels.width());
3935 EXPECT_EQ(quad->uv_bottom_right.y(),
3936 quad->rect.bottom() / gutter_texture_size_pixels.height());
3940 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
3941 return gfx::ToRoundedSize(
3942 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
3945 DrawQuad::Material gutter_quad_material_;
3946 gfx::Size gutter_texture_size_;
3947 gfx::Size viewport_size_;
3948 BlendStateCheckLayer* child_;
3949 bool did_activate_pending_tree_;
3952 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
3953 viewport_size_ = gfx::Size(1000, 1000);
3955 bool always_draw = false;
3956 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3958 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3959 SetupActiveTreeLayers();
3960 TestLayerCoversFullViewport();
3961 TestEmptyLayer();
3962 TestLayerInMiddleOfViewport();
3963 TestLayerIsLargerThanViewport();
3966 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
3967 viewport_size_ = gfx::Size(1000, 1000);
3969 bool always_draw = false;
3970 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3972 host_impl_->SetDeviceScaleFactor(2.f);
3973 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3974 SetupActiveTreeLayers();
3975 TestLayerCoversFullViewport();
3976 TestEmptyLayer();
3977 TestLayerInMiddleOfViewport();
3978 TestLayerIsLargerThanViewport();
3981 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
3982 viewport_size_ = gfx::Size(1000, 1000);
3984 bool always_draw = false;
3985 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3987 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3988 SetupActiveTreeLayers();
3990 // Specify an overhang bitmap to use.
3991 bool is_opaque = false;
3992 UIResourceBitmap ui_resource_bitmap(gfx::Size(2, 2), is_opaque);
3993 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
3994 UIResourceId ui_resource_id = 12345;
3995 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
3996 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
3997 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
3998 set_gutter_texture_size(gfx::Size(32, 32));
4000 TestLayerCoversFullViewport();
4001 TestEmptyLayer();
4002 TestLayerInMiddleOfViewport();
4003 TestLayerIsLargerThanViewport();
4005 // Change the resource size.
4006 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
4007 set_gutter_texture_size(gfx::Size(128, 16));
4009 TestLayerCoversFullViewport();
4010 TestEmptyLayer();
4011 TestLayerInMiddleOfViewport();
4012 TestLayerIsLargerThanViewport();
4014 // Change the device scale factor
4015 host_impl_->SetDeviceScaleFactor(2.f);
4016 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4018 TestLayerCoversFullViewport();
4019 TestEmptyLayer();
4020 TestLayerInMiddleOfViewport();
4021 TestLayerIsLargerThanViewport();
4024 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
4025 viewport_size_ = gfx::Size(1000, 1000);
4027 bool always_draw = true;
4028 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4030 // Pending tree to force active_tree size invalid. Not used otherwise.
4031 host_impl_->CreatePendingTree();
4032 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4033 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4035 SetupActiveTreeLayers();
4036 TestEmptyLayer();
4037 TestLayerInMiddleOfViewport();
4038 TestLayerIsLargerThanViewport();
4041 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
4042 viewport_size_ = gfx::Size(1000, 1000);
4044 bool always_draw = true;
4045 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4047 // Set larger viewport and activate it to active tree.
4048 host_impl_->CreatePendingTree();
4049 gfx::Size larger_viewport(viewport_size_.width() + 100,
4050 viewport_size_.height() + 100);
4051 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
4052 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4053 host_impl_->ActivateSyncTree();
4054 EXPECT_TRUE(did_activate_pending_tree_);
4055 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
4057 // Shrink pending tree viewport without activating.
4058 host_impl_->CreatePendingTree();
4059 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4060 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4062 SetupActiveTreeLayers();
4063 TestEmptyLayer();
4064 TestLayerInMiddleOfViewport();
4065 TestLayerIsLargerThanViewport();
4068 class FakeDrawableLayerImpl: public LayerImpl {
4069 public:
4070 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4071 return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(tree_impl, id));
4073 protected:
4074 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
4075 : LayerImpl(tree_impl, id) {}
4078 // Only reshape when we know we are going to draw. Otherwise, the reshape
4079 // can leave the window at the wrong size if we never draw and the proper
4080 // viewport size is never set.
4081 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
4082 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4083 scoped_ptr<OutputSurface> output_surface(
4084 FakeOutputSurface::Create3d(provider));
4085 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4087 scoped_ptr<LayerImpl> root =
4088 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4089 root->SetBounds(gfx::Size(10, 10));
4090 root->SetContentBounds(gfx::Size(10, 10));
4091 root->SetDrawsContent(true);
4092 host_impl_->active_tree()->SetRootLayer(root.Pass());
4093 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
4094 provider->TestContext3d()->clear_reshape_called();
4096 LayerTreeHostImpl::FrameData frame;
4097 host_impl_->SetViewportSize(gfx::Size(10, 10));
4098 host_impl_->SetDeviceScaleFactor(1.f);
4099 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4100 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4101 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4102 EXPECT_EQ(provider->TestContext3d()->width(), 10);
4103 EXPECT_EQ(provider->TestContext3d()->height(), 10);
4104 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4105 host_impl_->DidDrawAllLayers(frame);
4106 provider->TestContext3d()->clear_reshape_called();
4108 host_impl_->SetViewportSize(gfx::Size(20, 30));
4109 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4110 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4111 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4112 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4113 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4114 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4115 host_impl_->DidDrawAllLayers(frame);
4116 provider->TestContext3d()->clear_reshape_called();
4118 host_impl_->SetDeviceScaleFactor(2.f);
4119 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4120 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4121 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4122 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4123 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4124 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
4125 host_impl_->DidDrawAllLayers(frame);
4126 provider->TestContext3d()->clear_reshape_called();
4129 // Make sure damage tracking propagates all the way to the graphics context,
4130 // where it should request to swap only the sub-buffer that is damaged.
4131 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
4132 scoped_refptr<TestContextProvider> context_provider(
4133 TestContextProvider::Create());
4134 context_provider->BindToCurrentThread();
4135 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
4137 scoped_ptr<OutputSurface> output_surface(
4138 FakeOutputSurface::Create3d(context_provider));
4140 // This test creates its own LayerTreeHostImpl, so
4141 // that we can force partial swap enabled.
4142 LayerTreeSettings settings;
4143 settings.partial_swap_enabled = true;
4144 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4145 new TestSharedBitmapManager());
4146 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
4147 LayerTreeHostImpl::Create(settings,
4148 this,
4149 &proxy_,
4150 &stats_instrumentation_,
4151 shared_bitmap_manager.get(),
4153 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
4154 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
4156 scoped_ptr<LayerImpl> root =
4157 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
4158 scoped_ptr<LayerImpl> child =
4159 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
4160 child->SetPosition(gfx::PointF(12.f, 13.f));
4161 child->SetBounds(gfx::Size(14, 15));
4162 child->SetContentBounds(gfx::Size(14, 15));
4163 child->SetDrawsContent(true);
4164 root->SetBounds(gfx::Size(500, 500));
4165 root->SetContentBounds(gfx::Size(500, 500));
4166 root->SetDrawsContent(true);
4167 root->AddChild(child.Pass());
4168 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
4170 LayerTreeHostImpl::FrameData frame;
4172 // First frame, the entire screen should get swapped.
4173 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4174 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4175 layer_tree_host_impl->DidDrawAllLayers(frame);
4176 layer_tree_host_impl->SwapBuffers(frame);
4177 EXPECT_EQ(TestContextSupport::SWAP,
4178 context_provider->support()->last_swap_type());
4180 // Second frame, only the damaged area should get swapped. Damage should be
4181 // the union of old and new child rects.
4182 // expected damage rect: gfx::Rect(26, 28);
4183 // expected swap rect: vertically flipped, with origin at bottom left corner.
4184 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
4185 gfx::PointF());
4186 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4187 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4188 host_impl_->DidDrawAllLayers(frame);
4189 layer_tree_host_impl->SwapBuffers(frame);
4191 // Make sure that partial swap is constrained to the viewport dimensions
4192 // expected damage rect: gfx::Rect(500, 500);
4193 // expected swap rect: flipped damage rect, but also clamped to viewport
4194 EXPECT_EQ(TestContextSupport::PARTIAL_SWAP,
4195 context_provider->support()->last_swap_type());
4196 gfx::Rect expected_swap_rect(0, 500-28, 26, 28);
4197 EXPECT_EQ(expected_swap_rect.ToString(),
4198 context_provider->support()->
4199 last_partial_swap_rect().ToString());
4201 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
4202 // This will damage everything.
4203 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
4204 SK_ColorBLACK);
4205 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4206 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4207 host_impl_->DidDrawAllLayers(frame);
4208 layer_tree_host_impl->SwapBuffers(frame);
4210 EXPECT_EQ(TestContextSupport::SWAP,
4211 context_provider->support()->last_swap_type());
4214 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
4215 scoped_ptr<LayerImpl> root =
4216 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4217 scoped_ptr<LayerImpl> child =
4218 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
4219 child->SetBounds(gfx::Size(10, 10));
4220 child->SetContentBounds(gfx::Size(10, 10));
4221 child->SetDrawsContent(true);
4222 root->SetBounds(gfx::Size(10, 10));
4223 root->SetContentBounds(gfx::Size(10, 10));
4224 root->SetDrawsContent(true);
4225 root->SetForceRenderSurface(true);
4226 root->AddChild(child.Pass());
4228 host_impl_->active_tree()->SetRootLayer(root.Pass());
4230 LayerTreeHostImpl::FrameData frame;
4232 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4233 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
4234 EXPECT_EQ(1u, frame.render_passes.size());
4235 host_impl_->DidDrawAllLayers(frame);
4238 class FakeLayerWithQuads : public LayerImpl {
4239 public:
4240 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4241 return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(tree_impl, id));
4244 virtual void AppendQuads(RenderPass* render_pass,
4245 const OcclusionTracker<LayerImpl>& occlusion_tracker,
4246 AppendQuadsData* append_quads_data) OVERRIDE {
4247 SharedQuadState* shared_quad_state =
4248 render_pass->CreateAndAppendSharedQuadState();
4249 PopulateSharedQuadState(shared_quad_state);
4251 SkColor gray = SkColorSetRGB(100, 100, 100);
4252 gfx::Rect quad_rect(content_bounds());
4253 gfx::Rect visible_quad_rect(quad_rect);
4254 scoped_ptr<SolidColorDrawQuad> my_quad = SolidColorDrawQuad::Create();
4255 my_quad->SetNew(
4256 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
4257 render_pass->AppendDrawQuad(my_quad.PassAs<DrawQuad>());
4260 private:
4261 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
4262 : LayerImpl(tree_impl, id) {}
4265 class MockContext : public TestWebGraphicsContext3D {
4266 public:
4267 MOCK_METHOD1(useProgram, void(GLuint program));
4268 MOCK_METHOD5(uniform4f, void(GLint location,
4269 GLfloat x,
4270 GLfloat y,
4271 GLfloat z,
4272 GLfloat w));
4273 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
4274 GLsizei count,
4275 GLboolean transpose,
4276 const GLfloat* value));
4277 MOCK_METHOD4(drawElements, void(GLenum mode,
4278 GLsizei count,
4279 GLenum type,
4280 GLintptr offset));
4281 MOCK_METHOD1(enable, void(GLenum cap));
4282 MOCK_METHOD1(disable, void(GLenum cap));
4283 MOCK_METHOD4(scissor, void(GLint x,
4284 GLint y,
4285 GLsizei width,
4286 GLsizei height));
4289 class MockContextHarness {
4290 private:
4291 MockContext* context_;
4293 public:
4294 explicit MockContextHarness(MockContext* context)
4295 : context_(context) {
4296 context_->set_have_post_sub_buffer(true);
4298 // Catch "uninteresting" calls
4299 EXPECT_CALL(*context_, useProgram(_))
4300 .Times(0);
4302 EXPECT_CALL(*context_, drawElements(_, _, _, _))
4303 .Times(0);
4305 // These are not asserted
4306 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
4307 .WillRepeatedly(Return());
4309 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
4310 .WillRepeatedly(Return());
4312 // Any un-sanctioned calls to enable() are OK
4313 EXPECT_CALL(*context_, enable(_))
4314 .WillRepeatedly(Return());
4316 // Any un-sanctioned calls to disable() are OK
4317 EXPECT_CALL(*context_, disable(_))
4318 .WillRepeatedly(Return());
4321 void MustDrawSolidQuad() {
4322 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
4323 .WillOnce(Return())
4324 .RetiresOnSaturation();
4326 EXPECT_CALL(*context_, useProgram(_))
4327 .WillOnce(Return())
4328 .RetiresOnSaturation();
4331 void MustSetScissor(int x, int y, int width, int height) {
4332 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4333 .WillRepeatedly(Return());
4335 EXPECT_CALL(*context_, scissor(x, y, width, height))
4336 .Times(AtLeast(1))
4337 .WillRepeatedly(Return());
4340 void MustSetNoScissor() {
4341 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
4342 .WillRepeatedly(Return());
4344 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4345 .Times(0);
4347 EXPECT_CALL(*context_, scissor(_, _, _, _))
4348 .Times(0);
4352 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
4353 scoped_ptr<MockContext> mock_context_owned(new MockContext);
4354 MockContext* mock_context = mock_context_owned.get();
4356 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4357 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4358 MockContextHarness harness(mock_context);
4360 // Run test case
4361 LayerTreeSettings settings = DefaultSettings();
4362 settings.partial_swap_enabled = false;
4363 CreateHostImpl(settings, output_surface.Pass());
4364 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4366 // Without partial swap, and no clipping, no scissor is set.
4367 harness.MustDrawSolidQuad();
4368 harness.MustSetNoScissor();
4370 LayerTreeHostImpl::FrameData frame;
4371 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4372 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4373 host_impl_->DidDrawAllLayers(frame);
4375 Mock::VerifyAndClearExpectations(&mock_context);
4377 // Without partial swap, but a layer does clip its subtree, one scissor is
4378 // set.
4379 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
4380 harness.MustDrawSolidQuad();
4381 harness.MustSetScissor(0, 0, 10, 10);
4383 LayerTreeHostImpl::FrameData frame;
4384 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4385 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4386 host_impl_->DidDrawAllLayers(frame);
4388 Mock::VerifyAndClearExpectations(&mock_context);
4391 TEST_F(LayerTreeHostImplTest, PartialSwap) {
4392 scoped_ptr<MockContext> context_owned(new MockContext);
4393 MockContext* mock_context = context_owned.get();
4394 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4395 context_owned.PassAs<TestWebGraphicsContext3D>()));
4396 MockContextHarness harness(mock_context);
4398 LayerTreeSettings settings = DefaultSettings();
4399 settings.partial_swap_enabled = true;
4400 CreateHostImpl(settings, output_surface.Pass());
4401 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4403 // The first frame is not a partially-swapped one.
4404 harness.MustSetScissor(0, 0, 10, 10);
4405 harness.MustDrawSolidQuad();
4407 LayerTreeHostImpl::FrameData frame;
4408 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4409 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4410 host_impl_->DidDrawAllLayers(frame);
4412 Mock::VerifyAndClearExpectations(&mock_context);
4414 // Damage a portion of the frame.
4415 host_impl_->active_tree()->root_layer()->SetUpdateRect(
4416 gfx::Rect(0, 0, 2, 3));
4418 // The second frame will be partially-swapped (the y coordinates are flipped).
4419 harness.MustSetScissor(0, 7, 2, 3);
4420 harness.MustDrawSolidQuad();
4422 LayerTreeHostImpl::FrameData frame;
4423 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4424 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4425 host_impl_->DidDrawAllLayers(frame);
4427 Mock::VerifyAndClearExpectations(&mock_context);
4430 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
4431 bool partial_swap,
4432 LayerTreeHostImplClient* client,
4433 Proxy* proxy,
4434 SharedBitmapManager* manager,
4435 RenderingStatsInstrumentation* stats_instrumentation) {
4436 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4437 scoped_ptr<OutputSurface> output_surface(
4438 FakeOutputSurface::Create3d(provider));
4439 provider->BindToCurrentThread();
4440 provider->TestContext3d()->set_have_post_sub_buffer(true);
4442 LayerTreeSettings settings;
4443 settings.partial_swap_enabled = partial_swap;
4444 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
4445 settings, client, proxy, stats_instrumentation, manager, 0);
4446 my_host_impl->InitializeRenderer(output_surface.Pass());
4447 my_host_impl->SetViewportSize(gfx::Size(100, 100));
4450 Layers are created as follows:
4452 +--------------------+
4453 | 1 |
4454 | +-----------+ |
4455 | | 2 | |
4456 | | +-------------------+
4457 | | | 3 |
4458 | | +-------------------+
4459 | | | |
4460 | +-----------+ |
4463 +--------------------+
4465 Layers 1, 2 have render surfaces
4467 scoped_ptr<LayerImpl> root =
4468 LayerImpl::Create(my_host_impl->active_tree(), 1);
4469 scoped_ptr<LayerImpl> child =
4470 LayerImpl::Create(my_host_impl->active_tree(), 2);
4471 scoped_ptr<LayerImpl> grand_child =
4472 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
4474 gfx::Rect root_rect(0, 0, 100, 100);
4475 gfx::Rect child_rect(10, 10, 50, 50);
4476 gfx::Rect grand_child_rect(5, 5, 150, 150);
4478 root->CreateRenderSurface();
4479 root->SetPosition(root_rect.origin());
4480 root->SetBounds(root_rect.size());
4481 root->SetContentBounds(root->bounds());
4482 root->draw_properties().visible_content_rect = root_rect;
4483 root->SetDrawsContent(false);
4484 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
4486 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
4487 child->SetOpacity(0.5f);
4488 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
4489 child->SetContentBounds(child->bounds());
4490 child->draw_properties().visible_content_rect = child_rect;
4491 child->SetDrawsContent(false);
4492 child->SetForceRenderSurface(true);
4494 grand_child->SetPosition(grand_child_rect.origin());
4495 grand_child->SetBounds(grand_child_rect.size());
4496 grand_child->SetContentBounds(grand_child->bounds());
4497 grand_child->draw_properties().visible_content_rect = grand_child_rect;
4498 grand_child->SetDrawsContent(true);
4500 child->AddChild(grand_child.Pass());
4501 root->AddChild(child.Pass());
4503 my_host_impl->active_tree()->SetRootLayer(root.Pass());
4504 return my_host_impl.Pass();
4507 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
4508 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4509 new TestSharedBitmapManager());
4510 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4511 SetupLayersForOpacity(true,
4512 this,
4513 &proxy_,
4514 shared_bitmap_manager.get(),
4515 &stats_instrumentation_);
4517 LayerTreeHostImpl::FrameData frame;
4518 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4520 // Verify all quads have been computed
4521 ASSERT_EQ(2U, frame.render_passes.size());
4522 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4523 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4524 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4525 frame.render_passes[0]->quad_list[0]->material);
4526 EXPECT_EQ(DrawQuad::RENDER_PASS,
4527 frame.render_passes[1]->quad_list[0]->material);
4529 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4530 my_host_impl->DidDrawAllLayers(frame);
4534 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
4535 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4536 new TestSharedBitmapManager());
4537 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4538 SetupLayersForOpacity(false,
4539 this,
4540 &proxy_,
4541 shared_bitmap_manager.get(),
4542 &stats_instrumentation_);
4544 LayerTreeHostImpl::FrameData frame;
4545 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4547 // Verify all quads have been computed
4548 ASSERT_EQ(2U, frame.render_passes.size());
4549 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4550 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4551 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4552 frame.render_passes[0]->quad_list[0]->material);
4553 EXPECT_EQ(DrawQuad::RENDER_PASS,
4554 frame.render_passes[1]->quad_list[0]->material);
4556 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4557 my_host_impl->DidDrawAllLayers(frame);
4561 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
4562 scoped_ptr<TestWebGraphicsContext3D> context =
4563 TestWebGraphicsContext3D::Create();
4564 TestWebGraphicsContext3D* context3d = context.get();
4565 scoped_ptr<OutputSurface> output_surface(
4566 FakeOutputSurface::Create3d(context.Pass()));
4567 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4569 scoped_ptr<LayerImpl> root_layer =
4570 LayerImpl::Create(host_impl_->active_tree(), 1);
4571 root_layer->SetBounds(gfx::Size(10, 10));
4573 scoped_refptr<VideoFrame> softwareFrame =
4574 media::VideoFrame::CreateColorFrame(
4575 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
4576 FakeVideoFrameProvider provider;
4577 provider.set_frame(softwareFrame);
4578 scoped_ptr<VideoLayerImpl> video_layer =
4579 VideoLayerImpl::Create(host_impl_->active_tree(), 4, &provider);
4580 video_layer->SetBounds(gfx::Size(10, 10));
4581 video_layer->SetContentBounds(gfx::Size(10, 10));
4582 video_layer->SetDrawsContent(true);
4583 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
4585 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
4586 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
4587 io_surface_layer->SetBounds(gfx::Size(10, 10));
4588 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
4589 io_surface_layer->SetDrawsContent(true);
4590 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
4591 root_layer->AddChild(io_surface_layer.PassAs<LayerImpl>());
4593 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
4595 EXPECT_EQ(0u, context3d->NumTextures());
4597 LayerTreeHostImpl::FrameData frame;
4598 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4599 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4600 host_impl_->DidDrawAllLayers(frame);
4601 host_impl_->SwapBuffers(frame);
4603 EXPECT_GT(context3d->NumTextures(), 0u);
4605 // Kill the layer tree.
4606 host_impl_->active_tree()->SetRootLayer(
4607 LayerImpl::Create(host_impl_->active_tree(), 100));
4608 // There should be no textures left in use after.
4609 EXPECT_EQ(0u, context3d->NumTextures());
4612 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
4613 public:
4614 MOCK_METHOD1(useProgram, void(GLuint program));
4615 MOCK_METHOD4(drawElements, void(GLenum mode,
4616 GLsizei count,
4617 GLenum type,
4618 GLintptr offset));
4621 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
4622 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
4623 new MockDrawQuadsToFillScreenContext);
4624 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
4626 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4627 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4629 // Run test case
4630 LayerTreeSettings settings = DefaultSettings();
4631 settings.partial_swap_enabled = false;
4632 CreateHostImpl(settings, output_surface.Pass());
4633 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
4634 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
4636 // Verify one quad is drawn when transparent background set is not set.
4637 host_impl_->active_tree()->set_has_transparent_background(false);
4638 EXPECT_CALL(*mock_context, useProgram(_))
4639 .Times(1);
4640 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
4641 .Times(1);
4642 LayerTreeHostImpl::FrameData frame;
4643 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4644 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4645 host_impl_->DidDrawAllLayers(frame);
4646 Mock::VerifyAndClearExpectations(&mock_context);
4648 // Verify no quads are drawn when transparent background is set.
4649 host_impl_->active_tree()->set_has_transparent_background(true);
4650 host_impl_->SetFullRootLayerDamage();
4651 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4652 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4653 host_impl_->DidDrawAllLayers(frame);
4654 Mock::VerifyAndClearExpectations(&mock_context);
4657 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
4658 set_reduce_memory_result(false);
4660 // If changing the memory limit wouldn't result in changing what was
4661 // committed, then no commit should be requested.
4662 set_reduce_memory_result(false);
4663 host_impl_->set_max_memory_needed_bytes(
4664 host_impl_->memory_allocation_limit_bytes() - 1);
4665 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4666 host_impl_->memory_allocation_limit_bytes() - 1));
4667 EXPECT_FALSE(did_request_commit_);
4668 did_request_commit_ = false;
4670 // If changing the memory limit would result in changing what was
4671 // committed, then a commit should be requested, even though nothing was
4672 // evicted.
4673 set_reduce_memory_result(false);
4674 host_impl_->set_max_memory_needed_bytes(
4675 host_impl_->memory_allocation_limit_bytes());
4676 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4677 host_impl_->memory_allocation_limit_bytes() - 1));
4678 EXPECT_TRUE(did_request_commit_);
4679 did_request_commit_ = false;
4681 // Especially if changing the memory limit caused evictions, we need
4682 // to re-commit.
4683 set_reduce_memory_result(true);
4684 host_impl_->set_max_memory_needed_bytes(1);
4685 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4686 host_impl_->memory_allocation_limit_bytes() - 1));
4687 EXPECT_TRUE(did_request_commit_);
4688 did_request_commit_ = false;
4690 // But if we set it to the same value that it was before, we shouldn't
4691 // re-commit.
4692 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4693 host_impl_->memory_allocation_limit_bytes()));
4694 EXPECT_FALSE(did_request_commit_);
4697 class LayerTreeHostImplTestWithDelegatingRenderer
4698 : public LayerTreeHostImplTest {
4699 protected:
4700 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
4701 return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
4704 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
4705 bool expect_to_draw = !expected_damage.IsEmpty();
4707 LayerTreeHostImpl::FrameData frame;
4708 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4710 if (!expect_to_draw) {
4711 // With no damage, we don't draw, and no quads are created.
4712 ASSERT_EQ(0u, frame.render_passes.size());
4713 } else {
4714 ASSERT_EQ(1u, frame.render_passes.size());
4716 // Verify the damage rect for the root render pass.
4717 const RenderPass* root_render_pass = frame.render_passes.back();
4718 EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
4720 // Verify the root and child layers' quads are generated and not being
4721 // culled.
4722 ASSERT_EQ(2u, root_render_pass->quad_list.size());
4724 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
4725 gfx::RectF expected_child_visible_rect(child->content_bounds());
4726 EXPECT_RECT_EQ(expected_child_visible_rect,
4727 root_render_pass->quad_list[0]->visible_rect);
4729 LayerImpl* root = host_impl_->active_tree()->root_layer();
4730 gfx::RectF expected_root_visible_rect(root->content_bounds());
4731 EXPECT_RECT_EQ(expected_root_visible_rect,
4732 root_render_pass->quad_list[1]->visible_rect);
4735 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4736 host_impl_->DidDrawAllLayers(frame);
4737 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
4741 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
4742 scoped_ptr<SolidColorLayerImpl> root =
4743 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4744 root->SetPosition(gfx::PointF());
4745 root->SetBounds(gfx::Size(10, 10));
4746 root->SetContentBounds(gfx::Size(10, 10));
4747 root->SetDrawsContent(true);
4749 // Child layer is in the bottom right corner.
4750 scoped_ptr<SolidColorLayerImpl> child =
4751 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
4752 child->SetPosition(gfx::PointF(9.f, 9.f));
4753 child->SetBounds(gfx::Size(1, 1));
4754 child->SetContentBounds(gfx::Size(1, 1));
4755 child->SetDrawsContent(true);
4756 root->AddChild(child.PassAs<LayerImpl>());
4758 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
4760 // Draw a frame. In the first frame, the entire viewport should be damaged.
4761 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
4762 DrawFrameAndTestDamage(full_frame_damage);
4764 // The second frame has damage that doesn't touch the child layer. Its quads
4765 // should still be generated.
4766 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
4767 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
4768 DrawFrameAndTestDamage(small_damage);
4770 // The third frame should have no damage, so no quads should be generated.
4771 gfx::Rect no_damage;
4772 DrawFrameAndTestDamage(no_damage);
4775 // TODO(reveman): Remove this test and the ability to prevent on demand raster
4776 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
4777 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
4778 LayerTreeSettings settings;
4779 CreateHostImpl(settings, CreateOutputSurface());
4780 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
4783 class FakeMaskLayerImpl : public LayerImpl {
4784 public:
4785 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
4786 int id) {
4787 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
4790 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
4791 return 0;
4794 private:
4795 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
4796 : LayerImpl(tree_impl, id) {}
4799 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
4800 LayerTreeSettings settings;
4801 settings.layer_transforms_should_scale_layer_contents = true;
4802 CreateHostImpl(settings, CreateOutputSurface());
4804 // Root
4805 // |
4806 // +-- Scaling Layer (adds a 2x scale)
4807 // |
4808 // +-- Content Layer
4809 // +--Mask
4810 scoped_ptr<LayerImpl> scoped_root =
4811 LayerImpl::Create(host_impl_->active_tree(), 1);
4812 LayerImpl* root = scoped_root.get();
4813 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4815 scoped_ptr<LayerImpl> scoped_scaling_layer =
4816 LayerImpl::Create(host_impl_->active_tree(), 2);
4817 LayerImpl* scaling_layer = scoped_scaling_layer.get();
4818 root->AddChild(scoped_scaling_layer.Pass());
4820 scoped_ptr<LayerImpl> scoped_content_layer =
4821 LayerImpl::Create(host_impl_->active_tree(), 3);
4822 LayerImpl* content_layer = scoped_content_layer.get();
4823 scaling_layer->AddChild(scoped_content_layer.Pass());
4825 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4826 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4827 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4828 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4830 gfx::Size root_size(100, 100);
4831 root->SetBounds(root_size);
4832 root->SetContentBounds(root_size);
4833 root->SetPosition(gfx::PointF());
4835 gfx::Size scaling_layer_size(50, 50);
4836 scaling_layer->SetBounds(scaling_layer_size);
4837 scaling_layer->SetContentBounds(scaling_layer_size);
4838 scaling_layer->SetPosition(gfx::PointF());
4839 gfx::Transform scale;
4840 scale.Scale(2.f, 2.f);
4841 scaling_layer->SetTransform(scale);
4843 content_layer->SetBounds(scaling_layer_size);
4844 content_layer->SetContentBounds(scaling_layer_size);
4845 content_layer->SetPosition(gfx::PointF());
4846 content_layer->SetDrawsContent(true);
4848 mask_layer->SetBounds(scaling_layer_size);
4849 mask_layer->SetContentBounds(scaling_layer_size);
4850 mask_layer->SetPosition(gfx::PointF());
4851 mask_layer->SetDrawsContent(true);
4854 // Check that the tree scaling is correctly taken into account for the mask,
4855 // that should fully map onto the quad.
4856 float device_scale_factor = 1.f;
4857 host_impl_->SetViewportSize(root_size);
4858 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4860 LayerTreeHostImpl::FrameData frame;
4861 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4863 ASSERT_EQ(1u, frame.render_passes.size());
4864 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4865 ASSERT_EQ(DrawQuad::RENDER_PASS,
4866 frame.render_passes[0]->quad_list[0]->material);
4867 const RenderPassDrawQuad* render_pass_quad =
4868 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4869 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4870 render_pass_quad->rect.ToString());
4871 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4872 render_pass_quad->mask_uv_rect.ToString());
4874 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4875 host_impl_->DidDrawAllLayers(frame);
4879 // Applying a DSF should change the render surface size, but won't affect
4880 // which part of the mask is used.
4881 device_scale_factor = 2.f;
4882 gfx::Size device_viewport =
4883 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4884 host_impl_->SetViewportSize(device_viewport);
4885 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4886 host_impl_->active_tree()->set_needs_update_draw_properties();
4888 LayerTreeHostImpl::FrameData frame;
4889 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4891 ASSERT_EQ(1u, frame.render_passes.size());
4892 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4893 ASSERT_EQ(DrawQuad::RENDER_PASS,
4894 frame.render_passes[0]->quad_list[0]->material);
4895 const RenderPassDrawQuad* render_pass_quad =
4896 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4897 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4898 render_pass_quad->rect.ToString());
4899 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4900 render_pass_quad->mask_uv_rect.ToString());
4902 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4903 host_impl_->DidDrawAllLayers(frame);
4907 // Applying an equivalent content scale on the content layer and the mask
4908 // should still result in the same part of the mask being used.
4909 gfx::Size content_bounds =
4910 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
4911 device_scale_factor));
4912 content_layer->SetContentBounds(content_bounds);
4913 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4914 mask_layer->SetContentBounds(content_bounds);
4915 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4916 host_impl_->active_tree()->set_needs_update_draw_properties();
4918 LayerTreeHostImpl::FrameData frame;
4919 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4921 ASSERT_EQ(1u, frame.render_passes.size());
4922 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4923 ASSERT_EQ(DrawQuad::RENDER_PASS,
4924 frame.render_passes[0]->quad_list[0]->material);
4925 const RenderPassDrawQuad* render_pass_quad =
4926 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4927 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4928 render_pass_quad->rect.ToString());
4929 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4930 render_pass_quad->mask_uv_rect.ToString());
4932 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4933 host_impl_->DidDrawAllLayers(frame);
4937 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
4938 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4939 // 50x50.
4941 scoped_ptr<LayerImpl> scoped_root =
4942 LayerImpl::Create(host_impl_->active_tree(), 1);
4943 LayerImpl* root = scoped_root.get();
4944 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4946 scoped_ptr<LayerImpl> scoped_content_layer =
4947 LayerImpl::Create(host_impl_->active_tree(), 3);
4948 LayerImpl* content_layer = scoped_content_layer.get();
4949 root->AddChild(scoped_content_layer.Pass());
4951 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4952 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4953 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4954 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4956 gfx::Size root_size(100, 100);
4957 root->SetBounds(root_size);
4958 root->SetContentBounds(root_size);
4959 root->SetPosition(gfx::PointF());
4961 gfx::Size layer_size(50, 50);
4962 content_layer->SetBounds(layer_size);
4963 content_layer->SetContentBounds(layer_size);
4964 content_layer->SetPosition(gfx::PointF());
4965 content_layer->SetDrawsContent(true);
4967 gfx::Size mask_size(100, 100);
4968 mask_layer->SetBounds(mask_size);
4969 mask_layer->SetContentBounds(mask_size);
4970 mask_layer->SetPosition(gfx::PointF());
4971 mask_layer->SetDrawsContent(true);
4973 // Check that the mask fills the surface.
4974 float device_scale_factor = 1.f;
4975 host_impl_->SetViewportSize(root_size);
4976 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4978 LayerTreeHostImpl::FrameData frame;
4979 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4981 ASSERT_EQ(1u, frame.render_passes.size());
4982 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4983 ASSERT_EQ(DrawQuad::RENDER_PASS,
4984 frame.render_passes[0]->quad_list[0]->material);
4985 const RenderPassDrawQuad* render_pass_quad =
4986 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4987 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4988 render_pass_quad->rect.ToString());
4989 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4990 render_pass_quad->mask_uv_rect.ToString());
4992 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4993 host_impl_->DidDrawAllLayers(frame);
4996 // Applying a DSF should change the render surface size, but won't affect
4997 // which part of the mask is used.
4998 device_scale_factor = 2.f;
4999 gfx::Size device_viewport =
5000 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5001 host_impl_->SetViewportSize(device_viewport);
5002 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5003 host_impl_->active_tree()->set_needs_update_draw_properties();
5005 LayerTreeHostImpl::FrameData frame;
5006 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5008 ASSERT_EQ(1u, frame.render_passes.size());
5009 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5010 ASSERT_EQ(DrawQuad::RENDER_PASS,
5011 frame.render_passes[0]->quad_list[0]->material);
5012 const RenderPassDrawQuad* render_pass_quad =
5013 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5014 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5015 render_pass_quad->rect.ToString());
5016 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5017 render_pass_quad->mask_uv_rect.ToString());
5019 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5020 host_impl_->DidDrawAllLayers(frame);
5023 // Applying an equivalent content scale on the content layer and the mask
5024 // should still result in the same part of the mask being used.
5025 gfx::Size layer_size_large =
5026 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5027 content_layer->SetContentBounds(layer_size_large);
5028 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5029 gfx::Size mask_size_large =
5030 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5031 mask_layer->SetContentBounds(mask_size_large);
5032 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5033 host_impl_->active_tree()->set_needs_update_draw_properties();
5035 LayerTreeHostImpl::FrameData frame;
5036 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5038 ASSERT_EQ(1u, frame.render_passes.size());
5039 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5040 ASSERT_EQ(DrawQuad::RENDER_PASS,
5041 frame.render_passes[0]->quad_list[0]->material);
5042 const RenderPassDrawQuad* render_pass_quad =
5043 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5044 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5045 render_pass_quad->rect.ToString());
5046 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5047 render_pass_quad->mask_uv_rect.ToString());
5049 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5050 host_impl_->DidDrawAllLayers(frame);
5053 // Applying a different contents scale to the mask layer means it will have
5054 // a larger texture, but it should use the same tex coords to cover the
5055 // layer it masks.
5056 mask_layer->SetContentBounds(mask_size);
5057 mask_layer->SetContentsScale(1.f, 1.f);
5058 host_impl_->active_tree()->set_needs_update_draw_properties();
5060 LayerTreeHostImpl::FrameData frame;
5061 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5063 ASSERT_EQ(1u, frame.render_passes.size());
5064 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5065 ASSERT_EQ(DrawQuad::RENDER_PASS,
5066 frame.render_passes[0]->quad_list[0]->material);
5067 const RenderPassDrawQuad* render_pass_quad =
5068 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5069 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5070 render_pass_quad->rect.ToString());
5071 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5072 render_pass_quad->mask_uv_rect.ToString());
5074 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5075 host_impl_->DidDrawAllLayers(frame);
5079 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
5080 // The replica's mask layer has bounds 100x100 but the replica is of a
5081 // layer with bounds 50x50.
5083 scoped_ptr<LayerImpl> scoped_root =
5084 LayerImpl::Create(host_impl_->active_tree(), 1);
5085 LayerImpl* root = scoped_root.get();
5086 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5088 scoped_ptr<LayerImpl> scoped_content_layer =
5089 LayerImpl::Create(host_impl_->active_tree(), 3);
5090 LayerImpl* content_layer = scoped_content_layer.get();
5091 root->AddChild(scoped_content_layer.Pass());
5093 scoped_ptr<LayerImpl> scoped_replica_layer =
5094 LayerImpl::Create(host_impl_->active_tree(), 2);
5095 LayerImpl* replica_layer = scoped_replica_layer.get();
5096 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5098 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5099 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5100 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5101 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5103 gfx::Size root_size(100, 100);
5104 root->SetBounds(root_size);
5105 root->SetContentBounds(root_size);
5106 root->SetPosition(gfx::PointF());
5108 gfx::Size layer_size(50, 50);
5109 content_layer->SetBounds(layer_size);
5110 content_layer->SetContentBounds(layer_size);
5111 content_layer->SetPosition(gfx::PointF());
5112 content_layer->SetDrawsContent(true);
5114 gfx::Size mask_size(100, 100);
5115 mask_layer->SetBounds(mask_size);
5116 mask_layer->SetContentBounds(mask_size);
5117 mask_layer->SetPosition(gfx::PointF());
5118 mask_layer->SetDrawsContent(true);
5120 // Check that the mask fills the surface.
5121 float device_scale_factor = 1.f;
5122 host_impl_->SetViewportSize(root_size);
5123 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5125 LayerTreeHostImpl::FrameData frame;
5126 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5128 ASSERT_EQ(1u, frame.render_passes.size());
5129 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5130 ASSERT_EQ(DrawQuad::RENDER_PASS,
5131 frame.render_passes[0]->quad_list[1]->material);
5132 const RenderPassDrawQuad* replica_quad =
5133 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5134 EXPECT_TRUE(replica_quad->is_replica);
5135 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5136 replica_quad->rect.ToString());
5137 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5138 replica_quad->mask_uv_rect.ToString());
5140 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5141 host_impl_->DidDrawAllLayers(frame);
5144 // Applying a DSF should change the render surface size, but won't affect
5145 // which part of the mask is used.
5146 device_scale_factor = 2.f;
5147 gfx::Size device_viewport =
5148 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5149 host_impl_->SetViewportSize(device_viewport);
5150 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5151 host_impl_->active_tree()->set_needs_update_draw_properties();
5153 LayerTreeHostImpl::FrameData frame;
5154 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5156 ASSERT_EQ(1u, frame.render_passes.size());
5157 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5158 ASSERT_EQ(DrawQuad::RENDER_PASS,
5159 frame.render_passes[0]->quad_list[1]->material);
5160 const RenderPassDrawQuad* replica_quad =
5161 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5162 EXPECT_TRUE(replica_quad->is_replica);
5163 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5164 replica_quad->rect.ToString());
5165 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5166 replica_quad->mask_uv_rect.ToString());
5168 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5169 host_impl_->DidDrawAllLayers(frame);
5172 // Applying an equivalent content scale on the content layer and the mask
5173 // should still result in the same part of the mask being used.
5174 gfx::Size layer_size_large =
5175 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5176 content_layer->SetContentBounds(layer_size_large);
5177 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5178 gfx::Size mask_size_large =
5179 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5180 mask_layer->SetContentBounds(mask_size_large);
5181 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5182 host_impl_->active_tree()->set_needs_update_draw_properties();
5184 LayerTreeHostImpl::FrameData frame;
5185 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5187 ASSERT_EQ(1u, frame.render_passes.size());
5188 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5189 ASSERT_EQ(DrawQuad::RENDER_PASS,
5190 frame.render_passes[0]->quad_list[1]->material);
5191 const RenderPassDrawQuad* replica_quad =
5192 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5193 EXPECT_TRUE(replica_quad->is_replica);
5194 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5195 replica_quad->rect.ToString());
5196 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5197 replica_quad->mask_uv_rect.ToString());
5199 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5200 host_impl_->DidDrawAllLayers(frame);
5203 // Applying a different contents scale to the mask layer means it will have
5204 // a larger texture, but it should use the same tex coords to cover the
5205 // layer it masks.
5206 mask_layer->SetContentBounds(mask_size);
5207 mask_layer->SetContentsScale(1.f, 1.f);
5208 host_impl_->active_tree()->set_needs_update_draw_properties();
5210 LayerTreeHostImpl::FrameData frame;
5211 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5213 ASSERT_EQ(1u, frame.render_passes.size());
5214 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5215 ASSERT_EQ(DrawQuad::RENDER_PASS,
5216 frame.render_passes[0]->quad_list[1]->material);
5217 const RenderPassDrawQuad* replica_quad =
5218 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5219 EXPECT_TRUE(replica_quad->is_replica);
5220 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5221 replica_quad->rect.ToString());
5222 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5223 replica_quad->mask_uv_rect.ToString());
5225 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5226 host_impl_->DidDrawAllLayers(frame);
5230 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
5231 // The replica is of a layer with bounds 50x50, but it has a child that causes
5232 // the surface bounds to be larger.
5234 scoped_ptr<LayerImpl> scoped_root =
5235 LayerImpl::Create(host_impl_->active_tree(), 1);
5236 LayerImpl* root = scoped_root.get();
5237 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5239 scoped_ptr<LayerImpl> scoped_content_layer =
5240 LayerImpl::Create(host_impl_->active_tree(), 2);
5241 LayerImpl* content_layer = scoped_content_layer.get();
5242 root->AddChild(scoped_content_layer.Pass());
5244 scoped_ptr<LayerImpl> scoped_content_child_layer =
5245 LayerImpl::Create(host_impl_->active_tree(), 3);
5246 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5247 content_layer->AddChild(scoped_content_child_layer.Pass());
5249 scoped_ptr<LayerImpl> scoped_replica_layer =
5250 LayerImpl::Create(host_impl_->active_tree(), 4);
5251 LayerImpl* replica_layer = scoped_replica_layer.get();
5252 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5254 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5255 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
5256 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5257 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5259 gfx::Size root_size(100, 100);
5260 root->SetBounds(root_size);
5261 root->SetContentBounds(root_size);
5262 root->SetPosition(gfx::PointF());
5264 gfx::Size layer_size(50, 50);
5265 content_layer->SetBounds(layer_size);
5266 content_layer->SetContentBounds(layer_size);
5267 content_layer->SetPosition(gfx::PointF());
5268 content_layer->SetDrawsContent(true);
5270 gfx::Size child_size(50, 50);
5271 content_child_layer->SetBounds(child_size);
5272 content_child_layer->SetContentBounds(child_size);
5273 content_child_layer->SetPosition(gfx::Point(50, 0));
5274 content_child_layer->SetDrawsContent(true);
5276 gfx::Size mask_size(50, 50);
5277 mask_layer->SetBounds(mask_size);
5278 mask_layer->SetContentBounds(mask_size);
5279 mask_layer->SetPosition(gfx::PointF());
5280 mask_layer->SetDrawsContent(true);
5282 float device_scale_factor = 1.f;
5283 host_impl_->SetViewportSize(root_size);
5284 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5286 LayerTreeHostImpl::FrameData frame;
5287 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5289 ASSERT_EQ(1u, frame.render_passes.size());
5290 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5292 // The surface is 100x50.
5293 ASSERT_EQ(DrawQuad::RENDER_PASS,
5294 frame.render_passes[0]->quad_list[0]->material);
5295 const RenderPassDrawQuad* render_pass_quad =
5296 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5297 EXPECT_FALSE(render_pass_quad->is_replica);
5298 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5299 render_pass_quad->rect.ToString());
5301 // The mask covers the owning layer only.
5302 ASSERT_EQ(DrawQuad::RENDER_PASS,
5303 frame.render_passes[0]->quad_list[1]->material);
5304 const RenderPassDrawQuad* replica_quad =
5305 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5306 EXPECT_TRUE(replica_quad->is_replica);
5307 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5308 replica_quad->rect.ToString());
5309 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
5310 replica_quad->mask_uv_rect.ToString());
5312 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5313 host_impl_->DidDrawAllLayers(frame);
5316 // Move the child to (-50, 0) instead. Now the mask should be moved to still
5317 // cover the layer being replicated.
5318 content_child_layer->SetPosition(gfx::Point(-50, 0));
5320 LayerTreeHostImpl::FrameData frame;
5321 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5323 ASSERT_EQ(1u, frame.render_passes.size());
5324 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5326 // The surface is 100x50 with its origin at (-50, 0).
5327 ASSERT_EQ(DrawQuad::RENDER_PASS,
5328 frame.render_passes[0]->quad_list[0]->material);
5329 const RenderPassDrawQuad* render_pass_quad =
5330 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5331 EXPECT_FALSE(render_pass_quad->is_replica);
5332 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5333 render_pass_quad->rect.ToString());
5335 // The mask covers the owning layer only.
5336 ASSERT_EQ(DrawQuad::RENDER_PASS,
5337 frame.render_passes[0]->quad_list[1]->material);
5338 const RenderPassDrawQuad* replica_quad =
5339 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5340 EXPECT_TRUE(replica_quad->is_replica);
5341 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5342 replica_quad->rect.ToString());
5343 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
5344 replica_quad->mask_uv_rect.ToString());
5346 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5347 host_impl_->DidDrawAllLayers(frame);
5351 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
5352 // The masked layer has bounds 50x50, but it has a child that causes
5353 // the surface bounds to be larger. It also has a parent that clips the
5354 // masked layer and its surface.
5356 scoped_ptr<LayerImpl> scoped_root =
5357 LayerImpl::Create(host_impl_->active_tree(), 1);
5358 LayerImpl* root = scoped_root.get();
5359 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5361 scoped_ptr<LayerImpl> scoped_clipping_layer =
5362 LayerImpl::Create(host_impl_->active_tree(), 2);
5363 LayerImpl* clipping_layer = scoped_clipping_layer.get();
5364 root->AddChild(scoped_clipping_layer.Pass());
5366 scoped_ptr<LayerImpl> scoped_content_layer =
5367 LayerImpl::Create(host_impl_->active_tree(), 3);
5368 LayerImpl* content_layer = scoped_content_layer.get();
5369 clipping_layer->AddChild(scoped_content_layer.Pass());
5371 scoped_ptr<LayerImpl> scoped_content_child_layer =
5372 LayerImpl::Create(host_impl_->active_tree(), 4);
5373 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5374 content_layer->AddChild(scoped_content_child_layer.Pass());
5376 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5377 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
5378 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5379 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5381 gfx::Size root_size(100, 100);
5382 root->SetBounds(root_size);
5383 root->SetContentBounds(root_size);
5384 root->SetPosition(gfx::PointF());
5386 gfx::Rect clipping_rect(20, 10, 10, 20);
5387 clipping_layer->SetBounds(clipping_rect.size());
5388 clipping_layer->SetContentBounds(clipping_rect.size());
5389 clipping_layer->SetPosition(clipping_rect.origin());
5390 clipping_layer->SetMasksToBounds(true);
5392 gfx::Size layer_size(50, 50);
5393 content_layer->SetBounds(layer_size);
5394 content_layer->SetContentBounds(layer_size);
5395 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
5396 content_layer->SetDrawsContent(true);
5398 gfx::Size child_size(50, 50);
5399 content_child_layer->SetBounds(child_size);
5400 content_child_layer->SetContentBounds(child_size);
5401 content_child_layer->SetPosition(gfx::Point(50, 0));
5402 content_child_layer->SetDrawsContent(true);
5404 gfx::Size mask_size(100, 100);
5405 mask_layer->SetBounds(mask_size);
5406 mask_layer->SetContentBounds(mask_size);
5407 mask_layer->SetPosition(gfx::PointF());
5408 mask_layer->SetDrawsContent(true);
5410 float device_scale_factor = 1.f;
5411 host_impl_->SetViewportSize(root_size);
5412 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5414 LayerTreeHostImpl::FrameData frame;
5415 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5417 ASSERT_EQ(1u, frame.render_passes.size());
5418 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5420 // The surface is clipped to 10x20.
5421 ASSERT_EQ(DrawQuad::RENDER_PASS,
5422 frame.render_passes[0]->quad_list[0]->material);
5423 const RenderPassDrawQuad* render_pass_quad =
5424 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5425 EXPECT_FALSE(render_pass_quad->is_replica);
5426 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
5427 render_pass_quad->rect.ToString());
5429 // The masked layer is 50x50, but the surface size is 10x20. So the texture
5430 // coords in the mask are scaled by 10/50 and 20/50.
5431 // The surface is clipped to (20,10) so the mask texture coords are offset
5432 // by 20/50 and 10/50
5433 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f),
5434 1.f / 50.f).ToString(),
5435 render_pass_quad->mask_uv_rect.ToString());
5437 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5438 host_impl_->DidDrawAllLayers(frame);
5442 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
5443 public:
5444 using GLRenderer::SetupQuadForAntialiasing;
5447 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
5448 // Due to precision issues (especially on Android), sometimes far
5449 // away quads can end up thinking they need AA.
5450 float device_scale_factor = 4.f / 3.f;
5451 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5452 gfx::Size root_size(2000, 1000);
5453 gfx::Size device_viewport_size =
5454 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
5455 host_impl_->SetViewportSize(device_viewport_size);
5457 host_impl_->CreatePendingTree();
5458 host_impl_->pending_tree()
5459 ->SetPageScaleFactorAndLimits(1.f, 1.f / 16.f, 16.f);
5461 scoped_ptr<LayerImpl> scoped_root =
5462 LayerImpl::Create(host_impl_->pending_tree(), 1);
5463 LayerImpl* root = scoped_root.get();
5465 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
5467 scoped_ptr<LayerImpl> scoped_scrolling_layer =
5468 LayerImpl::Create(host_impl_->pending_tree(), 2);
5469 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
5470 root->AddChild(scoped_scrolling_layer.Pass());
5472 gfx::Size content_layer_bounds(100000, 100);
5473 gfx::Size pile_tile_size(3000, 3000);
5474 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
5475 pile_tile_size, content_layer_bounds));
5477 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
5478 FakePictureLayerImpl::CreateWithPile(host_impl_->pending_tree(), 3, pile);
5479 LayerImpl* content_layer = scoped_content_layer.get();
5480 scrolling_layer->AddChild(scoped_content_layer.PassAs<LayerImpl>());
5481 content_layer->SetBounds(content_layer_bounds);
5482 content_layer->SetDrawsContent(true);
5484 root->SetBounds(root_size);
5486 gfx::Vector2d scroll_offset(100000, 0);
5487 scrolling_layer->SetScrollClipLayer(root->id());
5488 scrolling_layer->SetScrollOffset(scroll_offset);
5490 host_impl_->ActivateSyncTree();
5492 host_impl_->active_tree()->UpdateDrawProperties();
5493 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
5495 LayerTreeHostImpl::FrameData frame;
5496 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5498 ASSERT_EQ(1u, frame.render_passes.size());
5499 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
5500 const DrawQuad* quad = frame.render_passes[0]->quad_list[0];
5502 float edge[24];
5503 gfx::QuadF device_layer_quad;
5504 bool antialiased =
5505 GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
5506 quad->quadTransform(), quad, &device_layer_quad, edge);
5507 EXPECT_FALSE(antialiased);
5509 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5510 host_impl_->DidDrawAllLayers(frame);
5514 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
5515 public:
5516 CompositorFrameMetadataTest()
5517 : swap_buffers_complete_(0) {}
5519 virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {
5520 swap_buffers_complete_++;
5523 int swap_buffers_complete_;
5526 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
5527 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5529 LayerTreeHostImpl::FrameData frame;
5530 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5531 host_impl_->DrawLayers(&frame, base::TimeTicks());
5532 host_impl_->DidDrawAllLayers(frame);
5534 CompositorFrameAck ack;
5535 host_impl_->ReclaimResources(&ack);
5536 host_impl_->DidSwapBuffersComplete();
5537 EXPECT_EQ(swap_buffers_complete_, 1);
5540 class CountingSoftwareDevice : public SoftwareOutputDevice {
5541 public:
5542 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5544 virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
5545 ++frames_began_;
5546 return SoftwareOutputDevice::BeginPaint(damage_rect);
5548 virtual void EndPaint(SoftwareFrameData* frame_data) OVERRIDE {
5549 ++frames_ended_;
5550 SoftwareOutputDevice::EndPaint(frame_data);
5553 int frames_began_, frames_ended_;
5556 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
5557 // No main thread evictions in resourceless software mode.
5558 set_reduce_memory_result(false);
5559 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
5560 bool delegated_rendering = false;
5561 FakeOutputSurface* output_surface =
5562 FakeOutputSurface::CreateDeferredGL(
5563 scoped_ptr<SoftwareOutputDevice>(software_device),
5564 delegated_rendering).release();
5565 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5566 scoped_ptr<OutputSurface>(output_surface)));
5567 host_impl_->SetViewportSize(gfx::Size(50, 50));
5569 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5571 output_surface->set_forced_draw_to_software_device(true);
5572 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5574 EXPECT_EQ(0, software_device->frames_began_);
5575 EXPECT_EQ(0, software_device->frames_ended_);
5577 DrawFrame();
5579 EXPECT_EQ(1, software_device->frames_began_);
5580 EXPECT_EQ(1, software_device->frames_ended_);
5582 // Call other API methods that are likely to hit NULL pointer in this mode.
5583 EXPECT_TRUE(host_impl_->AsValue());
5584 EXPECT_TRUE(host_impl_->ActivationStateAsValue());
5587 TEST_F(LayerTreeHostImplTest,
5588 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
5589 set_reduce_memory_result(false);
5590 bool delegated_rendering = false;
5591 FakeOutputSurface* output_surface =
5592 FakeOutputSurface::CreateDeferredGL(
5593 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5594 delegated_rendering).release();
5595 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5596 scoped_ptr<OutputSurface>(output_surface)));
5598 output_surface->set_forced_draw_to_software_device(true);
5599 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5601 // SolidColorLayerImpl will be drawn.
5602 scoped_ptr<SolidColorLayerImpl> root_layer =
5603 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5605 // VideoLayerImpl will not be drawn.
5606 FakeVideoFrameProvider provider;
5607 scoped_ptr<VideoLayerImpl> video_layer =
5608 VideoLayerImpl::Create(host_impl_->active_tree(), 2, &provider);
5609 video_layer->SetBounds(gfx::Size(10, 10));
5610 video_layer->SetContentBounds(gfx::Size(10, 10));
5611 video_layer->SetDrawsContent(true);
5612 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
5613 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5615 LayerTreeHostImpl::FrameData frame;
5616 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5617 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5618 host_impl_->DidDrawAllLayers(frame);
5620 EXPECT_EQ(1u, frame.will_draw_layers.size());
5621 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
5624 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
5625 protected:
5626 virtual void SetUp() OVERRIDE {
5627 LayerTreeHostImplTest::SetUp();
5629 set_reduce_memory_result(false);
5631 bool delegated_rendering = false;
5632 scoped_ptr<FakeOutputSurface> output_surface(
5633 FakeOutputSurface::CreateDeferredGL(
5634 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5635 delegated_rendering));
5636 output_surface_ = output_surface.get();
5638 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5639 output_surface.PassAs<OutputSurface>()));
5641 scoped_ptr<SolidColorLayerImpl> root_layer =
5642 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5643 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5645 onscreen_context_provider_ = TestContextProvider::Create();
5648 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {
5649 did_update_renderer_capabilities_ = true;
5652 FakeOutputSurface* output_surface_;
5653 scoped_refptr<TestContextProvider> onscreen_context_provider_;
5654 bool did_update_renderer_capabilities_;
5658 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
5659 // Software draw.
5660 DrawFrame();
5662 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5664 // DeferredInitialize and hardware draw.
5665 did_update_renderer_capabilities_ = false;
5666 EXPECT_TRUE(
5667 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5668 EXPECT_EQ(onscreen_context_provider_,
5669 host_impl_->output_surface()->context_provider());
5670 EXPECT_TRUE(did_update_renderer_capabilities_);
5672 // Defer intialized GL draw.
5673 DrawFrame();
5675 // Revert back to software.
5676 did_update_renderer_capabilities_ = false;
5677 output_surface_->ReleaseGL();
5678 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5679 EXPECT_TRUE(did_update_renderer_capabilities_);
5681 // Software draw again.
5682 DrawFrame();
5685 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails) {
5686 // Software draw.
5687 DrawFrame();
5689 // Fail initialization of the onscreen context before the OutputSurface binds
5690 // it to the thread.
5691 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5693 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5695 // DeferredInitialize fails.
5696 did_update_renderer_capabilities_ = false;
5697 EXPECT_FALSE(
5698 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5699 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5700 EXPECT_FALSE(did_update_renderer_capabilities_);
5702 // Software draw again.
5703 DrawFrame();
5706 // Checks that we have a non-0 default allocation if we pass a context that
5707 // doesn't support memory management extensions.
5708 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5709 LayerTreeSettings settings;
5710 host_impl_ = LayerTreeHostImpl::Create(settings,
5711 this,
5712 &proxy_,
5713 &stats_instrumentation_,
5714 shared_bitmap_manager_.get(),
5717 scoped_ptr<OutputSurface> output_surface(
5718 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5719 host_impl_->InitializeRenderer(output_surface.Pass());
5720 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5723 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5724 ManagedMemoryPolicy policy1(
5725 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5726 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5727 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5728 int allow_nice_to_have_cutoff_value =
5729 ManagedMemoryPolicy::PriorityCutoffToValue(
5730 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
5731 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5732 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5734 // GPU rasterization should be disabled by default on the tree(s)
5735 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
5736 EXPECT_TRUE(host_impl_->pending_tree() == NULL);
5738 host_impl_->SetVisible(true);
5739 host_impl_->SetMemoryPolicy(policy1);
5740 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5741 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5743 host_impl_->SetVisible(false);
5744 EXPECT_EQ(0u, current_limit_bytes_);
5745 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5747 host_impl_->SetVisible(true);
5748 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5749 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5751 // Now enable GPU rasterization and test if we get nice to have cutoff,
5752 // when visible.
5753 LayerTreeSettings settings;
5754 settings.gpu_rasterization_enabled = true;
5755 host_impl_ = LayerTreeHostImpl::Create(
5756 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
5757 host_impl_->SetUseGpuRasterization(true);
5758 host_impl_->SetVisible(true);
5759 host_impl_->SetMemoryPolicy(policy1);
5760 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5761 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
5763 host_impl_->SetVisible(false);
5764 EXPECT_EQ(0u, current_limit_bytes_);
5765 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5768 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
5769 ASSERT_TRUE(host_impl_->active_tree());
5771 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5772 host_impl_->SetVisible(false);
5773 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5774 host_impl_->SetVisible(true);
5775 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5776 host_impl_->SetVisible(false);
5777 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5779 host_impl_->CreatePendingTree();
5780 host_impl_->ActivateSyncTree();
5782 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5783 host_impl_->SetVisible(true);
5784 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5787 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
5788 ASSERT_TRUE(host_impl_->active_tree());
5789 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
5791 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5792 host_impl_->SetUseGpuRasterization(false);
5793 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5794 host_impl_->SetUseGpuRasterization(true);
5795 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5796 host_impl_->SetUseGpuRasterization(false);
5797 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5799 host_impl_->CreatePendingTree();
5800 host_impl_->ActivateSyncTree();
5802 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5803 host_impl_->SetUseGpuRasterization(true);
5804 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5807 class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
5808 public:
5809 virtual void SetUp() OVERRIDE {
5810 LayerTreeSettings settings;
5811 settings.impl_side_painting = true;
5813 fake_host_impl_ = new FakeLayerTreeHostImpl(
5814 settings, &proxy_, shared_bitmap_manager_.get());
5815 host_impl_.reset(fake_host_impl_);
5816 host_impl_->InitializeRenderer(CreateOutputSurface());
5817 host_impl_->SetViewportSize(gfx::Size(10, 10));
5820 FakeLayerTreeHostImpl* fake_host_impl_;
5823 TEST_F(LayerTreeHostImplTestManageTiles, ManageTilesWhenInvisible) {
5824 fake_host_impl_->DidModifyTilePriorities();
5825 EXPECT_TRUE(fake_host_impl_->manage_tiles_needed());
5826 fake_host_impl_->SetVisible(false);
5827 EXPECT_FALSE(fake_host_impl_->manage_tiles_needed());
5830 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
5831 scoped_ptr<TestWebGraphicsContext3D> context =
5832 TestWebGraphicsContext3D::Create();
5833 TestWebGraphicsContext3D* context3d = context.get();
5834 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5835 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5837 EXPECT_EQ(0u, context3d->NumTextures());
5839 UIResourceId ui_resource_id = 1;
5840 bool is_opaque = false;
5841 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
5842 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5843 EXPECT_EQ(1u, context3d->NumTextures());
5844 ResourceProvider::ResourceId id1 =
5845 host_impl_->ResourceIdForUIResource(ui_resource_id);
5846 EXPECT_NE(0u, id1);
5848 // Multiple requests with the same id is allowed. The previous texture is
5849 // deleted.
5850 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5851 EXPECT_EQ(1u, context3d->NumTextures());
5852 ResourceProvider::ResourceId id2 =
5853 host_impl_->ResourceIdForUIResource(ui_resource_id);
5854 EXPECT_NE(0u, id2);
5855 EXPECT_NE(id1, id2);
5857 // Deleting invalid UIResourceId is allowed and does not change state.
5858 host_impl_->DeleteUIResource(-1);
5859 EXPECT_EQ(1u, context3d->NumTextures());
5861 // Should return zero for invalid UIResourceId. Number of textures should
5862 // not change.
5863 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
5864 EXPECT_EQ(1u, context3d->NumTextures());
5866 host_impl_->DeleteUIResource(ui_resource_id);
5867 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
5868 EXPECT_EQ(0u, context3d->NumTextures());
5870 // Should not change state for multiple deletion on one UIResourceId
5871 host_impl_->DeleteUIResource(ui_resource_id);
5872 EXPECT_EQ(0u, context3d->NumTextures());
5875 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
5876 scoped_ptr<TestWebGraphicsContext3D> context =
5877 TestWebGraphicsContext3D::Create();
5878 TestWebGraphicsContext3D* context3d = context.get();
5879 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5880 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5882 EXPECT_EQ(0u, context3d->NumTextures());
5884 gfx::Size size(4, 4);
5885 // SkImageInfo has no support for ETC1. The |info| below contains the right
5886 // total pixel size for the bitmap but not the right height and width. The
5887 // correct width/height are passed directly to UIResourceBitmap.
5888 SkImageInfo info =
5889 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
5890 skia::RefPtr<SkPixelRef> pixel_ref =
5891 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
5892 pixel_ref->setImmutable();
5893 UIResourceBitmap bitmap(pixel_ref, size);
5894 UIResourceId ui_resource_id = 1;
5895 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5896 EXPECT_EQ(1u, context3d->NumTextures());
5897 ResourceProvider::ResourceId id1 =
5898 host_impl_->ResourceIdForUIResource(ui_resource_id);
5899 EXPECT_NE(0u, id1);
5902 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
5905 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
5906 scoped_refptr<TestContextProvider> context_provider =
5907 TestContextProvider::Create();
5909 CreateHostImpl(
5910 DefaultSettings(),
5911 FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>());
5913 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5915 ScopedPtrVector<CopyOutputRequest> requests;
5916 requests.push_back(CopyOutputRequest::CreateRequest(
5917 base::Bind(&ShutdownReleasesContext_Callback)));
5919 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
5921 LayerTreeHostImpl::FrameData frame;
5922 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5923 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5924 host_impl_->DidDrawAllLayers(frame);
5926 // The CopyOutputResult's callback has a ref on the ContextProvider and a
5927 // texture in a texture mailbox.
5928 EXPECT_FALSE(context_provider->HasOneRef());
5929 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
5931 host_impl_.reset();
5933 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
5934 // released, and the texture deleted.
5935 EXPECT_TRUE(context_provider->HasOneRef());
5936 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
5939 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
5940 // When flinging via touch, only the child should scroll (we should not
5941 // bubble).
5942 gfx::Size surface_size(10, 10);
5943 gfx::Size content_size(20, 20);
5944 scoped_ptr<LayerImpl> root_clip =
5945 LayerImpl::Create(host_impl_->active_tree(), 3);
5946 scoped_ptr<LayerImpl> root =
5947 CreateScrollableLayer(1, content_size, root_clip.get());
5948 root->SetIsContainerForFixedPositionLayers(true);
5949 scoped_ptr<LayerImpl> child =
5950 CreateScrollableLayer(2, content_size, root_clip.get());
5952 root->AddChild(child.Pass());
5953 int root_id = root->id();
5954 root_clip->AddChild(root.Pass());
5956 host_impl_->SetViewportSize(surface_size);
5957 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
5958 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
5959 host_impl_->active_tree()->DidBecomeActive();
5960 DrawFrame();
5962 EXPECT_EQ(InputHandler::ScrollStarted,
5963 host_impl_->ScrollBegin(gfx::Point(),
5964 InputHandler::Gesture));
5966 EXPECT_EQ(InputHandler::ScrollStarted,
5967 host_impl_->FlingScrollBegin());
5969 gfx::Vector2d scroll_delta(0, 100);
5970 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5971 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5973 host_impl_->ScrollEnd();
5975 scoped_ptr<ScrollAndScaleSet> scroll_info =
5976 host_impl_->ProcessScrollDeltas();
5978 // Only the child should have scrolled.
5979 ASSERT_EQ(1u, scroll_info->scrolls.size());
5980 ExpectNone(*scroll_info.get(), root_id);
5984 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
5985 // Scroll a child layer beyond its maximum scroll range and make sure the
5986 // the scroll doesn't bubble up to the parent layer.
5987 gfx::Size surface_size(10, 10);
5988 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
5989 scoped_ptr<LayerImpl> root_scrolling =
5990 CreateScrollableLayer(2, surface_size, root.get());
5992 scoped_ptr<LayerImpl> grand_child =
5993 CreateScrollableLayer(4, surface_size, root.get());
5994 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
5996 scoped_ptr<LayerImpl> child =
5997 CreateScrollableLayer(3, surface_size, root.get());
5998 child->SetScrollOffset(gfx::Vector2d(0, 4));
5999 child->AddChild(grand_child.Pass());
6001 root_scrolling->AddChild(child.Pass());
6002 root->AddChild(root_scrolling.Pass());
6003 host_impl_->active_tree()->SetRootLayer(root.Pass());
6004 host_impl_->active_tree()->DidBecomeActive();
6005 host_impl_->SetViewportSize(surface_size);
6006 DrawFrame();
6008 scoped_ptr<ScrollAndScaleSet> scroll_info;
6009 LayerImpl* child =
6010 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6011 LayerImpl* grand_child = child->children()[0];
6013 gfx::Vector2d scroll_delta(0, -2);
6014 EXPECT_EQ(InputHandler::ScrollStarted,
6015 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6016 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6018 // The grand child should have scrolled up to its limit.
6019 scroll_info = host_impl_->ProcessScrollDeltas();
6020 ASSERT_EQ(1u, scroll_info->scrolls.size());
6021 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6022 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6024 // The child should have received the bubbled delta, but the locked
6025 // scrolling layer should remain set as the grand child.
6026 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6027 scroll_info = host_impl_->ProcessScrollDeltas();
6028 ASSERT_EQ(2u, scroll_info->scrolls.size());
6029 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6030 ExpectContains(*scroll_info, child->id(), scroll_delta);
6031 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6033 // The first |ScrollBy| after the fling should re-lock the scrolling
6034 // layer to the first layer that scrolled, which is the child.
6035 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6036 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6037 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6039 // The child should have scrolled up to its limit.
6040 scroll_info = host_impl_->ProcessScrollDeltas();
6041 ASSERT_EQ(2u, scroll_info->scrolls.size());
6042 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6043 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
6045 // As the locked layer is at it's limit, no further scrolling can occur.
6046 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6047 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6048 host_impl_->ScrollEnd();
6052 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6053 // When flinging via wheel, the root should eventually scroll (we should
6054 // bubble).
6055 gfx::Size surface_size(10, 10);
6056 gfx::Size content_size(20, 20);
6057 scoped_ptr<LayerImpl> root_clip =
6058 LayerImpl::Create(host_impl_->active_tree(), 3);
6059 scoped_ptr<LayerImpl> root_scroll =
6060 CreateScrollableLayer(1, content_size, root_clip.get());
6061 int root_scroll_id = root_scroll->id();
6062 scoped_ptr<LayerImpl> child =
6063 CreateScrollableLayer(2, content_size, root_clip.get());
6065 root_scroll->AddChild(child.Pass());
6066 root_clip->AddChild(root_scroll.Pass());
6068 host_impl_->SetViewportSize(surface_size);
6069 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6070 host_impl_->active_tree()->DidBecomeActive();
6071 DrawFrame();
6073 EXPECT_EQ(InputHandler::ScrollStarted,
6074 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6076 EXPECT_EQ(InputHandler::ScrollStarted,
6077 host_impl_->FlingScrollBegin());
6079 gfx::Vector2d scroll_delta(0, 100);
6080 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6081 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6083 host_impl_->ScrollEnd();
6085 scoped_ptr<ScrollAndScaleSet> scroll_info =
6086 host_impl_->ProcessScrollDeltas();
6088 // The root should have scrolled.
6089 ASSERT_EQ(2u, scroll_info->scrolls.size());
6090 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
6094 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6095 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6096 // we should return ScrollUnknown.
6097 gfx::Size content_size(100, 100);
6098 SetupScrollAndContentsLayers(content_size);
6100 int scroll_layer_id = 2;
6101 LayerImpl* scroll_layer =
6102 host_impl_->active_tree()->LayerById(scroll_layer_id);
6103 scroll_layer->SetDrawsContent(true);
6105 int page_scale_layer_id = 5;
6106 LayerImpl* page_scale_layer =
6107 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6109 int occluder_layer_id = 6;
6110 scoped_ptr<LayerImpl> occluder_layer =
6111 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6112 occluder_layer->SetDrawsContent(true);
6113 occluder_layer->SetBounds(content_size);
6114 occluder_layer->SetContentBounds(content_size);
6115 occluder_layer->SetPosition(gfx::PointF());
6117 // The parent of the occluder is *above* the scroller.
6118 page_scale_layer->AddChild(occluder_layer.Pass());
6120 DrawFrame();
6122 EXPECT_EQ(InputHandler::ScrollUnknown,
6123 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6126 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6127 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6128 // is not the first scroller we encounter when walking up from the layer, we
6129 // should also return ScrollUnknown.
6130 gfx::Size content_size(100, 100);
6131 SetupScrollAndContentsLayers(content_size);
6133 int scroll_layer_id = 2;
6134 LayerImpl* scroll_layer =
6135 host_impl_->active_tree()->LayerById(scroll_layer_id);
6136 scroll_layer->SetDrawsContent(true);
6138 int occluder_layer_id = 6;
6139 scoped_ptr<LayerImpl> occluder_layer =
6140 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6141 occluder_layer->SetDrawsContent(true);
6142 occluder_layer->SetBounds(content_size);
6143 occluder_layer->SetContentBounds(content_size);
6144 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6146 int child_scroll_clip_layer_id = 7;
6147 scoped_ptr<LayerImpl> child_scroll_clip =
6148 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6150 int child_scroll_layer_id = 8;
6151 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6152 child_scroll_layer_id, content_size, child_scroll_clip.get());
6154 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6156 child_scroll->AddChild(occluder_layer.Pass());
6157 scroll_layer->AddChild(child_scroll.Pass());
6159 DrawFrame();
6161 EXPECT_EQ(InputHandler::ScrollUnknown,
6162 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6165 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) {
6166 gfx::Size content_size(100, 100);
6167 SetupScrollAndContentsLayers(content_size);
6169 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6171 int scroll_layer_id = 2;
6172 LayerImpl* scroll_layer =
6173 host_impl_->active_tree()->LayerById(scroll_layer_id);
6175 int child_scroll_layer_id = 7;
6176 scoped_ptr<LayerImpl> child_scroll =
6177 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6178 child_scroll->SetDrawsContent(false);
6180 scroll_layer->AddChild(child_scroll.Pass());
6182 DrawFrame();
6184 // We should not have scrolled |child_scroll| even though we technically "hit"
6185 // it. The reason for this is that if the scrolling the scroll would not move
6186 // any layer that is a drawn RSLL member, then we can ignore the hit.
6188 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6189 // overscrolling the inner viewport.
6190 EXPECT_EQ(InputHandler::ScrollStarted,
6191 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6193 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6196 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6197 // This test case is very similar to the one above with one key difference:
6198 // the invisible scroller has a scroll child that is indeed draw contents.
6199 // If we attempt to initiate a gesture scroll off of the visible scroll child
6200 // we should still start the scroll child.
6201 gfx::Size content_size(100, 100);
6202 SetupScrollAndContentsLayers(content_size);
6204 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6206 int scroll_layer_id = 2;
6207 LayerImpl* scroll_layer =
6208 host_impl_->active_tree()->LayerById(scroll_layer_id);
6210 int scroll_child_id = 6;
6211 scoped_ptr<LayerImpl> scroll_child =
6212 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6213 scroll_child->SetDrawsContent(true);
6214 scroll_child->SetBounds(content_size);
6215 scroll_child->SetContentBounds(content_size);
6216 // Move the scroll child so it's not hit by our test point.
6217 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6219 int invisible_scroll_layer_id = 7;
6220 scoped_ptr<LayerImpl> invisible_scroll =
6221 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6222 invisible_scroll->SetDrawsContent(false);
6224 int container_id = 8;
6225 scoped_ptr<LayerImpl> container =
6226 LayerImpl::Create(host_impl_->active_tree(), container_id);
6228 scoped_ptr<std::set<LayerImpl*> > scroll_children(new std::set<LayerImpl*>());
6229 scroll_children->insert(scroll_child.get());
6230 invisible_scroll->SetScrollChildren(scroll_children.release());
6232 scroll_child->SetScrollParent(invisible_scroll.get());
6234 container->AddChild(invisible_scroll.Pass());
6235 container->AddChild(scroll_child.Pass());
6237 scroll_layer->AddChild(container.Pass());
6239 DrawFrame();
6241 // We should not have scrolled |child_scroll| even though we technically "hit"
6242 // it. The reason for this is that if the scrolling the scroll would not move
6243 // any layer that is a drawn RSLL member, then we can ignore the hit.
6245 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6246 // overscrolling the inner viewport.
6247 EXPECT_EQ(InputHandler::ScrollStarted,
6248 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6250 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6253 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6254 // to CompositorFrameMetadata after SwapBuffers();
6255 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6256 scoped_ptr<SolidColorLayerImpl> root =
6257 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6258 root->SetPosition(gfx::PointF());
6259 root->SetBounds(gfx::Size(10, 10));
6260 root->SetContentBounds(gfx::Size(10, 10));
6261 root->SetDrawsContent(true);
6263 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
6265 FakeOutputSurface* fake_output_surface =
6266 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6268 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6269 fake_output_surface->last_sent_frame().metadata.latency_info;
6270 EXPECT_TRUE(metadata_latency_before.empty());
6272 ui::LatencyInfo latency_info;
6273 latency_info.AddLatencyNumber(
6274 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6275 scoped_ptr<SwapPromise> swap_promise(
6276 new LatencyInfoSwapPromise(latency_info));
6277 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
6278 host_impl_->SetNeedsRedraw();
6280 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6281 LayerTreeHostImpl::FrameData frame;
6282 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6283 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6284 host_impl_->DidDrawAllLayers(frame);
6285 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6287 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6288 fake_output_surface->last_sent_frame().metadata.latency_info;
6289 EXPECT_EQ(1u, metadata_latency_after.size());
6290 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6291 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6294 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
6295 int root_layer_id = 1;
6296 scoped_ptr<SolidColorLayerImpl> root =
6297 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
6298 root->SetPosition(gfx::PointF());
6299 root->SetBounds(gfx::Size(10, 10));
6300 root->SetContentBounds(gfx::Size(10, 10));
6301 root->SetDrawsContent(true);
6303 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
6305 // Ensure the default frame selection bounds are empty.
6306 FakeOutputSurface* fake_output_surface =
6307 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6308 const ViewportSelectionBound& selection_anchor_before =
6309 fake_output_surface->last_sent_frame().metadata.selection_anchor;
6310 const ViewportSelectionBound& selection_focus_before =
6311 fake_output_surface->last_sent_frame().metadata.selection_focus;
6312 EXPECT_EQ(ViewportSelectionBound(), selection_anchor_before);
6313 EXPECT_EQ(ViewportSelectionBound(), selection_focus_before);
6315 // Plumb the layer-local selection bounds.
6316 gfx::Rect selection_rect(5, 0, 0, 5);
6317 LayerSelectionBound anchor, focus;
6318 anchor.type = SELECTION_BOUND_CENTER;
6319 anchor.layer_id = root_layer_id;
6320 anchor.layer_rect = selection_rect;
6321 focus = anchor;
6322 host_impl_->active_tree()->RegisterSelection(anchor, focus);
6324 // Trigger a draw-swap sequence.
6325 host_impl_->SetNeedsRedraw();
6327 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6328 LayerTreeHostImpl::FrameData frame;
6329 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6330 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6331 host_impl_->DidDrawAllLayers(frame);
6332 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6334 // Ensure the selection bounds have propagated to the frame metadata.
6335 const ViewportSelectionBound& selection_anchor_after =
6336 fake_output_surface->last_sent_frame().metadata.selection_anchor;
6337 const ViewportSelectionBound& selection_focus_after =
6338 fake_output_surface->last_sent_frame().metadata.selection_focus;
6339 EXPECT_EQ(anchor.type, selection_anchor_after.type);
6340 EXPECT_EQ(focus.type, selection_focus_after.type);
6341 EXPECT_EQ(selection_rect, selection_anchor_after.viewport_rect);
6342 EXPECT_EQ(selection_rect, selection_anchor_after.viewport_rect);
6343 EXPECT_TRUE(selection_anchor_after.visible);
6344 EXPECT_TRUE(selection_anchor_after.visible);
6347 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
6348 public:
6349 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
6350 LayerTreeHostImpl* layer_tree_host_impl,
6351 int* set_needs_commit_count,
6352 int* set_needs_redraw_count)
6353 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
6354 set_needs_commit_count_(set_needs_commit_count),
6355 set_needs_redraw_count_(set_needs_redraw_count) {}
6357 virtual ~SimpleSwapPromiseMonitor() {}
6359 virtual void OnSetNeedsCommitOnMain() OVERRIDE {
6360 (*set_needs_commit_count_)++;
6363 virtual void OnSetNeedsRedrawOnImpl() OVERRIDE {
6364 (*set_needs_redraw_count_)++;
6367 private:
6368 int* set_needs_commit_count_;
6369 int* set_needs_redraw_count_;
6372 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
6373 int set_needs_commit_count = 0;
6374 int set_needs_redraw_count = 0;
6377 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6378 new SimpleSwapPromiseMonitor(NULL,
6379 host_impl_.get(),
6380 &set_needs_commit_count,
6381 &set_needs_redraw_count));
6382 host_impl_->SetNeedsRedraw();
6383 EXPECT_EQ(0, set_needs_commit_count);
6384 EXPECT_EQ(1, set_needs_redraw_count);
6387 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6388 // monitored.
6389 host_impl_->SetNeedsRedraw();
6390 EXPECT_EQ(0, set_needs_commit_count);
6391 EXPECT_EQ(1, set_needs_redraw_count);
6394 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6395 new SimpleSwapPromiseMonitor(NULL,
6396 host_impl_.get(),
6397 &set_needs_commit_count,
6398 &set_needs_redraw_count));
6399 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
6400 EXPECT_EQ(0, set_needs_commit_count);
6401 EXPECT_EQ(2, set_needs_redraw_count);
6405 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6406 new SimpleSwapPromiseMonitor(NULL,
6407 host_impl_.get(),
6408 &set_needs_commit_count,
6409 &set_needs_redraw_count));
6410 // Empty damage rect won't signal the monitor.
6411 host_impl_->SetNeedsRedrawRect(gfx::Rect());
6412 EXPECT_EQ(0, set_needs_commit_count);
6413 EXPECT_EQ(2, set_needs_redraw_count);
6417 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
6418 public:
6419 virtual void SetUp() OVERRIDE {
6420 LayerTreeSettings settings = DefaultSettings();
6421 settings.calculate_top_controls_position = true;
6422 settings.top_controls_height = top_controls_height_;
6423 CreateHostImpl(settings, CreateOutputSurface());
6426 protected:
6427 static const int top_controls_height_;
6430 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
6432 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
6433 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6434 ->SetScrollOffset(gfx::Vector2d(0, 10));
6435 host_impl_->Animate(base::TimeTicks());
6436 EXPECT_FALSE(did_request_redraw_);
6439 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
6440 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6441 ->SetScrollOffset(gfx::Vector2d(0, 10));
6442 host_impl_->DidChangeTopControlsPosition();
6443 EXPECT_TRUE(did_request_animate_);
6444 EXPECT_TRUE(did_request_redraw_);
6447 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
6448 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6449 host_impl_->SetViewportSize(gfx::Size(100, 100));
6450 DrawFrame();
6452 EXPECT_EQ(InputHandler::ScrollStarted,
6453 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6454 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6455 EXPECT_EQ(gfx::Vector2dF().ToString(),
6456 scroll_layer->TotalScrollOffset().ToString());
6458 // Scroll just the top controls and verify that the scroll succeeds.
6459 const float residue = 10;
6460 float offset = top_controls_height_ - residue;
6461 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6462 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->controls_top_offset());
6463 EXPECT_EQ(gfx::Vector2dF().ToString(),
6464 scroll_layer->TotalScrollOffset().ToString());
6466 // Scroll across the boundary
6467 const float content_scroll = 20;
6468 offset = residue + content_scroll;
6469 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6470 EXPECT_EQ(-top_controls_height_,
6471 host_impl_->top_controls_manager()->controls_top_offset());
6472 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
6473 scroll_layer->TotalScrollOffset().ToString());
6475 // Now scroll back to the top of the content
6476 offset = -content_scroll;
6477 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6478 EXPECT_EQ(-top_controls_height_,
6479 host_impl_->top_controls_manager()->controls_top_offset());
6480 EXPECT_EQ(gfx::Vector2dF().ToString(),
6481 scroll_layer->TotalScrollOffset().ToString());
6483 // And scroll the top controls completely into view
6484 offset = -top_controls_height_;
6485 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6486 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6487 EXPECT_EQ(gfx::Vector2dF().ToString(),
6488 scroll_layer->TotalScrollOffset().ToString());
6490 // And attempt to scroll past the end
6491 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6492 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6493 EXPECT_EQ(gfx::Vector2dF().ToString(),
6494 scroll_layer->TotalScrollOffset().ToString());
6496 host_impl_->ScrollEnd();
6499 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
6500 public:
6501 void SetupVirtualViewportLayers(const gfx::Size& content_size,
6502 const gfx::Size& outer_viewport,
6503 const gfx::Size& inner_viewport) {
6504 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
6505 const int kOuterViewportClipLayerId = 6;
6506 const int kOuterViewportScrollLayerId = 7;
6507 const int kInnerViewportScrollLayerId = 2;
6508 const int kInnerViewportClipLayerId = 4;
6509 const int kPageScaleLayerId = 5;
6511 scoped_ptr<LayerImpl> inner_scroll =
6512 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
6513 inner_scroll->SetIsContainerForFixedPositionLayers(true);
6514 inner_scroll->SetScrollOffset(gfx::Vector2d());
6516 scoped_ptr<LayerImpl> inner_clip =
6517 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
6518 inner_clip->SetBounds(inner_viewport);
6520 scoped_ptr<LayerImpl> page_scale =
6521 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
6523 inner_scroll->SetScrollClipLayer(inner_clip->id());
6524 inner_scroll->SetBounds(outer_viewport);
6525 inner_scroll->SetContentBounds(outer_viewport);
6526 inner_scroll->SetPosition(gfx::PointF());
6528 scoped_ptr<LayerImpl> outer_clip =
6529 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
6530 outer_clip->SetBounds(outer_viewport);
6531 outer_clip->SetIsContainerForFixedPositionLayers(true);
6533 scoped_ptr<LayerImpl> outer_scroll =
6534 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
6535 outer_scroll->SetScrollClipLayer(outer_clip->id());
6536 outer_scroll->SetScrollOffset(gfx::Vector2d());
6537 outer_scroll->SetBounds(content_size);
6538 outer_scroll->SetContentBounds(content_size);
6539 outer_scroll->SetPosition(gfx::PointF());
6541 scoped_ptr<LayerImpl> contents =
6542 LayerImpl::Create(layer_tree_impl, 8);
6543 contents->SetDrawsContent(true);
6544 contents->SetBounds(content_size);
6545 contents->SetContentBounds(content_size);
6546 contents->SetPosition(gfx::PointF());
6548 outer_scroll->AddChild(contents.Pass());
6549 outer_clip->AddChild(outer_scroll.Pass());
6550 inner_scroll->AddChild(outer_clip.Pass());
6551 page_scale->AddChild(inner_scroll.Pass());
6552 inner_clip->AddChild(page_scale.Pass());
6554 layer_tree_impl->SetRootLayer(inner_clip.Pass());
6555 layer_tree_impl->SetViewportLayersFromIds(kPageScaleLayerId,
6556 kInnerViewportScrollLayerId, kOuterViewportScrollLayerId);
6558 host_impl_->active_tree()->DidBecomeActive();
6562 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
6563 gfx::Size content_size = gfx::Size(100, 160);
6564 gfx::Size outer_viewport = gfx::Size(50, 80);
6565 gfx::Size inner_viewport = gfx::Size(25, 40);
6567 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
6569 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
6570 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
6571 DrawFrame();
6573 gfx::Vector2dF inner_expected;
6574 gfx::Vector2dF outer_expected;
6575 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6576 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6578 // Make sure the fling goes to the outer viewport first
6579 EXPECT_EQ(InputHandler::ScrollStarted,
6580 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6581 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6583 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
6584 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6585 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6587 host_impl_->ScrollEnd();
6589 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6590 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6592 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
6593 EXPECT_EQ(InputHandler::ScrollStarted,
6594 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6595 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6597 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6598 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6600 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6601 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6603 host_impl_->ScrollEnd();
6605 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6606 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6610 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
6611 public:
6612 virtual void SetUp() OVERRIDE {
6613 LayerTreeSettings settings = DefaultSettings();
6614 settings.max_memory_for_prepaint_percentage = 50;
6615 CreateHostImpl(settings, CreateOutputSurface());
6619 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
6620 // Set up a memory policy and percentages which could cause
6621 // 32-bit integer overflows.
6622 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
6624 // Verify implicit limits are calculated correctly with no overflows
6625 host_impl_->SetMemoryPolicy(mem_policy);
6626 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
6627 300u * 1024u * 1024u);
6628 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
6629 150u * 1024u * 1024u);
6632 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
6633 const gfx::Size layer_size(100, 100);
6634 gfx::Transform external_transform;
6635 const gfx::Rect external_viewport(layer_size);
6636 const gfx::Rect external_clip(layer_size);
6637 const bool valid_for_tile_management = true;
6638 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
6640 host_impl_->SetExternalDrawConstraints(external_transform,
6641 external_viewport,
6642 external_clip,
6643 valid_for_tile_management);
6644 DrawFrame();
6645 EXPECT_TRANSFORMATION_MATRIX_EQ(
6646 external_transform, layer->draw_properties().target_space_transform);
6648 external_transform.Translate(20, 20);
6649 host_impl_->SetExternalDrawConstraints(external_transform,
6650 external_viewport,
6651 external_clip,
6652 valid_for_tile_management);
6653 DrawFrame();
6654 EXPECT_TRANSFORMATION_MATRIX_EQ(
6655 external_transform, layer->draw_properties().target_space_transform);
6658 } // namespace
6659 } // namespace cc