Provide core API permissions to extensions_unittests
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blobf9f3a90d51e8df65458ef6fc7ca71e564df1672d
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/begin_frame_args_test.h"
42 #include "cc/test/fake_layer_tree_host_impl.h"
43 #include "cc/test/fake_output_surface.h"
44 #include "cc/test/fake_output_surface_client.h"
45 #include "cc/test/fake_picture_layer_impl.h"
46 #include "cc/test/fake_picture_pile_impl.h"
47 #include "cc/test/fake_proxy.h"
48 #include "cc/test/fake_rendering_stats_instrumentation.h"
49 #include "cc/test/fake_video_frame_provider.h"
50 #include "cc/test/geometry_test_utils.h"
51 #include "cc/test/layer_test_common.h"
52 #include "cc/test/render_pass_test_common.h"
53 #include "cc/test/test_shared_bitmap_manager.h"
54 #include "cc/test/test_web_graphics_context_3d.h"
55 #include "cc/trees/layer_tree_impl.h"
56 #include "cc/trees/single_thread_proxy.h"
57 #include "media/base/media.h"
58 #include "testing/gmock/include/gmock/gmock.h"
59 #include "testing/gtest/include/gtest/gtest.h"
60 #include "third_party/skia/include/core/SkMallocPixelRef.h"
61 #include "ui/gfx/frame_time.h"
62 #include "ui/gfx/rect_conversions.h"
63 #include "ui/gfx/size_conversions.h"
64 #include "ui/gfx/vector2d_conversions.h"
66 using ::testing::Mock;
67 using ::testing::Return;
68 using ::testing::AnyNumber;
69 using ::testing::AtLeast;
70 using ::testing::_;
71 using media::VideoFrame;
73 namespace cc {
74 namespace {
76 class LayerTreeHostImplTest : public testing::Test,
77 public LayerTreeHostImplClient {
78 public:
79 LayerTreeHostImplTest()
80 : proxy_(base::MessageLoopProxy::current(),
81 base::MessageLoopProxy::current()),
82 always_impl_thread_(&proxy_),
83 always_main_thread_blocked_(&proxy_),
84 shared_bitmap_manager_(new TestSharedBitmapManager()),
85 on_can_draw_state_changed_called_(false),
86 did_notify_ready_to_activate_(false),
87 did_request_commit_(false),
88 did_request_redraw_(false),
89 did_request_animate_(false),
90 did_request_manage_tiles_(false),
91 did_upload_visible_tile_(false),
92 reduce_memory_result_(true),
93 current_limit_bytes_(0),
94 current_priority_cutoff_value_(0) {
95 media::InitializeMediaLibraryForTesting();
98 LayerTreeSettings DefaultSettings() {
99 LayerTreeSettings settings;
100 settings.minimum_occlusion_tracking_size = gfx::Size();
101 settings.impl_side_painting = true;
102 settings.texture_id_allocation_chunk_size = 1;
103 settings.report_overscroll_only_for_scrollable_axes = true;
104 return settings;
107 virtual void SetUp() OVERRIDE {
108 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
111 virtual void TearDown() OVERRIDE {}
113 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {}
114 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
115 virtual void CommitVSyncParameters(base::TimeTicks timebase,
116 base::TimeDelta interval) OVERRIDE {}
117 virtual void SetEstimatedParentDrawTime(base::TimeDelta draw_time) OVERRIDE {}
118 virtual void SetMaxSwapsPendingOnImplThread(int max) OVERRIDE {}
119 virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
120 virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {}
121 virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {}
122 virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
123 on_can_draw_state_changed_called_ = true;
125 virtual void NotifyReadyToActivate() OVERRIDE {
126 did_notify_ready_to_activate_ = true;
127 host_impl_->ActivateSyncTree();
129 virtual void SetNeedsRedrawOnImplThread() OVERRIDE {
130 did_request_redraw_ = true;
132 virtual void SetNeedsRedrawRectOnImplThread(
133 const gfx::Rect& damage_rect) OVERRIDE {
134 did_request_redraw_ = true;
136 virtual void SetNeedsAnimateOnImplThread() OVERRIDE {
137 did_request_animate_ = true;
139 virtual void SetNeedsManageTilesOnImplThread() OVERRIDE {
140 did_request_manage_tiles_ = true;
142 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {
143 did_upload_visible_tile_ = true;
145 virtual void SetNeedsCommitOnImplThread() OVERRIDE {
146 did_request_commit_ = true;
148 virtual void PostAnimationEventsToMainThreadOnImplThread(
149 scoped_ptr<AnimationEventsVector> events) OVERRIDE {}
150 virtual bool ReduceContentsTextureMemoryOnImplThread(
151 size_t limit_bytes, int priority_cutoff) OVERRIDE {
152 current_limit_bytes_ = limit_bytes;
153 current_priority_cutoff_value_ = priority_cutoff;
154 return reduce_memory_result_;
156 virtual bool IsInsideDraw() OVERRIDE { return false; }
157 virtual void RenewTreePriority() OVERRIDE {}
158 virtual void PostDelayedScrollbarFadeOnImplThread(
159 const base::Closure& start_fade,
160 base::TimeDelta delay) OVERRIDE {
161 scrollbar_fade_start_ = start_fade;
162 requested_scrollbar_animation_delay_ = delay;
164 virtual void DidActivateSyncTree() OVERRIDE {}
165 virtual void DidManageTiles() OVERRIDE {}
167 void set_reduce_memory_result(bool reduce_memory_result) {
168 reduce_memory_result_ = reduce_memory_result;
171 bool CreateHostImpl(const LayerTreeSettings& settings,
172 scoped_ptr<OutputSurface> output_surface) {
173 host_impl_ = LayerTreeHostImpl::Create(settings,
174 this,
175 &proxy_,
176 &stats_instrumentation_,
177 shared_bitmap_manager_.get(),
179 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
180 host_impl_->SetViewportSize(gfx::Size(10, 10));
181 return init;
184 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
185 root->SetPosition(gfx::PointF());
186 root->SetBounds(gfx::Size(10, 10));
187 root->SetContentBounds(gfx::Size(10, 10));
188 root->SetDrawsContent(true);
189 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
190 host_impl_->active_tree()->SetRootLayer(root.Pass());
193 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
194 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
195 for (size_t i = 0; i < layer->children().size(); ++i)
196 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
199 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
200 int id,
201 const gfx::Vector2d& scroll_delta) {
202 int times_encountered = 0;
204 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
205 if (scroll_info.scrolls[i].layer_id != id)
206 continue;
207 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
208 times_encountered++;
211 ASSERT_EQ(1, times_encountered);
214 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
215 int times_encountered = 0;
217 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
218 if (scroll_info.scrolls[i].layer_id != id)
219 continue;
220 times_encountered++;
223 ASSERT_EQ(0, times_encountered);
226 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
227 const gfx::Size& content_size) {
228 const int kInnerViewportScrollLayerId = 2;
229 const int kInnerViewportClipLayerId = 4;
230 const int kPageScaleLayerId = 5;
231 scoped_ptr<LayerImpl> root =
232 LayerImpl::Create(layer_tree_impl, 1);
233 root->SetBounds(content_size);
234 root->SetContentBounds(content_size);
235 root->SetPosition(gfx::PointF());
237 scoped_ptr<LayerImpl> scroll =
238 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
239 LayerImpl* scroll_layer = scroll.get();
240 scroll->SetIsContainerForFixedPositionLayers(true);
241 scroll->SetScrollOffset(gfx::Vector2d());
243 scoped_ptr<LayerImpl> clip =
244 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
245 clip->SetBounds(
246 gfx::Size(content_size.width() / 2, content_size.height() / 2));
248 scoped_ptr<LayerImpl> page_scale =
249 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
251 scroll->SetScrollClipLayer(clip->id());
252 scroll->SetBounds(content_size);
253 scroll->SetContentBounds(content_size);
254 scroll->SetPosition(gfx::PointF());
255 scroll->SetIsContainerForFixedPositionLayers(true);
257 scoped_ptr<LayerImpl> contents =
258 LayerImpl::Create(layer_tree_impl, 3);
259 contents->SetDrawsContent(true);
260 contents->SetBounds(content_size);
261 contents->SetContentBounds(content_size);
262 contents->SetPosition(gfx::PointF());
264 scroll->AddChild(contents.Pass());
265 page_scale->AddChild(scroll.Pass());
266 clip->AddChild(page_scale.Pass());
267 root->AddChild(clip.Pass());
269 layer_tree_impl->SetRootLayer(root.Pass());
270 layer_tree_impl->SetViewportLayersFromIds(
271 kPageScaleLayerId, kInnerViewportScrollLayerId, Layer::INVALID_ID);
273 return scroll_layer;
276 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
277 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
278 host_impl_->active_tree(), content_size);
279 host_impl_->active_tree()->DidBecomeActive();
280 return scroll_layer;
283 // TODO(wjmaclean) Add clip-layer pointer to parameters.
284 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
285 const gfx::Size& size,
286 LayerImpl* clip_layer) {
287 DCHECK(clip_layer);
288 DCHECK(id != clip_layer->id());
289 scoped_ptr<LayerImpl> layer =
290 LayerImpl::Create(host_impl_->active_tree(), id);
291 layer->SetScrollClipLayer(clip_layer->id());
292 layer->SetDrawsContent(true);
293 layer->SetBounds(size);
294 layer->SetContentBounds(size);
295 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
296 return layer.Pass();
299 void DrawFrame() {
300 LayerTreeHostImpl::FrameData frame;
301 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
302 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
303 host_impl_->DidDrawAllLayers(frame);
306 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
307 void pinch_zoom_pan_viewport_test(float device_scale_factor);
308 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
309 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
310 float device_scale_factor);
312 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
313 // Note: It is not possible to disable the renderer once it has been set,
314 // so we do not need to test that disabling the renderer notifies us
315 // that can_draw changed.
316 EXPECT_FALSE(host_impl_->CanDraw());
317 on_can_draw_state_changed_called_ = false;
319 // Set up the root layer, which allows us to draw.
320 SetupScrollAndContentsLayers(gfx::Size(100, 100));
321 EXPECT_TRUE(host_impl_->CanDraw());
322 EXPECT_TRUE(on_can_draw_state_changed_called_);
323 on_can_draw_state_changed_called_ = false;
325 // Toggle the root layer to make sure it toggles can_draw
326 host_impl_->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
327 EXPECT_FALSE(host_impl_->CanDraw());
328 EXPECT_TRUE(on_can_draw_state_changed_called_);
329 on_can_draw_state_changed_called_ = false;
331 SetupScrollAndContentsLayers(gfx::Size(100, 100));
332 EXPECT_TRUE(host_impl_->CanDraw());
333 EXPECT_TRUE(on_can_draw_state_changed_called_);
334 on_can_draw_state_changed_called_ = false;
336 // Toggle the device viewport size to make sure it toggles can_draw.
337 host_impl_->SetViewportSize(gfx::Size());
338 if (always_draw) {
339 EXPECT_TRUE(host_impl_->CanDraw());
340 } else {
341 EXPECT_FALSE(host_impl_->CanDraw());
343 EXPECT_TRUE(on_can_draw_state_changed_called_);
344 on_can_draw_state_changed_called_ = false;
346 host_impl_->SetViewportSize(gfx::Size(100, 100));
347 EXPECT_TRUE(host_impl_->CanDraw());
348 EXPECT_TRUE(on_can_draw_state_changed_called_);
349 on_can_draw_state_changed_called_ = false;
351 // Toggle contents textures purged without causing any evictions,
352 // and make sure that it does not change can_draw.
353 set_reduce_memory_result(false);
354 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
355 host_impl_->memory_allocation_limit_bytes() - 1));
356 EXPECT_TRUE(host_impl_->CanDraw());
357 EXPECT_FALSE(on_can_draw_state_changed_called_);
358 on_can_draw_state_changed_called_ = false;
360 // Toggle contents textures purged to make sure it toggles can_draw.
361 set_reduce_memory_result(true);
362 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
363 host_impl_->memory_allocation_limit_bytes() - 1));
364 if (always_draw) {
365 EXPECT_TRUE(host_impl_->CanDraw());
366 } else {
367 EXPECT_FALSE(host_impl_->CanDraw());
369 EXPECT_TRUE(on_can_draw_state_changed_called_);
370 on_can_draw_state_changed_called_ = false;
372 host_impl_->active_tree()->ResetContentsTexturesPurged();
373 EXPECT_TRUE(host_impl_->CanDraw());
374 EXPECT_TRUE(on_can_draw_state_changed_called_);
375 on_can_draw_state_changed_called_ = false;
378 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
380 protected:
381 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
382 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
385 void DrawOneFrame() {
386 LayerTreeHostImpl::FrameData frame_data;
387 host_impl_->PrepareToDraw(&frame_data);
388 host_impl_->DidDrawAllLayers(frame_data);
391 FakeProxy proxy_;
392 DebugScopedSetImplThread always_impl_thread_;
393 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
395 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
396 scoped_ptr<LayerTreeHostImpl> host_impl_;
397 FakeRenderingStatsInstrumentation stats_instrumentation_;
398 bool on_can_draw_state_changed_called_;
399 bool did_notify_ready_to_activate_;
400 bool did_request_commit_;
401 bool did_request_redraw_;
402 bool did_request_animate_;
403 bool did_request_manage_tiles_;
404 bool did_upload_visible_tile_;
405 bool reduce_memory_result_;
406 base::Closure scrollbar_fade_start_;
407 base::TimeDelta requested_scrollbar_animation_delay_;
408 size_t current_limit_bytes_;
409 int current_priority_cutoff_value_;
412 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
413 bool always_draw = false;
414 CheckNotifyCalledIfCanDrawChanged(always_draw);
417 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
418 scoped_ptr<FakeOutputSurface> output_surface(
419 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
420 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
422 bool always_draw = true;
423 CheckNotifyCalledIfCanDrawChanged(always_draw);
426 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
427 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
429 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
430 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
433 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
435 scoped_ptr<LayerImpl> root =
436 LayerImpl::Create(host_impl_->active_tree(), 1);
437 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
438 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
439 root->children()[1]->AddChild(
440 LayerImpl::Create(host_impl_->active_tree(), 4));
441 root->children()[1]->AddChild(
442 LayerImpl::Create(host_impl_->active_tree(), 5));
443 root->children()[1]->children()[0]->AddChild(
444 LayerImpl::Create(host_impl_->active_tree(), 6));
445 host_impl_->active_tree()->SetRootLayer(root.Pass());
447 LayerImpl* root = host_impl_->active_tree()->root_layer();
449 ExpectClearedScrollDeltasRecursive(root);
451 scoped_ptr<ScrollAndScaleSet> scroll_info;
453 scroll_info = host_impl_->ProcessScrollDeltas();
454 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
455 ExpectClearedScrollDeltasRecursive(root);
457 scroll_info = host_impl_->ProcessScrollDeltas();
458 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
459 ExpectClearedScrollDeltasRecursive(root);
462 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
463 gfx::Vector2d scroll_offset(20, 30);
464 gfx::Vector2d scroll_delta(11, -15);
466 scoped_ptr<LayerImpl> root_clip =
467 LayerImpl::Create(host_impl_->active_tree(), 2);
468 scoped_ptr<LayerImpl> root =
469 LayerImpl::Create(host_impl_->active_tree(), 1);
470 root_clip->SetBounds(gfx::Size(10, 10));
471 LayerImpl* root_layer = root.get();
472 root_clip->AddChild(root.Pass());
473 root_layer->SetBounds(gfx::Size(110, 110));
474 root_layer->SetScrollClipLayer(root_clip->id());
475 root_layer->SetScrollOffset(scroll_offset);
476 root_layer->ScrollBy(scroll_delta);
477 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
479 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
481 scoped_ptr<ScrollAndScaleSet> scroll_info;
483 scroll_info = host_impl_->ProcessScrollDeltas();
484 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
485 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta);
486 ExpectContains(*scroll_info, root->id(), scroll_delta);
488 gfx::Vector2d scroll_delta2(-5, 27);
489 root->ScrollBy(scroll_delta2);
490 scroll_info = host_impl_->ProcessScrollDeltas();
491 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
492 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
493 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
495 root->ScrollBy(gfx::Vector2d());
496 scroll_info = host_impl_->ProcessScrollDeltas();
497 EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
500 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
501 SetupScrollAndContentsLayers(gfx::Size(100, 100));
502 host_impl_->SetViewportSize(gfx::Size(50, 50));
503 DrawFrame();
505 EXPECT_EQ(InputHandler::ScrollStarted,
506 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
507 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
508 InputHandler::Wheel));
509 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
510 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
511 InputHandler::Wheel));
512 host_impl_->ScrollEnd();
513 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
514 InputHandler::Wheel));
515 EXPECT_TRUE(did_request_redraw_);
516 EXPECT_TRUE(did_request_commit_);
519 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
520 // We should not crash when trying to scroll an empty layer tree.
521 EXPECT_EQ(InputHandler::ScrollIgnored,
522 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
525 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
526 scoped_ptr<TestWebGraphicsContext3D> context_owned =
527 TestWebGraphicsContext3D::Create();
528 context_owned->set_context_lost(true);
530 scoped_ptr<FakeOutputSurface> output_surface(FakeOutputSurface::Create3d(
531 context_owned.Pass()));
533 // Initialization will fail.
534 EXPECT_FALSE(CreateHostImpl(DefaultSettings(),
535 output_surface.PassAs<OutputSurface>()));
537 SetupScrollAndContentsLayers(gfx::Size(100, 100));
539 // We should not crash when trying to scroll after the renderer initialization
540 // fails.
541 EXPECT_EQ(InputHandler::ScrollStarted,
542 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
545 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
546 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
547 host_impl_->SetViewportSize(gfx::Size(50, 50));
548 DrawFrame();
550 // We should not crash if the tree is replaced while we are scrolling.
551 EXPECT_EQ(InputHandler::ScrollStarted,
552 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
553 host_impl_->active_tree()->DetachLayerTree();
555 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
557 // We should still be scrolling, because the scrolled layer also exists in the
558 // new tree.
559 gfx::Vector2d scroll_delta(0, 10);
560 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
561 host_impl_->ScrollEnd();
562 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
563 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
566 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
567 SetupScrollAndContentsLayers(gfx::Size(100, 100));
568 host_impl_->SetViewportSize(gfx::Size(50, 50));
569 DrawFrame();
571 // We should be able to scroll even if the root layer loses its render surface
572 // after the most recent render.
573 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
574 host_impl_->active_tree()->set_needs_update_draw_properties();
576 EXPECT_EQ(InputHandler::ScrollStarted,
577 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
580 TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
581 SetupScrollAndContentsLayers(gfx::Size(100, 100));
582 host_impl_->SetViewportSize(gfx::Size(50, 50));
583 DrawFrame();
584 LayerImpl* root = host_impl_->active_tree()->root_layer();
586 root->SetHaveWheelEventHandlers(true);
588 // With registered event handlers, wheel scrolls have to go to the main
589 // thread.
590 EXPECT_EQ(InputHandler::ScrollOnMainThread,
591 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
593 // But gesture scrolls can still be handled.
594 EXPECT_EQ(InputHandler::ScrollStarted,
595 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
598 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
599 SetupScrollAndContentsLayers(gfx::Size(100, 100));
600 host_impl_->SetViewportSize(gfx::Size(50, 50));
601 DrawFrame();
603 // Ignore the fling since no layer is being scrolled
604 EXPECT_EQ(InputHandler::ScrollIgnored,
605 host_impl_->FlingScrollBegin());
607 // Start scrolling a layer
608 EXPECT_EQ(InputHandler::ScrollStarted,
609 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
611 // Now the fling should go ahead since we've started scrolling a layer
612 EXPECT_EQ(InputHandler::ScrollStarted,
613 host_impl_->FlingScrollBegin());
616 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
617 SetupScrollAndContentsLayers(gfx::Size(100, 100));
618 host_impl_->SetViewportSize(gfx::Size(50, 50));
619 DrawFrame();
621 // Ignore the fling since no layer is being scrolled
622 EXPECT_EQ(InputHandler::ScrollIgnored,
623 host_impl_->FlingScrollBegin());
625 // Start scrolling a layer
626 EXPECT_EQ(InputHandler::ScrollStarted,
627 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
629 // Now the fling should go ahead since we've started scrolling a layer
630 EXPECT_EQ(InputHandler::ScrollStarted,
631 host_impl_->FlingScrollBegin());
634 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
635 SetupScrollAndContentsLayers(gfx::Size(100, 100));
636 host_impl_->SetViewportSize(gfx::Size(50, 50));
637 DrawFrame();
638 LayerImpl* root = host_impl_->active_tree()->root_layer();
640 root->SetShouldScrollOnMainThread(true);
642 // Start scrolling a layer
643 EXPECT_EQ(InputHandler::ScrollOnMainThread,
644 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
646 // The fling should be ignored since there's no layer being scrolled impl-side
647 EXPECT_EQ(InputHandler::ScrollIgnored,
648 host_impl_->FlingScrollBegin());
651 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
652 SetupScrollAndContentsLayers(gfx::Size(100, 100));
653 host_impl_->SetViewportSize(gfx::Size(50, 50));
654 DrawFrame();
655 LayerImpl* root = host_impl_->active_tree()->root_layer();
657 root->SetShouldScrollOnMainThread(true);
659 EXPECT_EQ(InputHandler::ScrollOnMainThread,
660 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
661 EXPECT_EQ(InputHandler::ScrollOnMainThread,
662 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
665 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
666 SetupScrollAndContentsLayers(gfx::Size(200, 200));
667 host_impl_->SetViewportSize(gfx::Size(100, 100));
669 LayerImpl* root = host_impl_->active_tree()->root_layer();
670 root->SetContentsScale(2.f, 2.f);
671 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
673 DrawFrame();
675 // All scroll types inside the non-fast scrollable region should fail.
676 EXPECT_EQ(InputHandler::ScrollOnMainThread,
677 host_impl_->ScrollBegin(gfx::Point(25, 25),
678 InputHandler::Wheel));
679 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
680 InputHandler::Wheel));
681 EXPECT_EQ(InputHandler::ScrollOnMainThread,
682 host_impl_->ScrollBegin(gfx::Point(25, 25),
683 InputHandler::Gesture));
684 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
685 InputHandler::Gesture));
687 // All scroll types outside this region should succeed.
688 EXPECT_EQ(InputHandler::ScrollStarted,
689 host_impl_->ScrollBegin(gfx::Point(75, 75),
690 InputHandler::Wheel));
691 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
692 InputHandler::Gesture));
693 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
694 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
695 InputHandler::Gesture));
696 host_impl_->ScrollEnd();
697 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
698 InputHandler::Gesture));
699 EXPECT_EQ(InputHandler::ScrollStarted,
700 host_impl_->ScrollBegin(gfx::Point(75, 75),
701 InputHandler::Gesture));
702 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
703 InputHandler::Gesture));
704 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
705 host_impl_->ScrollEnd();
706 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
707 InputHandler::Gesture));
710 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
711 SetupScrollAndContentsLayers(gfx::Size(200, 200));
712 host_impl_->SetViewportSize(gfx::Size(100, 100));
714 LayerImpl* root = host_impl_->active_tree()->root_layer();
715 root->SetContentsScale(2.f, 2.f);
716 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
717 root->SetPosition(gfx::PointF(-25.f, 0.f));
719 DrawFrame();
721 // This point would fall into the non-fast scrollable region except that we've
722 // moved the layer down by 25 pixels.
723 EXPECT_EQ(InputHandler::ScrollStarted,
724 host_impl_->ScrollBegin(gfx::Point(40, 10),
725 InputHandler::Wheel));
726 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
727 InputHandler::Wheel));
728 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
729 host_impl_->ScrollEnd();
731 // This point is still inside the non-fast region.
732 EXPECT_EQ(InputHandler::ScrollOnMainThread,
733 host_impl_->ScrollBegin(gfx::Point(10, 10),
734 InputHandler::Wheel));
737 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
738 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
739 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
740 host_impl_->SetViewportSize(gfx::Size(50, 50));
741 DrawFrame();
743 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
744 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
745 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
746 host_impl_->ScrollEnd();
747 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
750 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
751 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
752 scroll_layer->SetHaveScrollEventHandlers(true);
753 host_impl_->SetViewportSize(gfx::Size(50, 50));
754 DrawFrame();
756 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
757 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
758 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
759 host_impl_->ScrollEnd();
760 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
763 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
764 SetupScrollAndContentsLayers(gfx::Size(200, 200));
765 host_impl_->SetViewportSize(gfx::Size(100, 100));
767 DrawFrame();
769 EXPECT_EQ(InputHandler::ScrollStarted,
770 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
772 // Trying to scroll to the left/top will not succeed.
773 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
774 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
775 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
777 // Scrolling to the right/bottom will succeed.
778 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
779 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
780 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
782 // Scrolling to left/top will now succeed.
783 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
784 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
785 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
787 // Scrolling diagonally against an edge will succeed.
788 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
789 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
790 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
792 // Trying to scroll more than the available space will also succeed.
793 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
796 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
797 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
798 host_impl_->SetViewportSize(gfx::Size(100, 1000));
800 DrawFrame();
802 EXPECT_EQ(InputHandler::ScrollStarted,
803 host_impl_->ScrollBegin(gfx::Point(),
804 InputHandler::Wheel));
806 // Trying to scroll without a vertical scrollbar will fail.
807 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
808 gfx::Point(), SCROLL_FORWARD));
809 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
810 gfx::Point(), SCROLL_BACKWARD));
812 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
813 PaintedScrollbarLayerImpl::Create(
814 host_impl_->active_tree(),
816 VERTICAL));
817 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
818 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
819 vertical_scrollbar.get());
821 // Trying to scroll with a vertical scrollbar will succeed.
822 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
823 gfx::Point(), SCROLL_FORWARD));
824 EXPECT_FLOAT_EQ(875.f,
825 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
826 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
827 gfx::Point(), SCROLL_BACKWARD));
830 // The user-scrollability breaks for zoomed-in pages. So disable this.
831 // http://crbug.com/322223
832 TEST_F(LayerTreeHostImplTest, DISABLED_ScrollWithUserUnscrollableLayers) {
833 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
834 host_impl_->SetViewportSize(gfx::Size(100, 100));
836 gfx::Size overflow_size(400, 400);
837 ASSERT_EQ(1u, scroll_layer->children().size());
838 LayerImpl* overflow = scroll_layer->children()[0];
839 overflow->SetBounds(overflow_size);
840 overflow->SetContentBounds(overflow_size);
841 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
842 overflow->SetScrollOffset(gfx::Vector2d());
843 overflow->SetPosition(gfx::PointF());
845 DrawFrame();
846 gfx::Point scroll_position(10, 10);
848 EXPECT_EQ(InputHandler::ScrollStarted,
849 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
850 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
851 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->TotalScrollOffset());
853 gfx::Vector2dF scroll_delta(10, 10);
854 host_impl_->ScrollBy(scroll_position, scroll_delta);
855 host_impl_->ScrollEnd();
856 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
857 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
859 overflow->set_user_scrollable_horizontal(false);
861 EXPECT_EQ(InputHandler::ScrollStarted,
862 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
863 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
864 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
866 host_impl_->ScrollBy(scroll_position, scroll_delta);
867 host_impl_->ScrollEnd();
868 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
869 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
871 overflow->set_user_scrollable_vertical(false);
873 EXPECT_EQ(InputHandler::ScrollStarted,
874 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
875 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
876 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
878 host_impl_->ScrollBy(scroll_position, scroll_delta);
879 host_impl_->ScrollEnd();
880 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->TotalScrollOffset());
881 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
884 TEST_F(LayerTreeHostImplTest,
885 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
886 SetupScrollAndContentsLayers(gfx::Size(100, 100));
887 host_impl_->SetViewportSize(gfx::Size(50, 50));
888 DrawFrame();
890 // We should be able to hit test for touch event handlers even if the root
891 // layer loses its render surface after the most recent render.
892 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
893 host_impl_->active_tree()->set_needs_update_draw_properties();
895 EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
898 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
899 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
900 host_impl_->SetViewportSize(gfx::Size(50, 50));
901 DrawFrame();
903 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
904 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
905 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
907 float min_page_scale = 1.f, max_page_scale = 4.f;
908 float page_scale_factor = 1.f;
910 // The impl-based pinch zoom should adjust the max scroll position.
912 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
913 page_scale_factor, min_page_scale, max_page_scale);
914 host_impl_->active_tree()->SetPageScaleDelta(1.f);
915 scroll_layer->SetScrollDelta(gfx::Vector2d());
917 float page_scale_delta = 2.f;
918 gfx::Vector2dF expected_container_size_delta(
919 container_layer->bounds().width(), container_layer->bounds().height());
920 expected_container_size_delta.Scale((1.f - page_scale_delta) /
921 (page_scale_factor * page_scale_delta));
923 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
924 host_impl_->PinchGestureBegin();
925 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
926 // While the gesture is still active, the scroll layer should have a
927 // container size delta = container->bounds() * ((1.f -
928 // page_scale_delta)/())
929 EXPECT_EQ(expected_container_size_delta,
930 scroll_layer->FixedContainerSizeDelta());
931 host_impl_->PinchGestureEnd();
932 host_impl_->ScrollEnd();
933 EXPECT_FALSE(did_request_animate_);
934 EXPECT_TRUE(did_request_redraw_);
935 EXPECT_TRUE(did_request_commit_);
936 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
938 scoped_ptr<ScrollAndScaleSet> scroll_info =
939 host_impl_->ProcessScrollDeltas();
940 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
942 EXPECT_EQ(gfx::Vector2d(75, 75).ToString(),
943 scroll_layer->MaxScrollOffset().ToString());
946 // Scrolling after a pinch gesture should always be in local space. The
947 // scroll deltas do not have the page scale factor applied.
949 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
950 page_scale_factor, min_page_scale, max_page_scale);
951 host_impl_->active_tree()->SetPageScaleDelta(1.f);
952 scroll_layer->SetScrollDelta(gfx::Vector2d());
954 float page_scale_delta = 2.f;
955 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
956 host_impl_->PinchGestureBegin();
957 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
958 host_impl_->PinchGestureEnd();
959 host_impl_->ScrollEnd();
961 gfx::Vector2d scroll_delta(0, 10);
962 EXPECT_EQ(InputHandler::ScrollStarted,
963 host_impl_->ScrollBegin(gfx::Point(5, 5),
964 InputHandler::Wheel));
965 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
966 host_impl_->ScrollEnd();
968 scoped_ptr<ScrollAndScaleSet> scroll_info =
969 host_impl_->ProcessScrollDeltas();
970 ExpectContains(*scroll_info.get(),
971 scroll_layer->id(),
972 scroll_delta);
976 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
977 ui::LatencyInfo latency_info;
978 latency_info.trace_id = 1234;
979 scoped_ptr<SwapPromise> swap_promise(
980 new LatencyInfoSwapPromise(latency_info));
982 SetupScrollAndContentsLayers(gfx::Size(100, 100));
983 EXPECT_EQ(InputHandler::ScrollStarted,
984 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
985 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
986 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
987 host_impl_->ScrollEnd();
989 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
990 EXPECT_EQ(1u, scroll_info->swap_promises.size());
991 EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId());
994 TEST_F(LayerTreeHostImplTest, PinchGesture) {
995 SetupScrollAndContentsLayers(gfx::Size(100, 100));
996 host_impl_->SetViewportSize(gfx::Size(50, 50));
997 DrawFrame();
999 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1000 DCHECK(scroll_layer);
1002 float min_page_scale = 1.f;
1003 float max_page_scale = 4.f;
1005 // Basic pinch zoom in gesture
1007 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1008 min_page_scale,
1009 max_page_scale);
1010 scroll_layer->SetScrollDelta(gfx::Vector2d());
1012 float page_scale_delta = 2.f;
1013 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1014 host_impl_->PinchGestureBegin();
1015 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1016 host_impl_->PinchGestureEnd();
1017 host_impl_->ScrollEnd();
1018 EXPECT_FALSE(did_request_animate_);
1019 EXPECT_TRUE(did_request_redraw_);
1020 EXPECT_TRUE(did_request_commit_);
1022 scoped_ptr<ScrollAndScaleSet> scroll_info =
1023 host_impl_->ProcessScrollDeltas();
1024 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1027 // Zoom-in clamping
1029 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1030 min_page_scale,
1031 max_page_scale);
1032 scroll_layer->SetScrollDelta(gfx::Vector2d());
1033 float page_scale_delta = 10.f;
1035 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1036 host_impl_->PinchGestureBegin();
1037 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1038 host_impl_->PinchGestureEnd();
1039 host_impl_->ScrollEnd();
1041 scoped_ptr<ScrollAndScaleSet> scroll_info =
1042 host_impl_->ProcessScrollDeltas();
1043 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1046 // Zoom-out clamping
1048 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1049 min_page_scale,
1050 max_page_scale);
1051 scroll_layer->SetScrollDelta(gfx::Vector2d());
1052 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1054 float page_scale_delta = 0.1f;
1055 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1056 host_impl_->PinchGestureBegin();
1057 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1058 host_impl_->PinchGestureEnd();
1059 host_impl_->ScrollEnd();
1061 scoped_ptr<ScrollAndScaleSet> scroll_info =
1062 host_impl_->ProcessScrollDeltas();
1063 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1065 EXPECT_TRUE(scroll_info->scrolls.empty());
1068 // Two-finger panning should not happen based on pinch events only
1070 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1071 min_page_scale,
1072 max_page_scale);
1073 scroll_layer->SetScrollDelta(gfx::Vector2d());
1074 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1076 float page_scale_delta = 1.f;
1077 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1078 host_impl_->PinchGestureBegin();
1079 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1080 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1081 host_impl_->PinchGestureEnd();
1082 host_impl_->ScrollEnd();
1084 scoped_ptr<ScrollAndScaleSet> scroll_info =
1085 host_impl_->ProcessScrollDeltas();
1086 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1087 EXPECT_TRUE(scroll_info->scrolls.empty());
1090 // Two-finger panning should work with interleaved scroll events
1092 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1093 min_page_scale,
1094 max_page_scale);
1095 scroll_layer->SetScrollDelta(gfx::Vector2d());
1096 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1098 float page_scale_delta = 1.f;
1099 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1100 host_impl_->PinchGestureBegin();
1101 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1102 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1103 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1104 host_impl_->PinchGestureEnd();
1105 host_impl_->ScrollEnd();
1107 scoped_ptr<ScrollAndScaleSet> scroll_info =
1108 host_impl_->ProcessScrollDeltas();
1109 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1110 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1113 // Two-finger panning should work when starting fully zoomed out.
1115 host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
1116 0.5f,
1117 4.f);
1118 scroll_layer->SetScrollDelta(gfx::Vector2d());
1119 scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
1121 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
1122 host_impl_->PinchGestureBegin();
1123 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1124 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1125 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1126 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1127 host_impl_->PinchGestureEnd();
1128 host_impl_->ScrollEnd();
1130 scoped_ptr<ScrollAndScaleSet> scroll_info =
1131 host_impl_->ProcessScrollDeltas();
1132 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1133 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1137 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1138 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1139 host_impl_->SetViewportSize(gfx::Size(50, 50));
1140 DrawFrame();
1142 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1143 DCHECK(scroll_layer);
1145 float min_page_scale = 0.5f;
1146 float max_page_scale = 4.f;
1147 base::TimeTicks start_time = base::TimeTicks() +
1148 base::TimeDelta::FromSeconds(1);
1149 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1150 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1151 base::TimeTicks end_time = start_time + duration;
1153 // Non-anchor zoom-in
1155 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1156 min_page_scale,
1157 max_page_scale);
1158 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1160 did_request_redraw_ = false;
1161 did_request_animate_ = false;
1162 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), false, 2.f, duration);
1163 EXPECT_FALSE(did_request_redraw_);
1164 EXPECT_TRUE(did_request_animate_);
1166 did_request_redraw_ = false;
1167 did_request_animate_ = false;
1168 host_impl_->Animate(start_time);
1169 EXPECT_TRUE(did_request_redraw_);
1170 EXPECT_TRUE(did_request_animate_);
1172 did_request_redraw_ = false;
1173 did_request_animate_ = false;
1174 host_impl_->Animate(halfway_through_animation);
1175 EXPECT_TRUE(did_request_redraw_);
1176 EXPECT_TRUE(did_request_animate_);
1178 did_request_redraw_ = false;
1179 did_request_animate_ = false;
1180 did_request_commit_ = false;
1181 host_impl_->Animate(end_time);
1182 EXPECT_TRUE(did_request_commit_);
1183 EXPECT_FALSE(did_request_animate_);
1185 scoped_ptr<ScrollAndScaleSet> scroll_info =
1186 host_impl_->ProcessScrollDeltas();
1187 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1188 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1191 // Anchor zoom-out
1193 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1194 min_page_scale,
1195 max_page_scale);
1196 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1198 did_request_redraw_ = false;
1199 did_request_animate_ = false;
1200 host_impl_->StartPageScaleAnimation(
1201 gfx::Vector2d(25, 25), true, min_page_scale, duration);
1202 EXPECT_FALSE(did_request_redraw_);
1203 EXPECT_TRUE(did_request_animate_);
1205 did_request_redraw_ = false;
1206 did_request_animate_ = false;
1207 host_impl_->Animate(start_time);
1208 EXPECT_TRUE(did_request_redraw_);
1209 EXPECT_TRUE(did_request_animate_);
1211 did_request_redraw_ = false;
1212 did_request_commit_ = false;
1213 did_request_animate_ = false;
1214 host_impl_->Animate(end_time);
1215 EXPECT_TRUE(did_request_redraw_);
1216 EXPECT_FALSE(did_request_animate_);
1217 EXPECT_TRUE(did_request_commit_);
1219 scoped_ptr<ScrollAndScaleSet> scroll_info =
1220 host_impl_->ProcessScrollDeltas();
1221 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1222 // Pushed to (0,0) via clamping against contents layer size.
1223 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1227 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1228 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1229 host_impl_->SetViewportSize(gfx::Size(50, 50));
1230 DrawFrame();
1232 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1233 DCHECK(scroll_layer);
1235 float min_page_scale = 0.5f;
1236 float max_page_scale = 4.f;
1237 base::TimeTicks start_time = base::TimeTicks() +
1238 base::TimeDelta::FromSeconds(1);
1239 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1240 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1241 base::TimeTicks end_time = start_time + duration;
1243 // Anchor zoom with unchanged page scale should not change scroll or scale.
1245 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1246 min_page_scale,
1247 max_page_scale);
1248 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1250 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), true, 1.f, duration);
1251 host_impl_->Animate(start_time);
1252 host_impl_->Animate(halfway_through_animation);
1253 EXPECT_TRUE(did_request_redraw_);
1254 host_impl_->Animate(end_time);
1255 EXPECT_TRUE(did_request_commit_);
1257 scoped_ptr<ScrollAndScaleSet> scroll_info =
1258 host_impl_->ProcessScrollDeltas();
1259 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1260 ExpectNone(*scroll_info, scroll_layer->id());
1264 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1265 public:
1266 LayerTreeHostImplOverridePhysicalTime(
1267 const LayerTreeSettings& settings,
1268 LayerTreeHostImplClient* client,
1269 Proxy* proxy,
1270 SharedBitmapManager* manager,
1271 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1272 : LayerTreeHostImpl(settings,
1273 client,
1274 proxy,
1275 rendering_stats_instrumentation,
1276 manager,
1277 0) {}
1279 virtual BeginFrameArgs CurrentBeginFrameArgs() const OVERRIDE {
1280 return CreateBeginFrameArgsForTesting(fake_current_physical_time_);
1283 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1284 fake_current_physical_time_ = fake_now;
1287 private:
1288 base::TimeTicks fake_current_physical_time_;
1291 #define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST() \
1292 gfx::Size viewport_size(10, 10); \
1293 gfx::Size content_size(100, 100); \
1295 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = \
1296 new LayerTreeHostImplOverridePhysicalTime(settings, \
1297 this, \
1298 &proxy_, \
1299 shared_bitmap_manager_.get(), \
1300 &stats_instrumentation_); \
1301 host_impl_ = make_scoped_ptr(host_impl_override_time); \
1302 host_impl_->InitializeRenderer(CreateOutputSurface()); \
1303 host_impl_->SetViewportSize(viewport_size); \
1305 scoped_ptr<LayerImpl> root = \
1306 LayerImpl::Create(host_impl_->active_tree(), 1); \
1307 root->SetBounds(viewport_size); \
1309 scoped_ptr<LayerImpl> scroll = \
1310 LayerImpl::Create(host_impl_->active_tree(), 2); \
1311 scroll->SetScrollClipLayer(root->id()); \
1312 scroll->SetScrollOffset(gfx::Vector2d()); \
1313 root->SetBounds(viewport_size); \
1314 scroll->SetBounds(content_size); \
1315 scroll->SetContentBounds(content_size); \
1316 scroll->SetIsContainerForFixedPositionLayers(true); \
1318 scoped_ptr<LayerImpl> contents = \
1319 LayerImpl::Create(host_impl_->active_tree(), 3); \
1320 contents->SetDrawsContent(true); \
1321 contents->SetBounds(content_size); \
1322 contents->SetContentBounds(content_size); \
1324 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = \
1325 SolidColorScrollbarLayerImpl::Create( \
1326 host_impl_->active_tree(), 4, VERTICAL, 10, 0, false, true); \
1327 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); \
1329 scroll->AddChild(contents.Pass()); \
1330 root->AddChild(scroll.Pass()); \
1331 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1); \
1332 root->AddChild(scrollbar.PassAs<LayerImpl>()); \
1334 host_impl_->active_tree()->SetRootLayer(root.Pass()); \
1335 host_impl_->active_tree()->SetViewportLayersFromIds( \
1336 1, 2, Layer::INVALID_ID); \
1337 host_impl_->active_tree()->DidBecomeActive(); \
1338 DrawFrame();
1340 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1341 LayerTreeSettings settings;
1342 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1343 settings.scrollbar_fade_delay_ms = 20;
1344 settings.scrollbar_fade_duration_ms = 20;
1346 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1348 base::TimeTicks fake_now = gfx::FrameTime::Now();
1350 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1351 EXPECT_FALSE(did_request_redraw_);
1353 // If no scroll happened during a scroll gesture, it should have no effect.
1354 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1355 host_impl_->ScrollEnd();
1356 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1357 EXPECT_FALSE(did_request_redraw_);
1358 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1360 // After a scroll, a fade animation should be scheduled about 20ms from now.
1361 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1362 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1363 host_impl_->ScrollEnd();
1364 did_request_redraw_ = false;
1365 did_request_animate_ = false;
1366 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1367 requested_scrollbar_animation_delay_);
1368 EXPECT_FALSE(did_request_redraw_);
1369 EXPECT_FALSE(did_request_animate_);
1370 requested_scrollbar_animation_delay_ = base::TimeDelta();
1371 scrollbar_fade_start_.Run();
1372 host_impl_->Animate(fake_now);
1374 // After the fade begins, we should start getting redraws instead of a
1375 // scheduled animation.
1376 fake_now += base::TimeDelta::FromMilliseconds(25);
1377 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1378 EXPECT_TRUE(did_request_animate_);
1379 did_request_animate_ = false;
1381 // Setting the scroll offset outside a scroll should also cause the scrollbar
1382 // to appear and to schedule a fade.
1383 host_impl_->InnerViewportScrollLayer()->SetScrollOffset(gfx::Vector2d(5, 5));
1384 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1385 requested_scrollbar_animation_delay_);
1386 EXPECT_FALSE(did_request_redraw_);
1387 EXPECT_FALSE(did_request_animate_);
1388 requested_scrollbar_animation_delay_ = base::TimeDelta();
1391 TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) {
1392 LayerTreeSettings settings;
1393 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1394 settings.scrollbar_fade_delay_ms = 20;
1395 settings.scrollbar_fade_duration_ms = 20;
1396 settings.use_pinch_zoom_scrollbars = true;
1398 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1400 base::TimeTicks fake_now = gfx::FrameTime::Now();
1402 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
1404 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1405 EXPECT_FALSE(did_request_animate_);
1407 // If no scroll happened during a scroll gesture, it should have no effect.
1408 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1409 host_impl_->ScrollEnd();
1410 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1411 EXPECT_FALSE(did_request_animate_);
1412 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1414 // After a scroll, no fade animation should be scheduled.
1415 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1416 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1417 host_impl_->ScrollEnd();
1418 did_request_redraw_ = false;
1419 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1420 EXPECT_FALSE(did_request_animate_);
1421 requested_scrollbar_animation_delay_ = base::TimeDelta();
1423 // We should not see any draw requests.
1424 fake_now += base::TimeDelta::FromMilliseconds(25);
1425 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1426 EXPECT_FALSE(did_request_animate_);
1428 // Make page scale > min so that subsequent scrolls will trigger fades.
1429 host_impl_->active_tree()->SetPageScaleDelta(1.1f);
1431 // After a scroll, a fade animation should be scheduled about 20ms from now.
1432 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1433 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1434 host_impl_->ScrollEnd();
1435 did_request_redraw_ = false;
1436 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1437 requested_scrollbar_animation_delay_);
1438 EXPECT_FALSE(did_request_animate_);
1439 requested_scrollbar_animation_delay_ = base::TimeDelta();
1440 scrollbar_fade_start_.Run();
1442 // After the fade begins, we should start getting redraws instead of a
1443 // scheduled animation.
1444 fake_now += base::TimeDelta::FromMilliseconds(25);
1445 host_impl_->Animate(fake_now);
1446 EXPECT_TRUE(did_request_animate_);
1449 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1450 float device_scale_factor) {
1451 LayerTreeSettings settings;
1452 settings.scrollbar_fade_delay_ms = 500;
1453 settings.scrollbar_fade_duration_ms = 300;
1454 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1456 gfx::Size viewport_size(300, 200);
1457 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1458 gfx::ScaleSize(viewport_size, device_scale_factor));
1459 gfx::Size content_size(1000, 1000);
1461 CreateHostImpl(settings, CreateOutputSurface());
1462 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1463 host_impl_->SetViewportSize(device_viewport_size);
1465 scoped_ptr<LayerImpl> root =
1466 LayerImpl::Create(host_impl_->active_tree(), 1);
1467 root->SetBounds(viewport_size);
1469 scoped_ptr<LayerImpl> scroll =
1470 LayerImpl::Create(host_impl_->active_tree(), 2);
1471 scroll->SetScrollClipLayer(root->id());
1472 scroll->SetScrollOffset(gfx::Vector2d());
1473 scroll->SetBounds(content_size);
1474 scroll->SetContentBounds(content_size);
1475 scroll->SetIsContainerForFixedPositionLayers(true);
1477 scoped_ptr<LayerImpl> contents =
1478 LayerImpl::Create(host_impl_->active_tree(), 3);
1479 contents->SetDrawsContent(true);
1480 contents->SetBounds(content_size);
1481 contents->SetContentBounds(content_size);
1483 // The scrollbar is on the right side.
1484 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1485 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1486 scrollbar->SetDrawsContent(true);
1487 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1488 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1489 scrollbar->SetPosition(gfx::Point(285, 0));
1491 scroll->AddChild(contents.Pass());
1492 root->AddChild(scroll.Pass());
1493 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1494 root->AddChild(scrollbar.PassAs<LayerImpl>());
1496 host_impl_->active_tree()->SetRootLayer(root.Pass());
1497 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
1498 host_impl_->active_tree()->DidBecomeActive();
1499 DrawFrame();
1501 LayerImpl* root_scroll =
1502 host_impl_->active_tree()->InnerViewportScrollLayer();
1503 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1504 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1505 static_cast<ScrollbarAnimationControllerThinning*>(
1506 root_scroll->scrollbar_animation_controller());
1507 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1509 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1510 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1512 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1513 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1515 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1516 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1518 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1519 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1520 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1522 did_request_redraw_ = false;
1523 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1524 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1525 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1526 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1527 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1528 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1529 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1532 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1533 SetupMouseMoveAtWithDeviceScale(1.f);
1536 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1537 SetupMouseMoveAtWithDeviceScale(2.f);
1540 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1541 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1542 host_impl_->SetViewportSize(gfx::Size(50, 50));
1543 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
1544 DrawFrame();
1546 CompositorFrameMetadata metadata =
1547 host_impl_->MakeCompositorFrameMetadata();
1548 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1549 EXPECT_EQ(1.f, metadata.page_scale_factor);
1550 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
1551 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1552 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1553 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1556 // Scrolling should update metadata immediately.
1557 EXPECT_EQ(InputHandler::ScrollStarted,
1558 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1559 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1561 CompositorFrameMetadata metadata =
1562 host_impl_->MakeCompositorFrameMetadata();
1563 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1565 host_impl_->ScrollEnd();
1567 CompositorFrameMetadata metadata =
1568 host_impl_->MakeCompositorFrameMetadata();
1569 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1572 // Page scale should update metadata correctly (shrinking only the viewport).
1573 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1574 host_impl_->PinchGestureBegin();
1575 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1576 host_impl_->PinchGestureEnd();
1577 host_impl_->ScrollEnd();
1579 CompositorFrameMetadata metadata =
1580 host_impl_->MakeCompositorFrameMetadata();
1581 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1582 EXPECT_EQ(2.f, metadata.page_scale_factor);
1583 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
1584 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1585 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1586 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1589 // Likewise if set from the main thread.
1590 host_impl_->ProcessScrollDeltas();
1591 host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
1592 host_impl_->active_tree()->SetPageScaleDelta(1.f);
1594 CompositorFrameMetadata metadata =
1595 host_impl_->MakeCompositorFrameMetadata();
1596 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1597 EXPECT_EQ(4.f, metadata.page_scale_factor);
1598 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
1599 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1600 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1601 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1605 class DidDrawCheckLayer : public LayerImpl {
1606 public:
1607 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1608 return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(tree_impl, id));
1611 virtual bool WillDraw(DrawMode draw_mode, ResourceProvider* provider)
1612 OVERRIDE {
1613 will_draw_called_ = true;
1614 if (will_draw_returns_false_)
1615 return false;
1616 return LayerImpl::WillDraw(draw_mode, provider);
1619 virtual void AppendQuads(RenderPass* render_pass,
1620 const OcclusionTracker<LayerImpl>& occlusion_tracker,
1621 AppendQuadsData* append_quads_data) OVERRIDE {
1622 append_quads_called_ = true;
1623 LayerImpl::AppendQuads(render_pass, occlusion_tracker, append_quads_data);
1626 virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
1627 did_draw_called_ = true;
1628 LayerImpl::DidDraw(provider);
1631 bool will_draw_called() const { return will_draw_called_; }
1632 bool append_quads_called() const { return append_quads_called_; }
1633 bool did_draw_called() const { return did_draw_called_; }
1635 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1637 void ClearDidDrawCheck() {
1638 will_draw_called_ = false;
1639 append_quads_called_ = false;
1640 did_draw_called_ = false;
1643 protected:
1644 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1645 : LayerImpl(tree_impl, id),
1646 will_draw_returns_false_(false),
1647 will_draw_called_(false),
1648 append_quads_called_(false),
1649 did_draw_called_(false) {
1650 SetBounds(gfx::Size(10, 10));
1651 SetContentBounds(gfx::Size(10, 10));
1652 SetDrawsContent(true);
1653 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1656 private:
1657 bool will_draw_returns_false_;
1658 bool will_draw_called_;
1659 bool append_quads_called_;
1660 bool did_draw_called_;
1663 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1664 // The root layer is always drawn, so run this test on a child layer that
1665 // will be masked out by the root layer's bounds.
1666 host_impl_->active_tree()->SetRootLayer(
1667 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1668 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1669 host_impl_->active_tree()->root_layer());
1671 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1672 DidDrawCheckLayer* layer =
1673 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1676 LayerTreeHostImpl::FrameData frame;
1677 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1678 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1679 host_impl_->DidDrawAllLayers(frame);
1681 EXPECT_TRUE(layer->will_draw_called());
1682 EXPECT_TRUE(layer->append_quads_called());
1683 EXPECT_TRUE(layer->did_draw_called());
1686 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
1689 LayerTreeHostImpl::FrameData frame;
1691 layer->set_will_draw_returns_false();
1692 layer->ClearDidDrawCheck();
1694 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1695 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1696 host_impl_->DidDrawAllLayers(frame);
1698 EXPECT_TRUE(layer->will_draw_called());
1699 EXPECT_FALSE(layer->append_quads_called());
1700 EXPECT_FALSE(layer->did_draw_called());
1704 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1705 // The root layer is always drawn, so run this test on a child layer that
1706 // will be masked out by the root layer's bounds.
1707 host_impl_->active_tree()->SetRootLayer(
1708 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1709 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1710 host_impl_->active_tree()->root_layer());
1711 root->SetMasksToBounds(true);
1713 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1714 DidDrawCheckLayer* layer =
1715 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1716 // Ensure visible_content_rect for layer is empty.
1717 layer->SetPosition(gfx::PointF(100.f, 100.f));
1718 layer->SetBounds(gfx::Size(10, 10));
1719 layer->SetContentBounds(gfx::Size(10, 10));
1721 LayerTreeHostImpl::FrameData frame;
1723 EXPECT_FALSE(layer->will_draw_called());
1724 EXPECT_FALSE(layer->did_draw_called());
1726 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1727 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1728 host_impl_->DidDrawAllLayers(frame);
1730 EXPECT_FALSE(layer->will_draw_called());
1731 EXPECT_FALSE(layer->did_draw_called());
1733 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1735 // Ensure visible_content_rect for layer is not empty
1736 layer->SetPosition(gfx::PointF());
1738 EXPECT_FALSE(layer->will_draw_called());
1739 EXPECT_FALSE(layer->did_draw_called());
1741 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1742 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1743 host_impl_->DidDrawAllLayers(frame);
1745 EXPECT_TRUE(layer->will_draw_called());
1746 EXPECT_TRUE(layer->did_draw_called());
1748 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1751 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1752 gfx::Size big_size(1000, 1000);
1753 host_impl_->SetViewportSize(big_size);
1755 host_impl_->active_tree()->SetRootLayer(
1756 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1757 DidDrawCheckLayer* root =
1758 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1760 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1761 DidDrawCheckLayer* occluded_layer =
1762 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1764 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1765 DidDrawCheckLayer* top_layer =
1766 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1767 // This layer covers the occluded_layer above. Make this layer large so it can
1768 // occlude.
1769 top_layer->SetBounds(big_size);
1770 top_layer->SetContentBounds(big_size);
1771 top_layer->SetContentsOpaque(true);
1773 LayerTreeHostImpl::FrameData frame;
1775 EXPECT_FALSE(occluded_layer->will_draw_called());
1776 EXPECT_FALSE(occluded_layer->did_draw_called());
1777 EXPECT_FALSE(top_layer->will_draw_called());
1778 EXPECT_FALSE(top_layer->did_draw_called());
1780 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1781 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1782 host_impl_->DidDrawAllLayers(frame);
1784 EXPECT_FALSE(occluded_layer->will_draw_called());
1785 EXPECT_FALSE(occluded_layer->did_draw_called());
1786 EXPECT_TRUE(top_layer->will_draw_called());
1787 EXPECT_TRUE(top_layer->did_draw_called());
1790 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1791 host_impl_->active_tree()->SetRootLayer(
1792 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1793 DidDrawCheckLayer* root =
1794 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1796 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1797 DidDrawCheckLayer* layer1 =
1798 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1800 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1801 DidDrawCheckLayer* layer2 =
1802 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1804 layer1->SetOpacity(0.3f);
1805 layer1->SetShouldFlattenTransform(true);
1807 EXPECT_FALSE(root->did_draw_called());
1808 EXPECT_FALSE(layer1->did_draw_called());
1809 EXPECT_FALSE(layer2->did_draw_called());
1811 LayerTreeHostImpl::FrameData frame;
1812 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
1813 host_impl_->active_tree()->root_layer());
1814 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1815 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1816 host_impl_->DidDrawAllLayers(frame);
1818 EXPECT_TRUE(root->did_draw_called());
1819 EXPECT_TRUE(layer1->did_draw_called());
1820 EXPECT_TRUE(layer2->did_draw_called());
1822 EXPECT_NE(root->render_surface(), layer1->render_surface());
1823 EXPECT_TRUE(!!layer1->render_surface());
1826 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1827 public:
1828 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1829 int id,
1830 bool tile_missing,
1831 bool had_incomplete_tile,
1832 bool animating,
1833 ResourceProvider* resource_provider) {
1834 return scoped_ptr<LayerImpl>(
1835 new MissingTextureAnimatingLayer(tree_impl,
1837 tile_missing,
1838 had_incomplete_tile,
1839 animating,
1840 resource_provider));
1843 virtual void AppendQuads(RenderPass* render_pass,
1844 const OcclusionTracker<LayerImpl>& occlusion_tracker,
1845 AppendQuadsData* append_quads_data) OVERRIDE {
1846 LayerImpl::AppendQuads(render_pass, occlusion_tracker, append_quads_data);
1847 if (had_incomplete_tile_)
1848 append_quads_data->num_incomplete_tiles++;
1849 if (tile_missing_)
1850 append_quads_data->num_missing_tiles++;
1853 private:
1854 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1855 int id,
1856 bool tile_missing,
1857 bool had_incomplete_tile,
1858 bool animating,
1859 ResourceProvider* resource_provider)
1860 : DidDrawCheckLayer(tree_impl, id),
1861 tile_missing_(tile_missing),
1862 had_incomplete_tile_(had_incomplete_tile) {
1863 if (animating)
1864 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1867 bool tile_missing_;
1868 bool had_incomplete_tile_;
1871 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsOnDefault) {
1872 host_impl_->active_tree()->SetRootLayer(
1873 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1874 DidDrawCheckLayer* root =
1875 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1877 bool tile_missing = false;
1878 bool had_incomplete_tile = false;
1879 bool is_animating = false;
1880 root->AddChild(
1881 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1883 tile_missing,
1884 had_incomplete_tile,
1885 is_animating,
1886 host_impl_->resource_provider()));
1888 LayerTreeHostImpl::FrameData frame;
1890 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1891 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1892 host_impl_->DidDrawAllLayers(frame);
1895 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) {
1896 host_impl_->active_tree()->SetRootLayer(
1897 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1898 DidDrawCheckLayer* root =
1899 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1900 bool tile_missing = false;
1901 bool had_incomplete_tile = false;
1902 bool is_animating = true;
1903 root->AddChild(
1904 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1906 tile_missing,
1907 had_incomplete_tile,
1908 is_animating,
1909 host_impl_->resource_provider()));
1911 LayerTreeHostImpl::FrameData frame;
1913 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1914 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1915 host_impl_->DidDrawAllLayers(frame);
1918 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithMissingTiles) {
1919 host_impl_->active_tree()->SetRootLayer(
1920 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1921 DidDrawCheckLayer* root =
1922 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1924 bool tile_missing = true;
1925 bool had_incomplete_tile = false;
1926 bool is_animating = false;
1927 root->AddChild(
1928 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1930 tile_missing,
1931 had_incomplete_tile,
1932 is_animating,
1933 host_impl_->resource_provider()));
1934 LayerTreeHostImpl::FrameData frame;
1935 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1936 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1937 host_impl_->DidDrawAllLayers(frame);
1940 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithIncompleteTile) {
1941 host_impl_->active_tree()->SetRootLayer(
1942 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1943 DidDrawCheckLayer* root =
1944 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1946 bool tile_missing = false;
1947 bool had_incomplete_tile = true;
1948 bool is_animating = false;
1949 root->AddChild(
1950 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1952 tile_missing,
1953 had_incomplete_tile,
1954 is_animating,
1955 host_impl_->resource_provider()));
1956 LayerTreeHostImpl::FrameData frame;
1957 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1958 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1959 host_impl_->DidDrawAllLayers(frame);
1962 TEST_F(LayerTreeHostImplTest,
1963 PrepareToDrawFailsWithAnimationAndMissingTilesUsesCheckerboard) {
1964 host_impl_->active_tree()->SetRootLayer(
1965 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
1966 DidDrawCheckLayer* root =
1967 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1968 bool tile_missing = true;
1969 bool had_incomplete_tile = false;
1970 bool is_animating = true;
1971 root->AddChild(
1972 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1974 tile_missing,
1975 had_incomplete_tile,
1976 is_animating,
1977 host_impl_->resource_provider()));
1978 LayerTreeHostImpl::FrameData frame;
1979 EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS,
1980 host_impl_->PrepareToDraw(&frame));
1981 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1982 host_impl_->DidDrawAllLayers(frame);
1985 TEST_F(LayerTreeHostImplTest,
1986 PrepareToDrawSucceedsWithAnimationAndIncompleteTiles) {
1987 host_impl_->active_tree()->SetRootLayer(
1988 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
1989 DidDrawCheckLayer* root =
1990 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1991 bool tile_missing = false;
1992 bool had_incomplete_tile = true;
1993 bool is_animating = true;
1994 root->AddChild(
1995 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1997 tile_missing,
1998 had_incomplete_tile,
1999 is_animating,
2000 host_impl_->resource_provider()));
2001 LayerTreeHostImpl::FrameData frame;
2002 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2003 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2004 host_impl_->DidDrawAllLayers(frame);
2007 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenHighResRequired) {
2008 host_impl_->active_tree()->SetRootLayer(
2009 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2010 DidDrawCheckLayer* root =
2011 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2012 bool tile_missing = false;
2013 bool had_incomplete_tile = false;
2014 bool is_animating = false;
2015 root->AddChild(
2016 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2018 tile_missing,
2019 had_incomplete_tile,
2020 is_animating,
2021 host_impl_->resource_provider()));
2022 host_impl_->active_tree()->SetRequiresHighResToDraw();
2023 LayerTreeHostImpl::FrameData frame;
2024 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2025 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2026 host_impl_->DidDrawAllLayers(frame);
2029 TEST_F(LayerTreeHostImplTest,
2030 PrepareToDrawFailsWhenHighResRequiredAndIncompleteTiles) {
2031 host_impl_->active_tree()->SetRootLayer(
2032 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2033 DidDrawCheckLayer* root =
2034 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2035 bool tile_missing = false;
2036 bool had_incomplete_tile = true;
2037 bool is_animating = false;
2038 root->AddChild(
2039 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2041 tile_missing,
2042 had_incomplete_tile,
2043 is_animating,
2044 host_impl_->resource_provider()));
2045 host_impl_->active_tree()->SetRequiresHighResToDraw();
2046 LayerTreeHostImpl::FrameData frame;
2047 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2048 host_impl_->PrepareToDraw(&frame));
2049 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2050 host_impl_->DidDrawAllLayers(frame);
2053 TEST_F(LayerTreeHostImplTest,
2054 PrepareToDrawFailsWhenHighResRequiredAndMissingTile) {
2055 host_impl_->active_tree()->SetRootLayer(
2056 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2057 DidDrawCheckLayer* root =
2058 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2059 bool tile_missing = true;
2060 bool had_incomplete_tile = false;
2061 bool is_animating = false;
2062 root->AddChild(
2063 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2065 tile_missing,
2066 had_incomplete_tile,
2067 is_animating,
2068 host_impl_->resource_provider()));
2069 host_impl_->active_tree()->SetRequiresHighResToDraw();
2070 LayerTreeHostImpl::FrameData frame;
2071 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2072 host_impl_->PrepareToDraw(&frame));
2073 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2074 host_impl_->DidDrawAllLayers(frame);
2077 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2078 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2079 root->SetScrollClipLayer(Layer::INVALID_ID);
2080 host_impl_->active_tree()->SetRootLayer(root.Pass());
2081 DrawFrame();
2083 // Scroll event is ignored because layer is not scrollable.
2084 EXPECT_EQ(InputHandler::ScrollIgnored,
2085 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2086 EXPECT_FALSE(did_request_redraw_);
2087 EXPECT_FALSE(did_request_commit_);
2090 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2091 public:
2092 LayerTreeHostImplTopControlsTest()
2093 // Make the clip size the same as the layer (content) size so the layer is
2094 // non-scrollable.
2095 : layer_size_(10, 10),
2096 clip_size_(layer_size_) {
2097 settings_.calculate_top_controls_position = true;
2098 settings_.top_controls_height = 50;
2100 viewport_size_ =
2101 gfx::Size(clip_size_.width(),
2102 clip_size_.height() + settings_.top_controls_height);
2105 void SetupTopControlsAndScrollLayer() {
2106 CreateHostImpl(settings_, CreateOutputSurface());
2108 scoped_ptr<LayerImpl> root =
2109 LayerImpl::Create(host_impl_->active_tree(), 1);
2110 scoped_ptr<LayerImpl> root_clip =
2111 LayerImpl::Create(host_impl_->active_tree(), 2);
2112 root_clip->SetBounds(clip_size_);
2113 root->SetScrollClipLayer(root_clip->id());
2114 root->SetBounds(layer_size_);
2115 root->SetContentBounds(layer_size_);
2116 root->SetPosition(gfx::PointF());
2117 root->SetDrawsContent(false);
2118 root->SetIsContainerForFixedPositionLayers(true);
2119 int inner_viewport_scroll_layer_id = root->id();
2120 int page_scale_layer_id = root_clip->id();
2121 root_clip->AddChild(root.Pass());
2122 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2123 host_impl_->active_tree()->SetViewportLayersFromIds(
2124 page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
2125 // Set a viewport size that is large enough to contain both the top controls
2126 // and some content.
2127 host_impl_->SetViewportSize(viewport_size_);
2128 host_impl_->SetTopControlsLayoutHeight(settings_.top_controls_height);
2129 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2130 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2133 protected:
2134 gfx::Size layer_size_;
2135 gfx::Size clip_size_;
2136 gfx::Size viewport_size_;
2138 LayerTreeSettings settings_;
2139 }; // class LayerTreeHostImplTopControlsTest
2141 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2142 SetupTopControlsAndScrollLayer();
2143 DrawFrame();
2145 EXPECT_EQ(InputHandler::ScrollStarted,
2146 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2148 // Make the test scroll delta a fractional amount, to verify that the
2149 // fixed container size delta is (1) non-zero, and (2) fractional, and
2150 // (3) matches the movement of the top controls.
2151 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2152 host_impl_->top_controls_manager()->ScrollBegin();
2153 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2154 host_impl_->top_controls_manager()->ScrollEnd();
2156 LayerImpl* inner_viewport_scroll_layer =
2157 host_impl_->active_tree()->InnerViewportScrollLayer();
2158 DCHECK(inner_viewport_scroll_layer);
2159 host_impl_->ScrollEnd();
2160 EXPECT_EQ(top_controls_scroll_delta,
2161 inner_viewport_scroll_layer->FixedContainerSizeDelta());
2164 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsWithPageScale) {
2165 SetupTopControlsAndScrollLayer();
2166 DrawFrame();
2168 EXPECT_EQ(InputHandler::ScrollStarted,
2169 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2171 float page_scale = 1.5f;
2172 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale, 1.f, 2.f);
2174 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.f);
2175 gfx::Vector2dF expected_container_size_delta =
2176 ScaleVector2d(top_controls_scroll_delta, 1.f / page_scale);
2177 host_impl_->top_controls_manager()->ScrollBegin();
2178 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2179 host_impl_->top_controls_manager()->ScrollEnd();
2181 LayerImpl* inner_viewport_scroll_layer =
2182 host_impl_->active_tree()->InnerViewportScrollLayer();
2183 DCHECK(inner_viewport_scroll_layer);
2184 host_impl_->ScrollEnd();
2186 // Use a tolerance that requires the container size delta to be within 0.01
2187 // pixels.
2188 double tolerance = 0.0001;
2189 EXPECT_LT(
2190 (expected_container_size_delta -
2191 inner_viewport_scroll_layer->FixedContainerSizeDelta()).LengthSquared(),
2192 tolerance);
2195 TEST_F(LayerTreeHostImplTopControlsTest,
2196 ScrollNonScrollableRootWithTopControls) {
2197 SetupTopControlsAndScrollLayer();
2198 DrawFrame();
2200 EXPECT_EQ(InputHandler::ScrollStarted,
2201 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2203 host_impl_->top_controls_manager()->ScrollBegin();
2204 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
2205 host_impl_->top_controls_manager()->ScrollEnd();
2206 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->content_top_offset());
2207 // Now that top controls have moved, expect the clip to resize.
2208 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2209 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2211 host_impl_->ScrollEnd();
2213 EXPECT_EQ(InputHandler::ScrollStarted,
2214 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2216 float scroll_increment_y = -25.f;
2217 host_impl_->top_controls_manager()->ScrollBegin();
2218 host_impl_->top_controls_manager()->ScrollBy(
2219 gfx::Vector2dF(0.f, scroll_increment_y));
2220 EXPECT_EQ(-scroll_increment_y,
2221 host_impl_->top_controls_manager()->content_top_offset());
2222 // Now that top controls have moved, expect the clip to resize.
2223 EXPECT_EQ(gfx::Size(viewport_size_.width(),
2224 viewport_size_.height() + scroll_increment_y),
2225 root_clip_ptr->bounds());
2227 host_impl_->top_controls_manager()->ScrollBy(
2228 gfx::Vector2dF(0.f, scroll_increment_y));
2229 host_impl_->top_controls_manager()->ScrollEnd();
2230 EXPECT_EQ(-2 * scroll_increment_y,
2231 host_impl_->top_controls_manager()->content_top_offset());
2232 // Now that top controls have moved, expect the clip to resize.
2233 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2235 host_impl_->ScrollEnd();
2237 // Verify the layer is once-again non-scrollable.
2238 EXPECT_EQ(
2239 gfx::Vector2d(),
2240 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
2242 EXPECT_EQ(InputHandler::ScrollStarted,
2243 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2246 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
2247 // Test the configuration where a non-composited root layer is embedded in a
2248 // scrollable outer layer.
2249 gfx::Size surface_size(10, 10);
2250 gfx::Size contents_size(20, 20);
2252 scoped_ptr<LayerImpl> content_layer =
2253 LayerImpl::Create(host_impl_->active_tree(), 1);
2254 content_layer->SetDrawsContent(true);
2255 content_layer->SetPosition(gfx::PointF());
2256 content_layer->SetBounds(contents_size);
2257 content_layer->SetContentBounds(contents_size);
2258 content_layer->SetContentsScale(2.f, 2.f);
2260 scoped_ptr<LayerImpl> scroll_clip_layer =
2261 LayerImpl::Create(host_impl_->active_tree(), 3);
2262 scroll_clip_layer->SetBounds(surface_size);
2264 scoped_ptr<LayerImpl> scroll_layer =
2265 LayerImpl::Create(host_impl_->active_tree(), 2);
2266 scroll_layer->SetScrollClipLayer(3);
2267 scroll_layer->SetBounds(contents_size);
2268 scroll_layer->SetContentBounds(contents_size);
2269 scroll_layer->SetPosition(gfx::PointF());
2270 scroll_layer->AddChild(content_layer.Pass());
2271 scroll_clip_layer->AddChild(scroll_layer.Pass());
2273 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
2274 host_impl_->SetViewportSize(surface_size);
2275 DrawFrame();
2277 EXPECT_EQ(InputHandler::ScrollStarted,
2278 host_impl_->ScrollBegin(gfx::Point(5, 5),
2279 InputHandler::Wheel));
2280 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2281 host_impl_->ScrollEnd();
2282 EXPECT_TRUE(did_request_redraw_);
2283 EXPECT_TRUE(did_request_commit_);
2286 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
2287 gfx::Size surface_size(10, 10);
2288 gfx::Size contents_size(20, 20);
2289 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2290 root->SetBounds(surface_size);
2291 root->SetContentBounds(contents_size);
2292 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
2293 host_impl_->active_tree()->SetRootLayer(root.Pass());
2294 host_impl_->SetViewportSize(surface_size);
2295 DrawFrame();
2297 EXPECT_EQ(InputHandler::ScrollStarted,
2298 host_impl_->ScrollBegin(gfx::Point(5, 5),
2299 InputHandler::Wheel));
2300 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2301 host_impl_->ScrollEnd();
2302 EXPECT_TRUE(did_request_redraw_);
2303 EXPECT_TRUE(did_request_commit_);
2306 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
2307 gfx::Size surface_size(10, 10);
2308 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2309 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
2310 host_impl_->active_tree()->SetRootLayer(root.Pass());
2311 host_impl_->SetViewportSize(surface_size);
2312 DrawFrame();
2314 // Scroll event is ignored because the input coordinate is outside the layer
2315 // boundaries.
2316 EXPECT_EQ(InputHandler::ScrollIgnored,
2317 host_impl_->ScrollBegin(gfx::Point(15, 5),
2318 InputHandler::Wheel));
2319 EXPECT_FALSE(did_request_redraw_);
2320 EXPECT_FALSE(did_request_commit_);
2323 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
2324 gfx::Size surface_size(10, 10);
2325 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2326 scoped_ptr<LayerImpl> child =
2327 CreateScrollableLayer(2, surface_size, root.get());
2328 host_impl_->SetViewportSize(surface_size);
2330 gfx::Transform matrix;
2331 matrix.RotateAboutXAxis(180.0);
2332 child->SetTransform(matrix);
2333 child->SetDoubleSided(false);
2335 root->AddChild(child.Pass());
2336 host_impl_->active_tree()->SetRootLayer(root.Pass());
2337 DrawFrame();
2339 // Scroll event is ignored because the scrollable layer is not facing the
2340 // viewer and there is nothing scrollable behind it.
2341 EXPECT_EQ(InputHandler::ScrollIgnored,
2342 host_impl_->ScrollBegin(gfx::Point(5, 5),
2343 InputHandler::Wheel));
2344 EXPECT_FALSE(did_request_redraw_);
2345 EXPECT_FALSE(did_request_commit_);
2348 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
2349 gfx::Size surface_size(10, 10);
2350 scoped_ptr<LayerImpl> clip_layer =
2351 LayerImpl::Create(host_impl_->active_tree(), 3);
2352 scoped_ptr<LayerImpl> content_layer =
2353 CreateScrollableLayer(1, surface_size, clip_layer.get());
2354 content_layer->SetShouldScrollOnMainThread(true);
2355 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
2357 // Note: we can use the same clip layer for both since both calls to
2358 // CreateScrollableLayer() use the same surface size.
2359 scoped_ptr<LayerImpl> scroll_layer =
2360 CreateScrollableLayer(2, surface_size, clip_layer.get());
2361 scroll_layer->AddChild(content_layer.Pass());
2362 clip_layer->AddChild(scroll_layer.Pass());
2364 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
2365 host_impl_->SetViewportSize(surface_size);
2366 DrawFrame();
2368 // Scrolling fails because the content layer is asking to be scrolled on the
2369 // main thread.
2370 EXPECT_EQ(InputHandler::ScrollOnMainThread,
2371 host_impl_->ScrollBegin(gfx::Point(5, 5),
2372 InputHandler::Wheel));
2375 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
2376 gfx::Size surface_size(20, 20);
2377 gfx::Size viewport_size(10, 10);
2378 float page_scale = 2.f;
2379 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2380 scoped_ptr<LayerImpl> root_clip =
2381 LayerImpl::Create(host_impl_->active_tree(), 2);
2382 scoped_ptr<LayerImpl> root_scrolling =
2383 CreateScrollableLayer(3, surface_size, root_clip.get());
2384 EXPECT_EQ(viewport_size, root_clip->bounds());
2385 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2386 root_clip->AddChild(root_scrolling.Pass());
2387 root->AddChild(root_clip.Pass());
2388 host_impl_->active_tree()->SetRootLayer(root.Pass());
2389 // The behaviour in this test assumes the page scale is applied at a layer
2390 // above the clip layer.
2391 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2392 host_impl_->active_tree()->DidBecomeActive();
2393 host_impl_->SetViewportSize(viewport_size);
2394 DrawFrame();
2396 LayerImpl* root_scroll =
2397 host_impl_->active_tree()->InnerViewportScrollLayer();
2398 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2400 gfx::Vector2d scroll_delta(0, 10);
2401 gfx::Vector2d expected_scroll_delta = scroll_delta;
2402 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2403 EXPECT_EQ(InputHandler::ScrollStarted,
2404 host_impl_->ScrollBegin(gfx::Point(5, 5),
2405 InputHandler::Wheel));
2406 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2407 host_impl_->ScrollEnd();
2409 // Set new page scale from main thread.
2410 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2411 page_scale,
2412 page_scale);
2414 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2415 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2417 // The scroll range should also have been updated.
2418 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2420 // The page scale delta remains constant because the impl thread did not
2421 // scale.
2422 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2425 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
2426 gfx::Size surface_size(20, 20);
2427 gfx::Size viewport_size(10, 10);
2428 float page_scale = 2.f;
2429 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2430 scoped_ptr<LayerImpl> root_clip =
2431 LayerImpl::Create(host_impl_->active_tree(), 2);
2432 scoped_ptr<LayerImpl> root_scrolling =
2433 CreateScrollableLayer(3, surface_size, root_clip.get());
2434 EXPECT_EQ(viewport_size, root_clip->bounds());
2435 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2436 root_clip->AddChild(root_scrolling.Pass());
2437 root->AddChild(root_clip.Pass());
2438 host_impl_->active_tree()->SetRootLayer(root.Pass());
2439 // The behaviour in this test assumes the page scale is applied at a layer
2440 // above the clip layer.
2441 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2442 host_impl_->active_tree()->DidBecomeActive();
2443 host_impl_->SetViewportSize(viewport_size);
2444 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
2445 DrawFrame();
2447 LayerImpl* root_scroll =
2448 host_impl_->active_tree()->InnerViewportScrollLayer();
2449 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2451 gfx::Vector2d scroll_delta(0, 10);
2452 gfx::Vector2d expected_scroll_delta = scroll_delta;
2453 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2454 EXPECT_EQ(InputHandler::ScrollStarted,
2455 host_impl_->ScrollBegin(gfx::Point(5, 5),
2456 InputHandler::Wheel));
2457 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2458 host_impl_->ScrollEnd();
2460 // Set new page scale on impl thread by pinching.
2461 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2462 host_impl_->PinchGestureBegin();
2463 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
2464 host_impl_->PinchGestureEnd();
2465 host_impl_->ScrollEnd();
2466 DrawOneFrame();
2468 // The scroll delta is not scaled because the main thread did not scale.
2469 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2470 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2472 // The scroll range should also have been updated.
2473 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2475 // The page scale delta should match the new scale on the impl side.
2476 EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
2479 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
2480 gfx::Size surface_size(10, 10);
2481 float default_page_scale = 1.f;
2482 gfx::Transform default_page_scale_matrix;
2483 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
2485 float new_page_scale = 2.f;
2486 gfx::Transform new_page_scale_matrix;
2487 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
2489 // Create a normal scrollable root layer and another scrollable child layer.
2490 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
2491 LayerImpl* root = host_impl_->active_tree()->root_layer();
2492 LayerImpl* child = scroll->children()[0];
2494 scoped_ptr<LayerImpl> scrollable_child_clip =
2495 LayerImpl::Create(host_impl_->active_tree(), 6);
2496 scoped_ptr<LayerImpl> scrollable_child =
2497 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
2498 scrollable_child_clip->AddChild(scrollable_child.Pass());
2499 child->AddChild(scrollable_child_clip.Pass());
2500 LayerImpl* grand_child = child->children()[0];
2502 // Set new page scale on impl thread by pinching.
2503 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2504 host_impl_->PinchGestureBegin();
2505 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
2506 host_impl_->PinchGestureEnd();
2507 host_impl_->ScrollEnd();
2508 DrawOneFrame();
2510 EXPECT_EQ(1.f, root->contents_scale_x());
2511 EXPECT_EQ(1.f, root->contents_scale_y());
2512 EXPECT_EQ(1.f, scroll->contents_scale_x());
2513 EXPECT_EQ(1.f, scroll->contents_scale_y());
2514 EXPECT_EQ(1.f, child->contents_scale_x());
2515 EXPECT_EQ(1.f, child->contents_scale_y());
2516 EXPECT_EQ(1.f, grand_child->contents_scale_x());
2517 EXPECT_EQ(1.f, grand_child->contents_scale_y());
2519 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
2520 // the page scale delta on the root layer is applied hierarchically.
2521 LayerTreeHostImpl::FrameData frame;
2522 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2523 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2524 host_impl_->DidDrawAllLayers(frame);
2526 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
2527 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
2528 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
2529 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
2530 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
2531 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
2532 EXPECT_EQ(new_page_scale,
2533 grand_child->draw_transform().matrix().getDouble(0, 0));
2534 EXPECT_EQ(new_page_scale,
2535 grand_child->draw_transform().matrix().getDouble(1, 1));
2538 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
2539 gfx::Size surface_size(30, 30);
2540 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2541 root->SetBounds(gfx::Size(5, 5));
2542 scoped_ptr<LayerImpl> root_scrolling =
2543 LayerImpl::Create(host_impl_->active_tree(), 2);
2544 root_scrolling->SetBounds(surface_size);
2545 root_scrolling->SetContentBounds(surface_size);
2546 root_scrolling->SetScrollClipLayer(root->id());
2547 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2548 LayerImpl* root_scrolling_ptr = root_scrolling.get();
2549 root->AddChild(root_scrolling.Pass());
2550 int child_scroll_layer_id = 3;
2551 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
2552 child_scroll_layer_id, surface_size, root_scrolling_ptr);
2553 LayerImpl* child = child_scrolling.get();
2554 root_scrolling_ptr->AddChild(child_scrolling.Pass());
2555 host_impl_->active_tree()->SetRootLayer(root.Pass());
2556 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2557 host_impl_->active_tree()->DidBecomeActive();
2558 host_impl_->SetViewportSize(surface_size);
2559 DrawFrame();
2561 gfx::Vector2d scroll_delta(0, 10);
2562 gfx::Vector2d expected_scroll_delta(scroll_delta);
2563 gfx::Vector2d expected_max_scroll(child->MaxScrollOffset());
2564 EXPECT_EQ(InputHandler::ScrollStarted,
2565 host_impl_->ScrollBegin(gfx::Point(5, 5),
2566 InputHandler::Wheel));
2567 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2568 host_impl_->ScrollEnd();
2570 float page_scale = 2.f;
2571 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2572 1.f,
2573 page_scale);
2575 DrawOneFrame();
2577 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2578 ExpectContains(
2579 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
2581 // The scroll range should not have changed.
2582 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
2584 // The page scale delta remains constant because the impl thread did not
2585 // scale.
2586 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2589 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
2590 // Scroll a child layer beyond its maximum scroll range and make sure the
2591 // parent layer is scrolled on the axis on which the child was unable to
2592 // scroll.
2593 gfx::Size surface_size(10, 10);
2594 gfx::Size content_size(20, 20);
2595 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2596 root->SetBounds(surface_size);
2598 scoped_ptr<LayerImpl> grand_child =
2599 CreateScrollableLayer(3, content_size, root.get());
2601 scoped_ptr<LayerImpl> child =
2602 CreateScrollableLayer(2, content_size, root.get());
2603 LayerImpl* grand_child_layer = grand_child.get();
2604 child->AddChild(grand_child.Pass());
2606 LayerImpl* child_layer = child.get();
2607 root->AddChild(child.Pass());
2608 host_impl_->active_tree()->SetRootLayer(root.Pass());
2609 host_impl_->active_tree()->DidBecomeActive();
2610 host_impl_->SetViewportSize(surface_size);
2611 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 5));
2612 child_layer->SetScrollOffset(gfx::Vector2d(3, 0));
2614 DrawFrame();
2616 gfx::Vector2d scroll_delta(-8, -7);
2617 EXPECT_EQ(InputHandler::ScrollStarted,
2618 host_impl_->ScrollBegin(gfx::Point(),
2619 InputHandler::Wheel));
2620 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2621 host_impl_->ScrollEnd();
2623 scoped_ptr<ScrollAndScaleSet> scroll_info =
2624 host_impl_->ProcessScrollDeltas();
2626 // The grand child should have scrolled up to its limit.
2627 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2628 LayerImpl* grand_child = child->children()[0];
2629 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
2631 // The child should have only scrolled on the other axis.
2632 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
2636 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
2637 // Scroll a child layer beyond its maximum scroll range and make sure the
2638 // the scroll doesn't bubble up to the parent layer.
2639 gfx::Size surface_size(20, 20);
2640 gfx::Size viewport_size(10, 10);
2641 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2642 scoped_ptr<LayerImpl> root_scrolling =
2643 CreateScrollableLayer(2, surface_size, root.get());
2644 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2646 scoped_ptr<LayerImpl> grand_child =
2647 CreateScrollableLayer(4, surface_size, root.get());
2649 scoped_ptr<LayerImpl> child =
2650 CreateScrollableLayer(3, surface_size, root.get());
2651 LayerImpl* grand_child_layer = grand_child.get();
2652 child->AddChild(grand_child.Pass());
2654 LayerImpl* child_layer = child.get();
2655 root_scrolling->AddChild(child.Pass());
2656 root->AddChild(root_scrolling.Pass());
2657 EXPECT_EQ(viewport_size, root->bounds());
2658 host_impl_->active_tree()->SetRootLayer(root.Pass());
2659 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2660 host_impl_->active_tree()->DidBecomeActive();
2661 host_impl_->SetViewportSize(viewport_size);
2663 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
2664 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
2666 DrawFrame();
2668 gfx::Vector2d scroll_delta(0, -10);
2669 EXPECT_EQ(InputHandler::ScrollStarted,
2670 host_impl_->ScrollBegin(gfx::Point(),
2671 InputHandler::NonBubblingGesture));
2672 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2673 host_impl_->ScrollEnd();
2675 scoped_ptr<ScrollAndScaleSet> scroll_info =
2676 host_impl_->ProcessScrollDeltas();
2678 // The grand child should have scrolled up to its limit.
2679 LayerImpl* child =
2680 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
2681 LayerImpl* grand_child = child->children()[0];
2682 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2684 // The child should not have scrolled.
2685 ExpectNone(*scroll_info.get(), child->id());
2687 // The next time we scroll we should only scroll the parent.
2688 scroll_delta = gfx::Vector2d(0, -3);
2689 EXPECT_EQ(InputHandler::ScrollStarted,
2690 host_impl_->ScrollBegin(gfx::Point(5, 5),
2691 InputHandler::NonBubblingGesture));
2692 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2693 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2694 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
2695 host_impl_->ScrollEnd();
2697 scroll_info = host_impl_->ProcessScrollDeltas();
2699 // The child should have scrolled up to its limit.
2700 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2702 // The grand child should not have scrolled.
2703 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2705 // After scrolling the parent, another scroll on the opposite direction
2706 // should still scroll the child.
2707 scroll_delta = gfx::Vector2d(0, 7);
2708 EXPECT_EQ(InputHandler::ScrollStarted,
2709 host_impl_->ScrollBegin(gfx::Point(5, 5),
2710 InputHandler::NonBubblingGesture));
2711 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2712 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2713 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2714 host_impl_->ScrollEnd();
2716 scroll_info = host_impl_->ProcessScrollDeltas();
2718 // The grand child should have scrolled.
2719 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
2721 // The child should not have scrolled.
2722 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2725 // Scrolling should be adjusted from viewport space.
2726 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
2727 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2729 scroll_delta = gfx::Vector2d(0, -2);
2730 EXPECT_EQ(InputHandler::ScrollStarted,
2731 host_impl_->ScrollBegin(gfx::Point(1, 1),
2732 InputHandler::NonBubblingGesture));
2733 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
2734 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2735 host_impl_->ScrollEnd();
2737 scroll_info = host_impl_->ProcessScrollDeltas();
2739 // Should have scrolled by half the amount in layer space (5 - 2/2)
2740 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
2743 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
2744 // When we try to scroll a non-scrollable child layer, the scroll delta
2745 // should be applied to one of its ancestors if possible.
2746 gfx::Size surface_size(10, 10);
2747 gfx::Size content_size(20, 20);
2748 scoped_ptr<LayerImpl> root_clip =
2749 LayerImpl::Create(host_impl_->active_tree(), 3);
2750 scoped_ptr<LayerImpl> root =
2751 CreateScrollableLayer(1, content_size, root_clip.get());
2752 // Make 'root' the clip layer for child: since they have the same sizes the
2753 // child will have zero max_scroll_offset and scrolls will bubble.
2754 scoped_ptr<LayerImpl> child =
2755 CreateScrollableLayer(2, content_size, root.get());
2756 child->SetIsContainerForFixedPositionLayers(true);
2757 root->SetBounds(content_size);
2759 int root_scroll_id = root->id();
2760 root->AddChild(child.Pass());
2761 root_clip->AddChild(root.Pass());
2763 host_impl_->SetViewportSize(surface_size);
2764 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2765 host_impl_->active_tree()->SetViewportLayersFromIds(3, 2, Layer::INVALID_ID);
2766 host_impl_->active_tree()->DidBecomeActive();
2767 DrawFrame();
2769 gfx::Vector2d scroll_delta(0, 4);
2770 EXPECT_EQ(InputHandler::ScrollStarted,
2771 host_impl_->ScrollBegin(gfx::Point(5, 5),
2772 InputHandler::Wheel));
2773 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2774 host_impl_->ScrollEnd();
2776 scoped_ptr<ScrollAndScaleSet> scroll_info =
2777 host_impl_->ProcessScrollDeltas();
2779 // Only the root scroll should have scrolled.
2780 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
2781 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
2785 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
2786 gfx::Size surface_size(10, 10);
2787 scoped_ptr<LayerImpl> root_clip =
2788 LayerImpl::Create(host_impl_->active_tree(), 1);
2789 scoped_ptr<LayerImpl> root_scroll =
2790 CreateScrollableLayer(2, surface_size, root_clip.get());
2791 root_scroll->SetIsContainerForFixedPositionLayers(true);
2792 root_clip->AddChild(root_scroll.Pass());
2793 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2794 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2795 host_impl_->active_tree()->DidBecomeActive();
2796 host_impl_->SetViewportSize(surface_size);
2798 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
2799 // synchronization.
2800 DrawFrame();
2801 host_impl_->active_tree()->DetachLayerTree();
2802 scoped_ptr<LayerImpl> root_clip2 =
2803 LayerImpl::Create(host_impl_->active_tree(), 3);
2804 scoped_ptr<LayerImpl> root_scroll2 =
2805 CreateScrollableLayer(4, surface_size, root_clip2.get());
2806 root_scroll2->SetIsContainerForFixedPositionLayers(true);
2807 root_clip2->AddChild(root_scroll2.Pass());
2808 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
2809 host_impl_->active_tree()->SetViewportLayersFromIds(3, 4, Layer::INVALID_ID);
2810 host_impl_->active_tree()->DidBecomeActive();
2812 // Scrolling should still work even though we did not draw yet.
2813 EXPECT_EQ(InputHandler::ScrollStarted,
2814 host_impl_->ScrollBegin(gfx::Point(5, 5),
2815 InputHandler::Wheel));
2818 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
2819 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2821 // Rotate the root layer 90 degrees counter-clockwise about its center.
2822 gfx::Transform rotate_transform;
2823 rotate_transform.Rotate(-90.0);
2824 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
2826 gfx::Size surface_size(50, 50);
2827 host_impl_->SetViewportSize(surface_size);
2828 DrawFrame();
2830 // Scroll to the right in screen coordinates with a gesture.
2831 gfx::Vector2d gesture_scroll_delta(10, 0);
2832 EXPECT_EQ(InputHandler::ScrollStarted,
2833 host_impl_->ScrollBegin(gfx::Point(),
2834 InputHandler::Gesture));
2835 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2836 host_impl_->ScrollEnd();
2838 // The layer should have scrolled down in its local coordinates.
2839 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2840 ExpectContains(*scroll_info.get(),
2841 scroll_layer->id(),
2842 gfx::Vector2d(0, gesture_scroll_delta.x()));
2844 // Reset and scroll down with the wheel.
2845 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2846 gfx::Vector2d wheel_scroll_delta(0, 10);
2847 EXPECT_EQ(InputHandler::ScrollStarted,
2848 host_impl_->ScrollBegin(gfx::Point(),
2849 InputHandler::Wheel));
2850 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2851 host_impl_->ScrollEnd();
2853 // The layer should have scrolled down in its local coordinates.
2854 scroll_info = host_impl_->ProcessScrollDeltas();
2855 ExpectContains(*scroll_info.get(),
2856 scroll_layer->id(),
2857 wheel_scroll_delta);
2860 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
2861 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2862 int child_clip_layer_id = 6;
2863 int child_layer_id = 7;
2864 float child_layer_angle = -20.f;
2866 // Create a child layer that is rotated to a non-axis-aligned angle.
2867 scoped_ptr<LayerImpl> clip_layer =
2868 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
2869 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
2870 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
2871 gfx::Transform rotate_transform;
2872 rotate_transform.Translate(-50.0, -50.0);
2873 rotate_transform.Rotate(child_layer_angle);
2874 rotate_transform.Translate(50.0, 50.0);
2875 clip_layer->SetTransform(rotate_transform);
2877 // Only allow vertical scrolling.
2878 clip_layer->SetBounds(
2879 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
2880 // The rotation depends on the layer's transform origin, and the child layer
2881 // is a different size than the clip, so make sure the clip layer's origin
2882 // lines up over the child.
2883 clip_layer->SetTransformOrigin(gfx::Point3F(
2884 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
2885 LayerImpl* child_ptr = child.get();
2886 clip_layer->AddChild(child.Pass());
2887 scroll_layer->AddChild(clip_layer.Pass());
2889 gfx::Size surface_size(50, 50);
2890 host_impl_->SetViewportSize(surface_size);
2891 DrawFrame();
2893 // Scroll down in screen coordinates with a gesture.
2894 gfx::Vector2d gesture_scroll_delta(0, 10);
2895 EXPECT_EQ(InputHandler::ScrollStarted,
2896 host_impl_->ScrollBegin(gfx::Point(1, 1),
2897 InputHandler::Gesture));
2898 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2899 host_impl_->ScrollEnd();
2901 // The child layer should have scrolled down in its local coordinates an
2902 // amount proportional to the angle between it and the input scroll delta.
2903 gfx::Vector2d expected_scroll_delta(
2905 gesture_scroll_delta.y() *
2906 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
2907 scoped_ptr<ScrollAndScaleSet> scroll_info =
2908 host_impl_->ProcessScrollDeltas();
2909 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2911 // The root scroll layer should not have scrolled, because the input delta
2912 // was close to the layer's axis of movement.
2913 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
2916 // Now reset and scroll the same amount horizontally.
2917 child_ptr->SetScrollDelta(gfx::Vector2dF());
2918 gfx::Vector2d gesture_scroll_delta(10, 0);
2919 EXPECT_EQ(InputHandler::ScrollStarted,
2920 host_impl_->ScrollBegin(gfx::Point(1, 1),
2921 InputHandler::Gesture));
2922 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2923 host_impl_->ScrollEnd();
2925 // The child layer should have scrolled down in its local coordinates an
2926 // amount proportional to the angle between it and the input scroll delta.
2927 gfx::Vector2d expected_scroll_delta(
2929 -gesture_scroll_delta.x() *
2930 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
2931 scoped_ptr<ScrollAndScaleSet> scroll_info =
2932 host_impl_->ProcessScrollDeltas();
2933 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2935 // The root scroll layer should have scrolled more, since the input scroll
2936 // delta was mostly orthogonal to the child layer's vertical scroll axis.
2937 gfx::Vector2d expected_root_scroll_delta(
2938 gesture_scroll_delta.x() *
2939 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
2941 ExpectContains(*scroll_info.get(),
2942 scroll_layer->id(),
2943 expected_root_scroll_delta);
2947 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
2948 LayerImpl* scroll_layer =
2949 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2951 // Scale the layer to twice its normal size.
2952 int scale = 2;
2953 gfx::Transform scale_transform;
2954 scale_transform.Scale(scale, scale);
2955 scroll_layer->SetTransform(scale_transform);
2957 gfx::Size surface_size(50, 50);
2958 host_impl_->SetViewportSize(surface_size);
2959 DrawFrame();
2961 // Scroll down in screen coordinates with a gesture.
2962 gfx::Vector2d scroll_delta(0, 10);
2963 EXPECT_EQ(InputHandler::ScrollStarted,
2964 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2965 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2966 host_impl_->ScrollEnd();
2968 // The layer should have scrolled down in its local coordinates, but half the
2969 // amount.
2970 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2971 ExpectContains(*scroll_info.get(),
2972 scroll_layer->id(),
2973 gfx::Vector2d(0, scroll_delta.y() / scale));
2975 // Reset and scroll down with the wheel.
2976 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2977 gfx::Vector2d wheel_scroll_delta(0, 10);
2978 EXPECT_EQ(InputHandler::ScrollStarted,
2979 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2980 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2981 host_impl_->ScrollEnd();
2983 // The scale should not have been applied to the scroll delta.
2984 scroll_info = host_impl_->ProcessScrollDeltas();
2985 ExpectContains(*scroll_info.get(),
2986 scroll_layer->id(),
2987 wheel_scroll_delta);
2990 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
2991 int width = 332;
2992 int height = 20;
2993 int scale = 3;
2994 SetupScrollAndContentsLayers(gfx::Size(width, height));
2995 host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
2996 gfx::Size(width * scale - 1, height * scale));
2997 host_impl_->SetDeviceScaleFactor(scale);
2998 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3000 LayerImpl* inner_viewport_scroll_layer =
3001 host_impl_->active_tree()->InnerViewportScrollLayer();
3002 EXPECT_EQ(gfx::Vector2d(0, 0),
3003 inner_viewport_scroll_layer->MaxScrollOffset());
3006 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
3007 public:
3008 TestScrollOffsetDelegate()
3009 : page_scale_factor_(0.f),
3010 min_page_scale_factor_(-1.f),
3011 max_page_scale_factor_(-1.f) {}
3013 virtual ~TestScrollOffsetDelegate() {}
3015 virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
3016 return getter_return_value_;
3019 virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
3021 virtual void UpdateRootLayerState(const gfx::Vector2dF& total_scroll_offset,
3022 const gfx::Vector2dF& max_scroll_offset,
3023 const gfx::SizeF& scrollable_size,
3024 float page_scale_factor,
3025 float min_page_scale_factor,
3026 float max_page_scale_factor) OVERRIDE {
3027 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
3028 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
3029 last_set_scroll_offset_ = total_scroll_offset;
3030 max_scroll_offset_ = max_scroll_offset;
3031 scrollable_size_ = scrollable_size;
3032 page_scale_factor_ = page_scale_factor;
3033 min_page_scale_factor_ = min_page_scale_factor;
3034 max_page_scale_factor_ = max_page_scale_factor;
3037 gfx::Vector2dF last_set_scroll_offset() {
3038 return last_set_scroll_offset_;
3041 void set_getter_return_value(const gfx::Vector2dF& value) {
3042 getter_return_value_ = value;
3045 gfx::Vector2dF max_scroll_offset() const {
3046 return max_scroll_offset_;
3049 gfx::SizeF scrollable_size() const {
3050 return scrollable_size_;
3053 float page_scale_factor() const {
3054 return page_scale_factor_;
3057 float min_page_scale_factor() const {
3058 return min_page_scale_factor_;
3061 float max_page_scale_factor() const {
3062 return max_page_scale_factor_;
3065 private:
3066 gfx::Vector2dF last_set_scroll_offset_;
3067 gfx::Vector2dF getter_return_value_;
3068 gfx::Vector2dF max_scroll_offset_;
3069 gfx::SizeF scrollable_size_;
3070 float page_scale_factor_;
3071 float min_page_scale_factor_;
3072 float max_page_scale_factor_;
3075 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
3076 TestScrollOffsetDelegate scroll_delegate;
3077 host_impl_->SetViewportSize(gfx::Size(10, 20));
3078 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3079 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3080 clip_layer->SetBounds(gfx::Size(10, 20));
3082 // Setting the delegate results in the current scroll offset being set.
3083 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
3084 scroll_layer->SetScrollOffset(gfx::Vector2d());
3085 scroll_layer->SetScrollDelta(initial_scroll_delta);
3086 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3087 EXPECT_EQ(initial_scroll_delta.ToString(),
3088 scroll_delegate.last_set_scroll_offset().ToString());
3090 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3091 // page_scale_factor and {min|max}_page_scale_factor being set.
3092 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
3093 EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
3094 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3095 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
3096 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
3098 // Updating page scale immediately updates the delegate.
3099 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
3100 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
3101 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3102 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3103 host_impl_->active_tree()->SetPageScaleDelta(1.5f);
3104 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
3105 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3106 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3107 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3108 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3109 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3110 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3111 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3113 // The pinch gesture doesn't put the delegate into a state where the scroll
3114 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3115 // delegate).
3116 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3117 host_impl_->PinchGestureBegin();
3118 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
3119 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
3120 host_impl_->PinchGestureEnd();
3121 host_impl_->ScrollEnd();
3123 // Scrolling should be relative to the offset as returned by the delegate.
3124 gfx::Vector2dF scroll_delta(0.f, 10.f);
3125 gfx::Vector2dF current_offset(7.f, 8.f);
3127 scroll_delegate.set_getter_return_value(current_offset);
3128 EXPECT_EQ(InputHandler::ScrollStarted,
3129 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3131 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3132 EXPECT_EQ(current_offset + scroll_delta,
3133 scroll_delegate.last_set_scroll_offset());
3135 current_offset = gfx::Vector2dF(42.f, 41.f);
3136 scroll_delegate.set_getter_return_value(current_offset);
3137 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3138 EXPECT_EQ(current_offset + scroll_delta,
3139 scroll_delegate.last_set_scroll_offset());
3140 host_impl_->ScrollEnd();
3141 scroll_delegate.set_getter_return_value(gfx::Vector2dF());
3143 // Forces a full tree synchronization and ensures that the scroll delegate
3144 // sees the correct size of the new tree.
3145 gfx::Size new_size(42, 24);
3146 host_impl_->CreatePendingTree();
3147 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
3148 host_impl_->ActivateSyncTree();
3149 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
3151 // Un-setting the delegate should propagate the delegate's current offset to
3152 // the root scrollable layer.
3153 current_offset = gfx::Vector2dF(13.f, 12.f);
3154 scroll_delegate.set_getter_return_value(current_offset);
3155 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3157 EXPECT_EQ(current_offset.ToString(),
3158 scroll_layer->TotalScrollOffset().ToString());
3161 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
3162 const gfx::Transform target_space_transform =
3163 layer->draw_properties().target_space_transform;
3164 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
3165 gfx::Point translated_point;
3166 target_space_transform.TransformPoint(&translated_point);
3167 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
3168 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
3171 TEST_F(LayerTreeHostImplTest,
3172 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
3173 TestScrollOffsetDelegate scroll_delegate;
3174 host_impl_->SetViewportSize(gfx::Size(10, 20));
3175 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3176 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3177 clip_layer->SetBounds(gfx::Size(10, 20));
3178 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3180 // Draw first frame to clear any pending draws and check scroll.
3181 DrawFrame();
3182 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
3183 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
3185 // Set external scroll delta on delegate and notify LayerTreeHost.
3186 gfx::Vector2dF scroll_delta(10.f, 10.f);
3187 scroll_delegate.set_getter_return_value(scroll_delta);
3188 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
3190 // Check scroll delta reflected in layer.
3191 DrawFrame();
3192 CheckLayerScrollDelta(scroll_layer, scroll_delta);
3194 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3197 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
3198 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3199 host_impl_->SetViewportSize(gfx::Size(50, 50));
3200 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3201 DrawFrame();
3202 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3204 // In-bounds scrolling does not affect overscroll.
3205 EXPECT_EQ(InputHandler::ScrollStarted,
3206 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3207 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3208 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3210 // Overscroll events are reflected immediately.
3211 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
3212 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3214 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
3215 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
3216 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3217 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
3218 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3219 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
3220 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3221 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
3222 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
3223 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
3224 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
3225 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
3226 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3228 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
3229 // as no scroll occurs.
3230 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3231 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
3232 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3233 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
3234 // Overscroll resets on valid scroll.
3235 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3236 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3237 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3238 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3239 host_impl_->ScrollEnd();
3243 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
3244 // Scroll child layers beyond their maximum scroll range and make sure root
3245 // overscroll does not accumulate.
3246 gfx::Size surface_size(10, 10);
3247 scoped_ptr<LayerImpl> root_clip =
3248 LayerImpl::Create(host_impl_->active_tree(), 4);
3249 scoped_ptr<LayerImpl> root =
3250 CreateScrollableLayer(1, surface_size, root_clip.get());
3252 scoped_ptr<LayerImpl> grand_child =
3253 CreateScrollableLayer(3, surface_size, root_clip.get());
3255 scoped_ptr<LayerImpl> child =
3256 CreateScrollableLayer(2, surface_size, root_clip.get());
3257 LayerImpl* grand_child_layer = grand_child.get();
3258 child->AddChild(grand_child.Pass());
3260 LayerImpl* child_layer = child.get();
3261 root->AddChild(child.Pass());
3262 root_clip->AddChild(root.Pass());
3263 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
3264 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
3265 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3266 host_impl_->active_tree()->DidBecomeActive();
3267 host_impl_->SetViewportSize(surface_size);
3268 DrawFrame();
3270 gfx::Vector2d scroll_delta(0, -10);
3271 EXPECT_EQ(InputHandler::ScrollStarted,
3272 host_impl_->ScrollBegin(gfx::Point(),
3273 InputHandler::NonBubblingGesture));
3274 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3275 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3276 host_impl_->ScrollEnd();
3278 // The next time we scroll we should only scroll the parent, but overscroll
3279 // should still not reach the root layer.
3280 scroll_delta = gfx::Vector2d(0, -30);
3281 EXPECT_EQ(InputHandler::ScrollStarted,
3282 host_impl_->ScrollBegin(gfx::Point(5, 5),
3283 InputHandler::NonBubblingGesture));
3284 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3285 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3286 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3287 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
3288 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3289 host_impl_->ScrollEnd();
3291 // After scrolling the parent, another scroll on the opposite direction
3292 // should scroll the child.
3293 scroll_delta = gfx::Vector2d(0, 70);
3294 EXPECT_EQ(InputHandler::ScrollStarted,
3295 host_impl_->ScrollBegin(gfx::Point(5, 5),
3296 InputHandler::NonBubblingGesture));
3297 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3298 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3299 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3300 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3301 host_impl_->ScrollEnd();
3305 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
3306 // When we try to scroll a non-scrollable child layer, the scroll delta
3307 // should be applied to one of its ancestors if possible. Overscroll should
3308 // be reflected only when it has bubbled up to the root scrolling layer.
3309 gfx::Size surface_size(10, 10);
3310 gfx::Size content_size(20, 20);
3311 scoped_ptr<LayerImpl> root_clip =
3312 LayerImpl::Create(host_impl_->active_tree(), 3);
3313 scoped_ptr<LayerImpl> root =
3314 CreateScrollableLayer(1, content_size, root_clip.get());
3315 root->SetIsContainerForFixedPositionLayers(true);
3316 scoped_ptr<LayerImpl> child =
3317 CreateScrollableLayer(2, content_size, root_clip.get());
3319 child->SetScrollClipLayer(Layer::INVALID_ID);
3320 root->AddChild(child.Pass());
3321 root_clip->AddChild(root.Pass());
3323 host_impl_->SetViewportSize(surface_size);
3324 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3325 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3326 host_impl_->active_tree()->DidBecomeActive();
3327 DrawFrame();
3329 gfx::Vector2d scroll_delta(0, 8);
3330 EXPECT_EQ(InputHandler::ScrollStarted,
3331 host_impl_->ScrollBegin(gfx::Point(5, 5),
3332 InputHandler::Wheel));
3333 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3334 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3335 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3336 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
3337 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3338 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
3339 host_impl_->ScrollEnd();
3343 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
3344 LayerTreeSettings settings;
3345 CreateHostImpl(settings, CreateOutputSurface());
3347 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
3348 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3349 clip_layer->SetBounds(gfx::Size(50, 50));
3350 host_impl_->SetViewportSize(gfx::Size(50, 50));
3351 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3352 DrawFrame();
3353 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3355 // Even though the layer can't scroll the overscroll still happens.
3356 EXPECT_EQ(InputHandler::ScrollStarted,
3357 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3358 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3359 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3362 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
3363 gfx::Size surface_size(980, 1439);
3364 gfx::Size content_size(980, 1438);
3365 float device_scale_factor = 1.5f;
3366 scoped_ptr<LayerImpl> root_clip =
3367 LayerImpl::Create(host_impl_->active_tree(), 3);
3368 scoped_ptr<LayerImpl> root =
3369 CreateScrollableLayer(1, content_size, root_clip.get());
3370 root->SetIsContainerForFixedPositionLayers(true);
3371 scoped_ptr<LayerImpl> child =
3372 CreateScrollableLayer(2, content_size, root_clip.get());
3373 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
3374 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
3375 0.326531f, 0.326531f, 5.f);
3376 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3377 child->SetScrollClipLayer(Layer::INVALID_ID);
3378 root->AddChild(child.Pass());
3379 root_clip->AddChild(root.Pass());
3381 host_impl_->SetViewportSize(surface_size);
3382 host_impl_->SetDeviceScaleFactor(device_scale_factor);
3383 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3384 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3385 host_impl_->active_tree()->DidBecomeActive();
3386 DrawFrame();
3388 // Horizontal & Vertical GlowEffect should not be applied when
3389 // content size is less then view port size. For Example Horizontal &
3390 // vertical GlowEffect should not be applied in about:blank page.
3391 EXPECT_EQ(InputHandler::ScrollStarted,
3392 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3393 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
3394 EXPECT_EQ(gfx::Vector2dF().ToString(),
3395 host_impl_->accumulated_root_overscroll().ToString());
3397 host_impl_->ScrollEnd();
3401 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
3402 gfx::Size surface_size(100, 100);
3403 gfx::Size content_size(200, 200);
3404 scoped_ptr<LayerImpl> root_clip =
3405 LayerImpl::Create(host_impl_->active_tree(), 3);
3406 scoped_ptr<LayerImpl> root =
3407 CreateScrollableLayer(1, content_size, root_clip.get());
3408 root->SetIsContainerForFixedPositionLayers(true);
3409 scoped_ptr<LayerImpl> child =
3410 CreateScrollableLayer(2, content_size, root_clip.get());
3412 child->SetScrollClipLayer(Layer::INVALID_ID);
3413 root->AddChild(child.Pass());
3414 root_clip->AddChild(root.Pass());
3416 host_impl_->SetViewportSize(surface_size);
3417 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3418 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3419 host_impl_->active_tree()->DidBecomeActive();
3420 DrawFrame();
3422 // Edge glow effect should be applicable only upon reaching Edges
3423 // of the content. unnecessary glow effect calls shouldn't be
3424 // called while scrolling up without reaching the edge of the content.
3425 EXPECT_EQ(InputHandler::ScrollStarted,
3426 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3427 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
3428 EXPECT_EQ(gfx::Vector2dF().ToString(),
3429 host_impl_->accumulated_root_overscroll().ToString());
3430 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
3431 EXPECT_EQ(gfx::Vector2dF().ToString(),
3432 host_impl_->accumulated_root_overscroll().ToString());
3433 host_impl_->ScrollEnd();
3434 // unusedrootDelta should be subtracted from applied delta so that
3435 // unwanted glow effect calls are not called.
3436 EXPECT_EQ(InputHandler::ScrollStarted,
3437 host_impl_->ScrollBegin(gfx::Point(0, 0),
3438 InputHandler::NonBubblingGesture));
3439 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
3440 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
3441 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3442 host_impl_->accumulated_root_overscroll().ToString());
3444 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
3445 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3446 host_impl_->accumulated_root_overscroll().ToString());
3447 host_impl_->ScrollEnd();
3448 // TestCase to check kEpsilon, which prevents minute values to trigger
3449 // gloweffect without reaching edge.
3450 EXPECT_EQ(InputHandler::ScrollStarted,
3451 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3452 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
3453 EXPECT_EQ(gfx::Vector2dF().ToString(),
3454 host_impl_->accumulated_root_overscroll().ToString());
3455 host_impl_->ScrollEnd();
3459 class BlendStateCheckLayer : public LayerImpl {
3460 public:
3461 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
3462 int id,
3463 ResourceProvider* resource_provider) {
3464 return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(tree_impl,
3466 resource_provider));
3469 virtual void AppendQuads(RenderPass* render_pass,
3470 const OcclusionTracker<LayerImpl>& occlusion_tracker,
3471 AppendQuadsData* append_quads_data) OVERRIDE {
3472 quads_appended_ = true;
3474 gfx::Rect opaque_rect;
3475 if (contents_opaque())
3476 opaque_rect = quad_rect_;
3477 else
3478 opaque_rect = opaque_content_rect_;
3479 gfx::Rect visible_quad_rect = quad_rect_;
3481 SharedQuadState* shared_quad_state =
3482 render_pass->CreateAndAppendSharedQuadState();
3483 PopulateSharedQuadState(shared_quad_state);
3485 TileDrawQuad* test_blending_draw_quad =
3486 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
3487 test_blending_draw_quad->SetNew(shared_quad_state,
3488 quad_rect_,
3489 opaque_rect,
3490 visible_quad_rect,
3491 resource_id_,
3492 gfx::RectF(0.f, 0.f, 1.f, 1.f),
3493 gfx::Size(1, 1),
3494 false);
3495 test_blending_draw_quad->visible_rect = quad_visible_rect_;
3496 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
3497 EXPECT_EQ(has_render_surface_, !!render_surface());
3500 void SetExpectation(bool blend, bool has_render_surface) {
3501 blend_ = blend;
3502 has_render_surface_ = has_render_surface;
3503 quads_appended_ = false;
3506 bool quads_appended() const { return quads_appended_; }
3508 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
3509 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
3510 void SetOpaqueContentRect(const gfx::Rect& rect) {
3511 opaque_content_rect_ = rect;
3514 private:
3515 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
3516 int id,
3517 ResourceProvider* resource_provider)
3518 : LayerImpl(tree_impl, id),
3519 blend_(false),
3520 has_render_surface_(false),
3521 quads_appended_(false),
3522 quad_rect_(5, 5, 5, 5),
3523 quad_visible_rect_(5, 5, 5, 5),
3524 resource_id_(resource_provider->CreateResource(
3525 gfx::Size(1, 1),
3526 GL_CLAMP_TO_EDGE,
3527 ResourceProvider::TextureHintImmutable,
3528 RGBA_8888)) {
3529 resource_provider->AllocateForTesting(resource_id_);
3530 SetBounds(gfx::Size(10, 10));
3531 SetContentBounds(gfx::Size(10, 10));
3532 SetDrawsContent(true);
3535 bool blend_;
3536 bool has_render_surface_;
3537 bool quads_appended_;
3538 gfx::Rect quad_rect_;
3539 gfx::Rect opaque_content_rect_;
3540 gfx::Rect quad_visible_rect_;
3541 ResourceProvider::ResourceId resource_id_;
3544 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
3546 scoped_ptr<LayerImpl> root =
3547 LayerImpl::Create(host_impl_->active_tree(), 1);
3548 root->SetBounds(gfx::Size(10, 10));
3549 root->SetContentBounds(root->bounds());
3550 root->SetDrawsContent(false);
3551 host_impl_->active_tree()->SetRootLayer(root.Pass());
3553 LayerImpl* root = host_impl_->active_tree()->root_layer();
3555 root->AddChild(
3556 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3558 host_impl_->resource_provider()));
3559 BlendStateCheckLayer* layer1 =
3560 static_cast<BlendStateCheckLayer*>(root->children()[0]);
3561 layer1->SetPosition(gfx::PointF(2.f, 2.f));
3563 LayerTreeHostImpl::FrameData frame;
3565 // Opaque layer, drawn without blending.
3566 layer1->SetContentsOpaque(true);
3567 layer1->SetExpectation(false, false);
3568 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3569 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3570 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3571 EXPECT_TRUE(layer1->quads_appended());
3572 host_impl_->DidDrawAllLayers(frame);
3574 // Layer with translucent content and painting, so drawn with blending.
3575 layer1->SetContentsOpaque(false);
3576 layer1->SetExpectation(true, false);
3577 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3578 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3579 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3580 EXPECT_TRUE(layer1->quads_appended());
3581 host_impl_->DidDrawAllLayers(frame);
3583 // Layer with translucent opacity, drawn with blending.
3584 layer1->SetContentsOpaque(true);
3585 layer1->SetOpacity(0.5f);
3586 layer1->SetExpectation(true, false);
3587 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3588 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3589 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3590 EXPECT_TRUE(layer1->quads_appended());
3591 host_impl_->DidDrawAllLayers(frame);
3593 // Layer with translucent opacity and painting, drawn with blending.
3594 layer1->SetContentsOpaque(true);
3595 layer1->SetOpacity(0.5f);
3596 layer1->SetExpectation(true, false);
3597 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3598 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3599 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3600 EXPECT_TRUE(layer1->quads_appended());
3601 host_impl_->DidDrawAllLayers(frame);
3603 layer1->AddChild(
3604 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3606 host_impl_->resource_provider()));
3607 BlendStateCheckLayer* layer2 =
3608 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
3609 layer2->SetPosition(gfx::PointF(4.f, 4.f));
3611 // 2 opaque layers, drawn without blending.
3612 layer1->SetContentsOpaque(true);
3613 layer1->SetOpacity(1.f);
3614 layer1->SetExpectation(false, false);
3615 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3616 layer2->SetContentsOpaque(true);
3617 layer2->SetOpacity(1.f);
3618 layer2->SetExpectation(false, false);
3619 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3620 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3621 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3622 EXPECT_TRUE(layer1->quads_appended());
3623 EXPECT_TRUE(layer2->quads_appended());
3624 host_impl_->DidDrawAllLayers(frame);
3626 // Parent layer with translucent content, drawn with blending.
3627 // Child layer with opaque content, drawn without blending.
3628 layer1->SetContentsOpaque(false);
3629 layer1->SetExpectation(true, false);
3630 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3631 layer2->SetExpectation(false, false);
3632 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3633 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3634 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3635 EXPECT_TRUE(layer1->quads_appended());
3636 EXPECT_TRUE(layer2->quads_appended());
3637 host_impl_->DidDrawAllLayers(frame);
3639 // Parent layer with translucent content but opaque painting, drawn without
3640 // blending.
3641 // Child layer with opaque content, drawn without blending.
3642 layer1->SetContentsOpaque(true);
3643 layer1->SetExpectation(false, false);
3644 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3645 layer2->SetExpectation(false, false);
3646 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3647 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3648 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3649 EXPECT_TRUE(layer1->quads_appended());
3650 EXPECT_TRUE(layer2->quads_appended());
3651 host_impl_->DidDrawAllLayers(frame);
3653 // Parent layer with translucent opacity and opaque content. Since it has a
3654 // drawing child, it's drawn to a render surface which carries the opacity,
3655 // so it's itself drawn without blending.
3656 // Child layer with opaque content, drawn without blending (parent surface
3657 // carries the inherited opacity).
3658 layer1->SetContentsOpaque(true);
3659 layer1->SetOpacity(0.5f);
3660 layer1->SetExpectation(false, true);
3661 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3662 layer2->SetExpectation(false, false);
3663 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3664 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
3665 host_impl_->active_tree()->root_layer());
3666 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3667 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3668 EXPECT_TRUE(layer1->quads_appended());
3669 EXPECT_TRUE(layer2->quads_appended());
3670 host_impl_->DidDrawAllLayers(frame);
3672 // Draw again, but with child non-opaque, to make sure
3673 // layer1 not culled.
3674 layer1->SetContentsOpaque(true);
3675 layer1->SetOpacity(1.f);
3676 layer1->SetExpectation(false, false);
3677 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3678 layer2->SetContentsOpaque(true);
3679 layer2->SetOpacity(0.5f);
3680 layer2->SetExpectation(true, false);
3681 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3682 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3683 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3684 EXPECT_TRUE(layer1->quads_appended());
3685 EXPECT_TRUE(layer2->quads_appended());
3686 host_impl_->DidDrawAllLayers(frame);
3688 // A second way of making the child non-opaque.
3689 layer1->SetContentsOpaque(true);
3690 layer1->SetOpacity(1.f);
3691 layer1->SetExpectation(false, false);
3692 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3693 layer2->SetContentsOpaque(false);
3694 layer2->SetOpacity(1.f);
3695 layer2->SetExpectation(true, false);
3696 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3697 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3698 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3699 EXPECT_TRUE(layer1->quads_appended());
3700 EXPECT_TRUE(layer2->quads_appended());
3701 host_impl_->DidDrawAllLayers(frame);
3703 // And when the layer says its not opaque but is painted opaque, it is not
3704 // blended.
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(1.f);
3711 layer2->SetExpectation(false, false);
3712 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3713 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3714 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3715 EXPECT_TRUE(layer1->quads_appended());
3716 EXPECT_TRUE(layer2->quads_appended());
3717 host_impl_->DidDrawAllLayers(frame);
3719 // Layer with partially opaque contents, drawn with blending.
3720 layer1->SetContentsOpaque(false);
3721 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3722 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
3723 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3724 layer1->SetExpectation(true, false);
3725 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3726 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3727 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3728 EXPECT_TRUE(layer1->quads_appended());
3729 host_impl_->DidDrawAllLayers(frame);
3731 // Layer with partially opaque contents partially culled, drawn with blending.
3732 layer1->SetContentsOpaque(false);
3733 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3734 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
3735 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3736 layer1->SetExpectation(true, false);
3737 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3738 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3739 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3740 EXPECT_TRUE(layer1->quads_appended());
3741 host_impl_->DidDrawAllLayers(frame);
3743 // Layer with partially opaque contents culled, drawn with blending.
3744 layer1->SetContentsOpaque(false);
3745 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3746 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
3747 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3748 layer1->SetExpectation(true, false);
3749 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3750 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3751 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3752 EXPECT_TRUE(layer1->quads_appended());
3753 host_impl_->DidDrawAllLayers(frame);
3755 // Layer with partially opaque contents and translucent contents culled, drawn
3756 // without blending.
3757 layer1->SetContentsOpaque(false);
3758 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3759 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
3760 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3761 layer1->SetExpectation(false, false);
3762 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3763 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3764 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3765 EXPECT_TRUE(layer1->quads_appended());
3766 host_impl_->DidDrawAllLayers(frame);
3769 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
3770 protected:
3771 LayerTreeHostImplViewportCoveredTest() :
3772 gutter_quad_material_(DrawQuad::SOLID_COLOR),
3773 child_(NULL),
3774 did_activate_pending_tree_(false) {}
3776 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
3777 if (always_draw) {
3778 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
3779 .PassAs<OutputSurface>();
3781 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
3784 void SetupActiveTreeLayers() {
3785 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
3786 host_impl_->active_tree()->SetRootLayer(
3787 LayerImpl::Create(host_impl_->active_tree(), 1));
3788 host_impl_->active_tree()->root_layer()->AddChild(
3789 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3791 host_impl_->resource_provider()));
3792 child_ = static_cast<BlendStateCheckLayer*>(
3793 host_impl_->active_tree()->root_layer()->children()[0]);
3794 child_->SetExpectation(false, false);
3795 child_->SetContentsOpaque(true);
3798 // Expect no gutter rects.
3799 void TestLayerCoversFullViewport() {
3800 gfx::Rect layer_rect(viewport_size_);
3801 child_->SetPosition(layer_rect.origin());
3802 child_->SetBounds(layer_rect.size());
3803 child_->SetContentBounds(layer_rect.size());
3804 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3805 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3807 LayerTreeHostImpl::FrameData frame;
3808 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3809 ASSERT_EQ(1u, frame.render_passes.size());
3811 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3812 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3813 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3815 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3816 host_impl_->DidDrawAllLayers(frame);
3819 // Expect fullscreen gutter rect.
3820 void TestEmptyLayer() {
3821 gfx::Rect layer_rect(0, 0, 0, 0);
3822 child_->SetPosition(layer_rect.origin());
3823 child_->SetBounds(layer_rect.size());
3824 child_->SetContentBounds(layer_rect.size());
3825 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3826 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3828 LayerTreeHostImpl::FrameData frame;
3829 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3830 ASSERT_EQ(1u, frame.render_passes.size());
3832 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
3833 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3834 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3836 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3837 host_impl_->DidDrawAllLayers(frame);
3840 // Expect four surrounding gutter rects.
3841 void TestLayerInMiddleOfViewport() {
3842 gfx::Rect layer_rect(500, 500, 200, 200);
3843 child_->SetPosition(layer_rect.origin());
3844 child_->SetBounds(layer_rect.size());
3845 child_->SetContentBounds(layer_rect.size());
3846 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3847 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3849 LayerTreeHostImpl::FrameData frame;
3850 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3851 ASSERT_EQ(1u, frame.render_passes.size());
3853 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
3854 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
3855 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3857 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3858 host_impl_->DidDrawAllLayers(frame);
3861 // Expect no gutter rects.
3862 void TestLayerIsLargerThanViewport() {
3863 gfx::Rect layer_rect(viewport_size_.width() + 10,
3864 viewport_size_.height() + 10);
3865 child_->SetPosition(layer_rect.origin());
3866 child_->SetBounds(layer_rect.size());
3867 child_->SetContentBounds(layer_rect.size());
3868 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3869 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3871 LayerTreeHostImpl::FrameData frame;
3872 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3873 ASSERT_EQ(1u, frame.render_passes.size());
3875 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3876 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3877 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3879 host_impl_->DidDrawAllLayers(frame);
3882 virtual void DidActivateSyncTree() OVERRIDE {
3883 did_activate_pending_tree_ = true;
3886 void set_gutter_quad_material(DrawQuad::Material material) {
3887 gutter_quad_material_ = material;
3889 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
3890 gutter_texture_size_ = gutter_texture_size;
3893 protected:
3894 size_t CountGutterQuads(const QuadList& quad_list) {
3895 size_t num_gutter_quads = 0;
3896 for (size_t i = 0; i < quad_list.size(); ++i) {
3897 num_gutter_quads += (quad_list[i]->material ==
3898 gutter_quad_material_) ? 1 : 0;
3900 return num_gutter_quads;
3903 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
3904 LayerTestCommon::VerifyQuadsExactlyCoverRect(
3905 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
3908 // Make sure that the texture coordinates match their expectations.
3909 void ValidateTextureDrawQuads(const QuadList& quad_list) {
3910 for (size_t i = 0; i < quad_list.size(); ++i) {
3911 if (quad_list[i]->material != DrawQuad::TEXTURE_CONTENT)
3912 continue;
3913 const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(quad_list[i]);
3914 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
3915 gutter_texture_size_, host_impl_->device_scale_factor());
3916 EXPECT_EQ(quad->uv_top_left.x(),
3917 quad->rect.x() / gutter_texture_size_pixels.width());
3918 EXPECT_EQ(quad->uv_top_left.y(),
3919 quad->rect.y() / gutter_texture_size_pixels.height());
3920 EXPECT_EQ(quad->uv_bottom_right.x(),
3921 quad->rect.right() / gutter_texture_size_pixels.width());
3922 EXPECT_EQ(quad->uv_bottom_right.y(),
3923 quad->rect.bottom() / gutter_texture_size_pixels.height());
3927 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
3928 return gfx::ToRoundedSize(
3929 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
3932 DrawQuad::Material gutter_quad_material_;
3933 gfx::Size gutter_texture_size_;
3934 gfx::Size viewport_size_;
3935 BlendStateCheckLayer* child_;
3936 bool did_activate_pending_tree_;
3939 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
3940 viewport_size_ = gfx::Size(1000, 1000);
3942 bool always_draw = false;
3943 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3945 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3946 SetupActiveTreeLayers();
3947 TestLayerCoversFullViewport();
3948 TestEmptyLayer();
3949 TestLayerInMiddleOfViewport();
3950 TestLayerIsLargerThanViewport();
3953 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
3954 viewport_size_ = gfx::Size(1000, 1000);
3956 bool always_draw = false;
3957 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3959 host_impl_->SetDeviceScaleFactor(2.f);
3960 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3961 SetupActiveTreeLayers();
3962 TestLayerCoversFullViewport();
3963 TestEmptyLayer();
3964 TestLayerInMiddleOfViewport();
3965 TestLayerIsLargerThanViewport();
3968 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
3969 viewport_size_ = gfx::Size(1000, 1000);
3971 bool always_draw = false;
3972 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3974 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3975 SetupActiveTreeLayers();
3977 // Specify an overhang bitmap to use.
3978 bool is_opaque = false;
3979 UIResourceBitmap ui_resource_bitmap(gfx::Size(2, 2), is_opaque);
3980 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
3981 UIResourceId ui_resource_id = 12345;
3982 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
3983 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
3984 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
3985 set_gutter_texture_size(gfx::Size(32, 32));
3987 TestLayerCoversFullViewport();
3988 TestEmptyLayer();
3989 TestLayerInMiddleOfViewport();
3990 TestLayerIsLargerThanViewport();
3992 // Change the resource size.
3993 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
3994 set_gutter_texture_size(gfx::Size(128, 16));
3996 TestLayerCoversFullViewport();
3997 TestEmptyLayer();
3998 TestLayerInMiddleOfViewport();
3999 TestLayerIsLargerThanViewport();
4001 // Change the device scale factor
4002 host_impl_->SetDeviceScaleFactor(2.f);
4003 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4005 TestLayerCoversFullViewport();
4006 TestEmptyLayer();
4007 TestLayerInMiddleOfViewport();
4008 TestLayerIsLargerThanViewport();
4011 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
4012 viewport_size_ = gfx::Size(1000, 1000);
4014 bool always_draw = true;
4015 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4017 // Pending tree to force active_tree size invalid. Not used otherwise.
4018 host_impl_->CreatePendingTree();
4019 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4020 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4022 SetupActiveTreeLayers();
4023 TestEmptyLayer();
4024 TestLayerInMiddleOfViewport();
4025 TestLayerIsLargerThanViewport();
4028 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
4029 viewport_size_ = gfx::Size(1000, 1000);
4031 bool always_draw = true;
4032 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4034 // Set larger viewport and activate it to active tree.
4035 host_impl_->CreatePendingTree();
4036 gfx::Size larger_viewport(viewport_size_.width() + 100,
4037 viewport_size_.height() + 100);
4038 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
4039 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4040 host_impl_->ActivateSyncTree();
4041 EXPECT_TRUE(did_activate_pending_tree_);
4042 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
4044 // Shrink pending tree viewport without activating.
4045 host_impl_->CreatePendingTree();
4046 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4047 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4049 SetupActiveTreeLayers();
4050 TestEmptyLayer();
4051 TestLayerInMiddleOfViewport();
4052 TestLayerIsLargerThanViewport();
4055 class FakeDrawableLayerImpl: public LayerImpl {
4056 public:
4057 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4058 return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(tree_impl, id));
4060 protected:
4061 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
4062 : LayerImpl(tree_impl, id) {}
4065 // Only reshape when we know we are going to draw. Otherwise, the reshape
4066 // can leave the window at the wrong size if we never draw and the proper
4067 // viewport size is never set.
4068 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
4069 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4070 scoped_ptr<OutputSurface> output_surface(
4071 FakeOutputSurface::Create3d(provider));
4072 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4074 scoped_ptr<LayerImpl> root =
4075 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4076 root->SetBounds(gfx::Size(10, 10));
4077 root->SetContentBounds(gfx::Size(10, 10));
4078 root->SetDrawsContent(true);
4079 host_impl_->active_tree()->SetRootLayer(root.Pass());
4080 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
4081 provider->TestContext3d()->clear_reshape_called();
4083 LayerTreeHostImpl::FrameData frame;
4084 host_impl_->SetViewportSize(gfx::Size(10, 10));
4085 host_impl_->SetDeviceScaleFactor(1.f);
4086 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4087 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4088 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4089 EXPECT_EQ(provider->TestContext3d()->width(), 10);
4090 EXPECT_EQ(provider->TestContext3d()->height(), 10);
4091 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4092 host_impl_->DidDrawAllLayers(frame);
4093 provider->TestContext3d()->clear_reshape_called();
4095 host_impl_->SetViewportSize(gfx::Size(20, 30));
4096 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4097 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4098 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4099 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4100 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4101 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4102 host_impl_->DidDrawAllLayers(frame);
4103 provider->TestContext3d()->clear_reshape_called();
4105 host_impl_->SetDeviceScaleFactor(2.f);
4106 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4107 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4108 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4109 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4110 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4111 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
4112 host_impl_->DidDrawAllLayers(frame);
4113 provider->TestContext3d()->clear_reshape_called();
4116 // Make sure damage tracking propagates all the way to the graphics context,
4117 // where it should request to swap only the sub-buffer that is damaged.
4118 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
4119 scoped_refptr<TestContextProvider> context_provider(
4120 TestContextProvider::Create());
4121 context_provider->BindToCurrentThread();
4122 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
4124 scoped_ptr<OutputSurface> output_surface(
4125 FakeOutputSurface::Create3d(context_provider));
4127 // This test creates its own LayerTreeHostImpl, so
4128 // that we can force partial swap enabled.
4129 LayerTreeSettings settings;
4130 settings.partial_swap_enabled = true;
4131 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4132 new TestSharedBitmapManager());
4133 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
4134 LayerTreeHostImpl::Create(settings,
4135 this,
4136 &proxy_,
4137 &stats_instrumentation_,
4138 shared_bitmap_manager.get(),
4140 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
4141 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
4143 scoped_ptr<LayerImpl> root =
4144 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
4145 scoped_ptr<LayerImpl> child =
4146 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
4147 child->SetPosition(gfx::PointF(12.f, 13.f));
4148 child->SetBounds(gfx::Size(14, 15));
4149 child->SetContentBounds(gfx::Size(14, 15));
4150 child->SetDrawsContent(true);
4151 root->SetBounds(gfx::Size(500, 500));
4152 root->SetContentBounds(gfx::Size(500, 500));
4153 root->SetDrawsContent(true);
4154 root->AddChild(child.Pass());
4155 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
4157 LayerTreeHostImpl::FrameData frame;
4159 // First frame, the entire screen should get swapped.
4160 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4161 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4162 layer_tree_host_impl->DidDrawAllLayers(frame);
4163 layer_tree_host_impl->SwapBuffers(frame);
4164 EXPECT_EQ(TestContextSupport::SWAP,
4165 context_provider->support()->last_swap_type());
4167 // Second frame, only the damaged area should get swapped. Damage should be
4168 // the union of old and new child rects.
4169 // expected damage rect: gfx::Rect(26, 28);
4170 // expected swap rect: vertically flipped, with origin at bottom left corner.
4171 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
4172 gfx::PointF());
4173 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4174 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4175 host_impl_->DidDrawAllLayers(frame);
4176 layer_tree_host_impl->SwapBuffers(frame);
4178 // Make sure that partial swap is constrained to the viewport dimensions
4179 // expected damage rect: gfx::Rect(500, 500);
4180 // expected swap rect: flipped damage rect, but also clamped to viewport
4181 EXPECT_EQ(TestContextSupport::PARTIAL_SWAP,
4182 context_provider->support()->last_swap_type());
4183 gfx::Rect expected_swap_rect(0, 500-28, 26, 28);
4184 EXPECT_EQ(expected_swap_rect.ToString(),
4185 context_provider->support()->
4186 last_partial_swap_rect().ToString());
4188 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
4189 // This will damage everything.
4190 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
4191 SK_ColorBLACK);
4192 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4193 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4194 host_impl_->DidDrawAllLayers(frame);
4195 layer_tree_host_impl->SwapBuffers(frame);
4197 EXPECT_EQ(TestContextSupport::SWAP,
4198 context_provider->support()->last_swap_type());
4201 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
4202 scoped_ptr<LayerImpl> root =
4203 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4204 scoped_ptr<LayerImpl> child =
4205 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
4206 child->SetBounds(gfx::Size(10, 10));
4207 child->SetContentBounds(gfx::Size(10, 10));
4208 child->SetDrawsContent(true);
4209 root->SetBounds(gfx::Size(10, 10));
4210 root->SetContentBounds(gfx::Size(10, 10));
4211 root->SetDrawsContent(true);
4212 root->SetForceRenderSurface(true);
4213 root->AddChild(child.Pass());
4215 host_impl_->active_tree()->SetRootLayer(root.Pass());
4217 LayerTreeHostImpl::FrameData frame;
4219 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4220 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
4221 EXPECT_EQ(1u, frame.render_passes.size());
4222 host_impl_->DidDrawAllLayers(frame);
4225 class FakeLayerWithQuads : public LayerImpl {
4226 public:
4227 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4228 return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(tree_impl, id));
4231 virtual void AppendQuads(RenderPass* render_pass,
4232 const OcclusionTracker<LayerImpl>& occlusion_tracker,
4233 AppendQuadsData* append_quads_data) OVERRIDE {
4234 SharedQuadState* shared_quad_state =
4235 render_pass->CreateAndAppendSharedQuadState();
4236 PopulateSharedQuadState(shared_quad_state);
4238 SkColor gray = SkColorSetRGB(100, 100, 100);
4239 gfx::Rect quad_rect(content_bounds());
4240 gfx::Rect visible_quad_rect(quad_rect);
4241 SolidColorDrawQuad* my_quad =
4242 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4243 my_quad->SetNew(
4244 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
4247 private:
4248 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
4249 : LayerImpl(tree_impl, id) {}
4252 class MockContext : public TestWebGraphicsContext3D {
4253 public:
4254 MOCK_METHOD1(useProgram, void(GLuint program));
4255 MOCK_METHOD5(uniform4f, void(GLint location,
4256 GLfloat x,
4257 GLfloat y,
4258 GLfloat z,
4259 GLfloat w));
4260 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
4261 GLsizei count,
4262 GLboolean transpose,
4263 const GLfloat* value));
4264 MOCK_METHOD4(drawElements, void(GLenum mode,
4265 GLsizei count,
4266 GLenum type,
4267 GLintptr offset));
4268 MOCK_METHOD1(enable, void(GLenum cap));
4269 MOCK_METHOD1(disable, void(GLenum cap));
4270 MOCK_METHOD4(scissor, void(GLint x,
4271 GLint y,
4272 GLsizei width,
4273 GLsizei height));
4276 class MockContextHarness {
4277 private:
4278 MockContext* context_;
4280 public:
4281 explicit MockContextHarness(MockContext* context)
4282 : context_(context) {
4283 context_->set_have_post_sub_buffer(true);
4285 // Catch "uninteresting" calls
4286 EXPECT_CALL(*context_, useProgram(_))
4287 .Times(0);
4289 EXPECT_CALL(*context_, drawElements(_, _, _, _))
4290 .Times(0);
4292 // These are not asserted
4293 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
4294 .WillRepeatedly(Return());
4296 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
4297 .WillRepeatedly(Return());
4299 // Any un-sanctioned calls to enable() are OK
4300 EXPECT_CALL(*context_, enable(_))
4301 .WillRepeatedly(Return());
4303 // Any un-sanctioned calls to disable() are OK
4304 EXPECT_CALL(*context_, disable(_))
4305 .WillRepeatedly(Return());
4308 void MustDrawSolidQuad() {
4309 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
4310 .WillOnce(Return())
4311 .RetiresOnSaturation();
4313 EXPECT_CALL(*context_, useProgram(_))
4314 .WillOnce(Return())
4315 .RetiresOnSaturation();
4318 void MustSetScissor(int x, int y, int width, int height) {
4319 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4320 .WillRepeatedly(Return());
4322 EXPECT_CALL(*context_, scissor(x, y, width, height))
4323 .Times(AtLeast(1))
4324 .WillRepeatedly(Return());
4327 void MustSetNoScissor() {
4328 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
4329 .WillRepeatedly(Return());
4331 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4332 .Times(0);
4334 EXPECT_CALL(*context_, scissor(_, _, _, _))
4335 .Times(0);
4339 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
4340 scoped_ptr<MockContext> mock_context_owned(new MockContext);
4341 MockContext* mock_context = mock_context_owned.get();
4343 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4344 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4345 MockContextHarness harness(mock_context);
4347 // Run test case
4348 LayerTreeSettings settings = DefaultSettings();
4349 settings.partial_swap_enabled = false;
4350 CreateHostImpl(settings, output_surface.Pass());
4351 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4353 // Without partial swap, and no clipping, no scissor is set.
4354 harness.MustDrawSolidQuad();
4355 harness.MustSetNoScissor();
4357 LayerTreeHostImpl::FrameData frame;
4358 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4359 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4360 host_impl_->DidDrawAllLayers(frame);
4362 Mock::VerifyAndClearExpectations(&mock_context);
4364 // Without partial swap, but a layer does clip its subtree, one scissor is
4365 // set.
4366 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
4367 harness.MustDrawSolidQuad();
4368 harness.MustSetScissor(0, 0, 10, 10);
4370 LayerTreeHostImpl::FrameData frame;
4371 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4372 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4373 host_impl_->DidDrawAllLayers(frame);
4375 Mock::VerifyAndClearExpectations(&mock_context);
4378 TEST_F(LayerTreeHostImplTest, PartialSwap) {
4379 scoped_ptr<MockContext> context_owned(new MockContext);
4380 MockContext* mock_context = context_owned.get();
4381 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4382 context_owned.PassAs<TestWebGraphicsContext3D>()));
4383 MockContextHarness harness(mock_context);
4385 LayerTreeSettings settings = DefaultSettings();
4386 settings.partial_swap_enabled = true;
4387 CreateHostImpl(settings, output_surface.Pass());
4388 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4390 // The first frame is not a partially-swapped one.
4391 harness.MustSetScissor(0, 0, 10, 10);
4392 harness.MustDrawSolidQuad();
4394 LayerTreeHostImpl::FrameData frame;
4395 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4396 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4397 host_impl_->DidDrawAllLayers(frame);
4399 Mock::VerifyAndClearExpectations(&mock_context);
4401 // Damage a portion of the frame.
4402 host_impl_->active_tree()->root_layer()->SetUpdateRect(
4403 gfx::Rect(0, 0, 2, 3));
4405 // The second frame will be partially-swapped (the y coordinates are flipped).
4406 harness.MustSetScissor(0, 7, 2, 3);
4407 harness.MustDrawSolidQuad();
4409 LayerTreeHostImpl::FrameData frame;
4410 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4411 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4412 host_impl_->DidDrawAllLayers(frame);
4414 Mock::VerifyAndClearExpectations(&mock_context);
4417 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
4418 bool partial_swap,
4419 LayerTreeHostImplClient* client,
4420 Proxy* proxy,
4421 SharedBitmapManager* manager,
4422 RenderingStatsInstrumentation* stats_instrumentation) {
4423 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4424 scoped_ptr<OutputSurface> output_surface(
4425 FakeOutputSurface::Create3d(provider));
4426 provider->BindToCurrentThread();
4427 provider->TestContext3d()->set_have_post_sub_buffer(true);
4429 LayerTreeSettings settings;
4430 settings.partial_swap_enabled = partial_swap;
4431 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
4432 settings, client, proxy, stats_instrumentation, manager, 0);
4433 my_host_impl->InitializeRenderer(output_surface.Pass());
4434 my_host_impl->SetViewportSize(gfx::Size(100, 100));
4437 Layers are created as follows:
4439 +--------------------+
4440 | 1 |
4441 | +-----------+ |
4442 | | 2 | |
4443 | | +-------------------+
4444 | | | 3 |
4445 | | +-------------------+
4446 | | | |
4447 | +-----------+ |
4450 +--------------------+
4452 Layers 1, 2 have render surfaces
4454 scoped_ptr<LayerImpl> root =
4455 LayerImpl::Create(my_host_impl->active_tree(), 1);
4456 scoped_ptr<LayerImpl> child =
4457 LayerImpl::Create(my_host_impl->active_tree(), 2);
4458 scoped_ptr<LayerImpl> grand_child =
4459 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
4461 gfx::Rect root_rect(0, 0, 100, 100);
4462 gfx::Rect child_rect(10, 10, 50, 50);
4463 gfx::Rect grand_child_rect(5, 5, 150, 150);
4465 root->CreateRenderSurface();
4466 root->SetPosition(root_rect.origin());
4467 root->SetBounds(root_rect.size());
4468 root->SetContentBounds(root->bounds());
4469 root->draw_properties().visible_content_rect = root_rect;
4470 root->SetDrawsContent(false);
4471 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
4473 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
4474 child->SetOpacity(0.5f);
4475 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
4476 child->SetContentBounds(child->bounds());
4477 child->draw_properties().visible_content_rect = child_rect;
4478 child->SetDrawsContent(false);
4479 child->SetForceRenderSurface(true);
4481 grand_child->SetPosition(grand_child_rect.origin());
4482 grand_child->SetBounds(grand_child_rect.size());
4483 grand_child->SetContentBounds(grand_child->bounds());
4484 grand_child->draw_properties().visible_content_rect = grand_child_rect;
4485 grand_child->SetDrawsContent(true);
4487 child->AddChild(grand_child.Pass());
4488 root->AddChild(child.Pass());
4490 my_host_impl->active_tree()->SetRootLayer(root.Pass());
4491 return my_host_impl.Pass();
4494 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
4495 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4496 new TestSharedBitmapManager());
4497 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4498 SetupLayersForOpacity(true,
4499 this,
4500 &proxy_,
4501 shared_bitmap_manager.get(),
4502 &stats_instrumentation_);
4504 LayerTreeHostImpl::FrameData frame;
4505 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4507 // Verify all quads have been computed
4508 ASSERT_EQ(2U, frame.render_passes.size());
4509 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4510 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4511 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4512 frame.render_passes[0]->quad_list[0]->material);
4513 EXPECT_EQ(DrawQuad::RENDER_PASS,
4514 frame.render_passes[1]->quad_list[0]->material);
4516 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4517 my_host_impl->DidDrawAllLayers(frame);
4521 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
4522 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4523 new TestSharedBitmapManager());
4524 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4525 SetupLayersForOpacity(false,
4526 this,
4527 &proxy_,
4528 shared_bitmap_manager.get(),
4529 &stats_instrumentation_);
4531 LayerTreeHostImpl::FrameData frame;
4532 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4534 // Verify all quads have been computed
4535 ASSERT_EQ(2U, frame.render_passes.size());
4536 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4537 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4538 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4539 frame.render_passes[0]->quad_list[0]->material);
4540 EXPECT_EQ(DrawQuad::RENDER_PASS,
4541 frame.render_passes[1]->quad_list[0]->material);
4543 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4544 my_host_impl->DidDrawAllLayers(frame);
4548 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
4549 scoped_ptr<TestWebGraphicsContext3D> context =
4550 TestWebGraphicsContext3D::Create();
4551 TestWebGraphicsContext3D* context3d = context.get();
4552 scoped_ptr<OutputSurface> output_surface(
4553 FakeOutputSurface::Create3d(context.Pass()));
4554 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4556 scoped_ptr<LayerImpl> root_layer =
4557 LayerImpl::Create(host_impl_->active_tree(), 1);
4558 root_layer->SetBounds(gfx::Size(10, 10));
4560 scoped_refptr<VideoFrame> softwareFrame =
4561 media::VideoFrame::CreateColorFrame(
4562 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
4563 FakeVideoFrameProvider provider;
4564 provider.set_frame(softwareFrame);
4565 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
4566 host_impl_->active_tree(), 4, &provider, media::VIDEO_ROTATION_0);
4567 video_layer->SetBounds(gfx::Size(10, 10));
4568 video_layer->SetContentBounds(gfx::Size(10, 10));
4569 video_layer->SetDrawsContent(true);
4570 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
4572 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
4573 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
4574 io_surface_layer->SetBounds(gfx::Size(10, 10));
4575 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
4576 io_surface_layer->SetDrawsContent(true);
4577 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
4578 root_layer->AddChild(io_surface_layer.PassAs<LayerImpl>());
4580 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
4582 EXPECT_EQ(0u, context3d->NumTextures());
4584 LayerTreeHostImpl::FrameData frame;
4585 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4586 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4587 host_impl_->DidDrawAllLayers(frame);
4588 host_impl_->SwapBuffers(frame);
4590 EXPECT_GT(context3d->NumTextures(), 0u);
4592 // Kill the layer tree.
4593 host_impl_->active_tree()->SetRootLayer(
4594 LayerImpl::Create(host_impl_->active_tree(), 100));
4595 // There should be no textures left in use after.
4596 EXPECT_EQ(0u, context3d->NumTextures());
4599 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
4600 public:
4601 MOCK_METHOD1(useProgram, void(GLuint program));
4602 MOCK_METHOD4(drawElements, void(GLenum mode,
4603 GLsizei count,
4604 GLenum type,
4605 GLintptr offset));
4608 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
4609 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
4610 new MockDrawQuadsToFillScreenContext);
4611 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
4613 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4614 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4616 // Run test case
4617 LayerTreeSettings settings = DefaultSettings();
4618 settings.partial_swap_enabled = false;
4619 CreateHostImpl(settings, output_surface.Pass());
4620 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
4621 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
4623 // Verify one quad is drawn when transparent background set is not set.
4624 host_impl_->active_tree()->set_has_transparent_background(false);
4625 EXPECT_CALL(*mock_context, useProgram(_))
4626 .Times(1);
4627 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
4628 .Times(1);
4629 LayerTreeHostImpl::FrameData frame;
4630 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4631 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4632 host_impl_->DidDrawAllLayers(frame);
4633 Mock::VerifyAndClearExpectations(&mock_context);
4635 // Verify no quads are drawn when transparent background is set.
4636 host_impl_->active_tree()->set_has_transparent_background(true);
4637 host_impl_->SetFullRootLayerDamage();
4638 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4639 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4640 host_impl_->DidDrawAllLayers(frame);
4641 Mock::VerifyAndClearExpectations(&mock_context);
4644 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
4645 set_reduce_memory_result(false);
4647 // If changing the memory limit wouldn't result in changing what was
4648 // committed, then no commit should be requested.
4649 set_reduce_memory_result(false);
4650 host_impl_->set_max_memory_needed_bytes(
4651 host_impl_->memory_allocation_limit_bytes() - 1);
4652 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4653 host_impl_->memory_allocation_limit_bytes() - 1));
4654 EXPECT_FALSE(did_request_commit_);
4655 did_request_commit_ = false;
4657 // If changing the memory limit would result in changing what was
4658 // committed, then a commit should be requested, even though nothing was
4659 // evicted.
4660 set_reduce_memory_result(false);
4661 host_impl_->set_max_memory_needed_bytes(
4662 host_impl_->memory_allocation_limit_bytes());
4663 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4664 host_impl_->memory_allocation_limit_bytes() - 1));
4665 EXPECT_TRUE(did_request_commit_);
4666 did_request_commit_ = false;
4668 // Especially if changing the memory limit caused evictions, we need
4669 // to re-commit.
4670 set_reduce_memory_result(true);
4671 host_impl_->set_max_memory_needed_bytes(1);
4672 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4673 host_impl_->memory_allocation_limit_bytes() - 1));
4674 EXPECT_TRUE(did_request_commit_);
4675 did_request_commit_ = false;
4677 // But if we set it to the same value that it was before, we shouldn't
4678 // re-commit.
4679 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4680 host_impl_->memory_allocation_limit_bytes()));
4681 EXPECT_FALSE(did_request_commit_);
4684 class LayerTreeHostImplTestWithDelegatingRenderer
4685 : public LayerTreeHostImplTest {
4686 protected:
4687 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
4688 return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
4691 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
4692 bool expect_to_draw = !expected_damage.IsEmpty();
4694 LayerTreeHostImpl::FrameData frame;
4695 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4697 if (!expect_to_draw) {
4698 // With no damage, we don't draw, and no quads are created.
4699 ASSERT_EQ(0u, frame.render_passes.size());
4700 } else {
4701 ASSERT_EQ(1u, frame.render_passes.size());
4703 // Verify the damage rect for the root render pass.
4704 const RenderPass* root_render_pass = frame.render_passes.back();
4705 EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
4707 // Verify the root and child layers' quads are generated and not being
4708 // culled.
4709 ASSERT_EQ(2u, root_render_pass->quad_list.size());
4711 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
4712 gfx::RectF expected_child_visible_rect(child->content_bounds());
4713 EXPECT_RECT_EQ(expected_child_visible_rect,
4714 root_render_pass->quad_list[0]->visible_rect);
4716 LayerImpl* root = host_impl_->active_tree()->root_layer();
4717 gfx::RectF expected_root_visible_rect(root->content_bounds());
4718 EXPECT_RECT_EQ(expected_root_visible_rect,
4719 root_render_pass->quad_list[1]->visible_rect);
4722 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4723 host_impl_->DidDrawAllLayers(frame);
4724 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
4728 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
4729 scoped_ptr<SolidColorLayerImpl> root =
4730 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4731 root->SetPosition(gfx::PointF());
4732 root->SetBounds(gfx::Size(10, 10));
4733 root->SetContentBounds(gfx::Size(10, 10));
4734 root->SetDrawsContent(true);
4736 // Child layer is in the bottom right corner.
4737 scoped_ptr<SolidColorLayerImpl> child =
4738 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
4739 child->SetPosition(gfx::PointF(9.f, 9.f));
4740 child->SetBounds(gfx::Size(1, 1));
4741 child->SetContentBounds(gfx::Size(1, 1));
4742 child->SetDrawsContent(true);
4743 root->AddChild(child.PassAs<LayerImpl>());
4745 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
4747 // Draw a frame. In the first frame, the entire viewport should be damaged.
4748 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
4749 DrawFrameAndTestDamage(full_frame_damage);
4751 // The second frame has damage that doesn't touch the child layer. Its quads
4752 // should still be generated.
4753 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
4754 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
4755 DrawFrameAndTestDamage(small_damage);
4757 // The third frame should have no damage, so no quads should be generated.
4758 gfx::Rect no_damage;
4759 DrawFrameAndTestDamage(no_damage);
4762 // TODO(reveman): Remove this test and the ability to prevent on demand raster
4763 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
4764 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
4765 LayerTreeSettings settings;
4766 CreateHostImpl(settings, CreateOutputSurface());
4767 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
4770 class FakeMaskLayerImpl : public LayerImpl {
4771 public:
4772 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
4773 int id) {
4774 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
4777 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
4778 return 0;
4781 private:
4782 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
4783 : LayerImpl(tree_impl, id) {}
4786 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
4787 LayerTreeSettings settings;
4788 settings.layer_transforms_should_scale_layer_contents = true;
4789 CreateHostImpl(settings, CreateOutputSurface());
4791 // Root
4792 // |
4793 // +-- Scaling Layer (adds a 2x scale)
4794 // |
4795 // +-- Content Layer
4796 // +--Mask
4797 scoped_ptr<LayerImpl> scoped_root =
4798 LayerImpl::Create(host_impl_->active_tree(), 1);
4799 LayerImpl* root = scoped_root.get();
4800 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4802 scoped_ptr<LayerImpl> scoped_scaling_layer =
4803 LayerImpl::Create(host_impl_->active_tree(), 2);
4804 LayerImpl* scaling_layer = scoped_scaling_layer.get();
4805 root->AddChild(scoped_scaling_layer.Pass());
4807 scoped_ptr<LayerImpl> scoped_content_layer =
4808 LayerImpl::Create(host_impl_->active_tree(), 3);
4809 LayerImpl* content_layer = scoped_content_layer.get();
4810 scaling_layer->AddChild(scoped_content_layer.Pass());
4812 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4813 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4814 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4815 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4817 gfx::Size root_size(100, 100);
4818 root->SetBounds(root_size);
4819 root->SetContentBounds(root_size);
4820 root->SetPosition(gfx::PointF());
4822 gfx::Size scaling_layer_size(50, 50);
4823 scaling_layer->SetBounds(scaling_layer_size);
4824 scaling_layer->SetContentBounds(scaling_layer_size);
4825 scaling_layer->SetPosition(gfx::PointF());
4826 gfx::Transform scale;
4827 scale.Scale(2.f, 2.f);
4828 scaling_layer->SetTransform(scale);
4830 content_layer->SetBounds(scaling_layer_size);
4831 content_layer->SetContentBounds(scaling_layer_size);
4832 content_layer->SetPosition(gfx::PointF());
4833 content_layer->SetDrawsContent(true);
4835 mask_layer->SetBounds(scaling_layer_size);
4836 mask_layer->SetContentBounds(scaling_layer_size);
4837 mask_layer->SetPosition(gfx::PointF());
4838 mask_layer->SetDrawsContent(true);
4841 // Check that the tree scaling is correctly taken into account for the mask,
4842 // that should fully map onto the quad.
4843 float device_scale_factor = 1.f;
4844 host_impl_->SetViewportSize(root_size);
4845 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4847 LayerTreeHostImpl::FrameData frame;
4848 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4850 ASSERT_EQ(1u, frame.render_passes.size());
4851 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4852 ASSERT_EQ(DrawQuad::RENDER_PASS,
4853 frame.render_passes[0]->quad_list[0]->material);
4854 const RenderPassDrawQuad* render_pass_quad =
4855 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4856 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4857 render_pass_quad->rect.ToString());
4858 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4859 render_pass_quad->mask_uv_rect.ToString());
4861 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4862 host_impl_->DidDrawAllLayers(frame);
4866 // Applying a DSF should change the render surface size, but won't affect
4867 // which part of the mask is used.
4868 device_scale_factor = 2.f;
4869 gfx::Size device_viewport =
4870 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4871 host_impl_->SetViewportSize(device_viewport);
4872 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4873 host_impl_->active_tree()->set_needs_update_draw_properties();
4875 LayerTreeHostImpl::FrameData frame;
4876 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4878 ASSERT_EQ(1u, frame.render_passes.size());
4879 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4880 ASSERT_EQ(DrawQuad::RENDER_PASS,
4881 frame.render_passes[0]->quad_list[0]->material);
4882 const RenderPassDrawQuad* render_pass_quad =
4883 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4884 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4885 render_pass_quad->rect.ToString());
4886 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4887 render_pass_quad->mask_uv_rect.ToString());
4889 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4890 host_impl_->DidDrawAllLayers(frame);
4894 // Applying an equivalent content scale on the content layer and the mask
4895 // should still result in the same part of the mask being used.
4896 gfx::Size content_bounds =
4897 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
4898 device_scale_factor));
4899 content_layer->SetContentBounds(content_bounds);
4900 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4901 mask_layer->SetContentBounds(content_bounds);
4902 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4903 host_impl_->active_tree()->set_needs_update_draw_properties();
4905 LayerTreeHostImpl::FrameData frame;
4906 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4908 ASSERT_EQ(1u, frame.render_passes.size());
4909 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4910 ASSERT_EQ(DrawQuad::RENDER_PASS,
4911 frame.render_passes[0]->quad_list[0]->material);
4912 const RenderPassDrawQuad* render_pass_quad =
4913 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4914 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4915 render_pass_quad->rect.ToString());
4916 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4917 render_pass_quad->mask_uv_rect.ToString());
4919 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4920 host_impl_->DidDrawAllLayers(frame);
4924 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
4925 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4926 // 50x50.
4928 scoped_ptr<LayerImpl> scoped_root =
4929 LayerImpl::Create(host_impl_->active_tree(), 1);
4930 LayerImpl* root = scoped_root.get();
4931 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4933 scoped_ptr<LayerImpl> scoped_content_layer =
4934 LayerImpl::Create(host_impl_->active_tree(), 3);
4935 LayerImpl* content_layer = scoped_content_layer.get();
4936 root->AddChild(scoped_content_layer.Pass());
4938 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4939 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4940 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4941 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4943 gfx::Size root_size(100, 100);
4944 root->SetBounds(root_size);
4945 root->SetContentBounds(root_size);
4946 root->SetPosition(gfx::PointF());
4948 gfx::Size layer_size(50, 50);
4949 content_layer->SetBounds(layer_size);
4950 content_layer->SetContentBounds(layer_size);
4951 content_layer->SetPosition(gfx::PointF());
4952 content_layer->SetDrawsContent(true);
4954 gfx::Size mask_size(100, 100);
4955 mask_layer->SetBounds(mask_size);
4956 mask_layer->SetContentBounds(mask_size);
4957 mask_layer->SetPosition(gfx::PointF());
4958 mask_layer->SetDrawsContent(true);
4960 // Check that the mask fills the surface.
4961 float device_scale_factor = 1.f;
4962 host_impl_->SetViewportSize(root_size);
4963 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4965 LayerTreeHostImpl::FrameData frame;
4966 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4968 ASSERT_EQ(1u, frame.render_passes.size());
4969 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4970 ASSERT_EQ(DrawQuad::RENDER_PASS,
4971 frame.render_passes[0]->quad_list[0]->material);
4972 const RenderPassDrawQuad* render_pass_quad =
4973 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4974 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4975 render_pass_quad->rect.ToString());
4976 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4977 render_pass_quad->mask_uv_rect.ToString());
4979 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4980 host_impl_->DidDrawAllLayers(frame);
4983 // Applying a DSF should change the render surface size, but won't affect
4984 // which part of the mask is used.
4985 device_scale_factor = 2.f;
4986 gfx::Size device_viewport =
4987 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4988 host_impl_->SetViewportSize(device_viewport);
4989 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4990 host_impl_->active_tree()->set_needs_update_draw_properties();
4992 LayerTreeHostImpl::FrameData frame;
4993 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4995 ASSERT_EQ(1u, frame.render_passes.size());
4996 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4997 ASSERT_EQ(DrawQuad::RENDER_PASS,
4998 frame.render_passes[0]->quad_list[0]->material);
4999 const RenderPassDrawQuad* render_pass_quad =
5000 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5001 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5002 render_pass_quad->rect.ToString());
5003 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5004 render_pass_quad->mask_uv_rect.ToString());
5006 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5007 host_impl_->DidDrawAllLayers(frame);
5010 // Applying an equivalent content scale on the content layer and the mask
5011 // should still result in the same part of the mask being used.
5012 gfx::Size layer_size_large =
5013 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5014 content_layer->SetContentBounds(layer_size_large);
5015 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5016 gfx::Size mask_size_large =
5017 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5018 mask_layer->SetContentBounds(mask_size_large);
5019 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5020 host_impl_->active_tree()->set_needs_update_draw_properties();
5022 LayerTreeHostImpl::FrameData frame;
5023 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5025 ASSERT_EQ(1u, frame.render_passes.size());
5026 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5027 ASSERT_EQ(DrawQuad::RENDER_PASS,
5028 frame.render_passes[0]->quad_list[0]->material);
5029 const RenderPassDrawQuad* render_pass_quad =
5030 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5031 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5032 render_pass_quad->rect.ToString());
5033 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5034 render_pass_quad->mask_uv_rect.ToString());
5036 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5037 host_impl_->DidDrawAllLayers(frame);
5040 // Applying a different contents scale to the mask layer means it will have
5041 // a larger texture, but it should use the same tex coords to cover the
5042 // layer it masks.
5043 mask_layer->SetContentBounds(mask_size);
5044 mask_layer->SetContentsScale(1.f, 1.f);
5045 host_impl_->active_tree()->set_needs_update_draw_properties();
5047 LayerTreeHostImpl::FrameData frame;
5048 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5050 ASSERT_EQ(1u, frame.render_passes.size());
5051 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5052 ASSERT_EQ(DrawQuad::RENDER_PASS,
5053 frame.render_passes[0]->quad_list[0]->material);
5054 const RenderPassDrawQuad* render_pass_quad =
5055 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5056 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5057 render_pass_quad->rect.ToString());
5058 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5059 render_pass_quad->mask_uv_rect.ToString());
5061 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5062 host_impl_->DidDrawAllLayers(frame);
5066 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
5067 // The replica's mask layer has bounds 100x100 but the replica is of a
5068 // layer with bounds 50x50.
5070 scoped_ptr<LayerImpl> scoped_root =
5071 LayerImpl::Create(host_impl_->active_tree(), 1);
5072 LayerImpl* root = scoped_root.get();
5073 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5075 scoped_ptr<LayerImpl> scoped_content_layer =
5076 LayerImpl::Create(host_impl_->active_tree(), 3);
5077 LayerImpl* content_layer = scoped_content_layer.get();
5078 root->AddChild(scoped_content_layer.Pass());
5080 scoped_ptr<LayerImpl> scoped_replica_layer =
5081 LayerImpl::Create(host_impl_->active_tree(), 2);
5082 LayerImpl* replica_layer = scoped_replica_layer.get();
5083 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5085 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5086 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5087 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5088 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5090 gfx::Size root_size(100, 100);
5091 root->SetBounds(root_size);
5092 root->SetContentBounds(root_size);
5093 root->SetPosition(gfx::PointF());
5095 gfx::Size layer_size(50, 50);
5096 content_layer->SetBounds(layer_size);
5097 content_layer->SetContentBounds(layer_size);
5098 content_layer->SetPosition(gfx::PointF());
5099 content_layer->SetDrawsContent(true);
5101 gfx::Size mask_size(100, 100);
5102 mask_layer->SetBounds(mask_size);
5103 mask_layer->SetContentBounds(mask_size);
5104 mask_layer->SetPosition(gfx::PointF());
5105 mask_layer->SetDrawsContent(true);
5107 // Check that the mask fills the surface.
5108 float device_scale_factor = 1.f;
5109 host_impl_->SetViewportSize(root_size);
5110 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5112 LayerTreeHostImpl::FrameData frame;
5113 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5115 ASSERT_EQ(1u, frame.render_passes.size());
5116 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5117 ASSERT_EQ(DrawQuad::RENDER_PASS,
5118 frame.render_passes[0]->quad_list[1]->material);
5119 const RenderPassDrawQuad* replica_quad =
5120 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5121 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5122 replica_quad->rect.ToString());
5123 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5124 replica_quad->mask_uv_rect.ToString());
5126 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5127 host_impl_->DidDrawAllLayers(frame);
5130 // Applying a DSF should change the render surface size, but won't affect
5131 // which part of the mask is used.
5132 device_scale_factor = 2.f;
5133 gfx::Size device_viewport =
5134 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5135 host_impl_->SetViewportSize(device_viewport);
5136 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5137 host_impl_->active_tree()->set_needs_update_draw_properties();
5139 LayerTreeHostImpl::FrameData frame;
5140 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5142 ASSERT_EQ(1u, frame.render_passes.size());
5143 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5144 ASSERT_EQ(DrawQuad::RENDER_PASS,
5145 frame.render_passes[0]->quad_list[1]->material);
5146 const RenderPassDrawQuad* replica_quad =
5147 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5148 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5149 replica_quad->rect.ToString());
5150 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5151 replica_quad->mask_uv_rect.ToString());
5153 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5154 host_impl_->DidDrawAllLayers(frame);
5157 // Applying an equivalent content scale on the content layer and the mask
5158 // should still result in the same part of the mask being used.
5159 gfx::Size layer_size_large =
5160 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5161 content_layer->SetContentBounds(layer_size_large);
5162 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5163 gfx::Size mask_size_large =
5164 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5165 mask_layer->SetContentBounds(mask_size_large);
5166 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5167 host_impl_->active_tree()->set_needs_update_draw_properties();
5169 LayerTreeHostImpl::FrameData frame;
5170 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5172 ASSERT_EQ(1u, frame.render_passes.size());
5173 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5174 ASSERT_EQ(DrawQuad::RENDER_PASS,
5175 frame.render_passes[0]->quad_list[1]->material);
5176 const RenderPassDrawQuad* replica_quad =
5177 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5178 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5179 replica_quad->rect.ToString());
5180 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5181 replica_quad->mask_uv_rect.ToString());
5183 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5184 host_impl_->DidDrawAllLayers(frame);
5187 // Applying a different contents scale to the mask layer means it will have
5188 // a larger texture, but it should use the same tex coords to cover the
5189 // layer it masks.
5190 mask_layer->SetContentBounds(mask_size);
5191 mask_layer->SetContentsScale(1.f, 1.f);
5192 host_impl_->active_tree()->set_needs_update_draw_properties();
5194 LayerTreeHostImpl::FrameData frame;
5195 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5197 ASSERT_EQ(1u, frame.render_passes.size());
5198 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5199 ASSERT_EQ(DrawQuad::RENDER_PASS,
5200 frame.render_passes[0]->quad_list[1]->material);
5201 const RenderPassDrawQuad* replica_quad =
5202 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5203 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5204 replica_quad->rect.ToString());
5205 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5206 replica_quad->mask_uv_rect.ToString());
5208 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5209 host_impl_->DidDrawAllLayers(frame);
5213 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
5214 // The replica is of a layer with bounds 50x50, but it has a child that causes
5215 // the surface bounds to be larger.
5217 scoped_ptr<LayerImpl> scoped_root =
5218 LayerImpl::Create(host_impl_->active_tree(), 1);
5219 LayerImpl* root = scoped_root.get();
5220 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5222 scoped_ptr<LayerImpl> scoped_content_layer =
5223 LayerImpl::Create(host_impl_->active_tree(), 2);
5224 LayerImpl* content_layer = scoped_content_layer.get();
5225 root->AddChild(scoped_content_layer.Pass());
5227 scoped_ptr<LayerImpl> scoped_content_child_layer =
5228 LayerImpl::Create(host_impl_->active_tree(), 3);
5229 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5230 content_layer->AddChild(scoped_content_child_layer.Pass());
5232 scoped_ptr<LayerImpl> scoped_replica_layer =
5233 LayerImpl::Create(host_impl_->active_tree(), 4);
5234 LayerImpl* replica_layer = scoped_replica_layer.get();
5235 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5237 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5238 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
5239 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5240 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5242 gfx::Size root_size(100, 100);
5243 root->SetBounds(root_size);
5244 root->SetContentBounds(root_size);
5245 root->SetPosition(gfx::PointF());
5247 gfx::Size layer_size(50, 50);
5248 content_layer->SetBounds(layer_size);
5249 content_layer->SetContentBounds(layer_size);
5250 content_layer->SetPosition(gfx::PointF());
5251 content_layer->SetDrawsContent(true);
5253 gfx::Size child_size(50, 50);
5254 content_child_layer->SetBounds(child_size);
5255 content_child_layer->SetContentBounds(child_size);
5256 content_child_layer->SetPosition(gfx::Point(50, 0));
5257 content_child_layer->SetDrawsContent(true);
5259 gfx::Size mask_size(50, 50);
5260 mask_layer->SetBounds(mask_size);
5261 mask_layer->SetContentBounds(mask_size);
5262 mask_layer->SetPosition(gfx::PointF());
5263 mask_layer->SetDrawsContent(true);
5265 float device_scale_factor = 1.f;
5266 host_impl_->SetViewportSize(root_size);
5267 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5269 LayerTreeHostImpl::FrameData frame;
5270 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5272 ASSERT_EQ(1u, frame.render_passes.size());
5273 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5275 // The surface is 100x50.
5276 ASSERT_EQ(DrawQuad::RENDER_PASS,
5277 frame.render_passes[0]->quad_list[0]->material);
5278 const RenderPassDrawQuad* render_pass_quad =
5279 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5280 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5281 render_pass_quad->rect.ToString());
5283 // The mask covers the owning layer only.
5284 ASSERT_EQ(DrawQuad::RENDER_PASS,
5285 frame.render_passes[0]->quad_list[1]->material);
5286 const RenderPassDrawQuad* replica_quad =
5287 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5288 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5289 replica_quad->rect.ToString());
5290 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
5291 replica_quad->mask_uv_rect.ToString());
5293 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5294 host_impl_->DidDrawAllLayers(frame);
5297 // Move the child to (-50, 0) instead. Now the mask should be moved to still
5298 // cover the layer being replicated.
5299 content_child_layer->SetPosition(gfx::Point(-50, 0));
5301 LayerTreeHostImpl::FrameData frame;
5302 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5304 ASSERT_EQ(1u, frame.render_passes.size());
5305 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5307 // The surface is 100x50 with its origin at (-50, 0).
5308 ASSERT_EQ(DrawQuad::RENDER_PASS,
5309 frame.render_passes[0]->quad_list[0]->material);
5310 const RenderPassDrawQuad* render_pass_quad =
5311 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5312 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5313 render_pass_quad->rect.ToString());
5315 // The mask covers the owning layer only.
5316 ASSERT_EQ(DrawQuad::RENDER_PASS,
5317 frame.render_passes[0]->quad_list[1]->material);
5318 const RenderPassDrawQuad* replica_quad =
5319 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5320 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5321 replica_quad->rect.ToString());
5322 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
5323 replica_quad->mask_uv_rect.ToString());
5325 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5326 host_impl_->DidDrawAllLayers(frame);
5330 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
5331 // The masked layer has bounds 50x50, but it has a child that causes
5332 // the surface bounds to be larger. It also has a parent that clips the
5333 // masked layer and its surface.
5335 scoped_ptr<LayerImpl> scoped_root =
5336 LayerImpl::Create(host_impl_->active_tree(), 1);
5337 LayerImpl* root = scoped_root.get();
5338 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5340 scoped_ptr<LayerImpl> scoped_clipping_layer =
5341 LayerImpl::Create(host_impl_->active_tree(), 2);
5342 LayerImpl* clipping_layer = scoped_clipping_layer.get();
5343 root->AddChild(scoped_clipping_layer.Pass());
5345 scoped_ptr<LayerImpl> scoped_content_layer =
5346 LayerImpl::Create(host_impl_->active_tree(), 3);
5347 LayerImpl* content_layer = scoped_content_layer.get();
5348 clipping_layer->AddChild(scoped_content_layer.Pass());
5350 scoped_ptr<LayerImpl> scoped_content_child_layer =
5351 LayerImpl::Create(host_impl_->active_tree(), 4);
5352 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5353 content_layer->AddChild(scoped_content_child_layer.Pass());
5355 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5356 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
5357 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5358 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5360 gfx::Size root_size(100, 100);
5361 root->SetBounds(root_size);
5362 root->SetContentBounds(root_size);
5363 root->SetPosition(gfx::PointF());
5365 gfx::Rect clipping_rect(20, 10, 10, 20);
5366 clipping_layer->SetBounds(clipping_rect.size());
5367 clipping_layer->SetContentBounds(clipping_rect.size());
5368 clipping_layer->SetPosition(clipping_rect.origin());
5369 clipping_layer->SetMasksToBounds(true);
5371 gfx::Size layer_size(50, 50);
5372 content_layer->SetBounds(layer_size);
5373 content_layer->SetContentBounds(layer_size);
5374 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
5375 content_layer->SetDrawsContent(true);
5377 gfx::Size child_size(50, 50);
5378 content_child_layer->SetBounds(child_size);
5379 content_child_layer->SetContentBounds(child_size);
5380 content_child_layer->SetPosition(gfx::Point(50, 0));
5381 content_child_layer->SetDrawsContent(true);
5383 gfx::Size mask_size(100, 100);
5384 mask_layer->SetBounds(mask_size);
5385 mask_layer->SetContentBounds(mask_size);
5386 mask_layer->SetPosition(gfx::PointF());
5387 mask_layer->SetDrawsContent(true);
5389 float device_scale_factor = 1.f;
5390 host_impl_->SetViewportSize(root_size);
5391 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5393 LayerTreeHostImpl::FrameData frame;
5394 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5396 ASSERT_EQ(1u, frame.render_passes.size());
5397 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5399 // The surface is clipped to 10x20.
5400 ASSERT_EQ(DrawQuad::RENDER_PASS,
5401 frame.render_passes[0]->quad_list[0]->material);
5402 const RenderPassDrawQuad* render_pass_quad =
5403 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5404 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
5405 render_pass_quad->rect.ToString());
5407 // The masked layer is 50x50, but the surface size is 10x20. So the texture
5408 // coords in the mask are scaled by 10/50 and 20/50.
5409 // The surface is clipped to (20,10) so the mask texture coords are offset
5410 // by 20/50 and 10/50
5411 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f),
5412 1.f / 50.f).ToString(),
5413 render_pass_quad->mask_uv_rect.ToString());
5415 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5416 host_impl_->DidDrawAllLayers(frame);
5420 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
5421 public:
5422 using GLRenderer::SetupQuadForAntialiasing;
5425 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
5426 // Due to precision issues (especially on Android), sometimes far
5427 // away quads can end up thinking they need AA.
5428 float device_scale_factor = 4.f / 3.f;
5429 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5430 gfx::Size root_size(2000, 1000);
5431 gfx::Size device_viewport_size =
5432 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
5433 host_impl_->SetViewportSize(device_viewport_size);
5435 host_impl_->CreatePendingTree();
5436 host_impl_->pending_tree()
5437 ->SetPageScaleFactorAndLimits(1.f, 1.f / 16.f, 16.f);
5439 scoped_ptr<LayerImpl> scoped_root =
5440 LayerImpl::Create(host_impl_->pending_tree(), 1);
5441 LayerImpl* root = scoped_root.get();
5443 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
5445 scoped_ptr<LayerImpl> scoped_scrolling_layer =
5446 LayerImpl::Create(host_impl_->pending_tree(), 2);
5447 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
5448 root->AddChild(scoped_scrolling_layer.Pass());
5450 gfx::Size content_layer_bounds(100000, 100);
5451 gfx::Size pile_tile_size(3000, 3000);
5452 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
5453 pile_tile_size, content_layer_bounds));
5455 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
5456 FakePictureLayerImpl::CreateWithPile(host_impl_->pending_tree(), 3, pile);
5457 LayerImpl* content_layer = scoped_content_layer.get();
5458 scrolling_layer->AddChild(scoped_content_layer.PassAs<LayerImpl>());
5459 content_layer->SetBounds(content_layer_bounds);
5460 content_layer->SetDrawsContent(true);
5462 root->SetBounds(root_size);
5464 gfx::Vector2d scroll_offset(100000, 0);
5465 scrolling_layer->SetScrollClipLayer(root->id());
5466 scrolling_layer->SetScrollOffset(scroll_offset);
5468 host_impl_->ActivateSyncTree();
5470 host_impl_->active_tree()->UpdateDrawProperties();
5471 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
5473 LayerTreeHostImpl::FrameData frame;
5474 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5476 ASSERT_EQ(1u, frame.render_passes.size());
5477 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
5478 const DrawQuad* quad = frame.render_passes[0]->quad_list[0];
5480 float edge[24];
5481 gfx::QuadF device_layer_quad;
5482 bool antialiased =
5483 GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
5484 quad->quadTransform(), quad, &device_layer_quad, edge);
5485 EXPECT_FALSE(antialiased);
5487 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5488 host_impl_->DidDrawAllLayers(frame);
5492 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
5493 public:
5494 CompositorFrameMetadataTest()
5495 : swap_buffers_complete_(0) {}
5497 virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {
5498 swap_buffers_complete_++;
5501 int swap_buffers_complete_;
5504 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
5505 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5507 LayerTreeHostImpl::FrameData frame;
5508 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5509 host_impl_->DrawLayers(&frame, base::TimeTicks());
5510 host_impl_->DidDrawAllLayers(frame);
5512 CompositorFrameAck ack;
5513 host_impl_->ReclaimResources(&ack);
5514 host_impl_->DidSwapBuffersComplete();
5515 EXPECT_EQ(swap_buffers_complete_, 1);
5518 class CountingSoftwareDevice : public SoftwareOutputDevice {
5519 public:
5520 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5522 virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
5523 ++frames_began_;
5524 return SoftwareOutputDevice::BeginPaint(damage_rect);
5526 virtual void EndPaint(SoftwareFrameData* frame_data) OVERRIDE {
5527 ++frames_ended_;
5528 SoftwareOutputDevice::EndPaint(frame_data);
5531 int frames_began_, frames_ended_;
5534 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
5535 // No main thread evictions in resourceless software mode.
5536 set_reduce_memory_result(false);
5537 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
5538 bool delegated_rendering = false;
5539 FakeOutputSurface* output_surface =
5540 FakeOutputSurface::CreateDeferredGL(
5541 scoped_ptr<SoftwareOutputDevice>(software_device),
5542 delegated_rendering).release();
5543 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5544 scoped_ptr<OutputSurface>(output_surface)));
5545 host_impl_->SetViewportSize(gfx::Size(50, 50));
5547 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5549 const gfx::Transform external_transform;
5550 const gfx::Rect external_viewport;
5551 const gfx::Rect external_clip;
5552 const bool resourceless_software_draw = true;
5553 host_impl_->SetExternalDrawConstraints(external_transform,
5554 external_viewport,
5555 external_clip,
5556 external_viewport,
5557 external_transform,
5558 resourceless_software_draw);
5560 EXPECT_EQ(0, software_device->frames_began_);
5561 EXPECT_EQ(0, software_device->frames_ended_);
5563 DrawFrame();
5565 EXPECT_EQ(1, software_device->frames_began_);
5566 EXPECT_EQ(1, software_device->frames_ended_);
5568 // Call other API methods that are likely to hit NULL pointer in this mode.
5569 EXPECT_TRUE(host_impl_->AsValue());
5570 EXPECT_TRUE(host_impl_->ActivationStateAsValue());
5573 TEST_F(LayerTreeHostImplTest,
5574 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
5575 set_reduce_memory_result(false);
5576 bool delegated_rendering = false;
5577 FakeOutputSurface* output_surface =
5578 FakeOutputSurface::CreateDeferredGL(
5579 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5580 delegated_rendering).release();
5581 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5582 scoped_ptr<OutputSurface>(output_surface)));
5584 const gfx::Transform external_transform;
5585 const gfx::Rect external_viewport;
5586 const gfx::Rect external_clip;
5587 const bool resourceless_software_draw = true;
5588 host_impl_->SetExternalDrawConstraints(external_transform,
5589 external_viewport,
5590 external_clip,
5591 external_viewport,
5592 external_transform,
5593 resourceless_software_draw);
5595 // SolidColorLayerImpl will be drawn.
5596 scoped_ptr<SolidColorLayerImpl> root_layer =
5597 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5599 // VideoLayerImpl will not be drawn.
5600 FakeVideoFrameProvider provider;
5601 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
5602 host_impl_->active_tree(), 2, &provider, media::VIDEO_ROTATION_0);
5603 video_layer->SetBounds(gfx::Size(10, 10));
5604 video_layer->SetContentBounds(gfx::Size(10, 10));
5605 video_layer->SetDrawsContent(true);
5606 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
5607 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5609 LayerTreeHostImpl::FrameData frame;
5610 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5611 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5612 host_impl_->DidDrawAllLayers(frame);
5614 EXPECT_EQ(1u, frame.will_draw_layers.size());
5615 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
5618 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
5619 protected:
5620 virtual void SetUp() OVERRIDE {
5621 LayerTreeHostImplTest::SetUp();
5623 set_reduce_memory_result(false);
5625 bool delegated_rendering = false;
5626 scoped_ptr<FakeOutputSurface> output_surface(
5627 FakeOutputSurface::CreateDeferredGL(
5628 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5629 delegated_rendering));
5630 output_surface_ = output_surface.get();
5632 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5633 output_surface.PassAs<OutputSurface>()));
5635 scoped_ptr<SolidColorLayerImpl> root_layer =
5636 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5637 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5639 onscreen_context_provider_ = TestContextProvider::Create();
5642 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {
5643 did_update_renderer_capabilities_ = true;
5646 FakeOutputSurface* output_surface_;
5647 scoped_refptr<TestContextProvider> onscreen_context_provider_;
5648 bool did_update_renderer_capabilities_;
5652 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
5653 // Software draw.
5654 DrawFrame();
5656 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5658 // DeferredInitialize and hardware draw.
5659 did_update_renderer_capabilities_ = false;
5660 EXPECT_TRUE(
5661 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5662 EXPECT_EQ(onscreen_context_provider_,
5663 host_impl_->output_surface()->context_provider());
5664 EXPECT_TRUE(did_update_renderer_capabilities_);
5666 // Defer intialized GL draw.
5667 DrawFrame();
5669 // Revert back to software.
5670 did_update_renderer_capabilities_ = false;
5671 output_surface_->ReleaseGL();
5672 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5673 EXPECT_TRUE(did_update_renderer_capabilities_);
5675 // Software draw again.
5676 DrawFrame();
5679 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails) {
5680 // Software draw.
5681 DrawFrame();
5683 // Fail initialization of the onscreen context before the OutputSurface binds
5684 // it to the thread.
5685 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5687 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5689 // DeferredInitialize fails.
5690 did_update_renderer_capabilities_ = false;
5691 EXPECT_FALSE(
5692 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5693 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5694 EXPECT_FALSE(did_update_renderer_capabilities_);
5696 // Software draw again.
5697 DrawFrame();
5700 // Checks that we have a non-0 default allocation if we pass a context that
5701 // doesn't support memory management extensions.
5702 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5703 LayerTreeSettings settings;
5704 host_impl_ = LayerTreeHostImpl::Create(settings,
5705 this,
5706 &proxy_,
5707 &stats_instrumentation_,
5708 shared_bitmap_manager_.get(),
5711 scoped_ptr<OutputSurface> output_surface(
5712 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5713 host_impl_->InitializeRenderer(output_surface.Pass());
5714 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5717 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5718 ManagedMemoryPolicy policy1(
5719 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5720 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5721 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5722 int allow_nice_to_have_cutoff_value =
5723 ManagedMemoryPolicy::PriorityCutoffToValue(
5724 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
5725 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5726 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5728 // GPU rasterization should be disabled by default on the tree(s)
5729 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
5730 EXPECT_TRUE(host_impl_->pending_tree() == NULL);
5732 host_impl_->SetVisible(true);
5733 host_impl_->SetMemoryPolicy(policy1);
5734 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5735 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5737 host_impl_->SetVisible(false);
5738 EXPECT_EQ(0u, current_limit_bytes_);
5739 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5741 host_impl_->SetVisible(true);
5742 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5743 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5745 // Now enable GPU rasterization and test if we get nice to have cutoff,
5746 // when visible.
5747 LayerTreeSettings settings;
5748 settings.gpu_rasterization_enabled = true;
5749 host_impl_ = LayerTreeHostImpl::Create(
5750 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
5751 host_impl_->SetUseGpuRasterization(true);
5752 host_impl_->SetVisible(true);
5753 host_impl_->SetMemoryPolicy(policy1);
5754 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5755 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
5757 host_impl_->SetVisible(false);
5758 EXPECT_EQ(0u, current_limit_bytes_);
5759 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5762 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
5763 ASSERT_TRUE(host_impl_->active_tree());
5765 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5766 host_impl_->SetVisible(false);
5767 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5768 host_impl_->SetVisible(true);
5769 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5770 host_impl_->SetVisible(false);
5771 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5773 host_impl_->CreatePendingTree();
5774 host_impl_->ActivateSyncTree();
5776 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5777 host_impl_->SetVisible(true);
5778 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5781 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
5782 ASSERT_TRUE(host_impl_->active_tree());
5783 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
5785 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5786 host_impl_->SetUseGpuRasterization(false);
5787 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5788 host_impl_->SetUseGpuRasterization(true);
5789 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5790 host_impl_->SetUseGpuRasterization(false);
5791 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5793 host_impl_->CreatePendingTree();
5794 host_impl_->ActivateSyncTree();
5796 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5797 host_impl_->SetUseGpuRasterization(true);
5798 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5801 class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
5802 public:
5803 virtual void SetUp() OVERRIDE {
5804 LayerTreeSettings settings;
5805 settings.impl_side_painting = true;
5807 fake_host_impl_ = new FakeLayerTreeHostImpl(
5808 settings, &proxy_, shared_bitmap_manager_.get());
5809 host_impl_.reset(fake_host_impl_);
5810 host_impl_->InitializeRenderer(CreateOutputSurface());
5811 host_impl_->SetViewportSize(gfx::Size(10, 10));
5814 FakeLayerTreeHostImpl* fake_host_impl_;
5817 TEST_F(LayerTreeHostImplTestManageTiles, ManageTilesWhenInvisible) {
5818 fake_host_impl_->DidModifyTilePriorities();
5819 EXPECT_TRUE(fake_host_impl_->manage_tiles_needed());
5820 fake_host_impl_->SetVisible(false);
5821 EXPECT_FALSE(fake_host_impl_->manage_tiles_needed());
5824 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
5825 scoped_ptr<TestWebGraphicsContext3D> context =
5826 TestWebGraphicsContext3D::Create();
5827 TestWebGraphicsContext3D* context3d = context.get();
5828 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5829 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5831 EXPECT_EQ(0u, context3d->NumTextures());
5833 UIResourceId ui_resource_id = 1;
5834 bool is_opaque = false;
5835 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
5836 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5837 EXPECT_EQ(1u, context3d->NumTextures());
5838 ResourceProvider::ResourceId id1 =
5839 host_impl_->ResourceIdForUIResource(ui_resource_id);
5840 EXPECT_NE(0u, id1);
5842 // Multiple requests with the same id is allowed. The previous texture is
5843 // deleted.
5844 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5845 EXPECT_EQ(1u, context3d->NumTextures());
5846 ResourceProvider::ResourceId id2 =
5847 host_impl_->ResourceIdForUIResource(ui_resource_id);
5848 EXPECT_NE(0u, id2);
5849 EXPECT_NE(id1, id2);
5851 // Deleting invalid UIResourceId is allowed and does not change state.
5852 host_impl_->DeleteUIResource(-1);
5853 EXPECT_EQ(1u, context3d->NumTextures());
5855 // Should return zero for invalid UIResourceId. Number of textures should
5856 // not change.
5857 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
5858 EXPECT_EQ(1u, context3d->NumTextures());
5860 host_impl_->DeleteUIResource(ui_resource_id);
5861 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
5862 EXPECT_EQ(0u, context3d->NumTextures());
5864 // Should not change state for multiple deletion on one UIResourceId
5865 host_impl_->DeleteUIResource(ui_resource_id);
5866 EXPECT_EQ(0u, context3d->NumTextures());
5869 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
5870 scoped_ptr<TestWebGraphicsContext3D> context =
5871 TestWebGraphicsContext3D::Create();
5872 TestWebGraphicsContext3D* context3d = context.get();
5873 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5874 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5876 EXPECT_EQ(0u, context3d->NumTextures());
5878 gfx::Size size(4, 4);
5879 // SkImageInfo has no support for ETC1. The |info| below contains the right
5880 // total pixel size for the bitmap but not the right height and width. The
5881 // correct width/height are passed directly to UIResourceBitmap.
5882 SkImageInfo info =
5883 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
5884 skia::RefPtr<SkPixelRef> pixel_ref =
5885 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
5886 pixel_ref->setImmutable();
5887 UIResourceBitmap bitmap(pixel_ref, size);
5888 UIResourceId ui_resource_id = 1;
5889 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5890 EXPECT_EQ(1u, context3d->NumTextures());
5891 ResourceProvider::ResourceId id1 =
5892 host_impl_->ResourceIdForUIResource(ui_resource_id);
5893 EXPECT_NE(0u, id1);
5896 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
5899 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
5900 scoped_refptr<TestContextProvider> context_provider =
5901 TestContextProvider::Create();
5903 CreateHostImpl(
5904 DefaultSettings(),
5905 FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>());
5907 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5909 ScopedPtrVector<CopyOutputRequest> requests;
5910 requests.push_back(CopyOutputRequest::CreateRequest(
5911 base::Bind(&ShutdownReleasesContext_Callback)));
5913 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
5915 LayerTreeHostImpl::FrameData frame;
5916 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5917 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5918 host_impl_->DidDrawAllLayers(frame);
5920 // The CopyOutputResult's callback has a ref on the ContextProvider and a
5921 // texture in a texture mailbox.
5922 EXPECT_FALSE(context_provider->HasOneRef());
5923 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
5925 host_impl_.reset();
5927 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
5928 // released, and the texture deleted.
5929 EXPECT_TRUE(context_provider->HasOneRef());
5930 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
5933 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
5934 // When flinging via touch, only the child should scroll (we should not
5935 // bubble).
5936 gfx::Size surface_size(10, 10);
5937 gfx::Size content_size(20, 20);
5938 scoped_ptr<LayerImpl> root_clip =
5939 LayerImpl::Create(host_impl_->active_tree(), 3);
5940 scoped_ptr<LayerImpl> root =
5941 CreateScrollableLayer(1, content_size, root_clip.get());
5942 root->SetIsContainerForFixedPositionLayers(true);
5943 scoped_ptr<LayerImpl> child =
5944 CreateScrollableLayer(2, content_size, root_clip.get());
5946 root->AddChild(child.Pass());
5947 int root_id = root->id();
5948 root_clip->AddChild(root.Pass());
5950 host_impl_->SetViewportSize(surface_size);
5951 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
5952 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
5953 host_impl_->active_tree()->DidBecomeActive();
5954 DrawFrame();
5956 EXPECT_EQ(InputHandler::ScrollStarted,
5957 host_impl_->ScrollBegin(gfx::Point(),
5958 InputHandler::Gesture));
5960 EXPECT_EQ(InputHandler::ScrollStarted,
5961 host_impl_->FlingScrollBegin());
5963 gfx::Vector2d scroll_delta(0, 100);
5964 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5965 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5967 host_impl_->ScrollEnd();
5969 scoped_ptr<ScrollAndScaleSet> scroll_info =
5970 host_impl_->ProcessScrollDeltas();
5972 // Only the child should have scrolled.
5973 ASSERT_EQ(1u, scroll_info->scrolls.size());
5974 ExpectNone(*scroll_info.get(), root_id);
5978 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
5979 // Scroll a child layer beyond its maximum scroll range and make sure the
5980 // the scroll doesn't bubble up to the parent layer.
5981 gfx::Size surface_size(10, 10);
5982 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
5983 scoped_ptr<LayerImpl> root_scrolling =
5984 CreateScrollableLayer(2, surface_size, root.get());
5986 scoped_ptr<LayerImpl> grand_child =
5987 CreateScrollableLayer(4, surface_size, root.get());
5988 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
5990 scoped_ptr<LayerImpl> child =
5991 CreateScrollableLayer(3, surface_size, root.get());
5992 child->SetScrollOffset(gfx::Vector2d(0, 4));
5993 child->AddChild(grand_child.Pass());
5995 root_scrolling->AddChild(child.Pass());
5996 root->AddChild(root_scrolling.Pass());
5997 host_impl_->active_tree()->SetRootLayer(root.Pass());
5998 host_impl_->active_tree()->DidBecomeActive();
5999 host_impl_->SetViewportSize(surface_size);
6000 DrawFrame();
6002 scoped_ptr<ScrollAndScaleSet> scroll_info;
6003 LayerImpl* child =
6004 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6005 LayerImpl* grand_child = child->children()[0];
6007 gfx::Vector2d scroll_delta(0, -2);
6008 EXPECT_EQ(InputHandler::ScrollStarted,
6009 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6010 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6012 // The grand child should have scrolled up to its limit.
6013 scroll_info = host_impl_->ProcessScrollDeltas();
6014 ASSERT_EQ(1u, scroll_info->scrolls.size());
6015 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6016 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6018 // The child should have received the bubbled delta, but the locked
6019 // scrolling layer should remain set as the grand child.
6020 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6021 scroll_info = host_impl_->ProcessScrollDeltas();
6022 ASSERT_EQ(2u, scroll_info->scrolls.size());
6023 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6024 ExpectContains(*scroll_info, child->id(), scroll_delta);
6025 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6027 // The first |ScrollBy| after the fling should re-lock the scrolling
6028 // layer to the first layer that scrolled, which is the child.
6029 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6030 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6031 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6033 // The child should have scrolled up to its limit.
6034 scroll_info = host_impl_->ProcessScrollDeltas();
6035 ASSERT_EQ(2u, scroll_info->scrolls.size());
6036 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6037 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
6039 // As the locked layer is at it's limit, no further scrolling can occur.
6040 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6041 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6042 host_impl_->ScrollEnd();
6046 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6047 // When flinging via wheel, the root should eventually scroll (we should
6048 // bubble).
6049 gfx::Size surface_size(10, 10);
6050 gfx::Size content_size(20, 20);
6051 scoped_ptr<LayerImpl> root_clip =
6052 LayerImpl::Create(host_impl_->active_tree(), 3);
6053 scoped_ptr<LayerImpl> root_scroll =
6054 CreateScrollableLayer(1, content_size, root_clip.get());
6055 int root_scroll_id = root_scroll->id();
6056 scoped_ptr<LayerImpl> child =
6057 CreateScrollableLayer(2, content_size, root_clip.get());
6059 root_scroll->AddChild(child.Pass());
6060 root_clip->AddChild(root_scroll.Pass());
6062 host_impl_->SetViewportSize(surface_size);
6063 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6064 host_impl_->active_tree()->DidBecomeActive();
6065 DrawFrame();
6067 EXPECT_EQ(InputHandler::ScrollStarted,
6068 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6070 EXPECT_EQ(InputHandler::ScrollStarted,
6071 host_impl_->FlingScrollBegin());
6073 gfx::Vector2d scroll_delta(0, 100);
6074 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6075 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6077 host_impl_->ScrollEnd();
6079 scoped_ptr<ScrollAndScaleSet> scroll_info =
6080 host_impl_->ProcessScrollDeltas();
6082 // The root should have scrolled.
6083 ASSERT_EQ(2u, scroll_info->scrolls.size());
6084 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
6088 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6089 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6090 // we should return ScrollUnknown.
6091 gfx::Size content_size(100, 100);
6092 SetupScrollAndContentsLayers(content_size);
6094 int scroll_layer_id = 2;
6095 LayerImpl* scroll_layer =
6096 host_impl_->active_tree()->LayerById(scroll_layer_id);
6097 scroll_layer->SetDrawsContent(true);
6099 int page_scale_layer_id = 5;
6100 LayerImpl* page_scale_layer =
6101 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6103 int occluder_layer_id = 6;
6104 scoped_ptr<LayerImpl> occluder_layer =
6105 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6106 occluder_layer->SetDrawsContent(true);
6107 occluder_layer->SetBounds(content_size);
6108 occluder_layer->SetContentBounds(content_size);
6109 occluder_layer->SetPosition(gfx::PointF());
6111 // The parent of the occluder is *above* the scroller.
6112 page_scale_layer->AddChild(occluder_layer.Pass());
6114 DrawFrame();
6116 EXPECT_EQ(InputHandler::ScrollUnknown,
6117 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6120 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6121 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6122 // is not the first scroller we encounter when walking up from the layer, we
6123 // should also return ScrollUnknown.
6124 gfx::Size content_size(100, 100);
6125 SetupScrollAndContentsLayers(content_size);
6127 int scroll_layer_id = 2;
6128 LayerImpl* scroll_layer =
6129 host_impl_->active_tree()->LayerById(scroll_layer_id);
6130 scroll_layer->SetDrawsContent(true);
6132 int occluder_layer_id = 6;
6133 scoped_ptr<LayerImpl> occluder_layer =
6134 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6135 occluder_layer->SetDrawsContent(true);
6136 occluder_layer->SetBounds(content_size);
6137 occluder_layer->SetContentBounds(content_size);
6138 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6140 int child_scroll_clip_layer_id = 7;
6141 scoped_ptr<LayerImpl> child_scroll_clip =
6142 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6144 int child_scroll_layer_id = 8;
6145 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6146 child_scroll_layer_id, content_size, child_scroll_clip.get());
6148 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6150 child_scroll->AddChild(occluder_layer.Pass());
6151 scroll_layer->AddChild(child_scroll.Pass());
6153 DrawFrame();
6155 EXPECT_EQ(InputHandler::ScrollUnknown,
6156 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6159 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) {
6160 gfx::Size content_size(100, 100);
6161 SetupScrollAndContentsLayers(content_size);
6163 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6165 int scroll_layer_id = 2;
6166 LayerImpl* scroll_layer =
6167 host_impl_->active_tree()->LayerById(scroll_layer_id);
6169 int child_scroll_layer_id = 7;
6170 scoped_ptr<LayerImpl> child_scroll =
6171 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6172 child_scroll->SetDrawsContent(false);
6174 scroll_layer->AddChild(child_scroll.Pass());
6176 DrawFrame();
6178 // We should not have scrolled |child_scroll| even though we technically "hit"
6179 // it. The reason for this is that if the scrolling the scroll would not move
6180 // any layer that is a drawn RSLL member, then we can ignore the hit.
6182 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6183 // overscrolling the inner viewport.
6184 EXPECT_EQ(InputHandler::ScrollStarted,
6185 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6187 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6190 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6191 // This test case is very similar to the one above with one key difference:
6192 // the invisible scroller has a scroll child that is indeed draw contents.
6193 // If we attempt to initiate a gesture scroll off of the visible scroll child
6194 // we should still start the scroll child.
6195 gfx::Size content_size(100, 100);
6196 SetupScrollAndContentsLayers(content_size);
6198 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6200 int scroll_layer_id = 2;
6201 LayerImpl* scroll_layer =
6202 host_impl_->active_tree()->LayerById(scroll_layer_id);
6204 int scroll_child_id = 6;
6205 scoped_ptr<LayerImpl> scroll_child =
6206 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6207 scroll_child->SetDrawsContent(true);
6208 scroll_child->SetBounds(content_size);
6209 scroll_child->SetContentBounds(content_size);
6210 // Move the scroll child so it's not hit by our test point.
6211 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6213 int invisible_scroll_layer_id = 7;
6214 scoped_ptr<LayerImpl> invisible_scroll =
6215 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6216 invisible_scroll->SetDrawsContent(false);
6218 int container_id = 8;
6219 scoped_ptr<LayerImpl> container =
6220 LayerImpl::Create(host_impl_->active_tree(), container_id);
6222 scoped_ptr<std::set<LayerImpl*> > scroll_children(new std::set<LayerImpl*>());
6223 scroll_children->insert(scroll_child.get());
6224 invisible_scroll->SetScrollChildren(scroll_children.release());
6226 scroll_child->SetScrollParent(invisible_scroll.get());
6228 container->AddChild(invisible_scroll.Pass());
6229 container->AddChild(scroll_child.Pass());
6231 scroll_layer->AddChild(container.Pass());
6233 DrawFrame();
6235 // We should not have scrolled |child_scroll| even though we technically "hit"
6236 // it. The reason for this is that if the scrolling the scroll would not move
6237 // any layer that is a drawn RSLL member, then we can ignore the hit.
6239 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6240 // overscrolling the inner viewport.
6241 EXPECT_EQ(InputHandler::ScrollStarted,
6242 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6244 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6247 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6248 // to CompositorFrameMetadata after SwapBuffers();
6249 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6250 scoped_ptr<SolidColorLayerImpl> root =
6251 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6252 root->SetPosition(gfx::PointF());
6253 root->SetBounds(gfx::Size(10, 10));
6254 root->SetContentBounds(gfx::Size(10, 10));
6255 root->SetDrawsContent(true);
6257 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
6259 FakeOutputSurface* fake_output_surface =
6260 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6262 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6263 fake_output_surface->last_sent_frame().metadata.latency_info;
6264 EXPECT_TRUE(metadata_latency_before.empty());
6266 ui::LatencyInfo latency_info;
6267 latency_info.AddLatencyNumber(
6268 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6269 scoped_ptr<SwapPromise> swap_promise(
6270 new LatencyInfoSwapPromise(latency_info));
6271 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
6272 host_impl_->SetNeedsRedraw();
6274 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6275 LayerTreeHostImpl::FrameData frame;
6276 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6277 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6278 host_impl_->DidDrawAllLayers(frame);
6279 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6281 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6282 fake_output_surface->last_sent_frame().metadata.latency_info;
6283 EXPECT_EQ(1u, metadata_latency_after.size());
6284 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6285 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6288 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
6289 int root_layer_id = 1;
6290 scoped_ptr<SolidColorLayerImpl> root =
6291 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
6292 root->SetPosition(gfx::PointF());
6293 root->SetBounds(gfx::Size(10, 10));
6294 root->SetContentBounds(gfx::Size(10, 10));
6295 root->SetDrawsContent(true);
6297 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
6299 // Ensure the default frame selection bounds are empty.
6300 FakeOutputSurface* fake_output_surface =
6301 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6302 const ViewportSelectionBound& selection_start_before =
6303 fake_output_surface->last_sent_frame().metadata.selection_start;
6304 const ViewportSelectionBound& selection_end_before =
6305 fake_output_surface->last_sent_frame().metadata.selection_end;
6306 EXPECT_EQ(ViewportSelectionBound(), selection_start_before);
6307 EXPECT_EQ(ViewportSelectionBound(), selection_end_before);
6309 // Plumb the layer-local selection bounds.
6310 gfx::Rect selection_rect(5, 0, 0, 5);
6311 LayerSelectionBound start, end;
6312 start.type = SELECTION_BOUND_CENTER;
6313 start.layer_id = root_layer_id;
6314 start.layer_rect = selection_rect;
6315 end = start;
6316 host_impl_->active_tree()->RegisterSelection(start, end);
6318 // Trigger a draw-swap sequence.
6319 host_impl_->SetNeedsRedraw();
6321 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6322 LayerTreeHostImpl::FrameData frame;
6323 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6324 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6325 host_impl_->DidDrawAllLayers(frame);
6326 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6328 // Ensure the selection bounds have propagated to the frame metadata.
6329 const ViewportSelectionBound& selection_start_after =
6330 fake_output_surface->last_sent_frame().metadata.selection_start;
6331 const ViewportSelectionBound& selection_end_after =
6332 fake_output_surface->last_sent_frame().metadata.selection_end;
6333 EXPECT_EQ(start.type, selection_start_after.type);
6334 EXPECT_EQ(end.type, selection_end_after.type);
6335 EXPECT_EQ(selection_rect, selection_start_after.viewport_rect);
6336 EXPECT_EQ(selection_rect, selection_start_after.viewport_rect);
6337 EXPECT_TRUE(selection_start_after.visible);
6338 EXPECT_TRUE(selection_start_after.visible);
6341 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
6342 public:
6343 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
6344 LayerTreeHostImpl* layer_tree_host_impl,
6345 int* set_needs_commit_count,
6346 int* set_needs_redraw_count,
6347 int* forward_to_main_count)
6348 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
6349 set_needs_commit_count_(set_needs_commit_count),
6350 set_needs_redraw_count_(set_needs_redraw_count),
6351 forward_to_main_count_(forward_to_main_count) {}
6353 virtual ~SimpleSwapPromiseMonitor() {}
6355 virtual void OnSetNeedsCommitOnMain() OVERRIDE {
6356 (*set_needs_commit_count_)++;
6359 virtual void OnSetNeedsRedrawOnImpl() OVERRIDE {
6360 (*set_needs_redraw_count_)++;
6363 virtual void OnForwardScrollUpdateToMainThreadOnImpl() OVERRIDE {
6364 (*forward_to_main_count_)++;
6367 private:
6368 int* set_needs_commit_count_;
6369 int* set_needs_redraw_count_;
6370 int* forward_to_main_count_;
6373 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
6374 int set_needs_commit_count = 0;
6375 int set_needs_redraw_count = 0;
6376 int forward_to_main_count = 0;
6379 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6380 new SimpleSwapPromiseMonitor(NULL,
6381 host_impl_.get(),
6382 &set_needs_commit_count,
6383 &set_needs_redraw_count,
6384 &forward_to_main_count));
6385 host_impl_->SetNeedsRedraw();
6386 EXPECT_EQ(0, set_needs_commit_count);
6387 EXPECT_EQ(1, set_needs_redraw_count);
6388 EXPECT_EQ(0, forward_to_main_count);
6391 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6392 // monitored.
6393 host_impl_->SetNeedsRedraw();
6394 EXPECT_EQ(0, set_needs_commit_count);
6395 EXPECT_EQ(1, set_needs_redraw_count);
6396 EXPECT_EQ(0, forward_to_main_count);
6399 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6400 new SimpleSwapPromiseMonitor(NULL,
6401 host_impl_.get(),
6402 &set_needs_commit_count,
6403 &set_needs_redraw_count,
6404 &forward_to_main_count));
6405 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
6406 EXPECT_EQ(0, set_needs_commit_count);
6407 EXPECT_EQ(2, set_needs_redraw_count);
6408 EXPECT_EQ(0, forward_to_main_count);
6412 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6413 new SimpleSwapPromiseMonitor(NULL,
6414 host_impl_.get(),
6415 &set_needs_commit_count,
6416 &set_needs_redraw_count,
6417 &forward_to_main_count));
6418 // Empty damage rect won't signal the monitor.
6419 host_impl_->SetNeedsRedrawRect(gfx::Rect());
6420 EXPECT_EQ(0, set_needs_commit_count);
6421 EXPECT_EQ(2, set_needs_redraw_count);
6422 EXPECT_EQ(0, forward_to_main_count);
6426 set_needs_commit_count = 0;
6427 set_needs_redraw_count = 0;
6428 forward_to_main_count = 0;
6429 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6430 new SimpleSwapPromiseMonitor(NULL,
6431 host_impl_.get(),
6432 &set_needs_commit_count,
6433 &set_needs_redraw_count,
6434 &forward_to_main_count));
6435 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
6437 // Scrolling normally should not trigger any forwarding.
6438 EXPECT_EQ(InputHandler::ScrollStarted,
6439 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6440 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
6441 host_impl_->ScrollEnd();
6443 EXPECT_EQ(0, set_needs_commit_count);
6444 EXPECT_EQ(1, set_needs_redraw_count);
6445 EXPECT_EQ(0, forward_to_main_count);
6447 // Scrolling with a scroll handler should defer the swap to the main
6448 // thread.
6449 scroll_layer->SetHaveScrollEventHandlers(true);
6450 EXPECT_EQ(InputHandler::ScrollStarted,
6451 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6452 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
6453 host_impl_->ScrollEnd();
6455 EXPECT_EQ(0, set_needs_commit_count);
6456 EXPECT_EQ(2, set_needs_redraw_count);
6457 EXPECT_EQ(1, forward_to_main_count);
6461 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
6462 public:
6463 virtual void SetUp() OVERRIDE {
6464 LayerTreeSettings settings = DefaultSettings();
6465 settings.calculate_top_controls_position = true;
6466 settings.top_controls_height = top_controls_height_;
6467 CreateHostImpl(settings, CreateOutputSurface());
6470 protected:
6471 static const int top_controls_height_;
6474 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
6476 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
6477 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6478 ->SetScrollOffset(gfx::Vector2d(0, 10));
6479 host_impl_->Animate(base::TimeTicks());
6480 EXPECT_FALSE(did_request_redraw_);
6483 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
6484 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6485 ->SetScrollOffset(gfx::Vector2d(0, 10));
6486 host_impl_->DidChangeTopControlsPosition();
6487 EXPECT_TRUE(did_request_animate_);
6488 EXPECT_TRUE(did_request_redraw_);
6491 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
6492 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6493 host_impl_->SetViewportSize(gfx::Size(100, 100));
6494 DrawFrame();
6496 EXPECT_EQ(InputHandler::ScrollStarted,
6497 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6498 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6499 EXPECT_EQ(gfx::Vector2dF().ToString(),
6500 scroll_layer->TotalScrollOffset().ToString());
6502 // Scroll just the top controls and verify that the scroll succeeds.
6503 const float residue = 10;
6504 float offset = top_controls_height_ - residue;
6505 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6506 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->controls_top_offset());
6507 EXPECT_EQ(gfx::Vector2dF().ToString(),
6508 scroll_layer->TotalScrollOffset().ToString());
6510 // Scroll across the boundary
6511 const float content_scroll = 20;
6512 offset = residue + content_scroll;
6513 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6514 EXPECT_EQ(-top_controls_height_,
6515 host_impl_->top_controls_manager()->controls_top_offset());
6516 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
6517 scroll_layer->TotalScrollOffset().ToString());
6519 // Now scroll back to the top of the content
6520 offset = -content_scroll;
6521 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6522 EXPECT_EQ(-top_controls_height_,
6523 host_impl_->top_controls_manager()->controls_top_offset());
6524 EXPECT_EQ(gfx::Vector2dF().ToString(),
6525 scroll_layer->TotalScrollOffset().ToString());
6527 // And scroll the top controls completely into view
6528 offset = -top_controls_height_;
6529 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6530 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6531 EXPECT_EQ(gfx::Vector2dF().ToString(),
6532 scroll_layer->TotalScrollOffset().ToString());
6534 // And attempt to scroll past the end
6535 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6536 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6537 EXPECT_EQ(gfx::Vector2dF().ToString(),
6538 scroll_layer->TotalScrollOffset().ToString());
6540 host_impl_->ScrollEnd();
6543 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
6544 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6545 host_impl_->SetViewportSize(gfx::Size(100, 200));
6546 DrawFrame();
6548 EXPECT_EQ(InputHandler::ScrollStarted,
6549 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6550 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6551 EXPECT_EQ(gfx::Vector2dF().ToString(),
6552 scroll_layer->TotalScrollOffset().ToString());
6554 // Scroll the top controls partially.
6555 const float residue = 35;
6556 float offset = top_controls_height_ - residue;
6557 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6558 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->controls_top_offset());
6559 EXPECT_EQ(gfx::Vector2dF().ToString(),
6560 scroll_layer->TotalScrollOffset().ToString());
6562 did_request_redraw_ = false;
6563 did_request_animate_ = false;
6564 did_request_commit_ = false;
6566 // End the scroll while the controls are still offset from their limit.
6567 host_impl_->ScrollEnd();
6568 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
6569 EXPECT_TRUE(did_request_animate_);
6570 EXPECT_TRUE(did_request_redraw_);
6571 EXPECT_FALSE(did_request_commit_);
6573 // The top controls should properly animate until finished, despite the scroll
6574 // offset being at the origin.
6575 base::TimeTicks animation_time = gfx::FrameTime::Now();
6576 while (did_request_animate_) {
6577 did_request_redraw_ = false;
6578 did_request_animate_ = false;
6579 did_request_commit_ = false;
6581 float old_offset =
6582 host_impl_->top_controls_manager()->controls_top_offset();
6584 animation_time += base::TimeDelta::FromMilliseconds(5);
6585 host_impl_->Animate(animation_time);
6586 EXPECT_EQ(gfx::Vector2dF().ToString(),
6587 scroll_layer->TotalScrollOffset().ToString());
6589 float new_offset =
6590 host_impl_->top_controls_manager()->controls_top_offset();
6592 // No commit is needed as the controls are animating the content offset,
6593 // not the scroll offset.
6594 EXPECT_FALSE(did_request_commit_);
6596 if (new_offset != old_offset)
6597 EXPECT_TRUE(did_request_redraw_);
6599 if (new_offset != 0) {
6600 EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
6601 EXPECT_TRUE(did_request_animate_);
6604 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
6607 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
6608 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6609 host_impl_->SetViewportSize(gfx::Size(100, 100));
6610 float initial_scroll_offset = 50;
6611 scroll_layer->SetScrollOffset(gfx::Vector2d(0, initial_scroll_offset));
6612 DrawFrame();
6614 EXPECT_EQ(InputHandler::ScrollStarted,
6615 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6616 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6617 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
6618 scroll_layer->TotalScrollOffset().ToString());
6620 // Scroll the top controls partially.
6621 const float residue = 15;
6622 float offset = top_controls_height_ - residue;
6623 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6624 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->controls_top_offset());
6625 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
6626 scroll_layer->TotalScrollOffset().ToString());
6628 did_request_redraw_ = false;
6629 did_request_animate_ = false;
6630 did_request_commit_ = false;
6632 // End the scroll while the controls are still offset from the limit.
6633 host_impl_->ScrollEnd();
6634 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
6635 EXPECT_TRUE(did_request_animate_);
6636 EXPECT_TRUE(did_request_redraw_);
6637 EXPECT_FALSE(did_request_commit_);
6639 // Animate the top controls to the limit.
6640 base::TimeTicks animation_time = gfx::FrameTime::Now();
6641 while (did_request_animate_) {
6642 did_request_redraw_ = false;
6643 did_request_animate_ = false;
6644 did_request_commit_ = false;
6646 float old_offset =
6647 host_impl_->top_controls_manager()->controls_top_offset();
6649 animation_time += base::TimeDelta::FromMilliseconds(5);
6650 host_impl_->Animate(animation_time);
6652 float new_offset =
6653 host_impl_->top_controls_manager()->controls_top_offset();
6655 if (new_offset != old_offset) {
6656 EXPECT_TRUE(did_request_redraw_);
6657 EXPECT_TRUE(did_request_commit_);
6660 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
6663 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
6664 public:
6665 void SetupVirtualViewportLayers(const gfx::Size& content_size,
6666 const gfx::Size& outer_viewport,
6667 const gfx::Size& inner_viewport) {
6668 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
6669 const int kOuterViewportClipLayerId = 6;
6670 const int kOuterViewportScrollLayerId = 7;
6671 const int kInnerViewportScrollLayerId = 2;
6672 const int kInnerViewportClipLayerId = 4;
6673 const int kPageScaleLayerId = 5;
6675 scoped_ptr<LayerImpl> inner_scroll =
6676 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
6677 inner_scroll->SetIsContainerForFixedPositionLayers(true);
6678 inner_scroll->SetScrollOffset(gfx::Vector2d());
6680 scoped_ptr<LayerImpl> inner_clip =
6681 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
6682 inner_clip->SetBounds(inner_viewport);
6684 scoped_ptr<LayerImpl> page_scale =
6685 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
6687 inner_scroll->SetScrollClipLayer(inner_clip->id());
6688 inner_scroll->SetBounds(outer_viewport);
6689 inner_scroll->SetContentBounds(outer_viewport);
6690 inner_scroll->SetPosition(gfx::PointF());
6692 scoped_ptr<LayerImpl> outer_clip =
6693 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
6694 outer_clip->SetBounds(outer_viewport);
6695 outer_clip->SetIsContainerForFixedPositionLayers(true);
6697 scoped_ptr<LayerImpl> outer_scroll =
6698 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
6699 outer_scroll->SetScrollClipLayer(outer_clip->id());
6700 outer_scroll->SetScrollOffset(gfx::Vector2d());
6701 outer_scroll->SetBounds(content_size);
6702 outer_scroll->SetContentBounds(content_size);
6703 outer_scroll->SetPosition(gfx::PointF());
6705 scoped_ptr<LayerImpl> contents =
6706 LayerImpl::Create(layer_tree_impl, 8);
6707 contents->SetDrawsContent(true);
6708 contents->SetBounds(content_size);
6709 contents->SetContentBounds(content_size);
6710 contents->SetPosition(gfx::PointF());
6712 outer_scroll->AddChild(contents.Pass());
6713 outer_clip->AddChild(outer_scroll.Pass());
6714 inner_scroll->AddChild(outer_clip.Pass());
6715 page_scale->AddChild(inner_scroll.Pass());
6716 inner_clip->AddChild(page_scale.Pass());
6718 layer_tree_impl->SetRootLayer(inner_clip.Pass());
6719 layer_tree_impl->SetViewportLayersFromIds(kPageScaleLayerId,
6720 kInnerViewportScrollLayerId, kOuterViewportScrollLayerId);
6722 host_impl_->active_tree()->DidBecomeActive();
6726 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
6727 gfx::Size content_size = gfx::Size(100, 160);
6728 gfx::Size outer_viewport = gfx::Size(50, 80);
6729 gfx::Size inner_viewport = gfx::Size(25, 40);
6731 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
6733 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
6734 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
6735 DrawFrame();
6737 gfx::Vector2dF inner_expected;
6738 gfx::Vector2dF outer_expected;
6739 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6740 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6742 // Make sure the fling goes to the outer viewport first
6743 EXPECT_EQ(InputHandler::ScrollStarted,
6744 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6745 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6747 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
6748 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6749 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6751 host_impl_->ScrollEnd();
6753 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6754 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6756 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
6757 EXPECT_EQ(InputHandler::ScrollStarted,
6758 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6759 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6761 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6762 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6764 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6765 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6767 host_impl_->ScrollEnd();
6769 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6770 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6774 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
6775 public:
6776 virtual void SetUp() OVERRIDE {
6777 LayerTreeSettings settings = DefaultSettings();
6778 settings.max_memory_for_prepaint_percentage = 50;
6779 CreateHostImpl(settings, CreateOutputSurface());
6783 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
6784 // Set up a memory policy and percentages which could cause
6785 // 32-bit integer overflows.
6786 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
6788 // Verify implicit limits are calculated correctly with no overflows
6789 host_impl_->SetMemoryPolicy(mem_policy);
6790 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
6791 300u * 1024u * 1024u);
6792 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
6793 150u * 1024u * 1024u);
6796 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
6797 const gfx::Size layer_size(100, 100);
6798 gfx::Transform external_transform;
6799 const gfx::Rect external_viewport(layer_size);
6800 const gfx::Rect external_clip(layer_size);
6801 const bool resourceless_software_draw = false;
6802 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
6804 host_impl_->SetExternalDrawConstraints(external_transform,
6805 external_viewport,
6806 external_clip,
6807 external_viewport,
6808 external_transform,
6809 resourceless_software_draw);
6810 DrawFrame();
6811 EXPECT_TRANSFORMATION_MATRIX_EQ(
6812 external_transform, layer->draw_properties().target_space_transform);
6814 external_transform.Translate(20, 20);
6815 host_impl_->SetExternalDrawConstraints(external_transform,
6816 external_viewport,
6817 external_clip,
6818 external_viewport,
6819 external_transform,
6820 resourceless_software_draw);
6821 DrawFrame();
6822 EXPECT_TRANSFORMATION_MATRIX_EQ(
6823 external_transform, layer->draw_properties().target_space_transform);
6826 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
6827 SetupScrollAndContentsLayers(gfx::Size(100, 200));
6828 DrawFrame();
6830 base::TimeTicks start_time =
6831 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
6833 EXPECT_EQ(InputHandler::ScrollStarted,
6834 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
6836 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
6838 host_impl_->Animate(start_time);
6839 host_impl_->UpdateAnimationState(true);
6841 EXPECT_EQ(gfx::Vector2dF(), scrolling_layer->TotalScrollOffset());
6843 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
6844 host_impl_->UpdateAnimationState(true);
6846 float y = scrolling_layer->TotalScrollOffset().y();
6847 EXPECT_TRUE(y > 1 && y < 49);
6849 // Update target.
6850 EXPECT_EQ(InputHandler::ScrollStarted,
6851 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
6853 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
6854 host_impl_->UpdateAnimationState(true);
6856 y = scrolling_layer->TotalScrollOffset().y();
6857 EXPECT_TRUE(y > 50 && y < 100);
6858 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
6860 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
6861 host_impl_->UpdateAnimationState(true);
6863 EXPECT_EQ(gfx::Vector2dF(0, 100), scrolling_layer->TotalScrollOffset());
6864 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
6867 TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairs) {
6868 host_impl_->CreatePendingTree();
6869 host_impl_->ActivateSyncTree();
6870 host_impl_->CreatePendingTree();
6872 LayerTreeImpl* active_tree = host_impl_->active_tree();
6873 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
6874 EXPECT_NE(active_tree, pending_tree);
6876 scoped_ptr<FakePictureLayerImpl> active_layer =
6877 FakePictureLayerImpl::Create(active_tree, 10);
6878 scoped_ptr<FakePictureLayerImpl> pending_layer =
6879 FakePictureLayerImpl::Create(pending_tree, 10);
6881 std::vector<PictureLayerImpl::Pair> layer_pairs;
6882 host_impl_->GetPictureLayerImplPairs(&layer_pairs);
6884 EXPECT_EQ(2u, layer_pairs.size());
6885 if (layer_pairs[0].active) {
6886 EXPECT_EQ(active_layer.get(), layer_pairs[0].active);
6887 EXPECT_EQ(NULL, layer_pairs[0].pending);
6888 } else {
6889 EXPECT_EQ(pending_layer.get(), layer_pairs[0].pending);
6890 EXPECT_EQ(NULL, layer_pairs[0].active);
6893 if (layer_pairs[1].active) {
6894 EXPECT_EQ(active_layer.get(), layer_pairs[1].active);
6895 EXPECT_EQ(NULL, layer_pairs[1].pending);
6896 } else {
6897 EXPECT_EQ(pending_layer.get(), layer_pairs[1].pending);
6898 EXPECT_EQ(NULL, layer_pairs[1].active);
6901 active_layer->set_twin_layer(pending_layer.get());
6902 pending_layer->set_twin_layer(active_layer.get());
6904 layer_pairs.clear();
6905 host_impl_->GetPictureLayerImplPairs(&layer_pairs);
6906 EXPECT_EQ(1u, layer_pairs.size());
6908 EXPECT_EQ(active_layer.get(), layer_pairs[0].active);
6909 EXPECT_EQ(pending_layer.get(), layer_pairs[0].pending);
6912 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
6913 host_impl_->CreatePendingTree();
6914 host_impl_->ActivateSyncTree();
6915 host_impl_->CreatePendingTree();
6917 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
6919 scoped_ptr<FakePictureLayerImpl> pending_layer =
6920 FakePictureLayerImpl::Create(pending_tree, 10);
6921 pending_layer->DoPostCommitInitializationIfNeeded();
6922 FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
6923 pending_tree->SetRootLayer(pending_layer.PassAs<LayerImpl>());
6924 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
6926 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
6927 pending_tree->DidBecomeActive();
6928 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
6930 scoped_ptr<FakePictureLayerImpl> mask_layer =
6931 FakePictureLayerImpl::Create(pending_tree, 11);
6932 mask_layer->DoPostCommitInitializationIfNeeded();
6933 FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
6934 raw_pending_layer->SetMaskLayer(mask_layer.PassAs<LayerImpl>());
6935 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
6937 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
6938 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
6939 pending_tree->DidBecomeActive();
6940 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
6941 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
6943 scoped_ptr<FakePictureLayerImpl> replica_layer =
6944 FakePictureLayerImpl::Create(pending_tree, 12);
6945 scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
6946 FakePictureLayerImpl::Create(pending_tree, 13);
6947 replica_mask_layer->DoPostCommitInitializationIfNeeded();
6948 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
6949 replica_layer->SetMaskLayer(replica_mask_layer.PassAs<LayerImpl>());
6950 raw_pending_layer->SetReplicaLayer(replica_layer.PassAs<LayerImpl>());
6951 ASSERT_EQ(raw_replica_mask_layer,
6952 raw_pending_layer->replica_layer()->mask_layer());
6954 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
6955 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
6956 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
6957 pending_tree->DidBecomeActive();
6958 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
6959 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
6960 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
6963 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
6964 public:
6965 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
6966 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {
6967 num_lost_surfaces_++;
6970 protected:
6971 int num_lost_surfaces_;
6974 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
6975 // The medium term, we plan to remove LayerTreeHostImpl::IsContextLost().
6976 // Until then, we need the state variable
6977 // LayerTreeHostImpl::have_valid_output_surface_ and we can
6978 // enforce the following behaviour, where calling DidLoseOutputSurface
6979 // twice in a row only causes one subsequent
6980 // call to LayerTreeHostImplClient::DidLoseOutputSurfaceOnImplThread().
6981 // Really we just need at least one client notification each time
6982 // we go from having a valid output surface to not having a valid output
6983 // surface.
6984 EXPECT_EQ(0, num_lost_surfaces_);
6985 EXPECT_FALSE(host_impl_->IsContextLost());
6986 host_impl_->DidLoseOutputSurface();
6987 EXPECT_TRUE(host_impl_->IsContextLost());
6988 EXPECT_EQ(1, num_lost_surfaces_);
6989 host_impl_->DidLoseOutputSurface();
6990 EXPECT_TRUE(host_impl_->IsContextLost());
6991 EXPECT_EQ(1, num_lost_surfaces_);
6994 } // namespace
6995 } // namespace cc