Lots of random cleanups, mostly for native_theme_win.cc:
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blob842a7977b59cbe88bd2559cffe46655980434335
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);
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, ScrollWithSwapPromises) {
975 ui::LatencyInfo latency_info;
976 latency_info.trace_id = 1234;
977 scoped_ptr<SwapPromise> swap_promise(
978 new LatencyInfoSwapPromise(latency_info));
980 SetupScrollAndContentsLayers(gfx::Size(100, 100));
981 EXPECT_EQ(InputHandler::ScrollStarted,
982 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
983 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
984 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
985 host_impl_->ScrollEnd();
987 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
988 EXPECT_EQ(1u, scroll_info->swap_promises.size());
989 EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId());
992 TEST_F(LayerTreeHostImplTest, MasksToBoundsDoesntClobberInnerContainerSize) {
993 SetupScrollAndContentsLayers(gfx::Size(100, 100));
994 host_impl_->SetViewportSize(gfx::Size(50, 50));
995 DrawFrame();
997 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
998 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
999 DCHECK(scroll_layer);
1001 float min_page_scale = 1.f;
1002 float max_page_scale = 4.f;
1003 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1004 min_page_scale,
1005 max_page_scale);
1007 // If the container's masks_to_bounds is false, the viewport size should
1008 // overwrite the inner viewport container layer's size.
1010 EXPECT_EQ(gfx::Size(50, 50),
1011 container_layer->bounds());
1012 container_layer->SetMasksToBounds(false);
1014 container_layer->SetBounds(gfx::Size(30, 25));
1015 EXPECT_EQ(gfx::Size(30, 25),
1016 container_layer->bounds());
1018 // This should cause a reset of the inner viewport container layer's bounds.
1019 host_impl_->DidChangeTopControlsPosition();
1021 EXPECT_EQ(gfx::Size(50, 50),
1022 container_layer->bounds());
1025 host_impl_->SetViewportSize(gfx::Size(50, 50));
1026 container_layer->SetBounds(gfx::Size(50, 50));
1028 // If the container's masks_to_bounds is true, the viewport size should
1029 // *NOT* overwrite the inner viewport container layer's size.
1031 EXPECT_EQ(gfx::Size(50, 50),
1032 container_layer->bounds());
1033 container_layer->SetMasksToBounds(true);
1035 container_layer->SetBounds(gfx::Size(30, 25));
1036 EXPECT_EQ(gfx::Size(30, 25),
1037 container_layer->bounds());
1039 // This should cause a reset of the inner viewport container layer's bounds.
1040 host_impl_->DidChangeTopControlsPosition();
1042 EXPECT_EQ(gfx::Size(30, 25),
1043 container_layer->bounds());
1047 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1048 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1049 host_impl_->SetViewportSize(gfx::Size(50, 50));
1050 DrawFrame();
1052 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1053 DCHECK(scroll_layer);
1055 float min_page_scale = 1.f;
1056 float max_page_scale = 4.f;
1058 // Basic pinch zoom in gesture
1060 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1061 min_page_scale,
1062 max_page_scale);
1063 scroll_layer->SetScrollDelta(gfx::Vector2d());
1065 float page_scale_delta = 2.f;
1066 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1067 host_impl_->PinchGestureBegin();
1068 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1069 host_impl_->PinchGestureEnd();
1070 host_impl_->ScrollEnd();
1071 EXPECT_FALSE(did_request_animate_);
1072 EXPECT_TRUE(did_request_redraw_);
1073 EXPECT_TRUE(did_request_commit_);
1075 scoped_ptr<ScrollAndScaleSet> scroll_info =
1076 host_impl_->ProcessScrollDeltas();
1077 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1080 // Zoom-in clamping
1082 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1083 min_page_scale,
1084 max_page_scale);
1085 scroll_layer->SetScrollDelta(gfx::Vector2d());
1086 float page_scale_delta = 10.f;
1088 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1089 host_impl_->PinchGestureBegin();
1090 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1091 host_impl_->PinchGestureEnd();
1092 host_impl_->ScrollEnd();
1094 scoped_ptr<ScrollAndScaleSet> scroll_info =
1095 host_impl_->ProcessScrollDeltas();
1096 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1099 // Zoom-out clamping
1101 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1102 min_page_scale,
1103 max_page_scale);
1104 scroll_layer->SetScrollDelta(gfx::Vector2d());
1105 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1107 float page_scale_delta = 0.1f;
1108 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1109 host_impl_->PinchGestureBegin();
1110 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1111 host_impl_->PinchGestureEnd();
1112 host_impl_->ScrollEnd();
1114 scoped_ptr<ScrollAndScaleSet> scroll_info =
1115 host_impl_->ProcessScrollDeltas();
1116 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1118 EXPECT_TRUE(scroll_info->scrolls.empty());
1121 // Two-finger panning should not happen based on pinch events only
1123 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1124 min_page_scale,
1125 max_page_scale);
1126 scroll_layer->SetScrollDelta(gfx::Vector2d());
1127 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1129 float page_scale_delta = 1.f;
1130 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1131 host_impl_->PinchGestureBegin();
1132 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1133 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1134 host_impl_->PinchGestureEnd();
1135 host_impl_->ScrollEnd();
1137 scoped_ptr<ScrollAndScaleSet> scroll_info =
1138 host_impl_->ProcessScrollDeltas();
1139 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1140 EXPECT_TRUE(scroll_info->scrolls.empty());
1143 // Two-finger panning should work with interleaved scroll events
1145 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1146 min_page_scale,
1147 max_page_scale);
1148 scroll_layer->SetScrollDelta(gfx::Vector2d());
1149 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1151 float page_scale_delta = 1.f;
1152 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1153 host_impl_->PinchGestureBegin();
1154 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1155 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1156 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1157 host_impl_->PinchGestureEnd();
1158 host_impl_->ScrollEnd();
1160 scoped_ptr<ScrollAndScaleSet> scroll_info =
1161 host_impl_->ProcessScrollDeltas();
1162 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1163 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1166 // Two-finger panning should work when starting fully zoomed out.
1168 host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
1169 0.5f,
1170 4.f);
1171 scroll_layer->SetScrollDelta(gfx::Vector2d());
1172 scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
1174 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
1175 host_impl_->PinchGestureBegin();
1176 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1177 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1178 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1179 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1180 host_impl_->PinchGestureEnd();
1181 host_impl_->ScrollEnd();
1183 scoped_ptr<ScrollAndScaleSet> scroll_info =
1184 host_impl_->ProcessScrollDeltas();
1185 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1186 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1190 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1191 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1192 host_impl_->SetViewportSize(gfx::Size(50, 50));
1193 DrawFrame();
1195 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1196 DCHECK(scroll_layer);
1198 float min_page_scale = 0.5f;
1199 float max_page_scale = 4.f;
1200 base::TimeTicks start_time = base::TimeTicks() +
1201 base::TimeDelta::FromSeconds(1);
1202 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1203 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1204 base::TimeTicks end_time = start_time + duration;
1206 // Non-anchor zoom-in
1208 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1209 min_page_scale,
1210 max_page_scale);
1211 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1213 did_request_redraw_ = false;
1214 did_request_animate_ = false;
1215 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), false, 2.f, duration);
1216 EXPECT_FALSE(did_request_redraw_);
1217 EXPECT_TRUE(did_request_animate_);
1219 did_request_redraw_ = false;
1220 did_request_animate_ = false;
1221 host_impl_->Animate(start_time);
1222 EXPECT_TRUE(did_request_redraw_);
1223 EXPECT_TRUE(did_request_animate_);
1225 did_request_redraw_ = false;
1226 did_request_animate_ = false;
1227 host_impl_->Animate(halfway_through_animation);
1228 EXPECT_TRUE(did_request_redraw_);
1229 EXPECT_TRUE(did_request_animate_);
1231 did_request_redraw_ = false;
1232 did_request_animate_ = false;
1233 did_request_commit_ = false;
1234 host_impl_->Animate(end_time);
1235 EXPECT_TRUE(did_request_commit_);
1236 EXPECT_FALSE(did_request_animate_);
1238 scoped_ptr<ScrollAndScaleSet> scroll_info =
1239 host_impl_->ProcessScrollDeltas();
1240 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1241 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1244 // Anchor zoom-out
1246 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1247 min_page_scale,
1248 max_page_scale);
1249 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1251 did_request_redraw_ = false;
1252 did_request_animate_ = false;
1253 host_impl_->StartPageScaleAnimation(
1254 gfx::Vector2d(25, 25), true, min_page_scale, duration);
1255 EXPECT_FALSE(did_request_redraw_);
1256 EXPECT_TRUE(did_request_animate_);
1258 did_request_redraw_ = false;
1259 did_request_animate_ = false;
1260 host_impl_->Animate(start_time);
1261 EXPECT_TRUE(did_request_redraw_);
1262 EXPECT_TRUE(did_request_animate_);
1264 did_request_redraw_ = false;
1265 did_request_commit_ = false;
1266 did_request_animate_ = false;
1267 host_impl_->Animate(end_time);
1268 EXPECT_TRUE(did_request_redraw_);
1269 EXPECT_FALSE(did_request_animate_);
1270 EXPECT_TRUE(did_request_commit_);
1272 scoped_ptr<ScrollAndScaleSet> scroll_info =
1273 host_impl_->ProcessScrollDeltas();
1274 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1275 // Pushed to (0,0) via clamping against contents layer size.
1276 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1280 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1281 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1282 host_impl_->SetViewportSize(gfx::Size(50, 50));
1283 DrawFrame();
1285 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1286 DCHECK(scroll_layer);
1288 float min_page_scale = 0.5f;
1289 float max_page_scale = 4.f;
1290 base::TimeTicks start_time = base::TimeTicks() +
1291 base::TimeDelta::FromSeconds(1);
1292 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1293 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1294 base::TimeTicks end_time = start_time + duration;
1296 // Anchor zoom with unchanged page scale should not change scroll or scale.
1298 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1299 min_page_scale,
1300 max_page_scale);
1301 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1303 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), true, 1.f, duration);
1304 host_impl_->Animate(start_time);
1305 host_impl_->Animate(halfway_through_animation);
1306 EXPECT_TRUE(did_request_redraw_);
1307 host_impl_->Animate(end_time);
1308 EXPECT_TRUE(did_request_commit_);
1310 scoped_ptr<ScrollAndScaleSet> scroll_info =
1311 host_impl_->ProcessScrollDeltas();
1312 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1313 ExpectNone(*scroll_info, scroll_layer->id());
1317 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1318 public:
1319 LayerTreeHostImplOverridePhysicalTime(
1320 const LayerTreeSettings& settings,
1321 LayerTreeHostImplClient* client,
1322 Proxy* proxy,
1323 SharedBitmapManager* manager,
1324 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1325 : LayerTreeHostImpl(settings,
1326 client,
1327 proxy,
1328 rendering_stats_instrumentation,
1329 manager,
1330 0) {}
1332 virtual base::TimeTicks CurrentFrameTimeTicks() OVERRIDE {
1333 return fake_current_physical_time_;
1336 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1337 fake_current_physical_time_ = fake_now;
1340 private:
1341 base::TimeTicks fake_current_physical_time_;
1344 #define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST() \
1345 gfx::Size viewport_size(10, 10); \
1346 gfx::Size content_size(100, 100); \
1348 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = \
1349 new LayerTreeHostImplOverridePhysicalTime(settings, \
1350 this, \
1351 &proxy_, \
1352 shared_bitmap_manager_.get(), \
1353 &stats_instrumentation_); \
1354 host_impl_ = make_scoped_ptr(host_impl_override_time); \
1355 host_impl_->InitializeRenderer(CreateOutputSurface()); \
1356 host_impl_->SetViewportSize(viewport_size); \
1358 scoped_ptr<LayerImpl> root = \
1359 LayerImpl::Create(host_impl_->active_tree(), 1); \
1360 root->SetBounds(viewport_size); \
1362 scoped_ptr<LayerImpl> scroll = \
1363 LayerImpl::Create(host_impl_->active_tree(), 2); \
1364 scroll->SetScrollClipLayer(root->id()); \
1365 scroll->SetScrollOffset(gfx::Vector2d()); \
1366 root->SetBounds(viewport_size); \
1367 scroll->SetBounds(content_size); \
1368 scroll->SetContentBounds(content_size); \
1369 scroll->SetIsContainerForFixedPositionLayers(true); \
1371 scoped_ptr<LayerImpl> contents = \
1372 LayerImpl::Create(host_impl_->active_tree(), 3); \
1373 contents->SetDrawsContent(true); \
1374 contents->SetBounds(content_size); \
1375 contents->SetContentBounds(content_size); \
1377 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = \
1378 SolidColorScrollbarLayerImpl::Create( \
1379 host_impl_->active_tree(), 4, VERTICAL, 10, 0, false, true); \
1380 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); \
1382 scroll->AddChild(contents.Pass()); \
1383 root->AddChild(scroll.Pass()); \
1384 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1); \
1385 root->AddChild(scrollbar.PassAs<LayerImpl>()); \
1387 host_impl_->active_tree()->SetRootLayer(root.Pass()); \
1388 host_impl_->active_tree()->SetViewportLayersFromIds( \
1389 1, 2, Layer::INVALID_ID); \
1390 host_impl_->active_tree()->DidBecomeActive(); \
1391 DrawFrame();
1393 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1394 LayerTreeSettings settings;
1395 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1396 settings.scrollbar_fade_delay_ms = 20;
1397 settings.scrollbar_fade_duration_ms = 20;
1399 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1401 base::TimeTicks fake_now = gfx::FrameTime::Now();
1403 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1404 EXPECT_FALSE(did_request_redraw_);
1406 // If no scroll happened during a scroll gesture, it should have no effect.
1407 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1408 host_impl_->ScrollEnd();
1409 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1410 EXPECT_FALSE(did_request_redraw_);
1411 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1413 // After a scroll, a fade animation should be scheduled about 20ms from now.
1414 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1415 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1416 host_impl_->ScrollEnd();
1417 did_request_redraw_ = false;
1418 did_request_animate_ = false;
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();
1424 scrollbar_fade_start_.Run();
1425 host_impl_->Animate(fake_now);
1427 // After the fade begins, we should start getting redraws instead of a
1428 // scheduled animation.
1429 fake_now += base::TimeDelta::FromMilliseconds(25);
1430 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1431 EXPECT_TRUE(did_request_animate_);
1432 did_request_animate_ = false;
1434 // Setting the scroll offset outside a scroll should also cause the scrollbar
1435 // to appear and to schedule a fade.
1436 host_impl_->InnerViewportScrollLayer()->SetScrollOffset(gfx::Vector2d(5, 5));
1437 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1438 requested_scrollbar_animation_delay_);
1439 EXPECT_FALSE(did_request_redraw_);
1440 EXPECT_FALSE(did_request_animate_);
1441 requested_scrollbar_animation_delay_ = base::TimeDelta();
1444 TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) {
1445 LayerTreeSettings settings;
1446 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1447 settings.scrollbar_fade_delay_ms = 20;
1448 settings.scrollbar_fade_duration_ms = 20;
1449 settings.use_pinch_zoom_scrollbars = true;
1451 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1453 base::TimeTicks fake_now = gfx::FrameTime::Now();
1455 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
1457 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1458 EXPECT_FALSE(did_request_animate_);
1460 // If no scroll happened during a scroll gesture, it should have no effect.
1461 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1462 host_impl_->ScrollEnd();
1463 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1464 EXPECT_FALSE(did_request_animate_);
1465 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1467 // After a scroll, no fade animation should be scheduled.
1468 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1469 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1470 host_impl_->ScrollEnd();
1471 did_request_redraw_ = false;
1472 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1473 EXPECT_FALSE(did_request_animate_);
1474 requested_scrollbar_animation_delay_ = base::TimeDelta();
1476 // We should not see any draw requests.
1477 fake_now += base::TimeDelta::FromMilliseconds(25);
1478 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1479 EXPECT_FALSE(did_request_animate_);
1481 // Make page scale > min so that subsequent scrolls will trigger fades.
1482 host_impl_->active_tree()->SetPageScaleDelta(1.1f);
1484 // After a scroll, a fade animation should be scheduled about 20ms from now.
1485 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1486 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1487 host_impl_->ScrollEnd();
1488 did_request_redraw_ = false;
1489 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1490 requested_scrollbar_animation_delay_);
1491 EXPECT_FALSE(did_request_animate_);
1492 requested_scrollbar_animation_delay_ = base::TimeDelta();
1493 scrollbar_fade_start_.Run();
1495 // After the fade begins, we should start getting redraws instead of a
1496 // scheduled animation.
1497 fake_now += base::TimeDelta::FromMilliseconds(25);
1498 host_impl_->Animate(fake_now);
1499 EXPECT_TRUE(did_request_animate_);
1502 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1503 float device_scale_factor) {
1504 LayerTreeSettings settings;
1505 settings.scrollbar_fade_delay_ms = 500;
1506 settings.scrollbar_fade_duration_ms = 300;
1507 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1509 gfx::Size viewport_size(300, 200);
1510 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1511 gfx::ScaleSize(viewport_size, device_scale_factor));
1512 gfx::Size content_size(1000, 1000);
1514 CreateHostImpl(settings, CreateOutputSurface());
1515 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1516 host_impl_->SetViewportSize(device_viewport_size);
1518 scoped_ptr<LayerImpl> root =
1519 LayerImpl::Create(host_impl_->active_tree(), 1);
1520 root->SetBounds(viewport_size);
1522 scoped_ptr<LayerImpl> scroll =
1523 LayerImpl::Create(host_impl_->active_tree(), 2);
1524 scroll->SetScrollClipLayer(root->id());
1525 scroll->SetScrollOffset(gfx::Vector2d());
1526 scroll->SetBounds(content_size);
1527 scroll->SetContentBounds(content_size);
1528 scroll->SetIsContainerForFixedPositionLayers(true);
1530 scoped_ptr<LayerImpl> contents =
1531 LayerImpl::Create(host_impl_->active_tree(), 3);
1532 contents->SetDrawsContent(true);
1533 contents->SetBounds(content_size);
1534 contents->SetContentBounds(content_size);
1536 // The scrollbar is on the right side.
1537 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1538 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1539 scrollbar->SetDrawsContent(true);
1540 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1541 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1542 scrollbar->SetPosition(gfx::Point(285, 0));
1544 scroll->AddChild(contents.Pass());
1545 root->AddChild(scroll.Pass());
1546 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1547 root->AddChild(scrollbar.PassAs<LayerImpl>());
1549 host_impl_->active_tree()->SetRootLayer(root.Pass());
1550 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
1551 host_impl_->active_tree()->DidBecomeActive();
1552 DrawFrame();
1554 LayerImpl* root_scroll =
1555 host_impl_->active_tree()->InnerViewportScrollLayer();
1556 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1557 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1558 static_cast<ScrollbarAnimationControllerThinning*>(
1559 root_scroll->scrollbar_animation_controller());
1560 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1562 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1563 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1565 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1566 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1568 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1569 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1571 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1572 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1573 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1575 did_request_redraw_ = false;
1576 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1577 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1578 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1579 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1580 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1581 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1582 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1585 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1586 SetupMouseMoveAtWithDeviceScale(1.f);
1589 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1590 SetupMouseMoveAtWithDeviceScale(2.f);
1593 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1594 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1595 host_impl_->SetViewportSize(gfx::Size(50, 50));
1596 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
1597 DrawFrame();
1599 CompositorFrameMetadata metadata =
1600 host_impl_->MakeCompositorFrameMetadata();
1601 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1602 EXPECT_EQ(1.f, metadata.page_scale_factor);
1603 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
1604 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1605 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1606 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1609 // Scrolling should update metadata immediately.
1610 EXPECT_EQ(InputHandler::ScrollStarted,
1611 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1612 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1614 CompositorFrameMetadata metadata =
1615 host_impl_->MakeCompositorFrameMetadata();
1616 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1618 host_impl_->ScrollEnd();
1620 CompositorFrameMetadata metadata =
1621 host_impl_->MakeCompositorFrameMetadata();
1622 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1625 // Page scale should update metadata correctly (shrinking only the viewport).
1626 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1627 host_impl_->PinchGestureBegin();
1628 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1629 host_impl_->PinchGestureEnd();
1630 host_impl_->ScrollEnd();
1632 CompositorFrameMetadata metadata =
1633 host_impl_->MakeCompositorFrameMetadata();
1634 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1635 EXPECT_EQ(2.f, metadata.page_scale_factor);
1636 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
1637 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1638 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1639 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1642 // Likewise if set from the main thread.
1643 host_impl_->ProcessScrollDeltas();
1644 host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
1645 host_impl_->active_tree()->SetPageScaleDelta(1.f);
1647 CompositorFrameMetadata metadata =
1648 host_impl_->MakeCompositorFrameMetadata();
1649 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1650 EXPECT_EQ(4.f, metadata.page_scale_factor);
1651 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
1652 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1653 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1654 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1658 class DidDrawCheckLayer : public LayerImpl {
1659 public:
1660 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1661 return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(tree_impl, id));
1664 virtual bool WillDraw(DrawMode draw_mode, ResourceProvider* provider)
1665 OVERRIDE {
1666 will_draw_called_ = true;
1667 if (will_draw_returns_false_)
1668 return false;
1669 return LayerImpl::WillDraw(draw_mode, provider);
1672 virtual void AppendQuads(RenderPass* render_pass,
1673 const OcclusionTracker<LayerImpl>& occlusion_tracker,
1674 AppendQuadsData* append_quads_data) OVERRIDE {
1675 append_quads_called_ = true;
1676 LayerImpl::AppendQuads(render_pass, occlusion_tracker, append_quads_data);
1679 virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
1680 did_draw_called_ = true;
1681 LayerImpl::DidDraw(provider);
1684 bool will_draw_called() const { return will_draw_called_; }
1685 bool append_quads_called() const { return append_quads_called_; }
1686 bool did_draw_called() const { return did_draw_called_; }
1688 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1690 void ClearDidDrawCheck() {
1691 will_draw_called_ = false;
1692 append_quads_called_ = false;
1693 did_draw_called_ = false;
1696 protected:
1697 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1698 : LayerImpl(tree_impl, id),
1699 will_draw_returns_false_(false),
1700 will_draw_called_(false),
1701 append_quads_called_(false),
1702 did_draw_called_(false) {
1703 SetBounds(gfx::Size(10, 10));
1704 SetContentBounds(gfx::Size(10, 10));
1705 SetDrawsContent(true);
1706 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1709 private:
1710 bool will_draw_returns_false_;
1711 bool will_draw_called_;
1712 bool append_quads_called_;
1713 bool did_draw_called_;
1716 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1717 // The root layer is always drawn, so run this test on a child layer that
1718 // will be masked out by the root layer's bounds.
1719 host_impl_->active_tree()->SetRootLayer(
1720 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1721 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1722 host_impl_->active_tree()->root_layer());
1724 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1725 DidDrawCheckLayer* layer =
1726 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1729 LayerTreeHostImpl::FrameData frame;
1730 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1731 host_impl_->DrawLayers(&frame);
1732 host_impl_->DidDrawAllLayers(frame);
1734 EXPECT_TRUE(layer->will_draw_called());
1735 EXPECT_TRUE(layer->append_quads_called());
1736 EXPECT_TRUE(layer->did_draw_called());
1739 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
1742 LayerTreeHostImpl::FrameData frame;
1744 layer->set_will_draw_returns_false();
1745 layer->ClearDidDrawCheck();
1747 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1748 host_impl_->DrawLayers(&frame);
1749 host_impl_->DidDrawAllLayers(frame);
1751 EXPECT_TRUE(layer->will_draw_called());
1752 EXPECT_FALSE(layer->append_quads_called());
1753 EXPECT_FALSE(layer->did_draw_called());
1757 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1758 // The root layer is always drawn, so run this test on a child layer that
1759 // will be masked out by the root layer's bounds.
1760 host_impl_->active_tree()->SetRootLayer(
1761 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1762 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1763 host_impl_->active_tree()->root_layer());
1764 root->SetMasksToBounds(true);
1766 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1767 DidDrawCheckLayer* layer =
1768 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1769 // Ensure visible_content_rect for layer is empty.
1770 layer->SetPosition(gfx::PointF(100.f, 100.f));
1771 layer->SetBounds(gfx::Size(10, 10));
1772 layer->SetContentBounds(gfx::Size(10, 10));
1774 LayerTreeHostImpl::FrameData frame;
1776 EXPECT_FALSE(layer->will_draw_called());
1777 EXPECT_FALSE(layer->did_draw_called());
1779 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1780 host_impl_->DrawLayers(&frame);
1781 host_impl_->DidDrawAllLayers(frame);
1783 EXPECT_FALSE(layer->will_draw_called());
1784 EXPECT_FALSE(layer->did_draw_called());
1786 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1788 // Ensure visible_content_rect for layer is not empty
1789 layer->SetPosition(gfx::PointF());
1791 EXPECT_FALSE(layer->will_draw_called());
1792 EXPECT_FALSE(layer->did_draw_called());
1794 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1795 host_impl_->DrawLayers(&frame);
1796 host_impl_->DidDrawAllLayers(frame);
1798 EXPECT_TRUE(layer->will_draw_called());
1799 EXPECT_TRUE(layer->did_draw_called());
1801 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1804 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1805 gfx::Size big_size(1000, 1000);
1806 host_impl_->SetViewportSize(big_size);
1808 host_impl_->active_tree()->SetRootLayer(
1809 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1810 DidDrawCheckLayer* root =
1811 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1813 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1814 DidDrawCheckLayer* occluded_layer =
1815 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1817 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1818 DidDrawCheckLayer* top_layer =
1819 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1820 // This layer covers the occluded_layer above. Make this layer large so it can
1821 // occlude.
1822 top_layer->SetBounds(big_size);
1823 top_layer->SetContentBounds(big_size);
1824 top_layer->SetContentsOpaque(true);
1826 LayerTreeHostImpl::FrameData frame;
1828 EXPECT_FALSE(occluded_layer->will_draw_called());
1829 EXPECT_FALSE(occluded_layer->did_draw_called());
1830 EXPECT_FALSE(top_layer->will_draw_called());
1831 EXPECT_FALSE(top_layer->did_draw_called());
1833 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1834 host_impl_->DrawLayers(&frame);
1835 host_impl_->DidDrawAllLayers(frame);
1837 EXPECT_FALSE(occluded_layer->will_draw_called());
1838 EXPECT_FALSE(occluded_layer->did_draw_called());
1839 EXPECT_TRUE(top_layer->will_draw_called());
1840 EXPECT_TRUE(top_layer->did_draw_called());
1843 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1844 host_impl_->active_tree()->SetRootLayer(
1845 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1846 DidDrawCheckLayer* root =
1847 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1849 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1850 DidDrawCheckLayer* layer1 =
1851 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1853 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1854 DidDrawCheckLayer* layer2 =
1855 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1857 layer1->SetOpacity(0.3f);
1858 layer1->SetShouldFlattenTransform(true);
1860 EXPECT_FALSE(root->did_draw_called());
1861 EXPECT_FALSE(layer1->did_draw_called());
1862 EXPECT_FALSE(layer2->did_draw_called());
1864 LayerTreeHostImpl::FrameData frame;
1865 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1866 host_impl_->DrawLayers(&frame);
1867 host_impl_->DidDrawAllLayers(frame);
1869 EXPECT_TRUE(root->did_draw_called());
1870 EXPECT_TRUE(layer1->did_draw_called());
1871 EXPECT_TRUE(layer2->did_draw_called());
1873 EXPECT_NE(root->render_surface(), layer1->render_surface());
1874 EXPECT_TRUE(!!layer1->render_surface());
1877 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1878 public:
1879 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1880 int id,
1881 bool tile_missing,
1882 bool had_incomplete_tile,
1883 bool animating,
1884 ResourceProvider* resource_provider) {
1885 return scoped_ptr<LayerImpl>(
1886 new MissingTextureAnimatingLayer(tree_impl,
1888 tile_missing,
1889 had_incomplete_tile,
1890 animating,
1891 resource_provider));
1894 virtual void AppendQuads(RenderPass* render_pass,
1895 const OcclusionTracker<LayerImpl>& occlusion_tracker,
1896 AppendQuadsData* append_quads_data) OVERRIDE {
1897 LayerImpl::AppendQuads(render_pass, occlusion_tracker, append_quads_data);
1898 if (had_incomplete_tile_)
1899 append_quads_data->had_incomplete_tile = true;
1900 if (tile_missing_)
1901 append_quads_data->num_missing_tiles++;
1904 private:
1905 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1906 int id,
1907 bool tile_missing,
1908 bool had_incomplete_tile,
1909 bool animating,
1910 ResourceProvider* resource_provider)
1911 : DidDrawCheckLayer(tree_impl, id),
1912 tile_missing_(tile_missing),
1913 had_incomplete_tile_(had_incomplete_tile) {
1914 if (animating)
1915 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1918 bool tile_missing_;
1919 bool had_incomplete_tile_;
1922 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsOnDefault) {
1923 host_impl_->active_tree()->SetRootLayer(
1924 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1925 DidDrawCheckLayer* root =
1926 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1928 bool tile_missing = false;
1929 bool had_incomplete_tile = false;
1930 bool is_animating = false;
1931 root->AddChild(
1932 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1934 tile_missing,
1935 had_incomplete_tile,
1936 is_animating,
1937 host_impl_->resource_provider()));
1939 LayerTreeHostImpl::FrameData frame;
1941 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1942 host_impl_->DrawLayers(&frame);
1943 host_impl_->DidDrawAllLayers(frame);
1946 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) {
1947 host_impl_->active_tree()->SetRootLayer(
1948 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1949 DidDrawCheckLayer* root =
1950 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1951 bool tile_missing = false;
1952 bool had_incomplete_tile = false;
1953 bool is_animating = true;
1954 root->AddChild(
1955 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1957 tile_missing,
1958 had_incomplete_tile,
1959 is_animating,
1960 host_impl_->resource_provider()));
1962 LayerTreeHostImpl::FrameData frame;
1964 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1965 host_impl_->DrawLayers(&frame);
1966 host_impl_->DidDrawAllLayers(frame);
1969 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithMissingTiles) {
1970 host_impl_->active_tree()->SetRootLayer(
1971 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1972 DidDrawCheckLayer* root =
1973 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1975 bool tile_missing = true;
1976 bool had_incomplete_tile = false;
1977 bool is_animating = false;
1978 root->AddChild(
1979 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1981 tile_missing,
1982 had_incomplete_tile,
1983 is_animating,
1984 host_impl_->resource_provider()));
1985 LayerTreeHostImpl::FrameData frame;
1986 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1987 host_impl_->DrawLayers(&frame);
1988 host_impl_->DidDrawAllLayers(frame);
1991 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithIncompleteTile) {
1992 host_impl_->active_tree()->SetRootLayer(
1993 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1994 DidDrawCheckLayer* root =
1995 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1997 bool tile_missing = false;
1998 bool had_incomplete_tile = true;
1999 bool is_animating = false;
2000 root->AddChild(
2001 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2003 tile_missing,
2004 had_incomplete_tile,
2005 is_animating,
2006 host_impl_->resource_provider()));
2007 LayerTreeHostImpl::FrameData frame;
2008 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2009 host_impl_->DrawLayers(&frame);
2010 host_impl_->DidDrawAllLayers(frame);
2013 TEST_F(LayerTreeHostImplTest,
2014 PrepareToDrawFailsWithAnimationAndMissingTilesUsesCheckerboard) {
2015 host_impl_->active_tree()->SetRootLayer(
2016 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
2017 DidDrawCheckLayer* root =
2018 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2019 bool tile_missing = true;
2020 bool had_incomplete_tile = false;
2021 bool is_animating = true;
2022 root->AddChild(
2023 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2025 tile_missing,
2026 had_incomplete_tile,
2027 is_animating,
2028 host_impl_->resource_provider()));
2029 LayerTreeHostImpl::FrameData frame;
2030 EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS,
2031 host_impl_->PrepareToDraw(&frame));
2032 host_impl_->DrawLayers(&frame);
2033 host_impl_->DidDrawAllLayers(frame);
2036 TEST_F(LayerTreeHostImplTest,
2037 PrepareToDrawSucceedsWithAnimationAndIncompleteTiles) {
2038 host_impl_->active_tree()->SetRootLayer(
2039 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
2040 DidDrawCheckLayer* root =
2041 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2042 bool tile_missing = false;
2043 bool had_incomplete_tile = true;
2044 bool is_animating = true;
2045 root->AddChild(
2046 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2048 tile_missing,
2049 had_incomplete_tile,
2050 is_animating,
2051 host_impl_->resource_provider()));
2052 LayerTreeHostImpl::FrameData frame;
2053 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2054 host_impl_->DrawLayers(&frame);
2055 host_impl_->DidDrawAllLayers(frame);
2058 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenHighResRequired) {
2059 host_impl_->active_tree()->SetRootLayer(
2060 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2061 DidDrawCheckLayer* root =
2062 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2063 bool tile_missing = false;
2064 bool had_incomplete_tile = false;
2065 bool is_animating = false;
2066 root->AddChild(
2067 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2069 tile_missing,
2070 had_incomplete_tile,
2071 is_animating,
2072 host_impl_->resource_provider()));
2073 host_impl_->active_tree()->SetRequiresHighResToDraw();
2074 LayerTreeHostImpl::FrameData frame;
2075 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2076 host_impl_->DrawLayers(&frame);
2077 host_impl_->DidDrawAllLayers(frame);
2080 TEST_F(LayerTreeHostImplTest,
2081 PrepareToDrawFailsWhenHighResRequiredAndIncompleteTiles) {
2082 host_impl_->active_tree()->SetRootLayer(
2083 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2084 DidDrawCheckLayer* root =
2085 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2086 bool tile_missing = false;
2087 bool had_incomplete_tile = true;
2088 bool is_animating = false;
2089 root->AddChild(
2090 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2092 tile_missing,
2093 had_incomplete_tile,
2094 is_animating,
2095 host_impl_->resource_provider()));
2096 host_impl_->active_tree()->SetRequiresHighResToDraw();
2097 LayerTreeHostImpl::FrameData frame;
2098 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2099 host_impl_->PrepareToDraw(&frame));
2100 host_impl_->DrawLayers(&frame);
2101 host_impl_->DidDrawAllLayers(frame);
2104 TEST_F(LayerTreeHostImplTest,
2105 PrepareToDrawSucceedsWhenHighResRequiredAndMissingTile) {
2106 host_impl_->active_tree()->SetRootLayer(
2107 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2108 DidDrawCheckLayer* root =
2109 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2110 bool tile_missing = true;
2111 bool had_incomplete_tile = false;
2112 bool is_animating = false;
2113 root->AddChild(
2114 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2116 tile_missing,
2117 had_incomplete_tile,
2118 is_animating,
2119 host_impl_->resource_provider()));
2120 host_impl_->active_tree()->SetRequiresHighResToDraw();
2121 LayerTreeHostImpl::FrameData frame;
2122 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2123 host_impl_->DrawLayers(&frame);
2124 host_impl_->DidDrawAllLayers(frame);
2127 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2128 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2129 root->SetScrollClipLayer(Layer::INVALID_ID);
2130 host_impl_->active_tree()->SetRootLayer(root.Pass());
2131 DrawFrame();
2133 // Scroll event is ignored because layer is not scrollable.
2134 EXPECT_EQ(InputHandler::ScrollIgnored,
2135 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2136 EXPECT_FALSE(did_request_redraw_);
2137 EXPECT_FALSE(did_request_commit_);
2140 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2141 public:
2142 LayerTreeHostImplTopControlsTest()
2143 // Make the clip size the same as the layer (content) size so the layer is
2144 // non-scrollable.
2145 : layer_size_(10, 10),
2146 clip_size_(layer_size_) {
2147 settings_.calculate_top_controls_position = true;
2148 settings_.top_controls_height = 50;
2150 viewport_size_ =
2151 gfx::Size(clip_size_.width(),
2152 clip_size_.height() + settings_.top_controls_height);
2155 void SetupTopControlsAndScrollLayer() {
2156 CreateHostImpl(settings_, CreateOutputSurface());
2158 scoped_ptr<LayerImpl> root =
2159 LayerImpl::Create(host_impl_->active_tree(), 1);
2160 scoped_ptr<LayerImpl> root_clip =
2161 LayerImpl::Create(host_impl_->active_tree(), 2);
2162 root_clip->SetBounds(clip_size_);
2163 root->SetScrollClipLayer(root_clip->id());
2164 root->SetBounds(layer_size_);
2165 root->SetContentBounds(layer_size_);
2166 root->SetPosition(gfx::PointF());
2167 root->SetDrawsContent(false);
2168 root->SetIsContainerForFixedPositionLayers(true);
2169 int inner_viewport_scroll_layer_id = root->id();
2170 int page_scale_layer_id = root_clip->id();
2171 root_clip->AddChild(root.Pass());
2172 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2173 host_impl_->active_tree()->SetViewportLayersFromIds(
2174 page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
2175 // Set a viewport size that is large enough to contain both the top controls
2176 // and some content.
2177 host_impl_->SetViewportSize(viewport_size_);
2178 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2179 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2182 protected:
2183 gfx::Size layer_size_;
2184 gfx::Size clip_size_;
2185 gfx::Size viewport_size_;
2187 LayerTreeSettings settings_;
2188 }; // class LayerTreeHostImplTopControlsTest
2190 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2191 SetupTopControlsAndScrollLayer();
2192 DrawFrame();
2194 EXPECT_EQ(InputHandler::ScrollStarted,
2195 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2197 // Make the test scroll delta a fractional amount, to verify that the
2198 // fixed container size delta is (1) non-zero, and (2) fractional, and
2199 // (3) matches the movement of the top controls.
2200 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2201 host_impl_->top_controls_manager()->ScrollBegin();
2202 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2203 host_impl_->top_controls_manager()->ScrollEnd();
2205 LayerImpl* inner_viewport_scroll_layer =
2206 host_impl_->active_tree()->InnerViewportScrollLayer();
2207 DCHECK(inner_viewport_scroll_layer);
2208 host_impl_->ScrollEnd();
2209 EXPECT_EQ(top_controls_scroll_delta,
2210 inner_viewport_scroll_layer->FixedContainerSizeDelta());
2213 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsWithPageScale) {
2214 SetupTopControlsAndScrollLayer();
2215 DrawFrame();
2217 EXPECT_EQ(InputHandler::ScrollStarted,
2218 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2220 float page_scale = 1.5f;
2221 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale, 1.f, 2.f);
2223 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.f);
2224 gfx::Vector2dF expected_container_size_delta =
2225 ScaleVector2d(top_controls_scroll_delta, 1.f / page_scale);
2226 host_impl_->top_controls_manager()->ScrollBegin();
2227 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2228 host_impl_->top_controls_manager()->ScrollEnd();
2230 LayerImpl* inner_viewport_scroll_layer =
2231 host_impl_->active_tree()->InnerViewportScrollLayer();
2232 DCHECK(inner_viewport_scroll_layer);
2233 host_impl_->ScrollEnd();
2235 // Use a tolerance that requires the container size delta to be within 0.01
2236 // pixels.
2237 double tolerance = 0.0001;
2238 EXPECT_LT(
2239 (expected_container_size_delta -
2240 inner_viewport_scroll_layer->FixedContainerSizeDelta()).LengthSquared(),
2241 tolerance);
2244 TEST_F(LayerTreeHostImplTopControlsTest,
2245 ScrollNonScrollableRootWithTopControls) {
2246 SetupTopControlsAndScrollLayer();
2247 DrawFrame();
2249 EXPECT_EQ(InputHandler::ScrollStarted,
2250 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2252 host_impl_->top_controls_manager()->ScrollBegin();
2253 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
2254 host_impl_->top_controls_manager()->ScrollEnd();
2255 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->content_top_offset());
2256 // Now that top controls have moved, expect the clip to resize.
2257 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2258 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2260 host_impl_->ScrollEnd();
2262 EXPECT_EQ(InputHandler::ScrollStarted,
2263 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2265 float scroll_increment_y = -25.f;
2266 host_impl_->top_controls_manager()->ScrollBegin();
2267 host_impl_->top_controls_manager()->ScrollBy(
2268 gfx::Vector2dF(0.f, scroll_increment_y));
2269 EXPECT_EQ(-scroll_increment_y,
2270 host_impl_->top_controls_manager()->content_top_offset());
2271 // Now that top controls have moved, expect the clip to resize.
2272 EXPECT_EQ(gfx::Size(viewport_size_.width(),
2273 viewport_size_.height() + scroll_increment_y),
2274 root_clip_ptr->bounds());
2276 host_impl_->top_controls_manager()->ScrollBy(
2277 gfx::Vector2dF(0.f, scroll_increment_y));
2278 host_impl_->top_controls_manager()->ScrollEnd();
2279 EXPECT_EQ(-2 * scroll_increment_y,
2280 host_impl_->top_controls_manager()->content_top_offset());
2281 // Now that top controls have moved, expect the clip to resize.
2282 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2284 host_impl_->ScrollEnd();
2286 // Verify the layer is once-again non-scrollable.
2287 EXPECT_EQ(
2288 gfx::Vector2d(),
2289 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
2291 EXPECT_EQ(InputHandler::ScrollStarted,
2292 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2295 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
2296 // Test the configuration where a non-composited root layer is embedded in a
2297 // scrollable outer layer.
2298 gfx::Size surface_size(10, 10);
2299 gfx::Size contents_size(20, 20);
2301 scoped_ptr<LayerImpl> content_layer =
2302 LayerImpl::Create(host_impl_->active_tree(), 1);
2303 content_layer->SetDrawsContent(true);
2304 content_layer->SetPosition(gfx::PointF());
2305 content_layer->SetBounds(contents_size);
2306 content_layer->SetContentBounds(contents_size);
2307 content_layer->SetContentsScale(2.f, 2.f);
2309 scoped_ptr<LayerImpl> scroll_clip_layer =
2310 LayerImpl::Create(host_impl_->active_tree(), 3);
2311 scroll_clip_layer->SetBounds(surface_size);
2313 scoped_ptr<LayerImpl> scroll_layer =
2314 LayerImpl::Create(host_impl_->active_tree(), 2);
2315 scroll_layer->SetScrollClipLayer(3);
2316 scroll_layer->SetBounds(contents_size);
2317 scroll_layer->SetContentBounds(contents_size);
2318 scroll_layer->SetPosition(gfx::PointF());
2319 scroll_layer->AddChild(content_layer.Pass());
2320 scroll_clip_layer->AddChild(scroll_layer.Pass());
2322 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
2323 host_impl_->SetViewportSize(surface_size);
2324 DrawFrame();
2326 EXPECT_EQ(InputHandler::ScrollStarted,
2327 host_impl_->ScrollBegin(gfx::Point(5, 5),
2328 InputHandler::Wheel));
2329 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2330 host_impl_->ScrollEnd();
2331 EXPECT_TRUE(did_request_redraw_);
2332 EXPECT_TRUE(did_request_commit_);
2335 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
2336 gfx::Size surface_size(10, 10);
2337 gfx::Size contents_size(20, 20);
2338 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2339 root->SetBounds(surface_size);
2340 root->SetContentBounds(contents_size);
2341 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
2342 host_impl_->active_tree()->SetRootLayer(root.Pass());
2343 host_impl_->SetViewportSize(surface_size);
2344 DrawFrame();
2346 EXPECT_EQ(InputHandler::ScrollStarted,
2347 host_impl_->ScrollBegin(gfx::Point(5, 5),
2348 InputHandler::Wheel));
2349 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2350 host_impl_->ScrollEnd();
2351 EXPECT_TRUE(did_request_redraw_);
2352 EXPECT_TRUE(did_request_commit_);
2355 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
2356 gfx::Size surface_size(10, 10);
2357 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2358 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
2359 host_impl_->active_tree()->SetRootLayer(root.Pass());
2360 host_impl_->SetViewportSize(surface_size);
2361 DrawFrame();
2363 // Scroll event is ignored because the input coordinate is outside the layer
2364 // boundaries.
2365 EXPECT_EQ(InputHandler::ScrollIgnored,
2366 host_impl_->ScrollBegin(gfx::Point(15, 5),
2367 InputHandler::Wheel));
2368 EXPECT_FALSE(did_request_redraw_);
2369 EXPECT_FALSE(did_request_commit_);
2372 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
2373 gfx::Size surface_size(10, 10);
2374 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2375 scoped_ptr<LayerImpl> child =
2376 CreateScrollableLayer(2, surface_size, root.get());
2377 host_impl_->SetViewportSize(surface_size);
2379 gfx::Transform matrix;
2380 matrix.RotateAboutXAxis(180.0);
2381 child->SetTransform(matrix);
2382 child->SetDoubleSided(false);
2384 root->AddChild(child.Pass());
2385 host_impl_->active_tree()->SetRootLayer(root.Pass());
2386 DrawFrame();
2388 // Scroll event is ignored because the scrollable layer is not facing the
2389 // viewer and there is nothing scrollable behind it.
2390 EXPECT_EQ(InputHandler::ScrollIgnored,
2391 host_impl_->ScrollBegin(gfx::Point(5, 5),
2392 InputHandler::Wheel));
2393 EXPECT_FALSE(did_request_redraw_);
2394 EXPECT_FALSE(did_request_commit_);
2397 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
2398 gfx::Size surface_size(10, 10);
2399 scoped_ptr<LayerImpl> clip_layer =
2400 LayerImpl::Create(host_impl_->active_tree(), 3);
2401 scoped_ptr<LayerImpl> content_layer =
2402 CreateScrollableLayer(1, surface_size, clip_layer.get());
2403 content_layer->SetShouldScrollOnMainThread(true);
2404 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
2406 // Note: we can use the same clip layer for both since both calls to
2407 // CreateScrollableLayer() use the same surface size.
2408 scoped_ptr<LayerImpl> scroll_layer =
2409 CreateScrollableLayer(2, surface_size, clip_layer.get());
2410 scroll_layer->AddChild(content_layer.Pass());
2411 clip_layer->AddChild(scroll_layer.Pass());
2413 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
2414 host_impl_->SetViewportSize(surface_size);
2415 DrawFrame();
2417 // Scrolling fails because the content layer is asking to be scrolled on the
2418 // main thread.
2419 EXPECT_EQ(InputHandler::ScrollOnMainThread,
2420 host_impl_->ScrollBegin(gfx::Point(5, 5),
2421 InputHandler::Wheel));
2424 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
2425 gfx::Size surface_size(20, 20);
2426 gfx::Size viewport_size(10, 10);
2427 float page_scale = 2.f;
2428 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2429 scoped_ptr<LayerImpl> root_clip =
2430 LayerImpl::Create(host_impl_->active_tree(), 2);
2431 scoped_ptr<LayerImpl> root_scrolling =
2432 CreateScrollableLayer(3, surface_size, root_clip.get());
2433 EXPECT_EQ(viewport_size, root_clip->bounds());
2434 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2435 root_clip->AddChild(root_scrolling.Pass());
2436 root->AddChild(root_clip.Pass());
2437 host_impl_->active_tree()->SetRootLayer(root.Pass());
2438 // The behaviour in this test assumes the page scale is applied at a layer
2439 // above the clip layer.
2440 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2441 host_impl_->active_tree()->DidBecomeActive();
2442 host_impl_->SetViewportSize(viewport_size);
2443 DrawFrame();
2445 LayerImpl* root_scroll =
2446 host_impl_->active_tree()->InnerViewportScrollLayer();
2447 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2449 gfx::Vector2d scroll_delta(0, 10);
2450 gfx::Vector2d expected_scroll_delta = scroll_delta;
2451 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2452 EXPECT_EQ(InputHandler::ScrollStarted,
2453 host_impl_->ScrollBegin(gfx::Point(5, 5),
2454 InputHandler::Wheel));
2455 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2456 host_impl_->ScrollEnd();
2458 // Set new page scale from main thread.
2459 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2460 page_scale,
2461 page_scale);
2463 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2464 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2466 // The scroll range should also have been updated.
2467 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2469 // The page scale delta remains constant because the impl thread did not
2470 // scale.
2471 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2474 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
2475 gfx::Size surface_size(20, 20);
2476 gfx::Size viewport_size(10, 10);
2477 float page_scale = 2.f;
2478 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2479 scoped_ptr<LayerImpl> root_clip =
2480 LayerImpl::Create(host_impl_->active_tree(), 2);
2481 scoped_ptr<LayerImpl> root_scrolling =
2482 CreateScrollableLayer(3, surface_size, root_clip.get());
2483 EXPECT_EQ(viewport_size, root_clip->bounds());
2484 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2485 root_clip->AddChild(root_scrolling.Pass());
2486 root->AddChild(root_clip.Pass());
2487 host_impl_->active_tree()->SetRootLayer(root.Pass());
2488 // The behaviour in this test assumes the page scale is applied at a layer
2489 // above the clip layer.
2490 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2491 host_impl_->active_tree()->DidBecomeActive();
2492 host_impl_->SetViewportSize(viewport_size);
2493 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
2494 DrawFrame();
2496 LayerImpl* root_scroll =
2497 host_impl_->active_tree()->InnerViewportScrollLayer();
2498 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2500 gfx::Vector2d scroll_delta(0, 10);
2501 gfx::Vector2d expected_scroll_delta = scroll_delta;
2502 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2503 EXPECT_EQ(InputHandler::ScrollStarted,
2504 host_impl_->ScrollBegin(gfx::Point(5, 5),
2505 InputHandler::Wheel));
2506 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2507 host_impl_->ScrollEnd();
2509 // Set new page scale on impl thread by pinching.
2510 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2511 host_impl_->PinchGestureBegin();
2512 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
2513 host_impl_->PinchGestureEnd();
2514 host_impl_->ScrollEnd();
2515 DrawOneFrame();
2517 // The scroll delta is not scaled because the main thread did not scale.
2518 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2519 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2521 // The scroll range should also have been updated.
2522 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2524 // The page scale delta should match the new scale on the impl side.
2525 EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
2528 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
2529 gfx::Size surface_size(10, 10);
2530 float default_page_scale = 1.f;
2531 gfx::Transform default_page_scale_matrix;
2532 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
2534 float new_page_scale = 2.f;
2535 gfx::Transform new_page_scale_matrix;
2536 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
2538 // Create a normal scrollable root layer and another scrollable child layer.
2539 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
2540 LayerImpl* root = host_impl_->active_tree()->root_layer();
2541 LayerImpl* child = scroll->children()[0];
2543 scoped_ptr<LayerImpl> scrollable_child_clip =
2544 LayerImpl::Create(host_impl_->active_tree(), 6);
2545 scoped_ptr<LayerImpl> scrollable_child =
2546 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
2547 scrollable_child_clip->AddChild(scrollable_child.Pass());
2548 child->AddChild(scrollable_child_clip.Pass());
2549 LayerImpl* grand_child = child->children()[0];
2551 // Set new page scale on impl thread by pinching.
2552 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2553 host_impl_->PinchGestureBegin();
2554 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
2555 host_impl_->PinchGestureEnd();
2556 host_impl_->ScrollEnd();
2557 DrawOneFrame();
2559 EXPECT_EQ(1.f, root->contents_scale_x());
2560 EXPECT_EQ(1.f, root->contents_scale_y());
2561 EXPECT_EQ(1.f, scroll->contents_scale_x());
2562 EXPECT_EQ(1.f, scroll->contents_scale_y());
2563 EXPECT_EQ(1.f, child->contents_scale_x());
2564 EXPECT_EQ(1.f, child->contents_scale_y());
2565 EXPECT_EQ(1.f, grand_child->contents_scale_x());
2566 EXPECT_EQ(1.f, grand_child->contents_scale_y());
2568 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
2569 // the page scale delta on the root layer is applied hierarchically.
2570 LayerTreeHostImpl::FrameData frame;
2571 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2572 host_impl_->DrawLayers(&frame);
2573 host_impl_->DidDrawAllLayers(frame);
2575 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
2576 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
2577 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
2578 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
2579 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
2580 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
2581 EXPECT_EQ(new_page_scale,
2582 grand_child->draw_transform().matrix().getDouble(0, 0));
2583 EXPECT_EQ(new_page_scale,
2584 grand_child->draw_transform().matrix().getDouble(1, 1));
2587 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
2588 gfx::Size surface_size(30, 30);
2589 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2590 root->SetBounds(gfx::Size(5, 5));
2591 scoped_ptr<LayerImpl> root_scrolling =
2592 LayerImpl::Create(host_impl_->active_tree(), 2);
2593 root_scrolling->SetBounds(surface_size);
2594 root_scrolling->SetContentBounds(surface_size);
2595 root_scrolling->SetScrollClipLayer(root->id());
2596 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2597 LayerImpl* root_scrolling_ptr = root_scrolling.get();
2598 root->AddChild(root_scrolling.Pass());
2599 int child_scroll_layer_id = 3;
2600 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
2601 child_scroll_layer_id, surface_size, root_scrolling_ptr);
2602 LayerImpl* child = child_scrolling.get();
2603 root_scrolling_ptr->AddChild(child_scrolling.Pass());
2604 host_impl_->active_tree()->SetRootLayer(root.Pass());
2605 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2606 host_impl_->active_tree()->DidBecomeActive();
2607 host_impl_->SetViewportSize(surface_size);
2608 DrawFrame();
2610 gfx::Vector2d scroll_delta(0, 10);
2611 gfx::Vector2d expected_scroll_delta(scroll_delta);
2612 gfx::Vector2d expected_max_scroll(child->MaxScrollOffset());
2613 EXPECT_EQ(InputHandler::ScrollStarted,
2614 host_impl_->ScrollBegin(gfx::Point(5, 5),
2615 InputHandler::Wheel));
2616 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2617 host_impl_->ScrollEnd();
2619 float page_scale = 2.f;
2620 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2621 1.f,
2622 page_scale);
2624 DrawOneFrame();
2626 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2627 ExpectContains(
2628 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
2630 // The scroll range should not have changed.
2631 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
2633 // The page scale delta remains constant because the impl thread did not
2634 // scale.
2635 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2638 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
2639 // Scroll a child layer beyond its maximum scroll range and make sure the
2640 // parent layer is scrolled on the axis on which the child was unable to
2641 // scroll.
2642 gfx::Size surface_size(10, 10);
2643 gfx::Size content_size(20, 20);
2644 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2645 root->SetBounds(surface_size);
2647 scoped_ptr<LayerImpl> grand_child =
2648 CreateScrollableLayer(3, content_size, root.get());
2650 scoped_ptr<LayerImpl> child =
2651 CreateScrollableLayer(2, content_size, root.get());
2652 LayerImpl* grand_child_layer = grand_child.get();
2653 child->AddChild(grand_child.Pass());
2655 LayerImpl* child_layer = child.get();
2656 root->AddChild(child.Pass());
2657 host_impl_->active_tree()->SetRootLayer(root.Pass());
2658 host_impl_->active_tree()->DidBecomeActive();
2659 host_impl_->SetViewportSize(surface_size);
2660 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 5));
2661 child_layer->SetScrollOffset(gfx::Vector2d(3, 0));
2663 DrawFrame();
2665 gfx::Vector2d scroll_delta(-8, -7);
2666 EXPECT_EQ(InputHandler::ScrollStarted,
2667 host_impl_->ScrollBegin(gfx::Point(),
2668 InputHandler::Wheel));
2669 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2670 host_impl_->ScrollEnd();
2672 scoped_ptr<ScrollAndScaleSet> scroll_info =
2673 host_impl_->ProcessScrollDeltas();
2675 // The grand child should have scrolled up to its limit.
2676 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2677 LayerImpl* grand_child = child->children()[0];
2678 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
2680 // The child should have only scrolled on the other axis.
2681 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
2685 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
2686 // Scroll a child layer beyond its maximum scroll range and make sure the
2687 // the scroll doesn't bubble up to the parent layer.
2688 gfx::Size surface_size(20, 20);
2689 gfx::Size viewport_size(10, 10);
2690 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2691 scoped_ptr<LayerImpl> root_scrolling =
2692 CreateScrollableLayer(2, surface_size, root.get());
2693 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2695 scoped_ptr<LayerImpl> grand_child =
2696 CreateScrollableLayer(4, surface_size, root.get());
2698 scoped_ptr<LayerImpl> child =
2699 CreateScrollableLayer(3, surface_size, root.get());
2700 LayerImpl* grand_child_layer = grand_child.get();
2701 child->AddChild(grand_child.Pass());
2703 LayerImpl* child_layer = child.get();
2704 root_scrolling->AddChild(child.Pass());
2705 root->AddChild(root_scrolling.Pass());
2706 EXPECT_EQ(viewport_size, root->bounds());
2707 host_impl_->active_tree()->SetRootLayer(root.Pass());
2708 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2709 host_impl_->active_tree()->DidBecomeActive();
2710 host_impl_->SetViewportSize(viewport_size);
2712 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
2713 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
2715 DrawFrame();
2717 gfx::Vector2d scroll_delta(0, -10);
2718 EXPECT_EQ(InputHandler::ScrollStarted,
2719 host_impl_->ScrollBegin(gfx::Point(),
2720 InputHandler::NonBubblingGesture));
2721 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2722 host_impl_->ScrollEnd();
2724 scoped_ptr<ScrollAndScaleSet> scroll_info =
2725 host_impl_->ProcessScrollDeltas();
2727 // The grand child should have scrolled up to its limit.
2728 LayerImpl* child =
2729 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
2730 LayerImpl* grand_child = child->children()[0];
2731 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2733 // The child should not have scrolled.
2734 ExpectNone(*scroll_info.get(), child->id());
2736 // The next time we scroll we should only scroll the parent.
2737 scroll_delta = gfx::Vector2d(0, -3);
2738 EXPECT_EQ(InputHandler::ScrollStarted,
2739 host_impl_->ScrollBegin(gfx::Point(5, 5),
2740 InputHandler::NonBubblingGesture));
2741 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2742 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2743 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
2744 host_impl_->ScrollEnd();
2746 scroll_info = host_impl_->ProcessScrollDeltas();
2748 // The child should have scrolled up to its limit.
2749 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2751 // The grand child should not have scrolled.
2752 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2754 // After scrolling the parent, another scroll on the opposite direction
2755 // should still scroll the child.
2756 scroll_delta = gfx::Vector2d(0, 7);
2757 EXPECT_EQ(InputHandler::ScrollStarted,
2758 host_impl_->ScrollBegin(gfx::Point(5, 5),
2759 InputHandler::NonBubblingGesture));
2760 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2761 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2762 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2763 host_impl_->ScrollEnd();
2765 scroll_info = host_impl_->ProcessScrollDeltas();
2767 // The grand child should have scrolled.
2768 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
2770 // The child should not have scrolled.
2771 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2774 // Scrolling should be adjusted from viewport space.
2775 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
2776 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2778 scroll_delta = gfx::Vector2d(0, -2);
2779 EXPECT_EQ(InputHandler::ScrollStarted,
2780 host_impl_->ScrollBegin(gfx::Point(1, 1),
2781 InputHandler::NonBubblingGesture));
2782 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
2783 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2784 host_impl_->ScrollEnd();
2786 scroll_info = host_impl_->ProcessScrollDeltas();
2788 // Should have scrolled by half the amount in layer space (5 - 2/2)
2789 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
2792 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
2793 // When we try to scroll a non-scrollable child layer, the scroll delta
2794 // should be applied to one of its ancestors if possible.
2795 gfx::Size surface_size(10, 10);
2796 gfx::Size content_size(20, 20);
2797 scoped_ptr<LayerImpl> root_clip =
2798 LayerImpl::Create(host_impl_->active_tree(), 3);
2799 scoped_ptr<LayerImpl> root =
2800 CreateScrollableLayer(1, content_size, root_clip.get());
2801 // Make 'root' the clip layer for child: since they have the same sizes the
2802 // child will have zero max_scroll_offset and scrolls will bubble.
2803 scoped_ptr<LayerImpl> child =
2804 CreateScrollableLayer(2, content_size, root.get());
2805 child->SetIsContainerForFixedPositionLayers(true);
2806 root->SetBounds(content_size);
2808 int root_scroll_id = root->id();
2809 root->AddChild(child.Pass());
2810 root_clip->AddChild(root.Pass());
2812 host_impl_->SetViewportSize(surface_size);
2813 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2814 host_impl_->active_tree()->SetViewportLayersFromIds(3, 2, Layer::INVALID_ID);
2815 host_impl_->active_tree()->DidBecomeActive();
2816 DrawFrame();
2818 gfx::Vector2d scroll_delta(0, 4);
2819 EXPECT_EQ(InputHandler::ScrollStarted,
2820 host_impl_->ScrollBegin(gfx::Point(5, 5),
2821 InputHandler::Wheel));
2822 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2823 host_impl_->ScrollEnd();
2825 scoped_ptr<ScrollAndScaleSet> scroll_info =
2826 host_impl_->ProcessScrollDeltas();
2828 // Only the root scroll should have scrolled.
2829 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
2830 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
2834 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
2835 gfx::Size surface_size(10, 10);
2836 scoped_ptr<LayerImpl> root_clip =
2837 LayerImpl::Create(host_impl_->active_tree(), 1);
2838 scoped_ptr<LayerImpl> root_scroll =
2839 CreateScrollableLayer(2, surface_size, root_clip.get());
2840 root_scroll->SetIsContainerForFixedPositionLayers(true);
2841 root_clip->AddChild(root_scroll.Pass());
2842 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2843 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2844 host_impl_->active_tree()->DidBecomeActive();
2845 host_impl_->SetViewportSize(surface_size);
2847 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
2848 // synchronization.
2849 DrawFrame();
2850 host_impl_->active_tree()->DetachLayerTree();
2851 scoped_ptr<LayerImpl> root_clip2 =
2852 LayerImpl::Create(host_impl_->active_tree(), 3);
2853 scoped_ptr<LayerImpl> root_scroll2 =
2854 CreateScrollableLayer(4, surface_size, root_clip2.get());
2855 root_scroll2->SetIsContainerForFixedPositionLayers(true);
2856 root_clip2->AddChild(root_scroll2.Pass());
2857 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
2858 host_impl_->active_tree()->SetViewportLayersFromIds(3, 4, Layer::INVALID_ID);
2859 host_impl_->active_tree()->DidBecomeActive();
2861 // Scrolling should still work even though we did not draw yet.
2862 EXPECT_EQ(InputHandler::ScrollStarted,
2863 host_impl_->ScrollBegin(gfx::Point(5, 5),
2864 InputHandler::Wheel));
2867 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
2868 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2870 // Rotate the root layer 90 degrees counter-clockwise about its center.
2871 gfx::Transform rotate_transform;
2872 rotate_transform.Rotate(-90.0);
2873 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
2875 gfx::Size surface_size(50, 50);
2876 host_impl_->SetViewportSize(surface_size);
2877 DrawFrame();
2879 // Scroll to the right in screen coordinates with a gesture.
2880 gfx::Vector2d gesture_scroll_delta(10, 0);
2881 EXPECT_EQ(InputHandler::ScrollStarted,
2882 host_impl_->ScrollBegin(gfx::Point(),
2883 InputHandler::Gesture));
2884 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2885 host_impl_->ScrollEnd();
2887 // The layer should have scrolled down in its local coordinates.
2888 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2889 ExpectContains(*scroll_info.get(),
2890 scroll_layer->id(),
2891 gfx::Vector2d(0, gesture_scroll_delta.x()));
2893 // Reset and scroll down with the wheel.
2894 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2895 gfx::Vector2d wheel_scroll_delta(0, 10);
2896 EXPECT_EQ(InputHandler::ScrollStarted,
2897 host_impl_->ScrollBegin(gfx::Point(),
2898 InputHandler::Wheel));
2899 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2900 host_impl_->ScrollEnd();
2902 // The layer should have scrolled down in its local coordinates.
2903 scroll_info = host_impl_->ProcessScrollDeltas();
2904 ExpectContains(*scroll_info.get(),
2905 scroll_layer->id(),
2906 wheel_scroll_delta);
2909 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
2910 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2911 int child_clip_layer_id = 6;
2912 int child_layer_id = 7;
2913 float child_layer_angle = -20.f;
2915 // Create a child layer that is rotated to a non-axis-aligned angle.
2916 scoped_ptr<LayerImpl> clip_layer =
2917 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
2918 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
2919 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
2920 gfx::Transform rotate_transform;
2921 rotate_transform.Translate(-50.0, -50.0);
2922 rotate_transform.Rotate(child_layer_angle);
2923 rotate_transform.Translate(50.0, 50.0);
2924 clip_layer->SetTransform(rotate_transform);
2926 // Only allow vertical scrolling.
2927 clip_layer->SetBounds(
2928 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
2929 // The rotation depends on the layer's transform origin, and the child layer
2930 // is a different size than the clip, so make sure the clip layer's origin
2931 // lines up over the child.
2932 clip_layer->SetTransformOrigin(gfx::Point3F(
2933 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
2934 LayerImpl* child_ptr = child.get();
2935 clip_layer->AddChild(child.Pass());
2936 scroll_layer->AddChild(clip_layer.Pass());
2938 gfx::Size surface_size(50, 50);
2939 host_impl_->SetViewportSize(surface_size);
2940 DrawFrame();
2942 // Scroll down in screen coordinates with a gesture.
2943 gfx::Vector2d gesture_scroll_delta(0, 10);
2944 EXPECT_EQ(InputHandler::ScrollStarted,
2945 host_impl_->ScrollBegin(gfx::Point(1, 1),
2946 InputHandler::Gesture));
2947 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2948 host_impl_->ScrollEnd();
2950 // The child layer should have scrolled down in its local coordinates an
2951 // amount proportional to the angle between it and the input scroll delta.
2952 gfx::Vector2d expected_scroll_delta(
2954 gesture_scroll_delta.y() *
2955 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
2956 scoped_ptr<ScrollAndScaleSet> scroll_info =
2957 host_impl_->ProcessScrollDeltas();
2958 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2960 // The root scroll layer should not have scrolled, because the input delta
2961 // was close to the layer's axis of movement.
2962 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
2965 // Now reset and scroll the same amount horizontally.
2966 child_ptr->SetScrollDelta(gfx::Vector2dF());
2967 gfx::Vector2d gesture_scroll_delta(10, 0);
2968 EXPECT_EQ(InputHandler::ScrollStarted,
2969 host_impl_->ScrollBegin(gfx::Point(1, 1),
2970 InputHandler::Gesture));
2971 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2972 host_impl_->ScrollEnd();
2974 // The child layer should have scrolled down in its local coordinates an
2975 // amount proportional to the angle between it and the input scroll delta.
2976 gfx::Vector2d expected_scroll_delta(
2978 -gesture_scroll_delta.x() *
2979 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
2980 scoped_ptr<ScrollAndScaleSet> scroll_info =
2981 host_impl_->ProcessScrollDeltas();
2982 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2984 // The root scroll layer should have scrolled more, since the input scroll
2985 // delta was mostly orthogonal to the child layer's vertical scroll axis.
2986 gfx::Vector2d expected_root_scroll_delta(
2987 gesture_scroll_delta.x() *
2988 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
2990 ExpectContains(*scroll_info.get(),
2991 scroll_layer->id(),
2992 expected_root_scroll_delta);
2996 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
2997 LayerImpl* scroll_layer =
2998 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3000 // Scale the layer to twice its normal size.
3001 int scale = 2;
3002 gfx::Transform scale_transform;
3003 scale_transform.Scale(scale, scale);
3004 scroll_layer->SetTransform(scale_transform);
3006 gfx::Size surface_size(50, 50);
3007 host_impl_->SetViewportSize(surface_size);
3008 DrawFrame();
3010 // Scroll down in screen coordinates with a gesture.
3011 gfx::Vector2d scroll_delta(0, 10);
3012 EXPECT_EQ(InputHandler::ScrollStarted,
3013 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3014 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3015 host_impl_->ScrollEnd();
3017 // The layer should have scrolled down in its local coordinates, but half the
3018 // amount.
3019 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3020 ExpectContains(*scroll_info.get(),
3021 scroll_layer->id(),
3022 gfx::Vector2d(0, scroll_delta.y() / scale));
3024 // Reset and scroll down with the wheel.
3025 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3026 gfx::Vector2d wheel_scroll_delta(0, 10);
3027 EXPECT_EQ(InputHandler::ScrollStarted,
3028 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3029 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3030 host_impl_->ScrollEnd();
3032 // The scale should not have been applied to the scroll delta.
3033 scroll_info = host_impl_->ProcessScrollDeltas();
3034 ExpectContains(*scroll_info.get(),
3035 scroll_layer->id(),
3036 wheel_scroll_delta);
3039 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
3040 public:
3041 TestScrollOffsetDelegate()
3042 : page_scale_factor_(0.f),
3043 min_page_scale_factor_(-1.f),
3044 max_page_scale_factor_(-1.f) {}
3046 virtual ~TestScrollOffsetDelegate() {}
3048 virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
3049 return getter_return_value_;
3052 virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
3054 virtual void UpdateRootLayerState(const gfx::Vector2dF& total_scroll_offset,
3055 const gfx::Vector2dF& max_scroll_offset,
3056 const gfx::SizeF& scrollable_size,
3057 float page_scale_factor,
3058 float min_page_scale_factor,
3059 float max_page_scale_factor) OVERRIDE {
3060 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
3061 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
3062 last_set_scroll_offset_ = total_scroll_offset;
3063 max_scroll_offset_ = max_scroll_offset;
3064 scrollable_size_ = scrollable_size;
3065 page_scale_factor_ = page_scale_factor;
3066 min_page_scale_factor_ = min_page_scale_factor;
3067 max_page_scale_factor_ = max_page_scale_factor;
3070 gfx::Vector2dF last_set_scroll_offset() {
3071 return last_set_scroll_offset_;
3074 void set_getter_return_value(const gfx::Vector2dF& value) {
3075 getter_return_value_ = value;
3078 gfx::Vector2dF max_scroll_offset() const {
3079 return max_scroll_offset_;
3082 gfx::SizeF scrollable_size() const {
3083 return scrollable_size_;
3086 float page_scale_factor() const {
3087 return page_scale_factor_;
3090 float min_page_scale_factor() const {
3091 return min_page_scale_factor_;
3094 float max_page_scale_factor() const {
3095 return max_page_scale_factor_;
3098 private:
3099 gfx::Vector2dF last_set_scroll_offset_;
3100 gfx::Vector2dF getter_return_value_;
3101 gfx::Vector2dF max_scroll_offset_;
3102 gfx::SizeF scrollable_size_;
3103 float page_scale_factor_;
3104 float min_page_scale_factor_;
3105 float max_page_scale_factor_;
3108 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
3109 TestScrollOffsetDelegate scroll_delegate;
3110 host_impl_->SetViewportSize(gfx::Size(10, 20));
3111 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3112 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3113 clip_layer->SetBounds(gfx::Size(10, 20));
3115 // Setting the delegate results in the current scroll offset being set.
3116 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
3117 scroll_layer->SetScrollOffset(gfx::Vector2d());
3118 scroll_layer->SetScrollDelta(initial_scroll_delta);
3119 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3120 EXPECT_EQ(initial_scroll_delta.ToString(),
3121 scroll_delegate.last_set_scroll_offset().ToString());
3123 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3124 // page_scale_factor and {min|max}_page_scale_factor being set.
3125 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
3126 EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
3127 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3128 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
3129 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
3131 // Updating page scale immediately updates the delegate.
3132 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
3133 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
3134 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3135 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3136 host_impl_->active_tree()->SetPageScaleDelta(1.5f);
3137 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
3138 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3139 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3140 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3141 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3142 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3143 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3144 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3146 // The pinch gesture doesn't put the delegate into a state where the scroll
3147 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3148 // delegate).
3149 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3150 host_impl_->PinchGestureBegin();
3151 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
3152 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
3153 host_impl_->PinchGestureEnd();
3154 host_impl_->ScrollEnd();
3156 // Scrolling should be relative to the offset as returned by the delegate.
3157 gfx::Vector2dF scroll_delta(0.f, 10.f);
3158 gfx::Vector2dF current_offset(7.f, 8.f);
3160 scroll_delegate.set_getter_return_value(current_offset);
3161 EXPECT_EQ(InputHandler::ScrollStarted,
3162 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3164 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3165 EXPECT_EQ(current_offset + scroll_delta,
3166 scroll_delegate.last_set_scroll_offset());
3168 current_offset = gfx::Vector2dF(42.f, 41.f);
3169 scroll_delegate.set_getter_return_value(current_offset);
3170 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3171 EXPECT_EQ(current_offset + scroll_delta,
3172 scroll_delegate.last_set_scroll_offset());
3173 host_impl_->ScrollEnd();
3174 scroll_delegate.set_getter_return_value(gfx::Vector2dF());
3176 // Forces a full tree synchronization and ensures that the scroll delegate
3177 // sees the correct size of the new tree.
3178 gfx::Size new_size(42, 24);
3179 host_impl_->CreatePendingTree();
3180 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
3181 host_impl_->ActivateSyncTree();
3182 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
3184 // Un-setting the delegate should propagate the delegate's current offset to
3185 // the root scrollable layer.
3186 current_offset = gfx::Vector2dF(13.f, 12.f);
3187 scroll_delegate.set_getter_return_value(current_offset);
3188 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3190 EXPECT_EQ(current_offset.ToString(),
3191 scroll_layer->TotalScrollOffset().ToString());
3194 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
3195 const gfx::Transform target_space_transform =
3196 layer->draw_properties().target_space_transform;
3197 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
3198 gfx::Point translated_point;
3199 target_space_transform.TransformPoint(&translated_point);
3200 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
3201 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
3204 TEST_F(LayerTreeHostImplTest,
3205 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
3206 TestScrollOffsetDelegate scroll_delegate;
3207 host_impl_->SetViewportSize(gfx::Size(10, 20));
3208 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3209 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3210 clip_layer->SetBounds(gfx::Size(10, 20));
3211 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3213 // Draw first frame to clear any pending draws and check scroll.
3214 DrawFrame();
3215 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
3216 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
3218 // Set external scroll delta on delegate and notify LayerTreeHost.
3219 gfx::Vector2dF scroll_delta(10.f, 10.f);
3220 scroll_delegate.set_getter_return_value(scroll_delta);
3221 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
3223 // Check scroll delta reflected in layer.
3224 DrawFrame();
3225 CheckLayerScrollDelta(scroll_layer, scroll_delta);
3227 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3230 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
3231 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3232 host_impl_->SetViewportSize(gfx::Size(50, 50));
3233 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3234 DrawFrame();
3235 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3237 // In-bounds scrolling does not affect overscroll.
3238 EXPECT_EQ(InputHandler::ScrollStarted,
3239 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3240 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3241 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3243 // Overscroll events are reflected immediately.
3244 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
3245 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3247 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
3248 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
3249 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3250 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
3251 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3252 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
3253 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3254 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
3255 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
3256 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
3257 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
3258 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
3259 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3261 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
3262 // as no scroll occurs.
3263 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3264 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
3265 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3266 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
3267 // Overscroll resets on valid scroll.
3268 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3269 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3270 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3271 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3272 host_impl_->ScrollEnd();
3276 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
3277 // Scroll child layers beyond their maximum scroll range and make sure root
3278 // overscroll does not accumulate.
3279 gfx::Size surface_size(10, 10);
3280 scoped_ptr<LayerImpl> root_clip =
3281 LayerImpl::Create(host_impl_->active_tree(), 4);
3282 scoped_ptr<LayerImpl> root =
3283 CreateScrollableLayer(1, surface_size, root_clip.get());
3285 scoped_ptr<LayerImpl> grand_child =
3286 CreateScrollableLayer(3, surface_size, root_clip.get());
3288 scoped_ptr<LayerImpl> child =
3289 CreateScrollableLayer(2, surface_size, root_clip.get());
3290 LayerImpl* grand_child_layer = grand_child.get();
3291 child->AddChild(grand_child.Pass());
3293 LayerImpl* child_layer = child.get();
3294 root->AddChild(child.Pass());
3295 root_clip->AddChild(root.Pass());
3296 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
3297 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
3298 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3299 host_impl_->active_tree()->DidBecomeActive();
3300 host_impl_->SetViewportSize(surface_size);
3301 DrawFrame();
3303 gfx::Vector2d scroll_delta(0, -10);
3304 EXPECT_EQ(InputHandler::ScrollStarted,
3305 host_impl_->ScrollBegin(gfx::Point(),
3306 InputHandler::NonBubblingGesture));
3307 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3308 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3309 host_impl_->ScrollEnd();
3311 // The next time we scroll we should only scroll the parent, but overscroll
3312 // should still not reach the root layer.
3313 scroll_delta = gfx::Vector2d(0, -30);
3314 EXPECT_EQ(InputHandler::ScrollStarted,
3315 host_impl_->ScrollBegin(gfx::Point(5, 5),
3316 InputHandler::NonBubblingGesture));
3317 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3318 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3319 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3320 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
3321 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3322 host_impl_->ScrollEnd();
3324 // After scrolling the parent, another scroll on the opposite direction
3325 // should scroll the child.
3326 scroll_delta = gfx::Vector2d(0, 70);
3327 EXPECT_EQ(InputHandler::ScrollStarted,
3328 host_impl_->ScrollBegin(gfx::Point(5, 5),
3329 InputHandler::NonBubblingGesture));
3330 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3331 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3332 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3333 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3334 host_impl_->ScrollEnd();
3338 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
3339 // When we try to scroll a non-scrollable child layer, the scroll delta
3340 // should be applied to one of its ancestors if possible. Overscroll should
3341 // be reflected only when it has bubbled up to the root scrolling layer.
3342 gfx::Size surface_size(10, 10);
3343 gfx::Size content_size(20, 20);
3344 scoped_ptr<LayerImpl> root_clip =
3345 LayerImpl::Create(host_impl_->active_tree(), 3);
3346 scoped_ptr<LayerImpl> root =
3347 CreateScrollableLayer(1, content_size, root_clip.get());
3348 root->SetIsContainerForFixedPositionLayers(true);
3349 scoped_ptr<LayerImpl> child =
3350 CreateScrollableLayer(2, content_size, root_clip.get());
3352 child->SetScrollClipLayer(Layer::INVALID_ID);
3353 root->AddChild(child.Pass());
3354 root_clip->AddChild(root.Pass());
3356 host_impl_->SetViewportSize(surface_size);
3357 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3358 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3359 host_impl_->active_tree()->DidBecomeActive();
3360 DrawFrame();
3362 gfx::Vector2d scroll_delta(0, 8);
3363 EXPECT_EQ(InputHandler::ScrollStarted,
3364 host_impl_->ScrollBegin(gfx::Point(5, 5),
3365 InputHandler::Wheel));
3366 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3367 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3368 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3369 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
3370 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3371 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
3372 host_impl_->ScrollEnd();
3376 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
3377 LayerTreeSettings settings;
3378 CreateHostImpl(settings, CreateOutputSurface());
3380 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
3381 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3382 clip_layer->SetBounds(gfx::Size(50, 50));
3383 host_impl_->SetViewportSize(gfx::Size(50, 50));
3384 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3385 DrawFrame();
3386 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3388 // Even though the layer can't scroll the overscroll still happens.
3389 EXPECT_EQ(InputHandler::ScrollStarted,
3390 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3391 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3392 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3395 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
3396 gfx::Size surface_size(980, 1439);
3397 gfx::Size content_size(980, 1438);
3398 float device_scale_factor = 1.5f;
3399 scoped_ptr<LayerImpl> root_clip =
3400 LayerImpl::Create(host_impl_->active_tree(), 3);
3401 scoped_ptr<LayerImpl> root =
3402 CreateScrollableLayer(1, content_size, root_clip.get());
3403 root->SetIsContainerForFixedPositionLayers(true);
3404 scoped_ptr<LayerImpl> child =
3405 CreateScrollableLayer(2, content_size, root_clip.get());
3406 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
3407 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
3408 0.326531f, 0.326531f, 5.f);
3409 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3410 child->SetScrollClipLayer(Layer::INVALID_ID);
3411 root->AddChild(child.Pass());
3412 root_clip->AddChild(root.Pass());
3414 host_impl_->SetViewportSize(surface_size);
3415 host_impl_->SetDeviceScaleFactor(device_scale_factor);
3416 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3417 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3418 host_impl_->active_tree()->DidBecomeActive();
3419 DrawFrame();
3421 // Horizontal & Vertical GlowEffect should not be applied when
3422 // content size is less then view port size. For Example Horizontal &
3423 // vertical GlowEffect should not be applied in about:blank page.
3424 EXPECT_EQ(InputHandler::ScrollStarted,
3425 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3426 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
3427 EXPECT_EQ(gfx::Vector2dF().ToString(),
3428 host_impl_->accumulated_root_overscroll().ToString());
3430 host_impl_->ScrollEnd();
3434 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
3435 gfx::Size surface_size(100, 100);
3436 gfx::Size content_size(200, 200);
3437 scoped_ptr<LayerImpl> root_clip =
3438 LayerImpl::Create(host_impl_->active_tree(), 3);
3439 scoped_ptr<LayerImpl> root =
3440 CreateScrollableLayer(1, content_size, root_clip.get());
3441 root->SetIsContainerForFixedPositionLayers(true);
3442 scoped_ptr<LayerImpl> child =
3443 CreateScrollableLayer(2, content_size, root_clip.get());
3445 child->SetScrollClipLayer(Layer::INVALID_ID);
3446 root->AddChild(child.Pass());
3447 root_clip->AddChild(root.Pass());
3449 host_impl_->SetViewportSize(surface_size);
3450 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3451 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3452 host_impl_->active_tree()->DidBecomeActive();
3453 DrawFrame();
3455 // Edge glow effect should be applicable only upon reaching Edges
3456 // of the content. unnecessary glow effect calls shouldn't be
3457 // called while scrolling up without reaching the edge of the content.
3458 EXPECT_EQ(InputHandler::ScrollStarted,
3459 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3460 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
3461 EXPECT_EQ(gfx::Vector2dF().ToString(),
3462 host_impl_->accumulated_root_overscroll().ToString());
3463 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
3464 EXPECT_EQ(gfx::Vector2dF().ToString(),
3465 host_impl_->accumulated_root_overscroll().ToString());
3466 host_impl_->ScrollEnd();
3467 // unusedrootDelta should be subtracted from applied delta so that
3468 // unwanted glow effect calls are not called.
3469 EXPECT_EQ(InputHandler::ScrollStarted,
3470 host_impl_->ScrollBegin(gfx::Point(0, 0),
3471 InputHandler::NonBubblingGesture));
3472 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
3473 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
3474 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3475 host_impl_->accumulated_root_overscroll().ToString());
3477 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
3478 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3479 host_impl_->accumulated_root_overscroll().ToString());
3480 host_impl_->ScrollEnd();
3481 // TestCase to check kEpsilon, which prevents minute values to trigger
3482 // gloweffect without reaching edge.
3483 EXPECT_EQ(InputHandler::ScrollStarted,
3484 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3485 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
3486 EXPECT_EQ(gfx::Vector2dF().ToString(),
3487 host_impl_->accumulated_root_overscroll().ToString());
3488 host_impl_->ScrollEnd();
3492 class BlendStateCheckLayer : public LayerImpl {
3493 public:
3494 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
3495 int id,
3496 ResourceProvider* resource_provider) {
3497 return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(tree_impl,
3499 resource_provider));
3502 virtual void AppendQuads(RenderPass* render_pass,
3503 const OcclusionTracker<LayerImpl>& occlusion_tracker,
3504 AppendQuadsData* append_quads_data) OVERRIDE {
3505 quads_appended_ = true;
3507 gfx::Rect opaque_rect;
3508 if (contents_opaque())
3509 opaque_rect = quad_rect_;
3510 else
3511 opaque_rect = opaque_content_rect_;
3512 gfx::Rect visible_quad_rect = quad_rect_;
3514 SharedQuadState* shared_quad_state =
3515 render_pass->CreateAndAppendSharedQuadState();
3516 PopulateSharedQuadState(shared_quad_state);
3518 TileDrawQuad* test_blending_draw_quad =
3519 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
3520 test_blending_draw_quad->SetNew(shared_quad_state,
3521 quad_rect_,
3522 opaque_rect,
3523 visible_quad_rect,
3524 resource_id_,
3525 gfx::RectF(0.f, 0.f, 1.f, 1.f),
3526 gfx::Size(1, 1),
3527 false);
3528 test_blending_draw_quad->visible_rect = quad_visible_rect_;
3529 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
3530 EXPECT_EQ(has_render_surface_, !!render_surface());
3533 void SetExpectation(bool blend, bool has_render_surface) {
3534 blend_ = blend;
3535 has_render_surface_ = has_render_surface;
3536 quads_appended_ = false;
3539 bool quads_appended() const { return quads_appended_; }
3541 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
3542 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
3543 void SetOpaqueContentRect(const gfx::Rect& rect) {
3544 opaque_content_rect_ = rect;
3547 private:
3548 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
3549 int id,
3550 ResourceProvider* resource_provider)
3551 : LayerImpl(tree_impl, id),
3552 blend_(false),
3553 has_render_surface_(false),
3554 quads_appended_(false),
3555 quad_rect_(5, 5, 5, 5),
3556 quad_visible_rect_(5, 5, 5, 5),
3557 resource_id_(resource_provider->CreateResource(
3558 gfx::Size(1, 1),
3559 GL_CLAMP_TO_EDGE,
3560 ResourceProvider::TextureUsageAny,
3561 RGBA_8888)) {
3562 resource_provider->AllocateForTesting(resource_id_);
3563 SetBounds(gfx::Size(10, 10));
3564 SetContentBounds(gfx::Size(10, 10));
3565 SetDrawsContent(true);
3568 bool blend_;
3569 bool has_render_surface_;
3570 bool quads_appended_;
3571 gfx::Rect quad_rect_;
3572 gfx::Rect opaque_content_rect_;
3573 gfx::Rect quad_visible_rect_;
3574 ResourceProvider::ResourceId resource_id_;
3577 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
3579 scoped_ptr<LayerImpl> root =
3580 LayerImpl::Create(host_impl_->active_tree(), 1);
3581 root->SetBounds(gfx::Size(10, 10));
3582 root->SetContentBounds(root->bounds());
3583 root->SetDrawsContent(false);
3584 host_impl_->active_tree()->SetRootLayer(root.Pass());
3586 LayerImpl* root = host_impl_->active_tree()->root_layer();
3588 root->AddChild(
3589 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3591 host_impl_->resource_provider()));
3592 BlendStateCheckLayer* layer1 =
3593 static_cast<BlendStateCheckLayer*>(root->children()[0]);
3594 layer1->SetPosition(gfx::PointF(2.f, 2.f));
3596 LayerTreeHostImpl::FrameData frame;
3598 // Opaque layer, drawn without blending.
3599 layer1->SetContentsOpaque(true);
3600 layer1->SetExpectation(false, false);
3601 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3602 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3603 host_impl_->DrawLayers(&frame);
3604 EXPECT_TRUE(layer1->quads_appended());
3605 host_impl_->DidDrawAllLayers(frame);
3607 // Layer with translucent content and painting, so drawn with blending.
3608 layer1->SetContentsOpaque(false);
3609 layer1->SetExpectation(true, false);
3610 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3611 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3612 host_impl_->DrawLayers(&frame);
3613 EXPECT_TRUE(layer1->quads_appended());
3614 host_impl_->DidDrawAllLayers(frame);
3616 // Layer with translucent opacity, drawn with blending.
3617 layer1->SetContentsOpaque(true);
3618 layer1->SetOpacity(0.5f);
3619 layer1->SetExpectation(true, false);
3620 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3621 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3622 host_impl_->DrawLayers(&frame);
3623 EXPECT_TRUE(layer1->quads_appended());
3624 host_impl_->DidDrawAllLayers(frame);
3626 // Layer with translucent opacity and painting, drawn with blending.
3627 layer1->SetContentsOpaque(true);
3628 layer1->SetOpacity(0.5f);
3629 layer1->SetExpectation(true, false);
3630 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3631 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3632 host_impl_->DrawLayers(&frame);
3633 EXPECT_TRUE(layer1->quads_appended());
3634 host_impl_->DidDrawAllLayers(frame);
3636 layer1->AddChild(
3637 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3639 host_impl_->resource_provider()));
3640 BlendStateCheckLayer* layer2 =
3641 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
3642 layer2->SetPosition(gfx::PointF(4.f, 4.f));
3644 // 2 opaque layers, drawn without blending.
3645 layer1->SetContentsOpaque(true);
3646 layer1->SetOpacity(1.f);
3647 layer1->SetExpectation(false, false);
3648 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3649 layer2->SetContentsOpaque(true);
3650 layer2->SetOpacity(1.f);
3651 layer2->SetExpectation(false, false);
3652 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3653 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3654 host_impl_->DrawLayers(&frame);
3655 EXPECT_TRUE(layer1->quads_appended());
3656 EXPECT_TRUE(layer2->quads_appended());
3657 host_impl_->DidDrawAllLayers(frame);
3659 // Parent layer with translucent content, drawn with blending.
3660 // Child layer with opaque content, drawn without blending.
3661 layer1->SetContentsOpaque(false);
3662 layer1->SetExpectation(true, false);
3663 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3664 layer2->SetExpectation(false, false);
3665 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3666 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3667 host_impl_->DrawLayers(&frame);
3668 EXPECT_TRUE(layer1->quads_appended());
3669 EXPECT_TRUE(layer2->quads_appended());
3670 host_impl_->DidDrawAllLayers(frame);
3672 // Parent layer with translucent content but opaque painting, drawn without
3673 // blending.
3674 // Child layer with opaque content, drawn without blending.
3675 layer1->SetContentsOpaque(true);
3676 layer1->SetExpectation(false, false);
3677 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3678 layer2->SetExpectation(false, false);
3679 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3680 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3681 host_impl_->DrawLayers(&frame);
3682 EXPECT_TRUE(layer1->quads_appended());
3683 EXPECT_TRUE(layer2->quads_appended());
3684 host_impl_->DidDrawAllLayers(frame);
3686 // Parent layer with translucent opacity and opaque content. Since it has a
3687 // drawing child, it's drawn to a render surface which carries the opacity,
3688 // so it's itself drawn without blending.
3689 // Child layer with opaque content, drawn without blending (parent surface
3690 // carries the inherited opacity).
3691 layer1->SetContentsOpaque(true);
3692 layer1->SetOpacity(0.5f);
3693 layer1->SetExpectation(false, true);
3694 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3695 layer2->SetExpectation(false, false);
3696 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3697 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3698 host_impl_->DrawLayers(&frame);
3699 EXPECT_TRUE(layer1->quads_appended());
3700 EXPECT_TRUE(layer2->quads_appended());
3701 host_impl_->DidDrawAllLayers(frame);
3703 // Draw again, but with child non-opaque, to make sure
3704 // layer1 not culled.
3705 layer1->SetContentsOpaque(true);
3706 layer1->SetOpacity(1.f);
3707 layer1->SetExpectation(false, false);
3708 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3709 layer2->SetContentsOpaque(true);
3710 layer2->SetOpacity(0.5f);
3711 layer2->SetExpectation(true, false);
3712 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3713 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3714 host_impl_->DrawLayers(&frame);
3715 EXPECT_TRUE(layer1->quads_appended());
3716 EXPECT_TRUE(layer2->quads_appended());
3717 host_impl_->DidDrawAllLayers(frame);
3719 // A second way of making the child non-opaque.
3720 layer1->SetContentsOpaque(true);
3721 layer1->SetOpacity(1.f);
3722 layer1->SetExpectation(false, false);
3723 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3724 layer2->SetContentsOpaque(false);
3725 layer2->SetOpacity(1.f);
3726 layer2->SetExpectation(true, false);
3727 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3728 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3729 host_impl_->DrawLayers(&frame);
3730 EXPECT_TRUE(layer1->quads_appended());
3731 EXPECT_TRUE(layer2->quads_appended());
3732 host_impl_->DidDrawAllLayers(frame);
3734 // And when the layer says its not opaque but is painted opaque, it is not
3735 // blended.
3736 layer1->SetContentsOpaque(true);
3737 layer1->SetOpacity(1.f);
3738 layer1->SetExpectation(false, false);
3739 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3740 layer2->SetContentsOpaque(true);
3741 layer2->SetOpacity(1.f);
3742 layer2->SetExpectation(false, false);
3743 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3744 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3745 host_impl_->DrawLayers(&frame);
3746 EXPECT_TRUE(layer1->quads_appended());
3747 EXPECT_TRUE(layer2->quads_appended());
3748 host_impl_->DidDrawAllLayers(frame);
3750 // Layer with partially opaque contents, drawn with blending.
3751 layer1->SetContentsOpaque(false);
3752 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3753 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
3754 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3755 layer1->SetExpectation(true, false);
3756 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3757 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3758 host_impl_->DrawLayers(&frame);
3759 EXPECT_TRUE(layer1->quads_appended());
3760 host_impl_->DidDrawAllLayers(frame);
3762 // Layer with partially opaque contents partially culled, drawn with blending.
3763 layer1->SetContentsOpaque(false);
3764 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3765 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
3766 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3767 layer1->SetExpectation(true, false);
3768 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3769 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3770 host_impl_->DrawLayers(&frame);
3771 EXPECT_TRUE(layer1->quads_appended());
3772 host_impl_->DidDrawAllLayers(frame);
3774 // Layer with partially opaque contents culled, drawn with blending.
3775 layer1->SetContentsOpaque(false);
3776 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3777 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
3778 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3779 layer1->SetExpectation(true, false);
3780 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3781 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3782 host_impl_->DrawLayers(&frame);
3783 EXPECT_TRUE(layer1->quads_appended());
3784 host_impl_->DidDrawAllLayers(frame);
3786 // Layer with partially opaque contents and translucent contents culled, drawn
3787 // without blending.
3788 layer1->SetContentsOpaque(false);
3789 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3790 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
3791 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3792 layer1->SetExpectation(false, false);
3793 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3794 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3795 host_impl_->DrawLayers(&frame);
3796 EXPECT_TRUE(layer1->quads_appended());
3797 host_impl_->DidDrawAllLayers(frame);
3800 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
3801 protected:
3802 LayerTreeHostImplViewportCoveredTest() :
3803 gutter_quad_material_(DrawQuad::SOLID_COLOR),
3804 child_(NULL),
3805 did_activate_pending_tree_(false) {}
3807 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
3808 if (always_draw) {
3809 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
3810 .PassAs<OutputSurface>();
3812 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
3815 void SetupActiveTreeLayers() {
3816 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
3817 host_impl_->active_tree()->SetRootLayer(
3818 LayerImpl::Create(host_impl_->active_tree(), 1));
3819 host_impl_->active_tree()->root_layer()->AddChild(
3820 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3822 host_impl_->resource_provider()));
3823 child_ = static_cast<BlendStateCheckLayer*>(
3824 host_impl_->active_tree()->root_layer()->children()[0]);
3825 child_->SetExpectation(false, false);
3826 child_->SetContentsOpaque(true);
3829 // Expect no gutter rects.
3830 void TestLayerCoversFullViewport() {
3831 gfx::Rect layer_rect(viewport_size_);
3832 child_->SetPosition(layer_rect.origin());
3833 child_->SetBounds(layer_rect.size());
3834 child_->SetContentBounds(layer_rect.size());
3835 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3836 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3838 LayerTreeHostImpl::FrameData frame;
3839 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3840 ASSERT_EQ(1u, frame.render_passes.size());
3842 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3843 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3844 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3846 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3847 host_impl_->DidDrawAllLayers(frame);
3850 // Expect fullscreen gutter rect.
3851 void TestEmptyLayer() {
3852 gfx::Rect layer_rect(0, 0, 0, 0);
3853 child_->SetPosition(layer_rect.origin());
3854 child_->SetBounds(layer_rect.size());
3855 child_->SetContentBounds(layer_rect.size());
3856 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3857 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3859 LayerTreeHostImpl::FrameData frame;
3860 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3861 ASSERT_EQ(1u, frame.render_passes.size());
3863 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
3864 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3865 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3867 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3868 host_impl_->DidDrawAllLayers(frame);
3871 // Expect four surrounding gutter rects.
3872 void TestLayerInMiddleOfViewport() {
3873 gfx::Rect layer_rect(500, 500, 200, 200);
3874 child_->SetPosition(layer_rect.origin());
3875 child_->SetBounds(layer_rect.size());
3876 child_->SetContentBounds(layer_rect.size());
3877 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3878 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3880 LayerTreeHostImpl::FrameData frame;
3881 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3882 ASSERT_EQ(1u, frame.render_passes.size());
3884 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
3885 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
3886 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3888 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3889 host_impl_->DidDrawAllLayers(frame);
3892 // Expect no gutter rects.
3893 void TestLayerIsLargerThanViewport() {
3894 gfx::Rect layer_rect(viewport_size_.width() + 10,
3895 viewport_size_.height() + 10);
3896 child_->SetPosition(layer_rect.origin());
3897 child_->SetBounds(layer_rect.size());
3898 child_->SetContentBounds(layer_rect.size());
3899 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3900 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3902 LayerTreeHostImpl::FrameData frame;
3903 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3904 ASSERT_EQ(1u, frame.render_passes.size());
3906 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3907 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3908 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3910 host_impl_->DidDrawAllLayers(frame);
3913 virtual void DidActivateSyncTree() OVERRIDE {
3914 did_activate_pending_tree_ = true;
3917 void set_gutter_quad_material(DrawQuad::Material material) {
3918 gutter_quad_material_ = material;
3920 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
3921 gutter_texture_size_ = gutter_texture_size;
3924 protected:
3925 size_t CountGutterQuads(const QuadList& quad_list) {
3926 size_t num_gutter_quads = 0;
3927 for (size_t i = 0; i < quad_list.size(); ++i) {
3928 num_gutter_quads += (quad_list[i]->material ==
3929 gutter_quad_material_) ? 1 : 0;
3931 return num_gutter_quads;
3934 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
3935 LayerTestCommon::VerifyQuadsExactlyCoverRect(
3936 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
3939 // Make sure that the texture coordinates match their expectations.
3940 void ValidateTextureDrawQuads(const QuadList& quad_list) {
3941 for (size_t i = 0; i < quad_list.size(); ++i) {
3942 if (quad_list[i]->material != DrawQuad::TEXTURE_CONTENT)
3943 continue;
3944 const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(quad_list[i]);
3945 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
3946 gutter_texture_size_, host_impl_->device_scale_factor());
3947 EXPECT_EQ(quad->uv_top_left.x(),
3948 quad->rect.x() / gutter_texture_size_pixels.width());
3949 EXPECT_EQ(quad->uv_top_left.y(),
3950 quad->rect.y() / gutter_texture_size_pixels.height());
3951 EXPECT_EQ(quad->uv_bottom_right.x(),
3952 quad->rect.right() / gutter_texture_size_pixels.width());
3953 EXPECT_EQ(quad->uv_bottom_right.y(),
3954 quad->rect.bottom() / gutter_texture_size_pixels.height());
3958 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
3959 return gfx::ToRoundedSize(
3960 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
3963 DrawQuad::Material gutter_quad_material_;
3964 gfx::Size gutter_texture_size_;
3965 gfx::Size viewport_size_;
3966 BlendStateCheckLayer* child_;
3967 bool did_activate_pending_tree_;
3970 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
3971 viewport_size_ = gfx::Size(1000, 1000);
3973 bool always_draw = false;
3974 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3976 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3977 SetupActiveTreeLayers();
3978 TestLayerCoversFullViewport();
3979 TestEmptyLayer();
3980 TestLayerInMiddleOfViewport();
3981 TestLayerIsLargerThanViewport();
3984 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
3985 viewport_size_ = gfx::Size(1000, 1000);
3987 bool always_draw = false;
3988 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3990 host_impl_->SetDeviceScaleFactor(2.f);
3991 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3992 SetupActiveTreeLayers();
3993 TestLayerCoversFullViewport();
3994 TestEmptyLayer();
3995 TestLayerInMiddleOfViewport();
3996 TestLayerIsLargerThanViewport();
3999 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
4000 viewport_size_ = gfx::Size(1000, 1000);
4002 bool always_draw = false;
4003 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4005 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4006 SetupActiveTreeLayers();
4008 // Specify an overhang bitmap to use.
4009 bool is_opaque = false;
4010 UIResourceBitmap ui_resource_bitmap(gfx::Size(2, 2), is_opaque);
4011 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
4012 UIResourceId ui_resource_id = 12345;
4013 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
4014 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
4015 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
4016 set_gutter_texture_size(gfx::Size(32, 32));
4018 TestLayerCoversFullViewport();
4019 TestEmptyLayer();
4020 TestLayerInMiddleOfViewport();
4021 TestLayerIsLargerThanViewport();
4023 // Change the resource size.
4024 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
4025 set_gutter_texture_size(gfx::Size(128, 16));
4027 TestLayerCoversFullViewport();
4028 TestEmptyLayer();
4029 TestLayerInMiddleOfViewport();
4030 TestLayerIsLargerThanViewport();
4032 // Change the device scale factor
4033 host_impl_->SetDeviceScaleFactor(2.f);
4034 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4036 TestLayerCoversFullViewport();
4037 TestEmptyLayer();
4038 TestLayerInMiddleOfViewport();
4039 TestLayerIsLargerThanViewport();
4042 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
4043 viewport_size_ = gfx::Size(1000, 1000);
4045 bool always_draw = true;
4046 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4048 // Pending tree to force active_tree size invalid. Not used otherwise.
4049 host_impl_->CreatePendingTree();
4050 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4051 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4053 SetupActiveTreeLayers();
4054 TestEmptyLayer();
4055 TestLayerInMiddleOfViewport();
4056 TestLayerIsLargerThanViewport();
4059 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
4060 viewport_size_ = gfx::Size(1000, 1000);
4062 bool always_draw = true;
4063 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4065 // Set larger viewport and activate it to active tree.
4066 host_impl_->CreatePendingTree();
4067 gfx::Size larger_viewport(viewport_size_.width() + 100,
4068 viewport_size_.height() + 100);
4069 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
4070 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4071 host_impl_->ActivateSyncTree();
4072 EXPECT_TRUE(did_activate_pending_tree_);
4073 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
4075 // Shrink pending tree viewport without activating.
4076 host_impl_->CreatePendingTree();
4077 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4078 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4080 SetupActiveTreeLayers();
4081 TestEmptyLayer();
4082 TestLayerInMiddleOfViewport();
4083 TestLayerIsLargerThanViewport();
4086 class FakeDrawableLayerImpl: public LayerImpl {
4087 public:
4088 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4089 return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(tree_impl, id));
4091 protected:
4092 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
4093 : LayerImpl(tree_impl, id) {}
4096 // Only reshape when we know we are going to draw. Otherwise, the reshape
4097 // can leave the window at the wrong size if we never draw and the proper
4098 // viewport size is never set.
4099 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
4100 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4101 scoped_ptr<OutputSurface> output_surface(
4102 FakeOutputSurface::Create3d(provider));
4103 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4105 scoped_ptr<LayerImpl> root =
4106 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4107 root->SetBounds(gfx::Size(10, 10));
4108 root->SetContentBounds(gfx::Size(10, 10));
4109 root->SetDrawsContent(true);
4110 host_impl_->active_tree()->SetRootLayer(root.Pass());
4111 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
4112 provider->TestContext3d()->clear_reshape_called();
4114 LayerTreeHostImpl::FrameData frame;
4115 host_impl_->SetViewportSize(gfx::Size(10, 10));
4116 host_impl_->SetDeviceScaleFactor(1.f);
4117 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4118 host_impl_->DrawLayers(&frame);
4119 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4120 EXPECT_EQ(provider->TestContext3d()->width(), 10);
4121 EXPECT_EQ(provider->TestContext3d()->height(), 10);
4122 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4123 host_impl_->DidDrawAllLayers(frame);
4124 provider->TestContext3d()->clear_reshape_called();
4126 host_impl_->SetViewportSize(gfx::Size(20, 30));
4127 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4128 host_impl_->DrawLayers(&frame);
4129 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4130 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4131 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4132 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4133 host_impl_->DidDrawAllLayers(frame);
4134 provider->TestContext3d()->clear_reshape_called();
4136 host_impl_->SetDeviceScaleFactor(2.f);
4137 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4138 host_impl_->DrawLayers(&frame);
4139 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4140 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4141 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4142 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
4143 host_impl_->DidDrawAllLayers(frame);
4144 provider->TestContext3d()->clear_reshape_called();
4147 // Make sure damage tracking propagates all the way to the graphics context,
4148 // where it should request to swap only the sub-buffer that is damaged.
4149 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
4150 scoped_refptr<TestContextProvider> context_provider(
4151 TestContextProvider::Create());
4152 context_provider->BindToCurrentThread();
4153 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
4155 scoped_ptr<OutputSurface> output_surface(
4156 FakeOutputSurface::Create3d(context_provider));
4158 // This test creates its own LayerTreeHostImpl, so
4159 // that we can force partial swap enabled.
4160 LayerTreeSettings settings;
4161 settings.partial_swap_enabled = true;
4162 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4163 new TestSharedBitmapManager());
4164 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
4165 LayerTreeHostImpl::Create(settings,
4166 this,
4167 &proxy_,
4168 &stats_instrumentation_,
4169 shared_bitmap_manager.get(),
4171 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
4172 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
4174 scoped_ptr<LayerImpl> root =
4175 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
4176 scoped_ptr<LayerImpl> child =
4177 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
4178 child->SetPosition(gfx::PointF(12.f, 13.f));
4179 child->SetBounds(gfx::Size(14, 15));
4180 child->SetContentBounds(gfx::Size(14, 15));
4181 child->SetDrawsContent(true);
4182 root->SetBounds(gfx::Size(500, 500));
4183 root->SetContentBounds(gfx::Size(500, 500));
4184 root->SetDrawsContent(true);
4185 root->AddChild(child.Pass());
4186 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
4188 LayerTreeHostImpl::FrameData frame;
4190 // First frame, the entire screen should get swapped.
4191 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4192 layer_tree_host_impl->DrawLayers(&frame);
4193 layer_tree_host_impl->DidDrawAllLayers(frame);
4194 layer_tree_host_impl->SwapBuffers(frame);
4195 EXPECT_EQ(TestContextSupport::SWAP,
4196 context_provider->support()->last_swap_type());
4198 // Second frame, only the damaged area should get swapped. Damage should be
4199 // the union of old and new child rects.
4200 // expected damage rect: gfx::Rect(26, 28);
4201 // expected swap rect: vertically flipped, with origin at bottom left corner.
4202 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
4203 gfx::PointF());
4204 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4205 layer_tree_host_impl->DrawLayers(&frame);
4206 host_impl_->DidDrawAllLayers(frame);
4207 layer_tree_host_impl->SwapBuffers(frame);
4209 // Make sure that partial swap is constrained to the viewport dimensions
4210 // expected damage rect: gfx::Rect(500, 500);
4211 // expected swap rect: flipped damage rect, but also clamped to viewport
4212 EXPECT_EQ(TestContextSupport::PARTIAL_SWAP,
4213 context_provider->support()->last_swap_type());
4214 gfx::Rect expected_swap_rect(0, 500-28, 26, 28);
4215 EXPECT_EQ(expected_swap_rect.ToString(),
4216 context_provider->support()->
4217 last_partial_swap_rect().ToString());
4219 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
4220 // This will damage everything.
4221 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
4222 SK_ColorBLACK);
4223 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4224 layer_tree_host_impl->DrawLayers(&frame);
4225 host_impl_->DidDrawAllLayers(frame);
4226 layer_tree_host_impl->SwapBuffers(frame);
4228 EXPECT_EQ(TestContextSupport::SWAP,
4229 context_provider->support()->last_swap_type());
4232 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
4233 scoped_ptr<LayerImpl> root =
4234 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4235 scoped_ptr<LayerImpl> child =
4236 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
4237 child->SetBounds(gfx::Size(10, 10));
4238 child->SetContentBounds(gfx::Size(10, 10));
4239 child->SetDrawsContent(true);
4240 root->SetBounds(gfx::Size(10, 10));
4241 root->SetContentBounds(gfx::Size(10, 10));
4242 root->SetDrawsContent(true);
4243 root->SetForceRenderSurface(true);
4244 root->AddChild(child.Pass());
4246 host_impl_->active_tree()->SetRootLayer(root.Pass());
4248 LayerTreeHostImpl::FrameData frame;
4250 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4251 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
4252 EXPECT_EQ(1u, frame.render_passes.size());
4253 host_impl_->DidDrawAllLayers(frame);
4256 class FakeLayerWithQuads : public LayerImpl {
4257 public:
4258 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4259 return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(tree_impl, id));
4262 virtual void AppendQuads(RenderPass* render_pass,
4263 const OcclusionTracker<LayerImpl>& occlusion_tracker,
4264 AppendQuadsData* append_quads_data) OVERRIDE {
4265 SharedQuadState* shared_quad_state =
4266 render_pass->CreateAndAppendSharedQuadState();
4267 PopulateSharedQuadState(shared_quad_state);
4269 SkColor gray = SkColorSetRGB(100, 100, 100);
4270 gfx::Rect quad_rect(content_bounds());
4271 gfx::Rect visible_quad_rect(quad_rect);
4272 SolidColorDrawQuad* my_quad =
4273 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4274 my_quad->SetNew(
4275 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
4278 private:
4279 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
4280 : LayerImpl(tree_impl, id) {}
4283 class MockContext : public TestWebGraphicsContext3D {
4284 public:
4285 MOCK_METHOD1(useProgram, void(GLuint program));
4286 MOCK_METHOD5(uniform4f, void(GLint location,
4287 GLfloat x,
4288 GLfloat y,
4289 GLfloat z,
4290 GLfloat w));
4291 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
4292 GLsizei count,
4293 GLboolean transpose,
4294 const GLfloat* value));
4295 MOCK_METHOD4(drawElements, void(GLenum mode,
4296 GLsizei count,
4297 GLenum type,
4298 GLintptr offset));
4299 MOCK_METHOD1(enable, void(GLenum cap));
4300 MOCK_METHOD1(disable, void(GLenum cap));
4301 MOCK_METHOD4(scissor, void(GLint x,
4302 GLint y,
4303 GLsizei width,
4304 GLsizei height));
4307 class MockContextHarness {
4308 private:
4309 MockContext* context_;
4311 public:
4312 explicit MockContextHarness(MockContext* context)
4313 : context_(context) {
4314 context_->set_have_post_sub_buffer(true);
4316 // Catch "uninteresting" calls
4317 EXPECT_CALL(*context_, useProgram(_))
4318 .Times(0);
4320 EXPECT_CALL(*context_, drawElements(_, _, _, _))
4321 .Times(0);
4323 // These are not asserted
4324 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
4325 .WillRepeatedly(Return());
4327 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
4328 .WillRepeatedly(Return());
4330 // Any un-sanctioned calls to enable() are OK
4331 EXPECT_CALL(*context_, enable(_))
4332 .WillRepeatedly(Return());
4334 // Any un-sanctioned calls to disable() are OK
4335 EXPECT_CALL(*context_, disable(_))
4336 .WillRepeatedly(Return());
4339 void MustDrawSolidQuad() {
4340 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
4341 .WillOnce(Return())
4342 .RetiresOnSaturation();
4344 EXPECT_CALL(*context_, useProgram(_))
4345 .WillOnce(Return())
4346 .RetiresOnSaturation();
4349 void MustSetScissor(int x, int y, int width, int height) {
4350 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4351 .WillRepeatedly(Return());
4353 EXPECT_CALL(*context_, scissor(x, y, width, height))
4354 .Times(AtLeast(1))
4355 .WillRepeatedly(Return());
4358 void MustSetNoScissor() {
4359 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
4360 .WillRepeatedly(Return());
4362 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4363 .Times(0);
4365 EXPECT_CALL(*context_, scissor(_, _, _, _))
4366 .Times(0);
4370 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
4371 scoped_ptr<MockContext> mock_context_owned(new MockContext);
4372 MockContext* mock_context = mock_context_owned.get();
4374 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4375 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4376 MockContextHarness harness(mock_context);
4378 // Run test case
4379 LayerTreeSettings settings = DefaultSettings();
4380 settings.partial_swap_enabled = false;
4381 CreateHostImpl(settings, output_surface.Pass());
4382 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4384 // Without partial swap, and no clipping, no scissor is set.
4385 harness.MustDrawSolidQuad();
4386 harness.MustSetNoScissor();
4388 LayerTreeHostImpl::FrameData frame;
4389 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4390 host_impl_->DrawLayers(&frame);
4391 host_impl_->DidDrawAllLayers(frame);
4393 Mock::VerifyAndClearExpectations(&mock_context);
4395 // Without partial swap, but a layer does clip its subtree, one scissor is
4396 // set.
4397 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
4398 harness.MustDrawSolidQuad();
4399 harness.MustSetScissor(0, 0, 10, 10);
4401 LayerTreeHostImpl::FrameData frame;
4402 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4403 host_impl_->DrawLayers(&frame);
4404 host_impl_->DidDrawAllLayers(frame);
4406 Mock::VerifyAndClearExpectations(&mock_context);
4409 TEST_F(LayerTreeHostImplTest, PartialSwap) {
4410 scoped_ptr<MockContext> context_owned(new MockContext);
4411 MockContext* mock_context = context_owned.get();
4412 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4413 context_owned.PassAs<TestWebGraphicsContext3D>()));
4414 MockContextHarness harness(mock_context);
4416 LayerTreeSettings settings = DefaultSettings();
4417 settings.partial_swap_enabled = true;
4418 CreateHostImpl(settings, output_surface.Pass());
4419 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4421 // The first frame is not a partially-swapped one.
4422 harness.MustSetScissor(0, 0, 10, 10);
4423 harness.MustDrawSolidQuad();
4425 LayerTreeHostImpl::FrameData frame;
4426 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4427 host_impl_->DrawLayers(&frame);
4428 host_impl_->DidDrawAllLayers(frame);
4430 Mock::VerifyAndClearExpectations(&mock_context);
4432 // Damage a portion of the frame.
4433 host_impl_->active_tree()->root_layer()->SetUpdateRect(
4434 gfx::Rect(0, 0, 2, 3));
4436 // The second frame will be partially-swapped (the y coordinates are flipped).
4437 harness.MustSetScissor(0, 7, 2, 3);
4438 harness.MustDrawSolidQuad();
4440 LayerTreeHostImpl::FrameData frame;
4441 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4442 host_impl_->DrawLayers(&frame);
4443 host_impl_->DidDrawAllLayers(frame);
4445 Mock::VerifyAndClearExpectations(&mock_context);
4448 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
4449 bool partial_swap,
4450 LayerTreeHostImplClient* client,
4451 Proxy* proxy,
4452 SharedBitmapManager* manager,
4453 RenderingStatsInstrumentation* stats_instrumentation) {
4454 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4455 scoped_ptr<OutputSurface> output_surface(
4456 FakeOutputSurface::Create3d(provider));
4457 provider->BindToCurrentThread();
4458 provider->TestContext3d()->set_have_post_sub_buffer(true);
4460 LayerTreeSettings settings;
4461 settings.partial_swap_enabled = partial_swap;
4462 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
4463 settings, client, proxy, stats_instrumentation, manager, 0);
4464 my_host_impl->InitializeRenderer(output_surface.Pass());
4465 my_host_impl->SetViewportSize(gfx::Size(100, 100));
4468 Layers are created as follows:
4470 +--------------------+
4471 | 1 |
4472 | +-----------+ |
4473 | | 2 | |
4474 | | +-------------------+
4475 | | | 3 |
4476 | | +-------------------+
4477 | | | |
4478 | +-----------+ |
4481 +--------------------+
4483 Layers 1, 2 have render surfaces
4485 scoped_ptr<LayerImpl> root =
4486 LayerImpl::Create(my_host_impl->active_tree(), 1);
4487 scoped_ptr<LayerImpl> child =
4488 LayerImpl::Create(my_host_impl->active_tree(), 2);
4489 scoped_ptr<LayerImpl> grand_child =
4490 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
4492 gfx::Rect root_rect(0, 0, 100, 100);
4493 gfx::Rect child_rect(10, 10, 50, 50);
4494 gfx::Rect grand_child_rect(5, 5, 150, 150);
4496 root->CreateRenderSurface();
4497 root->SetPosition(root_rect.origin());
4498 root->SetBounds(root_rect.size());
4499 root->SetContentBounds(root->bounds());
4500 root->draw_properties().visible_content_rect = root_rect;
4501 root->SetDrawsContent(false);
4502 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
4504 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
4505 child->SetOpacity(0.5f);
4506 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
4507 child->SetContentBounds(child->bounds());
4508 child->draw_properties().visible_content_rect = child_rect;
4509 child->SetDrawsContent(false);
4510 child->SetForceRenderSurface(true);
4512 grand_child->SetPosition(grand_child_rect.origin());
4513 grand_child->SetBounds(grand_child_rect.size());
4514 grand_child->SetContentBounds(grand_child->bounds());
4515 grand_child->draw_properties().visible_content_rect = grand_child_rect;
4516 grand_child->SetDrawsContent(true);
4518 child->AddChild(grand_child.Pass());
4519 root->AddChild(child.Pass());
4521 my_host_impl->active_tree()->SetRootLayer(root.Pass());
4522 return my_host_impl.Pass();
4525 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
4526 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4527 new TestSharedBitmapManager());
4528 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4529 SetupLayersForOpacity(true,
4530 this,
4531 &proxy_,
4532 shared_bitmap_manager.get(),
4533 &stats_instrumentation_);
4535 LayerTreeHostImpl::FrameData frame;
4536 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4538 // Verify all quads have been computed
4539 ASSERT_EQ(2U, frame.render_passes.size());
4540 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4541 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4542 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4543 frame.render_passes[0]->quad_list[0]->material);
4544 EXPECT_EQ(DrawQuad::RENDER_PASS,
4545 frame.render_passes[1]->quad_list[0]->material);
4547 my_host_impl->DrawLayers(&frame);
4548 my_host_impl->DidDrawAllLayers(frame);
4552 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
4553 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4554 new TestSharedBitmapManager());
4555 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4556 SetupLayersForOpacity(false,
4557 this,
4558 &proxy_,
4559 shared_bitmap_manager.get(),
4560 &stats_instrumentation_);
4562 LayerTreeHostImpl::FrameData frame;
4563 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4565 // Verify all quads have been computed
4566 ASSERT_EQ(2U, frame.render_passes.size());
4567 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4568 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4569 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4570 frame.render_passes[0]->quad_list[0]->material);
4571 EXPECT_EQ(DrawQuad::RENDER_PASS,
4572 frame.render_passes[1]->quad_list[0]->material);
4574 my_host_impl->DrawLayers(&frame);
4575 my_host_impl->DidDrawAllLayers(frame);
4579 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
4580 scoped_ptr<TestWebGraphicsContext3D> context =
4581 TestWebGraphicsContext3D::Create();
4582 TestWebGraphicsContext3D* context3d = context.get();
4583 scoped_ptr<OutputSurface> output_surface(
4584 FakeOutputSurface::Create3d(context.Pass()));
4585 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4587 scoped_ptr<LayerImpl> root_layer =
4588 LayerImpl::Create(host_impl_->active_tree(), 1);
4589 root_layer->SetBounds(gfx::Size(10, 10));
4591 scoped_refptr<VideoFrame> softwareFrame =
4592 media::VideoFrame::CreateColorFrame(
4593 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
4594 FakeVideoFrameProvider provider;
4595 provider.set_frame(softwareFrame);
4596 scoped_ptr<VideoLayerImpl> video_layer =
4597 VideoLayerImpl::Create(host_impl_->active_tree(), 4, &provider);
4598 video_layer->SetBounds(gfx::Size(10, 10));
4599 video_layer->SetContentBounds(gfx::Size(10, 10));
4600 video_layer->SetDrawsContent(true);
4601 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
4603 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
4604 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
4605 io_surface_layer->SetBounds(gfx::Size(10, 10));
4606 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
4607 io_surface_layer->SetDrawsContent(true);
4608 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
4609 root_layer->AddChild(io_surface_layer.PassAs<LayerImpl>());
4611 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
4613 EXPECT_EQ(0u, context3d->NumTextures());
4615 LayerTreeHostImpl::FrameData frame;
4616 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4617 host_impl_->DrawLayers(&frame);
4618 host_impl_->DidDrawAllLayers(frame);
4619 host_impl_->SwapBuffers(frame);
4621 EXPECT_GT(context3d->NumTextures(), 0u);
4623 // Kill the layer tree.
4624 host_impl_->active_tree()->SetRootLayer(
4625 LayerImpl::Create(host_impl_->active_tree(), 100));
4626 // There should be no textures left in use after.
4627 EXPECT_EQ(0u, context3d->NumTextures());
4630 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
4631 public:
4632 MOCK_METHOD1(useProgram, void(GLuint program));
4633 MOCK_METHOD4(drawElements, void(GLenum mode,
4634 GLsizei count,
4635 GLenum type,
4636 GLintptr offset));
4639 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
4640 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
4641 new MockDrawQuadsToFillScreenContext);
4642 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
4644 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4645 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4647 // Run test case
4648 LayerTreeSettings settings = DefaultSettings();
4649 settings.partial_swap_enabled = false;
4650 CreateHostImpl(settings, output_surface.Pass());
4651 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
4652 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
4654 // Verify one quad is drawn when transparent background set is not set.
4655 host_impl_->active_tree()->set_has_transparent_background(false);
4656 EXPECT_CALL(*mock_context, useProgram(_))
4657 .Times(1);
4658 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
4659 .Times(1);
4660 LayerTreeHostImpl::FrameData frame;
4661 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4662 host_impl_->DrawLayers(&frame);
4663 host_impl_->DidDrawAllLayers(frame);
4664 Mock::VerifyAndClearExpectations(&mock_context);
4666 // Verify no quads are drawn when transparent background is set.
4667 host_impl_->active_tree()->set_has_transparent_background(true);
4668 host_impl_->SetFullRootLayerDamage();
4669 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4670 host_impl_->DrawLayers(&frame);
4671 host_impl_->DidDrawAllLayers(frame);
4672 Mock::VerifyAndClearExpectations(&mock_context);
4675 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
4676 set_reduce_memory_result(false);
4678 // If changing the memory limit wouldn't result in changing what was
4679 // committed, then no commit should be requested.
4680 set_reduce_memory_result(false);
4681 host_impl_->set_max_memory_needed_bytes(
4682 host_impl_->memory_allocation_limit_bytes() - 1);
4683 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4684 host_impl_->memory_allocation_limit_bytes() - 1));
4685 EXPECT_FALSE(did_request_commit_);
4686 did_request_commit_ = false;
4688 // If changing the memory limit would result in changing what was
4689 // committed, then a commit should be requested, even though nothing was
4690 // evicted.
4691 set_reduce_memory_result(false);
4692 host_impl_->set_max_memory_needed_bytes(
4693 host_impl_->memory_allocation_limit_bytes());
4694 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4695 host_impl_->memory_allocation_limit_bytes() - 1));
4696 EXPECT_TRUE(did_request_commit_);
4697 did_request_commit_ = false;
4699 // Especially if changing the memory limit caused evictions, we need
4700 // to re-commit.
4701 set_reduce_memory_result(true);
4702 host_impl_->set_max_memory_needed_bytes(1);
4703 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4704 host_impl_->memory_allocation_limit_bytes() - 1));
4705 EXPECT_TRUE(did_request_commit_);
4706 did_request_commit_ = false;
4708 // But if we set it to the same value that it was before, we shouldn't
4709 // re-commit.
4710 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4711 host_impl_->memory_allocation_limit_bytes()));
4712 EXPECT_FALSE(did_request_commit_);
4715 class LayerTreeHostImplTestWithDelegatingRenderer
4716 : public LayerTreeHostImplTest {
4717 protected:
4718 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
4719 return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
4722 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
4723 bool expect_to_draw = !expected_damage.IsEmpty();
4725 LayerTreeHostImpl::FrameData frame;
4726 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4728 if (!expect_to_draw) {
4729 // With no damage, we don't draw, and no quads are created.
4730 ASSERT_EQ(0u, frame.render_passes.size());
4731 } else {
4732 ASSERT_EQ(1u, frame.render_passes.size());
4734 // Verify the damage rect for the root render pass.
4735 const RenderPass* root_render_pass = frame.render_passes.back();
4736 EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
4738 // Verify the root and child layers' quads are generated and not being
4739 // culled.
4740 ASSERT_EQ(2u, root_render_pass->quad_list.size());
4742 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
4743 gfx::RectF expected_child_visible_rect(child->content_bounds());
4744 EXPECT_RECT_EQ(expected_child_visible_rect,
4745 root_render_pass->quad_list[0]->visible_rect);
4747 LayerImpl* root = host_impl_->active_tree()->root_layer();
4748 gfx::RectF expected_root_visible_rect(root->content_bounds());
4749 EXPECT_RECT_EQ(expected_root_visible_rect,
4750 root_render_pass->quad_list[1]->visible_rect);
4753 host_impl_->DrawLayers(&frame);
4754 host_impl_->DidDrawAllLayers(frame);
4755 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
4759 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
4760 scoped_ptr<SolidColorLayerImpl> root =
4761 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4762 root->SetPosition(gfx::PointF());
4763 root->SetBounds(gfx::Size(10, 10));
4764 root->SetContentBounds(gfx::Size(10, 10));
4765 root->SetDrawsContent(true);
4767 // Child layer is in the bottom right corner.
4768 scoped_ptr<SolidColorLayerImpl> child =
4769 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
4770 child->SetPosition(gfx::PointF(9.f, 9.f));
4771 child->SetBounds(gfx::Size(1, 1));
4772 child->SetContentBounds(gfx::Size(1, 1));
4773 child->SetDrawsContent(true);
4774 root->AddChild(child.PassAs<LayerImpl>());
4776 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
4778 // Draw a frame. In the first frame, the entire viewport should be damaged.
4779 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
4780 DrawFrameAndTestDamage(full_frame_damage);
4782 // The second frame has damage that doesn't touch the child layer. Its quads
4783 // should still be generated.
4784 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
4785 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
4786 DrawFrameAndTestDamage(small_damage);
4788 // The third frame should have no damage, so no quads should be generated.
4789 gfx::Rect no_damage;
4790 DrawFrameAndTestDamage(no_damage);
4793 // TODO(reveman): Remove this test and the ability to prevent on demand raster
4794 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
4795 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
4796 LayerTreeSettings settings;
4797 CreateHostImpl(settings, CreateOutputSurface());
4798 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
4801 class FakeMaskLayerImpl : public LayerImpl {
4802 public:
4803 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
4804 int id) {
4805 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
4808 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
4809 return 0;
4812 private:
4813 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
4814 : LayerImpl(tree_impl, id) {}
4817 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
4818 LayerTreeSettings settings;
4819 settings.layer_transforms_should_scale_layer_contents = true;
4820 CreateHostImpl(settings, CreateOutputSurface());
4822 // Root
4823 // |
4824 // +-- Scaling Layer (adds a 2x scale)
4825 // |
4826 // +-- Content Layer
4827 // +--Mask
4828 scoped_ptr<LayerImpl> scoped_root =
4829 LayerImpl::Create(host_impl_->active_tree(), 1);
4830 LayerImpl* root = scoped_root.get();
4831 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4833 scoped_ptr<LayerImpl> scoped_scaling_layer =
4834 LayerImpl::Create(host_impl_->active_tree(), 2);
4835 LayerImpl* scaling_layer = scoped_scaling_layer.get();
4836 root->AddChild(scoped_scaling_layer.Pass());
4838 scoped_ptr<LayerImpl> scoped_content_layer =
4839 LayerImpl::Create(host_impl_->active_tree(), 3);
4840 LayerImpl* content_layer = scoped_content_layer.get();
4841 scaling_layer->AddChild(scoped_content_layer.Pass());
4843 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4844 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4845 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4846 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4848 gfx::Size root_size(100, 100);
4849 root->SetBounds(root_size);
4850 root->SetContentBounds(root_size);
4851 root->SetPosition(gfx::PointF());
4853 gfx::Size scaling_layer_size(50, 50);
4854 scaling_layer->SetBounds(scaling_layer_size);
4855 scaling_layer->SetContentBounds(scaling_layer_size);
4856 scaling_layer->SetPosition(gfx::PointF());
4857 gfx::Transform scale;
4858 scale.Scale(2.f, 2.f);
4859 scaling_layer->SetTransform(scale);
4861 content_layer->SetBounds(scaling_layer_size);
4862 content_layer->SetContentBounds(scaling_layer_size);
4863 content_layer->SetPosition(gfx::PointF());
4864 content_layer->SetDrawsContent(true);
4866 mask_layer->SetBounds(scaling_layer_size);
4867 mask_layer->SetContentBounds(scaling_layer_size);
4868 mask_layer->SetPosition(gfx::PointF());
4869 mask_layer->SetDrawsContent(true);
4872 // Check that the tree scaling is correctly taken into account for the mask,
4873 // that should fully map onto the quad.
4874 float device_scale_factor = 1.f;
4875 host_impl_->SetViewportSize(root_size);
4876 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4878 LayerTreeHostImpl::FrameData frame;
4879 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4881 ASSERT_EQ(1u, frame.render_passes.size());
4882 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4883 ASSERT_EQ(DrawQuad::RENDER_PASS,
4884 frame.render_passes[0]->quad_list[0]->material);
4885 const RenderPassDrawQuad* render_pass_quad =
4886 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4887 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4888 render_pass_quad->rect.ToString());
4889 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4890 render_pass_quad->mask_uv_rect.ToString());
4892 host_impl_->DrawLayers(&frame);
4893 host_impl_->DidDrawAllLayers(frame);
4897 // Applying a DSF should change the render surface size, but won't affect
4898 // which part of the mask is used.
4899 device_scale_factor = 2.f;
4900 gfx::Size device_viewport =
4901 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4902 host_impl_->SetViewportSize(device_viewport);
4903 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4904 host_impl_->active_tree()->set_needs_update_draw_properties();
4906 LayerTreeHostImpl::FrameData frame;
4907 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4909 ASSERT_EQ(1u, frame.render_passes.size());
4910 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4911 ASSERT_EQ(DrawQuad::RENDER_PASS,
4912 frame.render_passes[0]->quad_list[0]->material);
4913 const RenderPassDrawQuad* render_pass_quad =
4914 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4915 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4916 render_pass_quad->rect.ToString());
4917 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4918 render_pass_quad->mask_uv_rect.ToString());
4920 host_impl_->DrawLayers(&frame);
4921 host_impl_->DidDrawAllLayers(frame);
4925 // Applying an equivalent content scale on the content layer and the mask
4926 // should still result in the same part of the mask being used.
4927 gfx::Size content_bounds =
4928 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
4929 device_scale_factor));
4930 content_layer->SetContentBounds(content_bounds);
4931 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4932 mask_layer->SetContentBounds(content_bounds);
4933 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4934 host_impl_->active_tree()->set_needs_update_draw_properties();
4936 LayerTreeHostImpl::FrameData frame;
4937 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4939 ASSERT_EQ(1u, frame.render_passes.size());
4940 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4941 ASSERT_EQ(DrawQuad::RENDER_PASS,
4942 frame.render_passes[0]->quad_list[0]->material);
4943 const RenderPassDrawQuad* render_pass_quad =
4944 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4945 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4946 render_pass_quad->rect.ToString());
4947 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4948 render_pass_quad->mask_uv_rect.ToString());
4950 host_impl_->DrawLayers(&frame);
4951 host_impl_->DidDrawAllLayers(frame);
4955 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
4956 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4957 // 50x50.
4959 scoped_ptr<LayerImpl> scoped_root =
4960 LayerImpl::Create(host_impl_->active_tree(), 1);
4961 LayerImpl* root = scoped_root.get();
4962 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4964 scoped_ptr<LayerImpl> scoped_content_layer =
4965 LayerImpl::Create(host_impl_->active_tree(), 3);
4966 LayerImpl* content_layer = scoped_content_layer.get();
4967 root->AddChild(scoped_content_layer.Pass());
4969 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4970 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4971 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4972 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4974 gfx::Size root_size(100, 100);
4975 root->SetBounds(root_size);
4976 root->SetContentBounds(root_size);
4977 root->SetPosition(gfx::PointF());
4979 gfx::Size layer_size(50, 50);
4980 content_layer->SetBounds(layer_size);
4981 content_layer->SetContentBounds(layer_size);
4982 content_layer->SetPosition(gfx::PointF());
4983 content_layer->SetDrawsContent(true);
4985 gfx::Size mask_size(100, 100);
4986 mask_layer->SetBounds(mask_size);
4987 mask_layer->SetContentBounds(mask_size);
4988 mask_layer->SetPosition(gfx::PointF());
4989 mask_layer->SetDrawsContent(true);
4991 // Check that the mask fills the surface.
4992 float device_scale_factor = 1.f;
4993 host_impl_->SetViewportSize(root_size);
4994 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4996 LayerTreeHostImpl::FrameData frame;
4997 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4999 ASSERT_EQ(1u, frame.render_passes.size());
5000 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5001 ASSERT_EQ(DrawQuad::RENDER_PASS,
5002 frame.render_passes[0]->quad_list[0]->material);
5003 const RenderPassDrawQuad* render_pass_quad =
5004 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5005 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5006 render_pass_quad->rect.ToString());
5007 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5008 render_pass_quad->mask_uv_rect.ToString());
5010 host_impl_->DrawLayers(&frame);
5011 host_impl_->DidDrawAllLayers(frame);
5014 // Applying a DSF should change the render surface size, but won't affect
5015 // which part of the mask is used.
5016 device_scale_factor = 2.f;
5017 gfx::Size device_viewport =
5018 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5019 host_impl_->SetViewportSize(device_viewport);
5020 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5021 host_impl_->active_tree()->set_needs_update_draw_properties();
5023 LayerTreeHostImpl::FrameData frame;
5024 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5026 ASSERT_EQ(1u, frame.render_passes.size());
5027 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5028 ASSERT_EQ(DrawQuad::RENDER_PASS,
5029 frame.render_passes[0]->quad_list[0]->material);
5030 const RenderPassDrawQuad* render_pass_quad =
5031 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5032 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5033 render_pass_quad->rect.ToString());
5034 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5035 render_pass_quad->mask_uv_rect.ToString());
5037 host_impl_->DrawLayers(&frame);
5038 host_impl_->DidDrawAllLayers(frame);
5041 // Applying an equivalent content scale on the content layer and the mask
5042 // should still result in the same part of the mask being used.
5043 gfx::Size layer_size_large =
5044 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5045 content_layer->SetContentBounds(layer_size_large);
5046 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5047 gfx::Size mask_size_large =
5048 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5049 mask_layer->SetContentBounds(mask_size_large);
5050 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5051 host_impl_->active_tree()->set_needs_update_draw_properties();
5053 LayerTreeHostImpl::FrameData frame;
5054 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5056 ASSERT_EQ(1u, frame.render_passes.size());
5057 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5058 ASSERT_EQ(DrawQuad::RENDER_PASS,
5059 frame.render_passes[0]->quad_list[0]->material);
5060 const RenderPassDrawQuad* render_pass_quad =
5061 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5062 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5063 render_pass_quad->rect.ToString());
5064 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5065 render_pass_quad->mask_uv_rect.ToString());
5067 host_impl_->DrawLayers(&frame);
5068 host_impl_->DidDrawAllLayers(frame);
5071 // Applying a different contents scale to the mask layer means it will have
5072 // a larger texture, but it should use the same tex coords to cover the
5073 // layer it masks.
5074 mask_layer->SetContentBounds(mask_size);
5075 mask_layer->SetContentsScale(1.f, 1.f);
5076 host_impl_->active_tree()->set_needs_update_draw_properties();
5078 LayerTreeHostImpl::FrameData frame;
5079 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5081 ASSERT_EQ(1u, frame.render_passes.size());
5082 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5083 ASSERT_EQ(DrawQuad::RENDER_PASS,
5084 frame.render_passes[0]->quad_list[0]->material);
5085 const RenderPassDrawQuad* render_pass_quad =
5086 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5087 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5088 render_pass_quad->rect.ToString());
5089 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5090 render_pass_quad->mask_uv_rect.ToString());
5092 host_impl_->DrawLayers(&frame);
5093 host_impl_->DidDrawAllLayers(frame);
5097 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
5098 // The replica's mask layer has bounds 100x100 but the replica is of a
5099 // layer with bounds 50x50.
5101 scoped_ptr<LayerImpl> scoped_root =
5102 LayerImpl::Create(host_impl_->active_tree(), 1);
5103 LayerImpl* root = scoped_root.get();
5104 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5106 scoped_ptr<LayerImpl> scoped_content_layer =
5107 LayerImpl::Create(host_impl_->active_tree(), 3);
5108 LayerImpl* content_layer = scoped_content_layer.get();
5109 root->AddChild(scoped_content_layer.Pass());
5111 scoped_ptr<LayerImpl> scoped_replica_layer =
5112 LayerImpl::Create(host_impl_->active_tree(), 2);
5113 LayerImpl* replica_layer = scoped_replica_layer.get();
5114 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5116 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5117 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5118 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5119 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5121 gfx::Size root_size(100, 100);
5122 root->SetBounds(root_size);
5123 root->SetContentBounds(root_size);
5124 root->SetPosition(gfx::PointF());
5126 gfx::Size layer_size(50, 50);
5127 content_layer->SetBounds(layer_size);
5128 content_layer->SetContentBounds(layer_size);
5129 content_layer->SetPosition(gfx::PointF());
5130 content_layer->SetDrawsContent(true);
5132 gfx::Size mask_size(100, 100);
5133 mask_layer->SetBounds(mask_size);
5134 mask_layer->SetContentBounds(mask_size);
5135 mask_layer->SetPosition(gfx::PointF());
5136 mask_layer->SetDrawsContent(true);
5138 // Check that the mask fills the surface.
5139 float device_scale_factor = 1.f;
5140 host_impl_->SetViewportSize(root_size);
5141 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5143 LayerTreeHostImpl::FrameData frame;
5144 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5146 ASSERT_EQ(1u, frame.render_passes.size());
5147 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5148 ASSERT_EQ(DrawQuad::RENDER_PASS,
5149 frame.render_passes[0]->quad_list[1]->material);
5150 const RenderPassDrawQuad* replica_quad =
5151 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5152 EXPECT_TRUE(replica_quad->is_replica);
5153 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5154 replica_quad->rect.ToString());
5155 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5156 replica_quad->mask_uv_rect.ToString());
5158 host_impl_->DrawLayers(&frame);
5159 host_impl_->DidDrawAllLayers(frame);
5162 // Applying a DSF should change the render surface size, but won't affect
5163 // which part of the mask is used.
5164 device_scale_factor = 2.f;
5165 gfx::Size device_viewport =
5166 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5167 host_impl_->SetViewportSize(device_viewport);
5168 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5169 host_impl_->active_tree()->set_needs_update_draw_properties();
5171 LayerTreeHostImpl::FrameData frame;
5172 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5174 ASSERT_EQ(1u, frame.render_passes.size());
5175 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5176 ASSERT_EQ(DrawQuad::RENDER_PASS,
5177 frame.render_passes[0]->quad_list[1]->material);
5178 const RenderPassDrawQuad* replica_quad =
5179 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5180 EXPECT_TRUE(replica_quad->is_replica);
5181 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5182 replica_quad->rect.ToString());
5183 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5184 replica_quad->mask_uv_rect.ToString());
5186 host_impl_->DrawLayers(&frame);
5187 host_impl_->DidDrawAllLayers(frame);
5190 // Applying an equivalent content scale on the content layer and the mask
5191 // should still result in the same part of the mask being used.
5192 gfx::Size layer_size_large =
5193 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5194 content_layer->SetContentBounds(layer_size_large);
5195 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5196 gfx::Size mask_size_large =
5197 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5198 mask_layer->SetContentBounds(mask_size_large);
5199 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5200 host_impl_->active_tree()->set_needs_update_draw_properties();
5202 LayerTreeHostImpl::FrameData frame;
5203 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5205 ASSERT_EQ(1u, frame.render_passes.size());
5206 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5207 ASSERT_EQ(DrawQuad::RENDER_PASS,
5208 frame.render_passes[0]->quad_list[1]->material);
5209 const RenderPassDrawQuad* replica_quad =
5210 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5211 EXPECT_TRUE(replica_quad->is_replica);
5212 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5213 replica_quad->rect.ToString());
5214 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5215 replica_quad->mask_uv_rect.ToString());
5217 host_impl_->DrawLayers(&frame);
5218 host_impl_->DidDrawAllLayers(frame);
5221 // Applying a different contents scale to the mask layer means it will have
5222 // a larger texture, but it should use the same tex coords to cover the
5223 // layer it masks.
5224 mask_layer->SetContentBounds(mask_size);
5225 mask_layer->SetContentsScale(1.f, 1.f);
5226 host_impl_->active_tree()->set_needs_update_draw_properties();
5228 LayerTreeHostImpl::FrameData frame;
5229 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5231 ASSERT_EQ(1u, frame.render_passes.size());
5232 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5233 ASSERT_EQ(DrawQuad::RENDER_PASS,
5234 frame.render_passes[0]->quad_list[1]->material);
5235 const RenderPassDrawQuad* replica_quad =
5236 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5237 EXPECT_TRUE(replica_quad->is_replica);
5238 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5239 replica_quad->rect.ToString());
5240 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5241 replica_quad->mask_uv_rect.ToString());
5243 host_impl_->DrawLayers(&frame);
5244 host_impl_->DidDrawAllLayers(frame);
5248 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
5249 // The replica is of a layer with bounds 50x50, but it has a child that causes
5250 // the surface bounds to be larger.
5252 scoped_ptr<LayerImpl> scoped_root =
5253 LayerImpl::Create(host_impl_->active_tree(), 1);
5254 LayerImpl* root = scoped_root.get();
5255 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5257 scoped_ptr<LayerImpl> scoped_content_layer =
5258 LayerImpl::Create(host_impl_->active_tree(), 2);
5259 LayerImpl* content_layer = scoped_content_layer.get();
5260 root->AddChild(scoped_content_layer.Pass());
5262 scoped_ptr<LayerImpl> scoped_content_child_layer =
5263 LayerImpl::Create(host_impl_->active_tree(), 3);
5264 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5265 content_layer->AddChild(scoped_content_child_layer.Pass());
5267 scoped_ptr<LayerImpl> scoped_replica_layer =
5268 LayerImpl::Create(host_impl_->active_tree(), 4);
5269 LayerImpl* replica_layer = scoped_replica_layer.get();
5270 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5272 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5273 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
5274 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5275 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5277 gfx::Size root_size(100, 100);
5278 root->SetBounds(root_size);
5279 root->SetContentBounds(root_size);
5280 root->SetPosition(gfx::PointF());
5282 gfx::Size layer_size(50, 50);
5283 content_layer->SetBounds(layer_size);
5284 content_layer->SetContentBounds(layer_size);
5285 content_layer->SetPosition(gfx::PointF());
5286 content_layer->SetDrawsContent(true);
5288 gfx::Size child_size(50, 50);
5289 content_child_layer->SetBounds(child_size);
5290 content_child_layer->SetContentBounds(child_size);
5291 content_child_layer->SetPosition(gfx::Point(50, 0));
5292 content_child_layer->SetDrawsContent(true);
5294 gfx::Size mask_size(50, 50);
5295 mask_layer->SetBounds(mask_size);
5296 mask_layer->SetContentBounds(mask_size);
5297 mask_layer->SetPosition(gfx::PointF());
5298 mask_layer->SetDrawsContent(true);
5300 float device_scale_factor = 1.f;
5301 host_impl_->SetViewportSize(root_size);
5302 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5304 LayerTreeHostImpl::FrameData frame;
5305 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5307 ASSERT_EQ(1u, frame.render_passes.size());
5308 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5310 // The surface is 100x50.
5311 ASSERT_EQ(DrawQuad::RENDER_PASS,
5312 frame.render_passes[0]->quad_list[0]->material);
5313 const RenderPassDrawQuad* render_pass_quad =
5314 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5315 EXPECT_FALSE(render_pass_quad->is_replica);
5316 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5317 render_pass_quad->rect.ToString());
5319 // The mask covers the owning layer only.
5320 ASSERT_EQ(DrawQuad::RENDER_PASS,
5321 frame.render_passes[0]->quad_list[1]->material);
5322 const RenderPassDrawQuad* replica_quad =
5323 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5324 EXPECT_TRUE(replica_quad->is_replica);
5325 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5326 replica_quad->rect.ToString());
5327 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
5328 replica_quad->mask_uv_rect.ToString());
5330 host_impl_->DrawLayers(&frame);
5331 host_impl_->DidDrawAllLayers(frame);
5334 // Move the child to (-50, 0) instead. Now the mask should be moved to still
5335 // cover the layer being replicated.
5336 content_child_layer->SetPosition(gfx::Point(-50, 0));
5338 LayerTreeHostImpl::FrameData frame;
5339 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5341 ASSERT_EQ(1u, frame.render_passes.size());
5342 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5344 // The surface is 100x50 with its origin at (-50, 0).
5345 ASSERT_EQ(DrawQuad::RENDER_PASS,
5346 frame.render_passes[0]->quad_list[0]->material);
5347 const RenderPassDrawQuad* render_pass_quad =
5348 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5349 EXPECT_FALSE(render_pass_quad->is_replica);
5350 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5351 render_pass_quad->rect.ToString());
5353 // The mask covers the owning layer only.
5354 ASSERT_EQ(DrawQuad::RENDER_PASS,
5355 frame.render_passes[0]->quad_list[1]->material);
5356 const RenderPassDrawQuad* replica_quad =
5357 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5358 EXPECT_TRUE(replica_quad->is_replica);
5359 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5360 replica_quad->rect.ToString());
5361 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
5362 replica_quad->mask_uv_rect.ToString());
5364 host_impl_->DrawLayers(&frame);
5365 host_impl_->DidDrawAllLayers(frame);
5369 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
5370 // The masked layer has bounds 50x50, but it has a child that causes
5371 // the surface bounds to be larger. It also has a parent that clips the
5372 // masked layer and its surface.
5374 scoped_ptr<LayerImpl> scoped_root =
5375 LayerImpl::Create(host_impl_->active_tree(), 1);
5376 LayerImpl* root = scoped_root.get();
5377 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5379 scoped_ptr<LayerImpl> scoped_clipping_layer =
5380 LayerImpl::Create(host_impl_->active_tree(), 2);
5381 LayerImpl* clipping_layer = scoped_clipping_layer.get();
5382 root->AddChild(scoped_clipping_layer.Pass());
5384 scoped_ptr<LayerImpl> scoped_content_layer =
5385 LayerImpl::Create(host_impl_->active_tree(), 3);
5386 LayerImpl* content_layer = scoped_content_layer.get();
5387 clipping_layer->AddChild(scoped_content_layer.Pass());
5389 scoped_ptr<LayerImpl> scoped_content_child_layer =
5390 LayerImpl::Create(host_impl_->active_tree(), 4);
5391 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5392 content_layer->AddChild(scoped_content_child_layer.Pass());
5394 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5395 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
5396 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5397 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5399 gfx::Size root_size(100, 100);
5400 root->SetBounds(root_size);
5401 root->SetContentBounds(root_size);
5402 root->SetPosition(gfx::PointF());
5404 gfx::Rect clipping_rect(20, 10, 10, 20);
5405 clipping_layer->SetBounds(clipping_rect.size());
5406 clipping_layer->SetContentBounds(clipping_rect.size());
5407 clipping_layer->SetPosition(clipping_rect.origin());
5408 clipping_layer->SetMasksToBounds(true);
5410 gfx::Size layer_size(50, 50);
5411 content_layer->SetBounds(layer_size);
5412 content_layer->SetContentBounds(layer_size);
5413 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
5414 content_layer->SetDrawsContent(true);
5416 gfx::Size child_size(50, 50);
5417 content_child_layer->SetBounds(child_size);
5418 content_child_layer->SetContentBounds(child_size);
5419 content_child_layer->SetPosition(gfx::Point(50, 0));
5420 content_child_layer->SetDrawsContent(true);
5422 gfx::Size mask_size(100, 100);
5423 mask_layer->SetBounds(mask_size);
5424 mask_layer->SetContentBounds(mask_size);
5425 mask_layer->SetPosition(gfx::PointF());
5426 mask_layer->SetDrawsContent(true);
5428 float device_scale_factor = 1.f;
5429 host_impl_->SetViewportSize(root_size);
5430 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5432 LayerTreeHostImpl::FrameData frame;
5433 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5435 ASSERT_EQ(1u, frame.render_passes.size());
5436 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5438 // The surface is clipped to 10x20.
5439 ASSERT_EQ(DrawQuad::RENDER_PASS,
5440 frame.render_passes[0]->quad_list[0]->material);
5441 const RenderPassDrawQuad* render_pass_quad =
5442 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5443 EXPECT_FALSE(render_pass_quad->is_replica);
5444 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
5445 render_pass_quad->rect.ToString());
5447 // The masked layer is 50x50, but the surface size is 10x20. So the texture
5448 // coords in the mask are scaled by 10/50 and 20/50.
5449 // The surface is clipped to (20,10) so the mask texture coords are offset
5450 // by 20/50 and 10/50
5451 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f),
5452 1.f / 50.f).ToString(),
5453 render_pass_quad->mask_uv_rect.ToString());
5455 host_impl_->DrawLayers(&frame);
5456 host_impl_->DidDrawAllLayers(frame);
5460 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
5461 public:
5462 using GLRenderer::SetupQuadForAntialiasing;
5465 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
5466 // Due to precision issues (especially on Android), sometimes far
5467 // away quads can end up thinking they need AA.
5468 float device_scale_factor = 4.f / 3.f;
5469 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5470 gfx::Size root_size(2000, 1000);
5471 gfx::Size device_viewport_size =
5472 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
5473 host_impl_->SetViewportSize(device_viewport_size);
5475 host_impl_->CreatePendingTree();
5476 host_impl_->pending_tree()
5477 ->SetPageScaleFactorAndLimits(1.f, 1.f / 16.f, 16.f);
5479 scoped_ptr<LayerImpl> scoped_root =
5480 LayerImpl::Create(host_impl_->pending_tree(), 1);
5481 LayerImpl* root = scoped_root.get();
5483 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
5485 scoped_ptr<LayerImpl> scoped_scrolling_layer =
5486 LayerImpl::Create(host_impl_->pending_tree(), 2);
5487 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
5488 root->AddChild(scoped_scrolling_layer.Pass());
5490 gfx::Size content_layer_bounds(100000, 100);
5491 gfx::Size pile_tile_size(3000, 3000);
5492 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
5493 pile_tile_size, content_layer_bounds));
5495 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
5496 FakePictureLayerImpl::CreateWithPile(host_impl_->pending_tree(), 3, pile);
5497 LayerImpl* content_layer = scoped_content_layer.get();
5498 scrolling_layer->AddChild(scoped_content_layer.PassAs<LayerImpl>());
5499 content_layer->SetBounds(content_layer_bounds);
5500 content_layer->SetDrawsContent(true);
5502 root->SetBounds(root_size);
5504 gfx::Vector2d scroll_offset(100000, 0);
5505 scrolling_layer->SetScrollClipLayer(root->id());
5506 scrolling_layer->SetScrollOffset(scroll_offset);
5508 host_impl_->ActivateSyncTree();
5510 host_impl_->active_tree()->UpdateDrawProperties();
5511 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
5513 LayerTreeHostImpl::FrameData frame;
5514 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5516 ASSERT_EQ(1u, frame.render_passes.size());
5517 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
5518 const DrawQuad* quad = frame.render_passes[0]->quad_list[0];
5520 float edge[24];
5521 gfx::QuadF device_layer_quad;
5522 bool antialiased =
5523 GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
5524 quad->quadTransform(), quad, &device_layer_quad, edge);
5525 EXPECT_FALSE(antialiased);
5527 host_impl_->DrawLayers(&frame);
5528 host_impl_->DidDrawAllLayers(frame);
5532 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
5533 public:
5534 CompositorFrameMetadataTest()
5535 : swap_buffers_complete_(0) {}
5537 virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {
5538 swap_buffers_complete_++;
5541 int swap_buffers_complete_;
5544 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
5545 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5547 LayerTreeHostImpl::FrameData frame;
5548 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5549 host_impl_->DrawLayers(&frame);
5550 host_impl_->DidDrawAllLayers(frame);
5552 CompositorFrameAck ack;
5553 host_impl_->ReclaimResources(&ack);
5554 host_impl_->DidSwapBuffersComplete();
5555 EXPECT_EQ(swap_buffers_complete_, 1);
5558 class CountingSoftwareDevice : public SoftwareOutputDevice {
5559 public:
5560 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5562 virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
5563 ++frames_began_;
5564 return SoftwareOutputDevice::BeginPaint(damage_rect);
5566 virtual void EndPaint(SoftwareFrameData* frame_data) OVERRIDE {
5567 ++frames_ended_;
5568 SoftwareOutputDevice::EndPaint(frame_data);
5571 int frames_began_, frames_ended_;
5574 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
5575 // No main thread evictions in resourceless software mode.
5576 set_reduce_memory_result(false);
5577 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
5578 bool delegated_rendering = false;
5579 FakeOutputSurface* output_surface =
5580 FakeOutputSurface::CreateDeferredGL(
5581 scoped_ptr<SoftwareOutputDevice>(software_device),
5582 delegated_rendering).release();
5583 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5584 scoped_ptr<OutputSurface>(output_surface)));
5585 host_impl_->SetViewportSize(gfx::Size(50, 50));
5587 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5589 const gfx::Transform external_transform;
5590 const gfx::Rect external_viewport;
5591 const gfx::Rect external_clip;
5592 const bool resourceless_software_draw = true;
5593 host_impl_->SetExternalDrawConstraints(external_transform,
5594 external_viewport,
5595 external_clip,
5596 resourceless_software_draw);
5598 EXPECT_EQ(0, software_device->frames_began_);
5599 EXPECT_EQ(0, software_device->frames_ended_);
5601 DrawFrame();
5603 EXPECT_EQ(1, software_device->frames_began_);
5604 EXPECT_EQ(1, software_device->frames_ended_);
5606 // Call other API methods that are likely to hit NULL pointer in this mode.
5607 EXPECT_TRUE(host_impl_->AsValue());
5608 EXPECT_TRUE(host_impl_->ActivationStateAsValue());
5611 TEST_F(LayerTreeHostImplTest,
5612 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
5613 set_reduce_memory_result(false);
5614 bool delegated_rendering = false;
5615 FakeOutputSurface* output_surface =
5616 FakeOutputSurface::CreateDeferredGL(
5617 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5618 delegated_rendering).release();
5619 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5620 scoped_ptr<OutputSurface>(output_surface)));
5622 const gfx::Transform external_transform;
5623 const gfx::Rect external_viewport;
5624 const gfx::Rect external_clip;
5625 const bool resourceless_software_draw = true;
5626 host_impl_->SetExternalDrawConstraints(external_transform,
5627 external_viewport,
5628 external_clip,
5629 resourceless_software_draw);
5631 // SolidColorLayerImpl will be drawn.
5632 scoped_ptr<SolidColorLayerImpl> root_layer =
5633 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5635 // VideoLayerImpl will not be drawn.
5636 FakeVideoFrameProvider provider;
5637 scoped_ptr<VideoLayerImpl> video_layer =
5638 VideoLayerImpl::Create(host_impl_->active_tree(), 2, &provider);
5639 video_layer->SetBounds(gfx::Size(10, 10));
5640 video_layer->SetContentBounds(gfx::Size(10, 10));
5641 video_layer->SetDrawsContent(true);
5642 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
5643 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5645 LayerTreeHostImpl::FrameData frame;
5646 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5647 host_impl_->DrawLayers(&frame);
5648 host_impl_->DidDrawAllLayers(frame);
5650 EXPECT_EQ(1u, frame.will_draw_layers.size());
5651 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
5654 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
5655 protected:
5656 virtual void SetUp() OVERRIDE {
5657 LayerTreeHostImplTest::SetUp();
5659 set_reduce_memory_result(false);
5661 bool delegated_rendering = false;
5662 scoped_ptr<FakeOutputSurface> output_surface(
5663 FakeOutputSurface::CreateDeferredGL(
5664 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5665 delegated_rendering));
5666 output_surface_ = output_surface.get();
5668 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5669 output_surface.PassAs<OutputSurface>()));
5671 scoped_ptr<SolidColorLayerImpl> root_layer =
5672 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5673 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5675 onscreen_context_provider_ = TestContextProvider::Create();
5678 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {
5679 did_update_renderer_capabilities_ = true;
5682 FakeOutputSurface* output_surface_;
5683 scoped_refptr<TestContextProvider> onscreen_context_provider_;
5684 bool did_update_renderer_capabilities_;
5688 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
5689 // Software draw.
5690 DrawFrame();
5692 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5694 // DeferredInitialize and hardware draw.
5695 did_update_renderer_capabilities_ = false;
5696 EXPECT_TRUE(
5697 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5698 EXPECT_EQ(onscreen_context_provider_,
5699 host_impl_->output_surface()->context_provider());
5700 EXPECT_TRUE(did_update_renderer_capabilities_);
5702 // Defer intialized GL draw.
5703 DrawFrame();
5705 // Revert back to software.
5706 did_update_renderer_capabilities_ = false;
5707 output_surface_->ReleaseGL();
5708 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5709 EXPECT_TRUE(did_update_renderer_capabilities_);
5711 // Software draw again.
5712 DrawFrame();
5715 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails) {
5716 // Software draw.
5717 DrawFrame();
5719 // Fail initialization of the onscreen context before the OutputSurface binds
5720 // it to the thread.
5721 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5723 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5725 // DeferredInitialize fails.
5726 did_update_renderer_capabilities_ = false;
5727 EXPECT_FALSE(
5728 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5729 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5730 EXPECT_FALSE(did_update_renderer_capabilities_);
5732 // Software draw again.
5733 DrawFrame();
5736 // Checks that we have a non-0 default allocation if we pass a context that
5737 // doesn't support memory management extensions.
5738 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5739 LayerTreeSettings settings;
5740 host_impl_ = LayerTreeHostImpl::Create(settings,
5741 this,
5742 &proxy_,
5743 &stats_instrumentation_,
5744 shared_bitmap_manager_.get(),
5747 scoped_ptr<OutputSurface> output_surface(
5748 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5749 host_impl_->InitializeRenderer(output_surface.Pass());
5750 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5753 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5754 ManagedMemoryPolicy policy1(
5755 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5756 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5757 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5758 int allow_nice_to_have_cutoff_value =
5759 ManagedMemoryPolicy::PriorityCutoffToValue(
5760 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
5761 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5762 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5764 // GPU rasterization should be disabled by default on the tree(s)
5765 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
5766 EXPECT_TRUE(host_impl_->pending_tree() == NULL);
5768 host_impl_->SetVisible(true);
5769 host_impl_->SetMemoryPolicy(policy1);
5770 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5771 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5773 host_impl_->SetVisible(false);
5774 EXPECT_EQ(0u, current_limit_bytes_);
5775 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5777 host_impl_->SetVisible(true);
5778 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5779 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5781 // Now enable GPU rasterization and test if we get nice to have cutoff,
5782 // when visible.
5783 LayerTreeSettings settings;
5784 settings.gpu_rasterization_enabled = true;
5785 host_impl_ = LayerTreeHostImpl::Create(
5786 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
5787 host_impl_->SetUseGpuRasterization(true);
5788 host_impl_->SetVisible(true);
5789 host_impl_->SetMemoryPolicy(policy1);
5790 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5791 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
5793 host_impl_->SetVisible(false);
5794 EXPECT_EQ(0u, current_limit_bytes_);
5795 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5798 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
5799 ASSERT_TRUE(host_impl_->active_tree());
5801 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5802 host_impl_->SetVisible(false);
5803 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5804 host_impl_->SetVisible(true);
5805 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5806 host_impl_->SetVisible(false);
5807 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5809 host_impl_->CreatePendingTree();
5810 host_impl_->ActivateSyncTree();
5812 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5813 host_impl_->SetVisible(true);
5814 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5817 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
5818 ASSERT_TRUE(host_impl_->active_tree());
5819 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
5821 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5822 host_impl_->SetUseGpuRasterization(false);
5823 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5824 host_impl_->SetUseGpuRasterization(true);
5825 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5826 host_impl_->SetUseGpuRasterization(false);
5827 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5829 host_impl_->CreatePendingTree();
5830 host_impl_->ActivateSyncTree();
5832 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5833 host_impl_->SetUseGpuRasterization(true);
5834 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5837 class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
5838 public:
5839 virtual void SetUp() OVERRIDE {
5840 LayerTreeSettings settings;
5841 settings.impl_side_painting = true;
5843 fake_host_impl_ = new FakeLayerTreeHostImpl(
5844 settings, &proxy_, shared_bitmap_manager_.get());
5845 host_impl_.reset(fake_host_impl_);
5846 host_impl_->InitializeRenderer(CreateOutputSurface());
5847 host_impl_->SetViewportSize(gfx::Size(10, 10));
5850 FakeLayerTreeHostImpl* fake_host_impl_;
5853 TEST_F(LayerTreeHostImplTestManageTiles, ManageTilesWhenInvisible) {
5854 fake_host_impl_->DidModifyTilePriorities();
5855 EXPECT_TRUE(fake_host_impl_->manage_tiles_needed());
5856 fake_host_impl_->SetVisible(false);
5857 EXPECT_FALSE(fake_host_impl_->manage_tiles_needed());
5860 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
5861 scoped_ptr<TestWebGraphicsContext3D> context =
5862 TestWebGraphicsContext3D::Create();
5863 TestWebGraphicsContext3D* context3d = context.get();
5864 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5865 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5867 EXPECT_EQ(0u, context3d->NumTextures());
5869 UIResourceId ui_resource_id = 1;
5870 bool is_opaque = false;
5871 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
5872 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5873 EXPECT_EQ(1u, context3d->NumTextures());
5874 ResourceProvider::ResourceId id1 =
5875 host_impl_->ResourceIdForUIResource(ui_resource_id);
5876 EXPECT_NE(0u, id1);
5878 // Multiple requests with the same id is allowed. The previous texture is
5879 // deleted.
5880 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5881 EXPECT_EQ(1u, context3d->NumTextures());
5882 ResourceProvider::ResourceId id2 =
5883 host_impl_->ResourceIdForUIResource(ui_resource_id);
5884 EXPECT_NE(0u, id2);
5885 EXPECT_NE(id1, id2);
5887 // Deleting invalid UIResourceId is allowed and does not change state.
5888 host_impl_->DeleteUIResource(-1);
5889 EXPECT_EQ(1u, context3d->NumTextures());
5891 // Should return zero for invalid UIResourceId. Number of textures should
5892 // not change.
5893 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
5894 EXPECT_EQ(1u, context3d->NumTextures());
5896 host_impl_->DeleteUIResource(ui_resource_id);
5897 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
5898 EXPECT_EQ(0u, context3d->NumTextures());
5900 // Should not change state for multiple deletion on one UIResourceId
5901 host_impl_->DeleteUIResource(ui_resource_id);
5902 EXPECT_EQ(0u, context3d->NumTextures());
5905 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
5906 scoped_ptr<TestWebGraphicsContext3D> context =
5907 TestWebGraphicsContext3D::Create();
5908 TestWebGraphicsContext3D* context3d = context.get();
5909 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5910 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5912 EXPECT_EQ(0u, context3d->NumTextures());
5914 gfx::Size size(4, 4);
5915 // SkImageInfo has no support for ETC1. The |info| below contains the right
5916 // total pixel size for the bitmap but not the right height and width. The
5917 // correct width/height are passed directly to UIResourceBitmap.
5918 SkImageInfo info =
5919 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
5920 skia::RefPtr<SkPixelRef> pixel_ref =
5921 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
5922 pixel_ref->setImmutable();
5923 UIResourceBitmap bitmap(pixel_ref, size);
5924 UIResourceId ui_resource_id = 1;
5925 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5926 EXPECT_EQ(1u, context3d->NumTextures());
5927 ResourceProvider::ResourceId id1 =
5928 host_impl_->ResourceIdForUIResource(ui_resource_id);
5929 EXPECT_NE(0u, id1);
5932 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
5935 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
5936 scoped_refptr<TestContextProvider> context_provider =
5937 TestContextProvider::Create();
5939 CreateHostImpl(
5940 DefaultSettings(),
5941 FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>());
5943 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5945 ScopedPtrVector<CopyOutputRequest> requests;
5946 requests.push_back(CopyOutputRequest::CreateRequest(
5947 base::Bind(&ShutdownReleasesContext_Callback)));
5949 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
5951 LayerTreeHostImpl::FrameData frame;
5952 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5953 host_impl_->DrawLayers(&frame);
5954 host_impl_->DidDrawAllLayers(frame);
5956 // The CopyOutputResult's callback has a ref on the ContextProvider and a
5957 // texture in a texture mailbox.
5958 EXPECT_FALSE(context_provider->HasOneRef());
5959 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
5961 host_impl_.reset();
5963 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
5964 // released, and the texture deleted.
5965 EXPECT_TRUE(context_provider->HasOneRef());
5966 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
5969 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
5970 // When flinging via touch, only the child should scroll (we should not
5971 // bubble).
5972 gfx::Size surface_size(10, 10);
5973 gfx::Size content_size(20, 20);
5974 scoped_ptr<LayerImpl> root_clip =
5975 LayerImpl::Create(host_impl_->active_tree(), 3);
5976 scoped_ptr<LayerImpl> root =
5977 CreateScrollableLayer(1, content_size, root_clip.get());
5978 root->SetIsContainerForFixedPositionLayers(true);
5979 scoped_ptr<LayerImpl> child =
5980 CreateScrollableLayer(2, content_size, root_clip.get());
5982 root->AddChild(child.Pass());
5983 int root_id = root->id();
5984 root_clip->AddChild(root.Pass());
5986 host_impl_->SetViewportSize(surface_size);
5987 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
5988 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
5989 host_impl_->active_tree()->DidBecomeActive();
5990 DrawFrame();
5992 EXPECT_EQ(InputHandler::ScrollStarted,
5993 host_impl_->ScrollBegin(gfx::Point(),
5994 InputHandler::Gesture));
5996 EXPECT_EQ(InputHandler::ScrollStarted,
5997 host_impl_->FlingScrollBegin());
5999 gfx::Vector2d scroll_delta(0, 100);
6000 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6001 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6003 host_impl_->ScrollEnd();
6005 scoped_ptr<ScrollAndScaleSet> scroll_info =
6006 host_impl_->ProcessScrollDeltas();
6008 // Only the child should have scrolled.
6009 ASSERT_EQ(1u, scroll_info->scrolls.size());
6010 ExpectNone(*scroll_info.get(), root_id);
6014 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
6015 // Scroll a child layer beyond its maximum scroll range and make sure the
6016 // the scroll doesn't bubble up to the parent layer.
6017 gfx::Size surface_size(10, 10);
6018 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
6019 scoped_ptr<LayerImpl> root_scrolling =
6020 CreateScrollableLayer(2, surface_size, root.get());
6022 scoped_ptr<LayerImpl> grand_child =
6023 CreateScrollableLayer(4, surface_size, root.get());
6024 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
6026 scoped_ptr<LayerImpl> child =
6027 CreateScrollableLayer(3, surface_size, root.get());
6028 child->SetScrollOffset(gfx::Vector2d(0, 4));
6029 child->AddChild(grand_child.Pass());
6031 root_scrolling->AddChild(child.Pass());
6032 root->AddChild(root_scrolling.Pass());
6033 host_impl_->active_tree()->SetRootLayer(root.Pass());
6034 host_impl_->active_tree()->DidBecomeActive();
6035 host_impl_->SetViewportSize(surface_size);
6036 DrawFrame();
6038 scoped_ptr<ScrollAndScaleSet> scroll_info;
6039 LayerImpl* child =
6040 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6041 LayerImpl* grand_child = child->children()[0];
6043 gfx::Vector2d scroll_delta(0, -2);
6044 EXPECT_EQ(InputHandler::ScrollStarted,
6045 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6046 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6048 // The grand child should have scrolled up to its limit.
6049 scroll_info = host_impl_->ProcessScrollDeltas();
6050 ASSERT_EQ(1u, scroll_info->scrolls.size());
6051 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6052 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6054 // The child should have received the bubbled delta, but the locked
6055 // scrolling layer should remain set as the grand child.
6056 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6057 scroll_info = host_impl_->ProcessScrollDeltas();
6058 ASSERT_EQ(2u, scroll_info->scrolls.size());
6059 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6060 ExpectContains(*scroll_info, child->id(), scroll_delta);
6061 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6063 // The first |ScrollBy| after the fling should re-lock the scrolling
6064 // layer to the first layer that scrolled, which is the child.
6065 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6066 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6067 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6069 // The child should have scrolled up to its limit.
6070 scroll_info = host_impl_->ProcessScrollDeltas();
6071 ASSERT_EQ(2u, scroll_info->scrolls.size());
6072 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6073 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
6075 // As the locked layer is at it's limit, no further scrolling can occur.
6076 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6077 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6078 host_impl_->ScrollEnd();
6082 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6083 // When flinging via wheel, the root should eventually scroll (we should
6084 // bubble).
6085 gfx::Size surface_size(10, 10);
6086 gfx::Size content_size(20, 20);
6087 scoped_ptr<LayerImpl> root_clip =
6088 LayerImpl::Create(host_impl_->active_tree(), 3);
6089 scoped_ptr<LayerImpl> root_scroll =
6090 CreateScrollableLayer(1, content_size, root_clip.get());
6091 int root_scroll_id = root_scroll->id();
6092 scoped_ptr<LayerImpl> child =
6093 CreateScrollableLayer(2, content_size, root_clip.get());
6095 root_scroll->AddChild(child.Pass());
6096 root_clip->AddChild(root_scroll.Pass());
6098 host_impl_->SetViewportSize(surface_size);
6099 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6100 host_impl_->active_tree()->DidBecomeActive();
6101 DrawFrame();
6103 EXPECT_EQ(InputHandler::ScrollStarted,
6104 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6106 EXPECT_EQ(InputHandler::ScrollStarted,
6107 host_impl_->FlingScrollBegin());
6109 gfx::Vector2d scroll_delta(0, 100);
6110 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6111 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6113 host_impl_->ScrollEnd();
6115 scoped_ptr<ScrollAndScaleSet> scroll_info =
6116 host_impl_->ProcessScrollDeltas();
6118 // The root should have scrolled.
6119 ASSERT_EQ(2u, scroll_info->scrolls.size());
6120 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
6124 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6125 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6126 // we should return ScrollUnknown.
6127 gfx::Size content_size(100, 100);
6128 SetupScrollAndContentsLayers(content_size);
6130 int scroll_layer_id = 2;
6131 LayerImpl* scroll_layer =
6132 host_impl_->active_tree()->LayerById(scroll_layer_id);
6133 scroll_layer->SetDrawsContent(true);
6135 int page_scale_layer_id = 5;
6136 LayerImpl* page_scale_layer =
6137 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6139 int occluder_layer_id = 6;
6140 scoped_ptr<LayerImpl> occluder_layer =
6141 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6142 occluder_layer->SetDrawsContent(true);
6143 occluder_layer->SetBounds(content_size);
6144 occluder_layer->SetContentBounds(content_size);
6145 occluder_layer->SetPosition(gfx::PointF());
6147 // The parent of the occluder is *above* the scroller.
6148 page_scale_layer->AddChild(occluder_layer.Pass());
6150 DrawFrame();
6152 EXPECT_EQ(InputHandler::ScrollUnknown,
6153 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6156 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6157 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6158 // is not the first scroller we encounter when walking up from the layer, we
6159 // should also return ScrollUnknown.
6160 gfx::Size content_size(100, 100);
6161 SetupScrollAndContentsLayers(content_size);
6163 int scroll_layer_id = 2;
6164 LayerImpl* scroll_layer =
6165 host_impl_->active_tree()->LayerById(scroll_layer_id);
6166 scroll_layer->SetDrawsContent(true);
6168 int occluder_layer_id = 6;
6169 scoped_ptr<LayerImpl> occluder_layer =
6170 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6171 occluder_layer->SetDrawsContent(true);
6172 occluder_layer->SetBounds(content_size);
6173 occluder_layer->SetContentBounds(content_size);
6174 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6176 int child_scroll_clip_layer_id = 7;
6177 scoped_ptr<LayerImpl> child_scroll_clip =
6178 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6180 int child_scroll_layer_id = 8;
6181 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6182 child_scroll_layer_id, content_size, child_scroll_clip.get());
6184 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6186 child_scroll->AddChild(occluder_layer.Pass());
6187 scroll_layer->AddChild(child_scroll.Pass());
6189 DrawFrame();
6191 EXPECT_EQ(InputHandler::ScrollUnknown,
6192 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6195 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) {
6196 gfx::Size content_size(100, 100);
6197 SetupScrollAndContentsLayers(content_size);
6199 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6201 int scroll_layer_id = 2;
6202 LayerImpl* scroll_layer =
6203 host_impl_->active_tree()->LayerById(scroll_layer_id);
6205 int child_scroll_layer_id = 7;
6206 scoped_ptr<LayerImpl> child_scroll =
6207 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6208 child_scroll->SetDrawsContent(false);
6210 scroll_layer->AddChild(child_scroll.Pass());
6212 DrawFrame();
6214 // We should not have scrolled |child_scroll| even though we technically "hit"
6215 // it. The reason for this is that if the scrolling the scroll would not move
6216 // any layer that is a drawn RSLL member, then we can ignore the hit.
6218 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6219 // overscrolling the inner viewport.
6220 EXPECT_EQ(InputHandler::ScrollStarted,
6221 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6223 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6226 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6227 // This test case is very similar to the one above with one key difference:
6228 // the invisible scroller has a scroll child that is indeed draw contents.
6229 // If we attempt to initiate a gesture scroll off of the visible scroll child
6230 // we should still start the scroll child.
6231 gfx::Size content_size(100, 100);
6232 SetupScrollAndContentsLayers(content_size);
6234 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6236 int scroll_layer_id = 2;
6237 LayerImpl* scroll_layer =
6238 host_impl_->active_tree()->LayerById(scroll_layer_id);
6240 int scroll_child_id = 6;
6241 scoped_ptr<LayerImpl> scroll_child =
6242 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6243 scroll_child->SetDrawsContent(true);
6244 scroll_child->SetBounds(content_size);
6245 scroll_child->SetContentBounds(content_size);
6246 // Move the scroll child so it's not hit by our test point.
6247 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6249 int invisible_scroll_layer_id = 7;
6250 scoped_ptr<LayerImpl> invisible_scroll =
6251 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6252 invisible_scroll->SetDrawsContent(false);
6254 int container_id = 8;
6255 scoped_ptr<LayerImpl> container =
6256 LayerImpl::Create(host_impl_->active_tree(), container_id);
6258 scoped_ptr<std::set<LayerImpl*> > scroll_children(new std::set<LayerImpl*>());
6259 scroll_children->insert(scroll_child.get());
6260 invisible_scroll->SetScrollChildren(scroll_children.release());
6262 scroll_child->SetScrollParent(invisible_scroll.get());
6264 container->AddChild(invisible_scroll.Pass());
6265 container->AddChild(scroll_child.Pass());
6267 scroll_layer->AddChild(container.Pass());
6269 DrawFrame();
6271 // We should not have scrolled |child_scroll| even though we technically "hit"
6272 // it. The reason for this is that if the scrolling the scroll would not move
6273 // any layer that is a drawn RSLL member, then we can ignore the hit.
6275 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6276 // overscrolling the inner viewport.
6277 EXPECT_EQ(InputHandler::ScrollStarted,
6278 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6280 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6283 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6284 // to CompositorFrameMetadata after SwapBuffers();
6285 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6286 scoped_ptr<SolidColorLayerImpl> root =
6287 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6288 root->SetPosition(gfx::PointF());
6289 root->SetBounds(gfx::Size(10, 10));
6290 root->SetContentBounds(gfx::Size(10, 10));
6291 root->SetDrawsContent(true);
6293 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
6295 FakeOutputSurface* fake_output_surface =
6296 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6298 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6299 fake_output_surface->last_sent_frame().metadata.latency_info;
6300 EXPECT_TRUE(metadata_latency_before.empty());
6302 ui::LatencyInfo latency_info;
6303 latency_info.AddLatencyNumber(
6304 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6305 scoped_ptr<SwapPromise> swap_promise(
6306 new LatencyInfoSwapPromise(latency_info));
6307 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
6308 host_impl_->SetNeedsRedraw();
6310 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6311 LayerTreeHostImpl::FrameData frame;
6312 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6313 host_impl_->DrawLayers(&frame);
6314 host_impl_->DidDrawAllLayers(frame);
6315 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6317 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6318 fake_output_surface->last_sent_frame().metadata.latency_info;
6319 EXPECT_EQ(1u, metadata_latency_after.size());
6320 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6321 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6324 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
6325 int root_layer_id = 1;
6326 scoped_ptr<SolidColorLayerImpl> root =
6327 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
6328 root->SetPosition(gfx::PointF());
6329 root->SetBounds(gfx::Size(10, 10));
6330 root->SetContentBounds(gfx::Size(10, 10));
6331 root->SetDrawsContent(true);
6333 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
6335 // Ensure the default frame selection bounds are empty.
6336 FakeOutputSurface* fake_output_surface =
6337 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6338 const ViewportSelectionBound& selection_anchor_before =
6339 fake_output_surface->last_sent_frame().metadata.selection_anchor;
6340 const ViewportSelectionBound& selection_focus_before =
6341 fake_output_surface->last_sent_frame().metadata.selection_focus;
6342 EXPECT_EQ(ViewportSelectionBound(), selection_anchor_before);
6343 EXPECT_EQ(ViewportSelectionBound(), selection_focus_before);
6345 // Plumb the layer-local selection bounds.
6346 gfx::Rect selection_rect(5, 0, 0, 5);
6347 LayerSelectionBound anchor, focus;
6348 anchor.type = SELECTION_BOUND_CENTER;
6349 anchor.layer_id = root_layer_id;
6350 anchor.layer_rect = selection_rect;
6351 focus = anchor;
6352 host_impl_->active_tree()->RegisterSelection(anchor, focus);
6354 // Trigger a draw-swap sequence.
6355 host_impl_->SetNeedsRedraw();
6357 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6358 LayerTreeHostImpl::FrameData frame;
6359 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6360 host_impl_->DrawLayers(&frame);
6361 host_impl_->DidDrawAllLayers(frame);
6362 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6364 // Ensure the selection bounds have propagated to the frame metadata.
6365 const ViewportSelectionBound& selection_anchor_after =
6366 fake_output_surface->last_sent_frame().metadata.selection_anchor;
6367 const ViewportSelectionBound& selection_focus_after =
6368 fake_output_surface->last_sent_frame().metadata.selection_focus;
6369 EXPECT_EQ(anchor.type, selection_anchor_after.type);
6370 EXPECT_EQ(focus.type, selection_focus_after.type);
6371 EXPECT_EQ(selection_rect, selection_anchor_after.viewport_rect);
6372 EXPECT_EQ(selection_rect, selection_anchor_after.viewport_rect);
6373 EXPECT_TRUE(selection_anchor_after.visible);
6374 EXPECT_TRUE(selection_anchor_after.visible);
6377 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
6378 public:
6379 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
6380 LayerTreeHostImpl* layer_tree_host_impl,
6381 int* set_needs_commit_count,
6382 int* set_needs_redraw_count,
6383 int* forward_to_main_count)
6384 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
6385 set_needs_commit_count_(set_needs_commit_count),
6386 set_needs_redraw_count_(set_needs_redraw_count),
6387 forward_to_main_count_(forward_to_main_count) {}
6389 virtual ~SimpleSwapPromiseMonitor() {}
6391 virtual void OnSetNeedsCommitOnMain() OVERRIDE {
6392 (*set_needs_commit_count_)++;
6395 virtual void OnSetNeedsRedrawOnImpl() OVERRIDE {
6396 (*set_needs_redraw_count_)++;
6399 virtual void OnForwardScrollUpdateToMainThreadOnImpl() OVERRIDE {
6400 (*forward_to_main_count_)++;
6403 private:
6404 int* set_needs_commit_count_;
6405 int* set_needs_redraw_count_;
6406 int* forward_to_main_count_;
6409 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
6410 int set_needs_commit_count = 0;
6411 int set_needs_redraw_count = 0;
6412 int forward_to_main_count = 0;
6415 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6416 new SimpleSwapPromiseMonitor(NULL,
6417 host_impl_.get(),
6418 &set_needs_commit_count,
6419 &set_needs_redraw_count,
6420 &forward_to_main_count));
6421 host_impl_->SetNeedsRedraw();
6422 EXPECT_EQ(0, set_needs_commit_count);
6423 EXPECT_EQ(1, set_needs_redraw_count);
6424 EXPECT_EQ(0, forward_to_main_count);
6427 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6428 // monitored.
6429 host_impl_->SetNeedsRedraw();
6430 EXPECT_EQ(0, set_needs_commit_count);
6431 EXPECT_EQ(1, set_needs_redraw_count);
6432 EXPECT_EQ(0, forward_to_main_count);
6435 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6436 new SimpleSwapPromiseMonitor(NULL,
6437 host_impl_.get(),
6438 &set_needs_commit_count,
6439 &set_needs_redraw_count,
6440 &forward_to_main_count));
6441 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
6442 EXPECT_EQ(0, set_needs_commit_count);
6443 EXPECT_EQ(2, set_needs_redraw_count);
6444 EXPECT_EQ(0, forward_to_main_count);
6448 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6449 new SimpleSwapPromiseMonitor(NULL,
6450 host_impl_.get(),
6451 &set_needs_commit_count,
6452 &set_needs_redraw_count,
6453 &forward_to_main_count));
6454 // Empty damage rect won't signal the monitor.
6455 host_impl_->SetNeedsRedrawRect(gfx::Rect());
6456 EXPECT_EQ(0, set_needs_commit_count);
6457 EXPECT_EQ(2, set_needs_redraw_count);
6458 EXPECT_EQ(0, forward_to_main_count);
6462 set_needs_commit_count = 0;
6463 set_needs_redraw_count = 0;
6464 forward_to_main_count = 0;
6465 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6466 new SimpleSwapPromiseMonitor(NULL,
6467 host_impl_.get(),
6468 &set_needs_commit_count,
6469 &set_needs_redraw_count,
6470 &forward_to_main_count));
6471 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
6473 // Scrolling normally should not trigger any forwarding.
6474 EXPECT_EQ(InputHandler::ScrollStarted,
6475 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6476 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
6477 host_impl_->ScrollEnd();
6479 EXPECT_EQ(0, set_needs_commit_count);
6480 EXPECT_EQ(1, set_needs_redraw_count);
6481 EXPECT_EQ(0, forward_to_main_count);
6483 // Scrolling with a scroll handler should defer the swap to the main
6484 // thread.
6485 scroll_layer->SetHaveScrollEventHandlers(true);
6486 EXPECT_EQ(InputHandler::ScrollStarted,
6487 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6488 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
6489 host_impl_->ScrollEnd();
6491 EXPECT_EQ(0, set_needs_commit_count);
6492 EXPECT_EQ(2, set_needs_redraw_count);
6493 EXPECT_EQ(1, forward_to_main_count);
6497 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
6498 public:
6499 virtual void SetUp() OVERRIDE {
6500 LayerTreeSettings settings = DefaultSettings();
6501 settings.calculate_top_controls_position = true;
6502 settings.top_controls_height = top_controls_height_;
6503 CreateHostImpl(settings, CreateOutputSurface());
6506 protected:
6507 static const int top_controls_height_;
6510 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
6512 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
6513 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6514 ->SetScrollOffset(gfx::Vector2d(0, 10));
6515 host_impl_->Animate(base::TimeTicks());
6516 EXPECT_FALSE(did_request_redraw_);
6519 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
6520 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6521 ->SetScrollOffset(gfx::Vector2d(0, 10));
6522 host_impl_->DidChangeTopControlsPosition();
6523 EXPECT_TRUE(did_request_animate_);
6524 EXPECT_TRUE(did_request_redraw_);
6527 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
6528 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6529 host_impl_->SetViewportSize(gfx::Size(100, 100));
6530 DrawFrame();
6532 EXPECT_EQ(InputHandler::ScrollStarted,
6533 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6534 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6535 EXPECT_EQ(gfx::Vector2dF().ToString(),
6536 scroll_layer->TotalScrollOffset().ToString());
6538 // Scroll just the top controls and verify that the scroll succeeds.
6539 const float residue = 10;
6540 float offset = top_controls_height_ - residue;
6541 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6542 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->controls_top_offset());
6543 EXPECT_EQ(gfx::Vector2dF().ToString(),
6544 scroll_layer->TotalScrollOffset().ToString());
6546 // Scroll across the boundary
6547 const float content_scroll = 20;
6548 offset = residue + content_scroll;
6549 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6550 EXPECT_EQ(-top_controls_height_,
6551 host_impl_->top_controls_manager()->controls_top_offset());
6552 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
6553 scroll_layer->TotalScrollOffset().ToString());
6555 // Now scroll back to the top of the content
6556 offset = -content_scroll;
6557 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6558 EXPECT_EQ(-top_controls_height_,
6559 host_impl_->top_controls_manager()->controls_top_offset());
6560 EXPECT_EQ(gfx::Vector2dF().ToString(),
6561 scroll_layer->TotalScrollOffset().ToString());
6563 // And scroll the top controls completely into view
6564 offset = -top_controls_height_;
6565 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6566 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6567 EXPECT_EQ(gfx::Vector2dF().ToString(),
6568 scroll_layer->TotalScrollOffset().ToString());
6570 // And attempt to scroll past the end
6571 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6572 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6573 EXPECT_EQ(gfx::Vector2dF().ToString(),
6574 scroll_layer->TotalScrollOffset().ToString());
6576 host_impl_->ScrollEnd();
6579 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
6580 public:
6581 void SetupVirtualViewportLayers(const gfx::Size& content_size,
6582 const gfx::Size& outer_viewport,
6583 const gfx::Size& inner_viewport) {
6584 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
6585 const int kOuterViewportClipLayerId = 6;
6586 const int kOuterViewportScrollLayerId = 7;
6587 const int kInnerViewportScrollLayerId = 2;
6588 const int kInnerViewportClipLayerId = 4;
6589 const int kPageScaleLayerId = 5;
6591 scoped_ptr<LayerImpl> inner_scroll =
6592 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
6593 inner_scroll->SetIsContainerForFixedPositionLayers(true);
6594 inner_scroll->SetScrollOffset(gfx::Vector2d());
6596 scoped_ptr<LayerImpl> inner_clip =
6597 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
6598 inner_clip->SetBounds(inner_viewport);
6600 scoped_ptr<LayerImpl> page_scale =
6601 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
6603 inner_scroll->SetScrollClipLayer(inner_clip->id());
6604 inner_scroll->SetBounds(outer_viewport);
6605 inner_scroll->SetContentBounds(outer_viewport);
6606 inner_scroll->SetPosition(gfx::PointF());
6608 scoped_ptr<LayerImpl> outer_clip =
6609 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
6610 outer_clip->SetBounds(outer_viewport);
6611 outer_clip->SetIsContainerForFixedPositionLayers(true);
6613 scoped_ptr<LayerImpl> outer_scroll =
6614 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
6615 outer_scroll->SetScrollClipLayer(outer_clip->id());
6616 outer_scroll->SetScrollOffset(gfx::Vector2d());
6617 outer_scroll->SetBounds(content_size);
6618 outer_scroll->SetContentBounds(content_size);
6619 outer_scroll->SetPosition(gfx::PointF());
6621 scoped_ptr<LayerImpl> contents =
6622 LayerImpl::Create(layer_tree_impl, 8);
6623 contents->SetDrawsContent(true);
6624 contents->SetBounds(content_size);
6625 contents->SetContentBounds(content_size);
6626 contents->SetPosition(gfx::PointF());
6628 outer_scroll->AddChild(contents.Pass());
6629 outer_clip->AddChild(outer_scroll.Pass());
6630 inner_scroll->AddChild(outer_clip.Pass());
6631 page_scale->AddChild(inner_scroll.Pass());
6632 inner_clip->AddChild(page_scale.Pass());
6634 layer_tree_impl->SetRootLayer(inner_clip.Pass());
6635 layer_tree_impl->SetViewportLayersFromIds(kPageScaleLayerId,
6636 kInnerViewportScrollLayerId, kOuterViewportScrollLayerId);
6638 host_impl_->active_tree()->DidBecomeActive();
6642 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
6643 gfx::Size content_size = gfx::Size(100, 160);
6644 gfx::Size outer_viewport = gfx::Size(50, 80);
6645 gfx::Size inner_viewport = gfx::Size(25, 40);
6647 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
6649 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
6650 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
6651 DrawFrame();
6653 gfx::Vector2dF inner_expected;
6654 gfx::Vector2dF outer_expected;
6655 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6656 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6658 // Make sure the fling goes to the outer viewport first
6659 EXPECT_EQ(InputHandler::ScrollStarted,
6660 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6661 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6663 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
6664 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6665 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6667 host_impl_->ScrollEnd();
6669 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6670 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6672 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
6673 EXPECT_EQ(InputHandler::ScrollStarted,
6674 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6675 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6677 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6678 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6680 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6681 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6683 host_impl_->ScrollEnd();
6685 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6686 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6690 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
6691 public:
6692 virtual void SetUp() OVERRIDE {
6693 LayerTreeSettings settings = DefaultSettings();
6694 settings.max_memory_for_prepaint_percentage = 50;
6695 CreateHostImpl(settings, CreateOutputSurface());
6699 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
6700 // Set up a memory policy and percentages which could cause
6701 // 32-bit integer overflows.
6702 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
6704 // Verify implicit limits are calculated correctly with no overflows
6705 host_impl_->SetMemoryPolicy(mem_policy);
6706 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
6707 300u * 1024u * 1024u);
6708 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
6709 150u * 1024u * 1024u);
6712 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
6713 const gfx::Size layer_size(100, 100);
6714 gfx::Transform external_transform;
6715 const gfx::Rect external_viewport(layer_size);
6716 const gfx::Rect external_clip(layer_size);
6717 const bool resourceless_software_draw = false;
6718 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
6720 host_impl_->SetExternalDrawConstraints(external_transform,
6721 external_viewport,
6722 external_clip,
6723 resourceless_software_draw);
6724 DrawFrame();
6725 EXPECT_TRANSFORMATION_MATRIX_EQ(
6726 external_transform, layer->draw_properties().target_space_transform);
6728 external_transform.Translate(20, 20);
6729 host_impl_->SetExternalDrawConstraints(external_transform,
6730 external_viewport,
6731 external_clip,
6732 resourceless_software_draw);
6733 DrawFrame();
6734 EXPECT_TRANSFORMATION_MATRIX_EQ(
6735 external_transform, layer->draw_properties().target_space_transform);
6738 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
6739 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6740 host_impl_->SetViewportSize(gfx::Size(50, 50));
6741 DrawFrame();
6743 base::TimeTicks start_time =
6744 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
6746 EXPECT_EQ(InputHandler::ScrollStarted,
6747 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
6749 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
6751 host_impl_->Animate(start_time);
6752 host_impl_->UpdateAnimationState(true);
6754 EXPECT_EQ(gfx::Vector2dF(), scrolling_layer->TotalScrollOffset());
6756 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
6757 host_impl_->UpdateAnimationState(true);
6759 float y = scrolling_layer->TotalScrollOffset().y();
6760 EXPECT_TRUE(y > 1 && y < 49);
6762 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
6763 host_impl_->UpdateAnimationState(true);
6765 EXPECT_EQ(gfx::Vector2dF(0, 50), scrolling_layer->TotalScrollOffset());
6766 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
6769 } // namespace
6770 } // namespace cc