Factor out a BluetoothChannelMac base class and a BluetoothRfcommChannelMac subclass.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blob45d533b5fb883c173067cdc4d549d793a819fb77
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/quad_sink.h"
24 #include "cc/layers/render_surface_impl.h"
25 #include "cc/layers/solid_color_layer_impl.h"
26 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
27 #include "cc/layers/texture_layer_impl.h"
28 #include "cc/layers/tiled_layer_impl.h"
29 #include "cc/layers/video_layer_impl.h"
30 #include "cc/output/begin_frame_args.h"
31 #include "cc/output/compositor_frame_ack.h"
32 #include "cc/output/compositor_frame_metadata.h"
33 #include "cc/output/copy_output_request.h"
34 #include "cc/output/copy_output_result.h"
35 #include "cc/output/gl_renderer.h"
36 #include "cc/quads/render_pass_draw_quad.h"
37 #include "cc/quads/solid_color_draw_quad.h"
38 #include "cc/quads/texture_draw_quad.h"
39 #include "cc/quads/tile_draw_quad.h"
40 #include "cc/resources/layer_tiling_data.h"
41 #include "cc/test/animation_test_common.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 always_impl_thread_(&proxy_),
82 always_main_thread_blocked_(&proxy_),
83 shared_bitmap_manager_(new TestSharedBitmapManager()),
84 on_can_draw_state_changed_called_(false),
85 did_notify_ready_to_activate_(false),
86 did_request_commit_(false),
87 did_request_redraw_(false),
88 did_request_animate_(false),
89 did_request_manage_tiles_(false),
90 did_upload_visible_tile_(false),
91 reduce_memory_result_(true),
92 current_limit_bytes_(0),
93 current_priority_cutoff_value_(0) {
94 media::InitializeMediaLibraryForTesting();
97 LayerTreeSettings DefaultSettings() {
98 LayerTreeSettings settings;
99 settings.minimum_occlusion_tracking_size = gfx::Size();
100 settings.impl_side_painting = true;
101 settings.texture_id_allocation_chunk_size = 1;
102 settings.report_overscroll_only_for_scrollable_axes = true;
103 return settings;
106 virtual void SetUp() OVERRIDE {
107 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
110 virtual void TearDown() OVERRIDE {}
112 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {}
113 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
114 virtual void CommitVSyncParameters(base::TimeTicks timebase,
115 base::TimeDelta interval) OVERRIDE {}
116 virtual void SetEstimatedParentDrawTime(base::TimeDelta draw_time) OVERRIDE {}
117 virtual void SetMaxSwapsPendingOnImplThread(int max) OVERRIDE {}
118 virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
119 virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {}
120 virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {}
121 virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
122 on_can_draw_state_changed_called_ = true;
124 virtual void NotifyReadyToActivate() OVERRIDE {
125 did_notify_ready_to_activate_ = true;
126 host_impl_->ActivatePendingTree();
128 virtual void SetNeedsRedrawOnImplThread() OVERRIDE {
129 did_request_redraw_ = true;
131 virtual void SetNeedsRedrawRectOnImplThread(
132 const gfx::Rect& damage_rect) OVERRIDE {
133 did_request_redraw_ = true;
135 virtual void SetNeedsAnimateOnImplThread() OVERRIDE {
136 did_request_animate_ = true;
138 virtual void SetNeedsManageTilesOnImplThread() OVERRIDE {
139 did_request_manage_tiles_ = true;
141 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {
142 did_upload_visible_tile_ = true;
144 virtual void SetNeedsCommitOnImplThread() OVERRIDE {
145 did_request_commit_ = true;
147 virtual void PostAnimationEventsToMainThreadOnImplThread(
148 scoped_ptr<AnimationEventsVector> events) OVERRIDE {}
149 virtual bool ReduceContentsTextureMemoryOnImplThread(
150 size_t limit_bytes, int priority_cutoff) OVERRIDE {
151 current_limit_bytes_ = limit_bytes;
152 current_priority_cutoff_value_ = priority_cutoff;
153 return reduce_memory_result_;
155 virtual void SendManagedMemoryStats() OVERRIDE {}
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 DidActivatePendingTree() 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::ScrollIgnored,
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, MasksToBoundsDoesntClobberInnerContainerSize) {
977 SetupScrollAndContentsLayers(gfx::Size(100, 100));
978 host_impl_->SetViewportSize(gfx::Size(50, 50));
979 DrawFrame();
981 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
982 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
983 DCHECK(scroll_layer);
985 float min_page_scale = 1.f;
986 float max_page_scale = 4.f;
987 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
988 min_page_scale,
989 max_page_scale);
991 // If the container's masks_to_bounds is false, the viewport size should
992 // overwrite the inner viewport container layer's size.
994 EXPECT_EQ(gfx::Size(50, 50),
995 container_layer->bounds());
996 container_layer->SetMasksToBounds(false);
998 container_layer->SetBounds(gfx::Size(30, 25));
999 EXPECT_EQ(gfx::Size(30, 25),
1000 container_layer->bounds());
1002 // This should cause a reset of the inner viewport container layer's bounds.
1003 host_impl_->DidChangeTopControlsPosition();
1005 EXPECT_EQ(gfx::Size(50, 50),
1006 container_layer->bounds());
1009 host_impl_->SetViewportSize(gfx::Size(50, 50));
1010 container_layer->SetBounds(gfx::Size(50, 50));
1012 // If the container's masks_to_bounds is true, the viewport size should
1013 // *NOT* overwrite the inner viewport container layer's size.
1015 EXPECT_EQ(gfx::Size(50, 50),
1016 container_layer->bounds());
1017 container_layer->SetMasksToBounds(true);
1019 container_layer->SetBounds(gfx::Size(30, 25));
1020 EXPECT_EQ(gfx::Size(30, 25),
1021 container_layer->bounds());
1023 // This should cause a reset of the inner viewport container layer's bounds.
1024 host_impl_->DidChangeTopControlsPosition();
1026 EXPECT_EQ(gfx::Size(30, 25),
1027 container_layer->bounds());
1031 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1032 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1033 host_impl_->SetViewportSize(gfx::Size(50, 50));
1034 DrawFrame();
1036 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1037 DCHECK(scroll_layer);
1039 float min_page_scale = 1.f;
1040 float max_page_scale = 4.f;
1042 // Basic pinch zoom in gesture
1044 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1045 min_page_scale,
1046 max_page_scale);
1047 scroll_layer->SetScrollDelta(gfx::Vector2d());
1049 float page_scale_delta = 2.f;
1050 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1051 host_impl_->PinchGestureBegin();
1052 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1053 host_impl_->PinchGestureEnd();
1054 host_impl_->ScrollEnd();
1055 EXPECT_FALSE(did_request_animate_);
1056 EXPECT_TRUE(did_request_redraw_);
1057 EXPECT_TRUE(did_request_commit_);
1059 scoped_ptr<ScrollAndScaleSet> scroll_info =
1060 host_impl_->ProcessScrollDeltas();
1061 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1064 // Zoom-in clamping
1066 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1067 min_page_scale,
1068 max_page_scale);
1069 scroll_layer->SetScrollDelta(gfx::Vector2d());
1070 float page_scale_delta = 10.f;
1072 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1073 host_impl_->PinchGestureBegin();
1074 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1075 host_impl_->PinchGestureEnd();
1076 host_impl_->ScrollEnd();
1078 scoped_ptr<ScrollAndScaleSet> scroll_info =
1079 host_impl_->ProcessScrollDeltas();
1080 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1083 // Zoom-out clamping
1085 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1086 min_page_scale,
1087 max_page_scale);
1088 scroll_layer->SetScrollDelta(gfx::Vector2d());
1089 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1091 float page_scale_delta = 0.1f;
1092 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1093 host_impl_->PinchGestureBegin();
1094 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1095 host_impl_->PinchGestureEnd();
1096 host_impl_->ScrollEnd();
1098 scoped_ptr<ScrollAndScaleSet> scroll_info =
1099 host_impl_->ProcessScrollDeltas();
1100 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1102 EXPECT_TRUE(scroll_info->scrolls.empty());
1105 // Two-finger panning should not happen based on pinch events only
1107 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1108 min_page_scale,
1109 max_page_scale);
1110 scroll_layer->SetScrollDelta(gfx::Vector2d());
1111 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1113 float page_scale_delta = 1.f;
1114 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1115 host_impl_->PinchGestureBegin();
1116 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1117 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1118 host_impl_->PinchGestureEnd();
1119 host_impl_->ScrollEnd();
1121 scoped_ptr<ScrollAndScaleSet> scroll_info =
1122 host_impl_->ProcessScrollDeltas();
1123 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1124 EXPECT_TRUE(scroll_info->scrolls.empty());
1127 // Two-finger panning should work with interleaved scroll events
1129 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1130 min_page_scale,
1131 max_page_scale);
1132 scroll_layer->SetScrollDelta(gfx::Vector2d());
1133 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1135 float page_scale_delta = 1.f;
1136 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1137 host_impl_->PinchGestureBegin();
1138 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1139 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1140 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1141 host_impl_->PinchGestureEnd();
1142 host_impl_->ScrollEnd();
1144 scoped_ptr<ScrollAndScaleSet> scroll_info =
1145 host_impl_->ProcessScrollDeltas();
1146 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1147 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1150 // Two-finger panning should work when starting fully zoomed out.
1152 host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
1153 0.5f,
1154 4.f);
1155 scroll_layer->SetScrollDelta(gfx::Vector2d());
1156 scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
1158 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
1159 host_impl_->PinchGestureBegin();
1160 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1161 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1162 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1163 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1164 host_impl_->PinchGestureEnd();
1165 host_impl_->ScrollEnd();
1167 scoped_ptr<ScrollAndScaleSet> scroll_info =
1168 host_impl_->ProcessScrollDeltas();
1169 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1170 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1174 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1175 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1176 host_impl_->SetViewportSize(gfx::Size(50, 50));
1177 DrawFrame();
1179 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1180 DCHECK(scroll_layer);
1182 float min_page_scale = 0.5f;
1183 float max_page_scale = 4.f;
1184 base::TimeTicks start_time = base::TimeTicks() +
1185 base::TimeDelta::FromSeconds(1);
1186 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1187 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1188 base::TimeTicks end_time = start_time + duration;
1190 // Non-anchor zoom-in
1192 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1193 min_page_scale,
1194 max_page_scale);
1195 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1197 did_request_redraw_ = false;
1198 did_request_animate_ = false;
1199 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), false, 2.f, duration);
1200 EXPECT_FALSE(did_request_redraw_);
1201 EXPECT_TRUE(did_request_animate_);
1203 did_request_redraw_ = false;
1204 did_request_animate_ = false;
1205 host_impl_->Animate(start_time);
1206 EXPECT_TRUE(did_request_redraw_);
1207 EXPECT_TRUE(did_request_animate_);
1209 did_request_redraw_ = false;
1210 did_request_animate_ = false;
1211 host_impl_->Animate(halfway_through_animation);
1212 EXPECT_TRUE(did_request_redraw_);
1213 EXPECT_TRUE(did_request_animate_);
1215 did_request_redraw_ = false;
1216 did_request_animate_ = false;
1217 did_request_commit_ = false;
1218 host_impl_->Animate(end_time);
1219 EXPECT_TRUE(did_request_commit_);
1220 EXPECT_FALSE(did_request_animate_);
1222 scoped_ptr<ScrollAndScaleSet> scroll_info =
1223 host_impl_->ProcessScrollDeltas();
1224 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1225 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1228 // Anchor zoom-out
1230 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1231 min_page_scale,
1232 max_page_scale);
1233 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1235 did_request_redraw_ = false;
1236 did_request_animate_ = false;
1237 host_impl_->StartPageScaleAnimation(
1238 gfx::Vector2d(25, 25), true, min_page_scale, duration);
1239 EXPECT_FALSE(did_request_redraw_);
1240 EXPECT_TRUE(did_request_animate_);
1242 did_request_redraw_ = false;
1243 did_request_animate_ = false;
1244 host_impl_->Animate(start_time);
1245 EXPECT_TRUE(did_request_redraw_);
1246 EXPECT_TRUE(did_request_animate_);
1248 did_request_redraw_ = false;
1249 did_request_commit_ = false;
1250 did_request_animate_ = false;
1251 host_impl_->Animate(end_time);
1252 EXPECT_TRUE(did_request_redraw_);
1253 EXPECT_FALSE(did_request_animate_);
1254 EXPECT_TRUE(did_request_commit_);
1256 scoped_ptr<ScrollAndScaleSet> scroll_info =
1257 host_impl_->ProcessScrollDeltas();
1258 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1259 // Pushed to (0,0) via clamping against contents layer size.
1260 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1264 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1265 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1266 host_impl_->SetViewportSize(gfx::Size(50, 50));
1267 DrawFrame();
1269 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1270 DCHECK(scroll_layer);
1272 float min_page_scale = 0.5f;
1273 float max_page_scale = 4.f;
1274 base::TimeTicks start_time = base::TimeTicks() +
1275 base::TimeDelta::FromSeconds(1);
1276 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1277 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1278 base::TimeTicks end_time = start_time + duration;
1280 // Anchor zoom with unchanged page scale should not change scroll or scale.
1282 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1283 min_page_scale,
1284 max_page_scale);
1285 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1287 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), true, 1.f, duration);
1288 host_impl_->Animate(start_time);
1289 host_impl_->Animate(halfway_through_animation);
1290 EXPECT_TRUE(did_request_redraw_);
1291 host_impl_->Animate(end_time);
1292 EXPECT_TRUE(did_request_commit_);
1294 scoped_ptr<ScrollAndScaleSet> scroll_info =
1295 host_impl_->ProcessScrollDeltas();
1296 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1297 ExpectNone(*scroll_info, scroll_layer->id());
1301 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1302 public:
1303 LayerTreeHostImplOverridePhysicalTime(
1304 const LayerTreeSettings& settings,
1305 LayerTreeHostImplClient* client,
1306 Proxy* proxy,
1307 SharedBitmapManager* manager,
1308 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1309 : LayerTreeHostImpl(settings,
1310 client,
1311 proxy,
1312 rendering_stats_instrumentation,
1313 manager,
1314 0) {}
1316 virtual base::TimeTicks CurrentFrameTimeTicks() OVERRIDE {
1317 return fake_current_physical_time_;
1320 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1321 fake_current_physical_time_ = fake_now;
1324 private:
1325 base::TimeTicks fake_current_physical_time_;
1328 #define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST() \
1329 gfx::Size viewport_size(10, 10); \
1330 gfx::Size content_size(100, 100); \
1332 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = \
1333 new LayerTreeHostImplOverridePhysicalTime(settings, \
1334 this, \
1335 &proxy_, \
1336 shared_bitmap_manager_.get(), \
1337 &stats_instrumentation_); \
1338 host_impl_ = make_scoped_ptr(host_impl_override_time); \
1339 host_impl_->InitializeRenderer(CreateOutputSurface()); \
1340 host_impl_->SetViewportSize(viewport_size); \
1342 scoped_ptr<LayerImpl> root = \
1343 LayerImpl::Create(host_impl_->active_tree(), 1); \
1344 root->SetBounds(viewport_size); \
1346 scoped_ptr<LayerImpl> scroll = \
1347 LayerImpl::Create(host_impl_->active_tree(), 2); \
1348 scroll->SetScrollClipLayer(root->id()); \
1349 scroll->SetScrollOffset(gfx::Vector2d()); \
1350 root->SetBounds(viewport_size); \
1351 scroll->SetBounds(content_size); \
1352 scroll->SetContentBounds(content_size); \
1353 scroll->SetIsContainerForFixedPositionLayers(true); \
1355 scoped_ptr<LayerImpl> contents = \
1356 LayerImpl::Create(host_impl_->active_tree(), 3); \
1357 contents->SetDrawsContent(true); \
1358 contents->SetBounds(content_size); \
1359 contents->SetContentBounds(content_size); \
1361 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = \
1362 SolidColorScrollbarLayerImpl::Create( \
1363 host_impl_->active_tree(), 4, VERTICAL, 10, 0, false, true); \
1364 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); \
1365 scrollbar->SetScrollLayerById(2); \
1366 scrollbar->SetClipLayerById(1); \
1368 scroll->AddChild(contents.Pass()); \
1369 root->AddChild(scroll.Pass()); \
1370 root->AddChild(scrollbar.PassAs<LayerImpl>()); \
1372 host_impl_->active_tree()->SetRootLayer(root.Pass()); \
1373 host_impl_->active_tree()->SetViewportLayersFromIds( \
1374 1, 2, Layer::INVALID_ID); \
1375 host_impl_->active_tree()->DidBecomeActive(); \
1376 DrawFrame();
1378 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1379 LayerTreeSettings settings;
1380 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1381 settings.scrollbar_fade_delay_ms = 20;
1382 settings.scrollbar_fade_duration_ms = 20;
1384 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1386 base::TimeTicks fake_now = gfx::FrameTime::Now();
1388 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1389 EXPECT_FALSE(did_request_redraw_);
1391 // If no scroll happened during a scroll gesture, it should have no effect.
1392 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1393 host_impl_->ScrollEnd();
1394 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1395 EXPECT_FALSE(did_request_redraw_);
1396 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1398 // After a scroll, a fade animation should be scheduled about 20ms from now.
1399 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1400 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1401 host_impl_->ScrollEnd();
1402 did_request_redraw_ = false;
1403 did_request_animate_ = false;
1404 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1405 requested_scrollbar_animation_delay_);
1406 EXPECT_FALSE(did_request_redraw_);
1407 EXPECT_FALSE(did_request_animate_);
1408 requested_scrollbar_animation_delay_ = base::TimeDelta();
1409 scrollbar_fade_start_.Run();
1410 host_impl_->Animate(fake_now);
1412 // After the fade begins, we should start getting redraws instead of a
1413 // scheduled animation.
1414 fake_now += base::TimeDelta::FromMilliseconds(25);
1415 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1416 EXPECT_TRUE(did_request_animate_);
1417 did_request_animate_ = false;
1419 // Setting the scroll offset outside a scroll should also cause the scrollbar
1420 // to appear and to schedule a fade.
1421 host_impl_->InnerViewportScrollLayer()->SetScrollOffset(gfx::Vector2d(5, 5));
1422 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1423 requested_scrollbar_animation_delay_);
1424 EXPECT_FALSE(did_request_redraw_);
1425 EXPECT_FALSE(did_request_animate_);
1426 requested_scrollbar_animation_delay_ = base::TimeDelta();
1429 TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) {
1430 LayerTreeSettings settings;
1431 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1432 settings.scrollbar_fade_delay_ms = 20;
1433 settings.scrollbar_fade_duration_ms = 20;
1434 settings.use_pinch_zoom_scrollbars = true;
1436 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1438 base::TimeTicks fake_now = gfx::FrameTime::Now();
1440 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
1442 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1443 EXPECT_FALSE(did_request_animate_);
1445 // If no scroll happened during a scroll gesture, it should have no effect.
1446 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1447 host_impl_->ScrollEnd();
1448 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1449 EXPECT_FALSE(did_request_animate_);
1450 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1452 // After a scroll, no fade animation should be scheduled.
1453 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1454 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1455 host_impl_->ScrollEnd();
1456 did_request_redraw_ = false;
1457 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1458 EXPECT_FALSE(did_request_animate_);
1459 requested_scrollbar_animation_delay_ = base::TimeDelta();
1461 // We should not see any draw requests.
1462 fake_now += base::TimeDelta::FromMilliseconds(25);
1463 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1464 EXPECT_FALSE(did_request_animate_);
1466 // Make page scale > min so that subsequent scrolls will trigger fades.
1467 host_impl_->active_tree()->SetPageScaleDelta(1.1f);
1469 // After a scroll, a fade animation should be scheduled about 20ms from now.
1470 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1471 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1472 host_impl_->ScrollEnd();
1473 did_request_redraw_ = false;
1474 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1475 requested_scrollbar_animation_delay_);
1476 EXPECT_FALSE(did_request_animate_);
1477 requested_scrollbar_animation_delay_ = base::TimeDelta();
1478 scrollbar_fade_start_.Run();
1480 // After the fade begins, we should start getting redraws instead of a
1481 // scheduled animation.
1482 fake_now += base::TimeDelta::FromMilliseconds(25);
1483 host_impl_->Animate(fake_now);
1484 EXPECT_TRUE(did_request_animate_);
1487 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1488 float device_scale_factor) {
1489 LayerTreeSettings settings;
1490 settings.scrollbar_fade_delay_ms = 500;
1491 settings.scrollbar_fade_duration_ms = 300;
1492 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1494 gfx::Size viewport_size(300, 200);
1495 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1496 gfx::ScaleSize(viewport_size, device_scale_factor));
1497 gfx::Size content_size(1000, 1000);
1499 CreateHostImpl(settings, CreateOutputSurface());
1500 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1501 host_impl_->SetViewportSize(device_viewport_size);
1503 scoped_ptr<LayerImpl> root =
1504 LayerImpl::Create(host_impl_->active_tree(), 1);
1505 root->SetBounds(viewport_size);
1507 scoped_ptr<LayerImpl> scroll =
1508 LayerImpl::Create(host_impl_->active_tree(), 2);
1509 scroll->SetScrollClipLayer(root->id());
1510 scroll->SetScrollOffset(gfx::Vector2d());
1511 scroll->SetBounds(content_size);
1512 scroll->SetContentBounds(content_size);
1513 scroll->SetIsContainerForFixedPositionLayers(true);
1515 scoped_ptr<LayerImpl> contents =
1516 LayerImpl::Create(host_impl_->active_tree(), 3);
1517 contents->SetDrawsContent(true);
1518 contents->SetBounds(content_size);
1519 contents->SetContentBounds(content_size);
1521 // The scrollbar is on the right side.
1522 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1523 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1524 scrollbar->SetDrawsContent(true);
1525 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1526 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1527 scrollbar->SetPosition(gfx::Point(285, 0));
1528 scrollbar->SetClipLayerById(1);
1529 scrollbar->SetScrollLayerById(2);
1531 scroll->AddChild(contents.Pass());
1532 root->AddChild(scroll.Pass());
1533 root->AddChild(scrollbar.PassAs<LayerImpl>());
1535 host_impl_->active_tree()->SetRootLayer(root.Pass());
1536 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
1537 host_impl_->active_tree()->DidBecomeActive();
1538 DrawFrame();
1540 LayerImpl* root_scroll =
1541 host_impl_->active_tree()->InnerViewportScrollLayer();
1542 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1543 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1544 static_cast<ScrollbarAnimationControllerThinning*>(
1545 root_scroll->scrollbar_animation_controller());
1546 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1548 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1549 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1551 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1552 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1554 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1555 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1557 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1558 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1559 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1561 did_request_redraw_ = false;
1562 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1563 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1564 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1565 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1566 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1567 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1568 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1571 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1572 SetupMouseMoveAtWithDeviceScale(1.f);
1575 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1576 SetupMouseMoveAtWithDeviceScale(2.f);
1579 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1580 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1581 host_impl_->SetViewportSize(gfx::Size(50, 50));
1582 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
1583 DrawFrame();
1585 CompositorFrameMetadata metadata =
1586 host_impl_->MakeCompositorFrameMetadata();
1587 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1588 EXPECT_EQ(1.f, metadata.page_scale_factor);
1589 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.viewport_size);
1590 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1591 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1592 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1595 // Scrolling should update metadata immediately.
1596 EXPECT_EQ(InputHandler::ScrollStarted,
1597 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1598 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1600 CompositorFrameMetadata metadata =
1601 host_impl_->MakeCompositorFrameMetadata();
1602 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1604 host_impl_->ScrollEnd();
1606 CompositorFrameMetadata metadata =
1607 host_impl_->MakeCompositorFrameMetadata();
1608 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1611 // Page scale should update metadata correctly (shrinking only the viewport).
1612 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1613 host_impl_->PinchGestureBegin();
1614 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1615 host_impl_->PinchGestureEnd();
1616 host_impl_->ScrollEnd();
1618 CompositorFrameMetadata metadata =
1619 host_impl_->MakeCompositorFrameMetadata();
1620 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1621 EXPECT_EQ(2.f, metadata.page_scale_factor);
1622 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.viewport_size);
1623 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1624 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1625 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1628 // Likewise if set from the main thread.
1629 host_impl_->ProcessScrollDeltas();
1630 host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
1631 host_impl_->active_tree()->SetPageScaleDelta(1.f);
1633 CompositorFrameMetadata metadata =
1634 host_impl_->MakeCompositorFrameMetadata();
1635 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1636 EXPECT_EQ(4.f, metadata.page_scale_factor);
1637 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.viewport_size);
1638 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1639 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1640 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1644 // TODO(enne): Convert this to PictureLayerImpl
1645 class DidDrawCheckLayer : public TiledLayerImpl {
1646 public:
1647 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1648 return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(tree_impl, id));
1651 virtual bool WillDraw(DrawMode draw_mode, ResourceProvider* provider)
1652 OVERRIDE {
1653 will_draw_called_ = true;
1654 if (will_draw_returns_false_)
1655 return false;
1656 return TiledLayerImpl::WillDraw(draw_mode, provider);
1659 virtual void AppendQuads(QuadSink* quad_sink,
1660 AppendQuadsData* append_quads_data) OVERRIDE {
1661 append_quads_called_ = true;
1662 TiledLayerImpl::AppendQuads(quad_sink, append_quads_data);
1665 virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
1666 did_draw_called_ = true;
1667 TiledLayerImpl::DidDraw(provider);
1670 bool will_draw_called() const { return will_draw_called_; }
1671 bool append_quads_called() const { return append_quads_called_; }
1672 bool did_draw_called() const { return did_draw_called_; }
1674 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1676 void ClearDidDrawCheck() {
1677 will_draw_called_ = false;
1678 append_quads_called_ = false;
1679 did_draw_called_ = false;
1682 protected:
1683 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1684 : TiledLayerImpl(tree_impl, id),
1685 will_draw_returns_false_(false),
1686 will_draw_called_(false),
1687 append_quads_called_(false),
1688 did_draw_called_(false) {
1689 SetBounds(gfx::Size(10, 10));
1690 SetContentBounds(gfx::Size(10, 10));
1691 SetDrawsContent(true);
1692 set_skips_draw(false);
1693 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1695 scoped_ptr<LayerTilingData> tiler =
1696 LayerTilingData::Create(gfx::Size(100, 100),
1697 LayerTilingData::HAS_BORDER_TEXELS);
1698 tiler->SetTilingRect(gfx::Rect(content_bounds()));
1699 SetTilingData(*tiler.get());
1702 private:
1703 bool will_draw_returns_false_;
1704 bool will_draw_called_;
1705 bool append_quads_called_;
1706 bool did_draw_called_;
1709 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1710 // The root layer is always drawn, so run this test on a child layer that
1711 // will be masked out by the root layer's bounds.
1712 host_impl_->active_tree()->SetRootLayer(
1713 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1714 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1715 host_impl_->active_tree()->root_layer());
1717 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1718 DidDrawCheckLayer* layer =
1719 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1722 LayerTreeHostImpl::FrameData frame;
1723 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1724 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1725 host_impl_->DidDrawAllLayers(frame);
1727 EXPECT_TRUE(layer->will_draw_called());
1728 EXPECT_TRUE(layer->append_quads_called());
1729 EXPECT_TRUE(layer->did_draw_called());
1732 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
1735 LayerTreeHostImpl::FrameData frame;
1737 layer->set_will_draw_returns_false();
1738 layer->ClearDidDrawCheck();
1740 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1741 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1742 host_impl_->DidDrawAllLayers(frame);
1744 EXPECT_TRUE(layer->will_draw_called());
1745 EXPECT_FALSE(layer->append_quads_called());
1746 EXPECT_FALSE(layer->did_draw_called());
1750 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1751 // The root layer is always drawn, so run this test on a child layer that
1752 // will be masked out by the root layer's bounds.
1753 host_impl_->active_tree()->SetRootLayer(
1754 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1755 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1756 host_impl_->active_tree()->root_layer());
1757 root->SetMasksToBounds(true);
1759 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1760 DidDrawCheckLayer* layer =
1761 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1762 // Ensure visible_content_rect for layer is empty.
1763 layer->SetPosition(gfx::PointF(100.f, 100.f));
1764 layer->SetBounds(gfx::Size(10, 10));
1765 layer->SetContentBounds(gfx::Size(10, 10));
1767 LayerTreeHostImpl::FrameData frame;
1769 EXPECT_FALSE(layer->will_draw_called());
1770 EXPECT_FALSE(layer->did_draw_called());
1772 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1773 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1774 host_impl_->DidDrawAllLayers(frame);
1776 EXPECT_FALSE(layer->will_draw_called());
1777 EXPECT_FALSE(layer->did_draw_called());
1779 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1781 // Ensure visible_content_rect for layer is not empty
1782 layer->SetPosition(gfx::PointF());
1784 EXPECT_FALSE(layer->will_draw_called());
1785 EXPECT_FALSE(layer->did_draw_called());
1787 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1788 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1789 host_impl_->DidDrawAllLayers(frame);
1791 EXPECT_TRUE(layer->will_draw_called());
1792 EXPECT_TRUE(layer->did_draw_called());
1794 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1797 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1798 gfx::Size big_size(1000, 1000);
1799 host_impl_->SetViewportSize(big_size);
1801 host_impl_->active_tree()->SetRootLayer(
1802 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1803 DidDrawCheckLayer* root =
1804 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1806 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1807 DidDrawCheckLayer* occluded_layer =
1808 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1810 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1811 DidDrawCheckLayer* top_layer =
1812 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1813 // This layer covers the occluded_layer above. Make this layer large so it can
1814 // occlude.
1815 top_layer->SetBounds(big_size);
1816 top_layer->SetContentBounds(big_size);
1817 top_layer->SetContentsOpaque(true);
1819 LayerTreeHostImpl::FrameData frame;
1821 EXPECT_FALSE(occluded_layer->will_draw_called());
1822 EXPECT_FALSE(occluded_layer->did_draw_called());
1823 EXPECT_FALSE(top_layer->will_draw_called());
1824 EXPECT_FALSE(top_layer->did_draw_called());
1826 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1827 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1828 host_impl_->DidDrawAllLayers(frame);
1830 EXPECT_FALSE(occluded_layer->will_draw_called());
1831 EXPECT_FALSE(occluded_layer->did_draw_called());
1832 EXPECT_TRUE(top_layer->will_draw_called());
1833 EXPECT_TRUE(top_layer->did_draw_called());
1836 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1837 host_impl_->active_tree()->SetRootLayer(
1838 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1839 DidDrawCheckLayer* root =
1840 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1842 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1843 DidDrawCheckLayer* layer1 =
1844 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1846 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1847 DidDrawCheckLayer* layer2 =
1848 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1850 layer1->SetOpacity(0.3f);
1851 layer1->SetShouldFlattenTransform(true);
1853 EXPECT_FALSE(root->did_draw_called());
1854 EXPECT_FALSE(layer1->did_draw_called());
1855 EXPECT_FALSE(layer2->did_draw_called());
1857 LayerTreeHostImpl::FrameData frame;
1858 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1859 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1860 host_impl_->DidDrawAllLayers(frame);
1862 EXPECT_TRUE(root->did_draw_called());
1863 EXPECT_TRUE(layer1->did_draw_called());
1864 EXPECT_TRUE(layer2->did_draw_called());
1866 EXPECT_NE(root->render_surface(), layer1->render_surface());
1867 EXPECT_TRUE(!!layer1->render_surface());
1870 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1871 public:
1872 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1873 int id,
1874 bool tile_missing,
1875 bool skips_draw,
1876 bool animating,
1877 ResourceProvider* resource_provider) {
1878 return scoped_ptr<LayerImpl>(new MissingTextureAnimatingLayer(
1879 tree_impl,
1881 tile_missing,
1882 skips_draw,
1883 animating,
1884 resource_provider));
1887 virtual void AppendQuads(QuadSink* quad_sink,
1888 AppendQuadsData* append_quads_data) OVERRIDE {
1889 TiledLayerImpl::AppendQuads(quad_sink, append_quads_data);
1890 if (tile_missing_)
1891 append_quads_data->had_incomplete_tile = true;
1894 private:
1895 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1896 int id,
1897 bool tile_missing,
1898 bool skips_draw,
1899 bool animating,
1900 ResourceProvider* resource_provider)
1901 : DidDrawCheckLayer(tree_impl, id), tile_missing_(tile_missing) {
1902 scoped_ptr<LayerTilingData> tiling_data =
1903 LayerTilingData::Create(gfx::Size(10, 10),
1904 LayerTilingData::NO_BORDER_TEXELS);
1905 tiling_data->SetTilingRect(gfx::Rect(bounds()));
1906 SetTilingData(*tiling_data.get());
1907 set_skips_draw(skips_draw);
1908 if (!tile_missing) {
1909 ResourceProvider::ResourceId resource =
1910 resource_provider->CreateResource(gfx::Size(1, 1),
1911 GL_CLAMP_TO_EDGE,
1912 ResourceProvider::TextureUsageAny,
1913 RGBA_8888);
1914 resource_provider->AllocateForTesting(resource);
1915 PushTileProperties(0, 0, resource, gfx::Rect(), false);
1917 if (animating)
1918 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1921 bool tile_missing_;
1924 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenNoTexturesMissing) {
1925 host_impl_->active_tree()->SetRootLayer(
1926 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1927 DidDrawCheckLayer* root =
1928 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1930 bool tile_missing = false;
1931 bool skips_draw = false;
1932 bool is_animating = false;
1933 root->AddChild(
1934 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1936 tile_missing,
1937 skips_draw,
1938 is_animating,
1939 host_impl_->resource_provider()));
1941 LayerTreeHostImpl::FrameData frame;
1943 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1944 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1945 host_impl_->DidDrawAllLayers(frame);
1948 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) {
1949 host_impl_->active_tree()->SetRootLayer(
1950 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1951 DidDrawCheckLayer* root =
1952 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1953 bool tile_missing = false;
1954 bool skips_draw = false;
1955 bool is_animating = true;
1956 root->AddChild(
1957 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1959 tile_missing,
1960 skips_draw,
1961 is_animating,
1962 host_impl_->resource_provider()));
1964 LayerTreeHostImpl::FrameData frame;
1966 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1967 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1968 host_impl_->DidDrawAllLayers(frame);
1971 TEST_F(LayerTreeHostImplTest,
1972 PrepareToDrawSucceedsWithNonAnimatedMissingTexture) {
1973 // When a texture is missing and we're not animating, we draw as usual with
1974 // checkerboarding.
1975 host_impl_->active_tree()->SetRootLayer(
1976 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1977 DidDrawCheckLayer* root =
1978 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1980 bool tile_missing = true;
1981 bool skips_draw = false;
1982 bool is_animating = false;
1983 root->AddChild(
1984 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1986 tile_missing,
1987 skips_draw,
1988 is_animating,
1989 host_impl_->resource_provider()));
1990 LayerTreeHostImpl::FrameData frame;
1991 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1992 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1993 host_impl_->DidDrawAllLayers(frame);
1996 TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
1997 // When a texture is missing and we're animating, we don't want to draw
1998 // anything.
1999 host_impl_->active_tree()->SetRootLayer(
2000 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
2001 DidDrawCheckLayer* root =
2002 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2003 bool tile_missing = true;
2004 bool skips_draw = false;
2005 bool is_animating = true;
2006 root->AddChild(
2007 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2009 tile_missing,
2010 skips_draw,
2011 is_animating,
2012 host_impl_->resource_provider()));
2013 LayerTreeHostImpl::FrameData frame;
2014 EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS,
2015 host_impl_->PrepareToDraw(&frame));
2016 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2017 host_impl_->DidDrawAllLayers(frame);
2020 TEST_F(LayerTreeHostImplTest,
2021 PrepareToDrawSucceedsWithMissingSkippedAnimatedLayer) {
2022 // When the layer skips draw and we're animating, we still draw the frame.
2023 host_impl_->active_tree()->SetRootLayer(
2024 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2025 DidDrawCheckLayer* root =
2026 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2027 bool tile_missing = false;
2028 bool skips_draw = true;
2029 bool is_animating = true;
2030 root->AddChild(
2031 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2033 tile_missing,
2034 skips_draw,
2035 is_animating,
2036 host_impl_->resource_provider()));
2037 LayerTreeHostImpl::FrameData frame;
2038 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2039 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2040 host_impl_->DidDrawAllLayers(frame);
2043 TEST_F(LayerTreeHostImplTest,
2044 PrepareToDrawSucceedsWhenHighResRequiredButNoMissingTextures) {
2045 // When the layer skips draw and we're animating, we still draw the frame.
2046 host_impl_->active_tree()->SetRootLayer(
2047 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2048 DidDrawCheckLayer* root =
2049 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2050 bool tile_missing = false;
2051 bool skips_draw = false;
2052 bool is_animating = false;
2053 root->AddChild(
2054 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2056 tile_missing,
2057 skips_draw,
2058 is_animating,
2059 host_impl_->resource_provider()));
2060 host_impl_->active_tree()->SetRequiresHighResToDraw();
2061 LayerTreeHostImpl::FrameData frame;
2062 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2063 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2064 host_impl_->DidDrawAllLayers(frame);
2067 TEST_F(LayerTreeHostImplTest,
2068 PrepareToDrawFailsWhenHighResRequiredAndMissingTextures) {
2069 // When the layer skips draw and we're animating, we still draw the frame.
2070 host_impl_->active_tree()->SetRootLayer(
2071 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2072 DidDrawCheckLayer* root =
2073 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2074 bool tile_missing = true;
2075 bool skips_draw = false;
2076 bool is_animating = false;
2077 root->AddChild(
2078 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2080 tile_missing,
2081 skips_draw,
2082 is_animating,
2083 host_impl_->resource_provider()));
2084 host_impl_->active_tree()->SetRequiresHighResToDraw();
2085 LayerTreeHostImpl::FrameData frame;
2086 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2087 host_impl_->PrepareToDraw(&frame));
2088 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2089 host_impl_->DidDrawAllLayers(frame);
2092 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2093 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2094 root->SetScrollClipLayer(Layer::INVALID_ID);
2095 host_impl_->active_tree()->SetRootLayer(root.Pass());
2096 DrawFrame();
2098 // Scroll event is ignored because layer is not scrollable.
2099 EXPECT_EQ(InputHandler::ScrollIgnored,
2100 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2101 EXPECT_FALSE(did_request_redraw_);
2102 EXPECT_FALSE(did_request_commit_);
2105 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2106 public:
2107 LayerTreeHostImplTopControlsTest()
2108 // Make the clip size the same as the layer (content) size so the layer is
2109 // non-scrollable.
2110 : layer_size_(10, 10),
2111 clip_size_(layer_size_) {
2112 settings_.calculate_top_controls_position = true;
2113 settings_.top_controls_height = 50;
2115 viewport_size_ =
2116 gfx::Size(clip_size_.width(),
2117 clip_size_.height() + settings_.top_controls_height);
2120 void SetupTopControlsAndScrollLayer() {
2121 CreateHostImpl(settings_, CreateOutputSurface());
2123 scoped_ptr<LayerImpl> root =
2124 LayerImpl::Create(host_impl_->active_tree(), 1);
2125 scoped_ptr<LayerImpl> root_clip =
2126 LayerImpl::Create(host_impl_->active_tree(), 2);
2127 root_clip->SetBounds(clip_size_);
2128 root->SetScrollClipLayer(root_clip->id());
2129 root->SetBounds(layer_size_);
2130 root->SetContentBounds(layer_size_);
2131 root->SetPosition(gfx::PointF());
2132 root->SetDrawsContent(false);
2133 root->SetIsContainerForFixedPositionLayers(true);
2134 int inner_viewport_scroll_layer_id = root->id();
2135 int page_scale_layer_id = root_clip->id();
2136 root_clip->AddChild(root.Pass());
2137 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2138 host_impl_->active_tree()->SetViewportLayersFromIds(
2139 page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
2140 // Set a viewport size that is large enough to contain both the top controls
2141 // and some content.
2142 host_impl_->SetViewportSize(viewport_size_);
2143 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2144 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2147 protected:
2148 gfx::Size layer_size_;
2149 gfx::Size clip_size_;
2150 gfx::Size viewport_size_;
2152 LayerTreeSettings settings_;
2153 }; // class LayerTreeHostImplTopControlsTest
2155 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2156 SetupTopControlsAndScrollLayer();
2157 DrawFrame();
2159 EXPECT_EQ(InputHandler::ScrollStarted,
2160 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2162 // Make the test scroll delta a fractional amount, to verify that the
2163 // fixed container size delta is (1) non-zero, and (2) fractional, and
2164 // (3) matches the movement of the top controls.
2165 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2166 host_impl_->top_controls_manager()->ScrollBegin();
2167 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2168 host_impl_->top_controls_manager()->ScrollEnd();
2170 LayerImpl* inner_viewport_scroll_layer =
2171 host_impl_->active_tree()->InnerViewportScrollLayer();
2172 DCHECK(inner_viewport_scroll_layer);
2173 host_impl_->ScrollEnd();
2174 EXPECT_EQ(top_controls_scroll_delta,
2175 inner_viewport_scroll_layer->FixedContainerSizeDelta());
2178 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsWithPageScale) {
2179 SetupTopControlsAndScrollLayer();
2180 DrawFrame();
2182 EXPECT_EQ(InputHandler::ScrollStarted,
2183 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2185 float page_scale = 1.5f;
2186 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale, 1.f, 2.f);
2188 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.f);
2189 gfx::Vector2dF expected_container_size_delta =
2190 ScaleVector2d(top_controls_scroll_delta, 1.f / page_scale);
2191 host_impl_->top_controls_manager()->ScrollBegin();
2192 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2193 host_impl_->top_controls_manager()->ScrollEnd();
2195 LayerImpl* inner_viewport_scroll_layer =
2196 host_impl_->active_tree()->InnerViewportScrollLayer();
2197 DCHECK(inner_viewport_scroll_layer);
2198 host_impl_->ScrollEnd();
2200 // Use a tolerance that requires the container size delta to be within 0.01
2201 // pixels.
2202 double tolerance = 0.0001;
2203 EXPECT_LT(
2204 (expected_container_size_delta -
2205 inner_viewport_scroll_layer->FixedContainerSizeDelta()).LengthSquared(),
2206 tolerance);
2209 TEST_F(LayerTreeHostImplTopControlsTest,
2210 ScrollNonScrollableRootWithTopControls) {
2211 SetupTopControlsAndScrollLayer();
2212 DrawFrame();
2214 EXPECT_EQ(InputHandler::ScrollStarted,
2215 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2217 host_impl_->top_controls_manager()->ScrollBegin();
2218 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
2219 host_impl_->top_controls_manager()->ScrollEnd();
2220 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->content_top_offset());
2221 // Now that top controls have moved, expect the clip to resize.
2222 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2223 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2225 host_impl_->ScrollEnd();
2227 EXPECT_EQ(InputHandler::ScrollStarted,
2228 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2230 float scroll_increment_y = -25.f;
2231 host_impl_->top_controls_manager()->ScrollBegin();
2232 host_impl_->top_controls_manager()->ScrollBy(
2233 gfx::Vector2dF(0.f, scroll_increment_y));
2234 EXPECT_EQ(-scroll_increment_y,
2235 host_impl_->top_controls_manager()->content_top_offset());
2236 // Now that top controls have moved, expect the clip to resize.
2237 EXPECT_EQ(gfx::Size(viewport_size_.width(),
2238 viewport_size_.height() + scroll_increment_y),
2239 root_clip_ptr->bounds());
2241 host_impl_->top_controls_manager()->ScrollBy(
2242 gfx::Vector2dF(0.f, scroll_increment_y));
2243 host_impl_->top_controls_manager()->ScrollEnd();
2244 EXPECT_EQ(-2 * scroll_increment_y,
2245 host_impl_->top_controls_manager()->content_top_offset());
2246 // Now that top controls have moved, expect the clip to resize.
2247 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2249 host_impl_->ScrollEnd();
2251 // Verify the layer is once-again non-scrollable.
2252 EXPECT_EQ(
2253 gfx::Vector2d(),
2254 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
2256 EXPECT_EQ(InputHandler::ScrollStarted,
2257 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2260 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
2261 // Test the configuration where a non-composited root layer is embedded in a
2262 // scrollable outer layer.
2263 gfx::Size surface_size(10, 10);
2264 gfx::Size contents_size(20, 20);
2266 scoped_ptr<LayerImpl> content_layer =
2267 LayerImpl::Create(host_impl_->active_tree(), 1);
2268 content_layer->SetDrawsContent(true);
2269 content_layer->SetPosition(gfx::PointF());
2270 content_layer->SetBounds(contents_size);
2271 content_layer->SetContentBounds(contents_size);
2272 content_layer->SetContentsScale(2.f, 2.f);
2274 scoped_ptr<LayerImpl> scroll_clip_layer =
2275 LayerImpl::Create(host_impl_->active_tree(), 3);
2276 scroll_clip_layer->SetBounds(surface_size);
2278 scoped_ptr<LayerImpl> scroll_layer =
2279 LayerImpl::Create(host_impl_->active_tree(), 2);
2280 scroll_layer->SetScrollClipLayer(3);
2281 scroll_layer->SetBounds(contents_size);
2282 scroll_layer->SetContentBounds(contents_size);
2283 scroll_layer->SetPosition(gfx::PointF());
2284 scroll_layer->AddChild(content_layer.Pass());
2285 scroll_clip_layer->AddChild(scroll_layer.Pass());
2287 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
2288 host_impl_->SetViewportSize(surface_size);
2289 DrawFrame();
2291 EXPECT_EQ(InputHandler::ScrollStarted,
2292 host_impl_->ScrollBegin(gfx::Point(5, 5),
2293 InputHandler::Wheel));
2294 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2295 host_impl_->ScrollEnd();
2296 EXPECT_TRUE(did_request_redraw_);
2297 EXPECT_TRUE(did_request_commit_);
2300 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
2301 gfx::Size surface_size(10, 10);
2302 gfx::Size contents_size(20, 20);
2303 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2304 root->SetBounds(surface_size);
2305 root->SetContentBounds(contents_size);
2306 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
2307 host_impl_->active_tree()->SetRootLayer(root.Pass());
2308 host_impl_->SetViewportSize(surface_size);
2309 DrawFrame();
2311 EXPECT_EQ(InputHandler::ScrollStarted,
2312 host_impl_->ScrollBegin(gfx::Point(5, 5),
2313 InputHandler::Wheel));
2314 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2315 host_impl_->ScrollEnd();
2316 EXPECT_TRUE(did_request_redraw_);
2317 EXPECT_TRUE(did_request_commit_);
2320 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
2321 gfx::Size surface_size(10, 10);
2322 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2323 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
2324 host_impl_->active_tree()->SetRootLayer(root.Pass());
2325 host_impl_->SetViewportSize(surface_size);
2326 DrawFrame();
2328 // Scroll event is ignored because the input coordinate is outside the layer
2329 // boundaries.
2330 EXPECT_EQ(InputHandler::ScrollIgnored,
2331 host_impl_->ScrollBegin(gfx::Point(15, 5),
2332 InputHandler::Wheel));
2333 EXPECT_FALSE(did_request_redraw_);
2334 EXPECT_FALSE(did_request_commit_);
2337 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
2338 gfx::Size surface_size(10, 10);
2339 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2340 scoped_ptr<LayerImpl> child =
2341 CreateScrollableLayer(2, surface_size, root.get());
2342 host_impl_->SetViewportSize(surface_size);
2344 gfx::Transform matrix;
2345 matrix.RotateAboutXAxis(180.0);
2346 child->SetTransform(matrix);
2347 child->SetDoubleSided(false);
2349 root->AddChild(child.Pass());
2350 host_impl_->active_tree()->SetRootLayer(root.Pass());
2351 DrawFrame();
2353 // Scroll event is ignored because the scrollable layer is not facing the
2354 // viewer and there is nothing scrollable behind it.
2355 EXPECT_EQ(InputHandler::ScrollIgnored,
2356 host_impl_->ScrollBegin(gfx::Point(5, 5),
2357 InputHandler::Wheel));
2358 EXPECT_FALSE(did_request_redraw_);
2359 EXPECT_FALSE(did_request_commit_);
2362 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
2363 gfx::Size surface_size(10, 10);
2364 scoped_ptr<LayerImpl> clip_layer =
2365 LayerImpl::Create(host_impl_->active_tree(), 3);
2366 scoped_ptr<LayerImpl> content_layer =
2367 CreateScrollableLayer(1, surface_size, clip_layer.get());
2368 content_layer->SetShouldScrollOnMainThread(true);
2369 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
2371 // Note: we can use the same clip layer for both since both calls to
2372 // CreateScrollableLayer() use the same surface size.
2373 scoped_ptr<LayerImpl> scroll_layer =
2374 CreateScrollableLayer(2, surface_size, clip_layer.get());
2375 scroll_layer->AddChild(content_layer.Pass());
2376 clip_layer->AddChild(scroll_layer.Pass());
2378 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
2379 host_impl_->SetViewportSize(surface_size);
2380 DrawFrame();
2382 // Scrolling fails because the content layer is asking to be scrolled on the
2383 // main thread.
2384 EXPECT_EQ(InputHandler::ScrollOnMainThread,
2385 host_impl_->ScrollBegin(gfx::Point(5, 5),
2386 InputHandler::Wheel));
2389 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
2390 gfx::Size surface_size(20, 20);
2391 gfx::Size viewport_size(10, 10);
2392 float page_scale = 2.f;
2393 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2394 scoped_ptr<LayerImpl> root_clip =
2395 LayerImpl::Create(host_impl_->active_tree(), 2);
2396 scoped_ptr<LayerImpl> root_scrolling =
2397 CreateScrollableLayer(3, surface_size, root_clip.get());
2398 EXPECT_EQ(viewport_size, root_clip->bounds());
2399 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2400 root_clip->AddChild(root_scrolling.Pass());
2401 root->AddChild(root_clip.Pass());
2402 host_impl_->active_tree()->SetRootLayer(root.Pass());
2403 // The behaviour in this test assumes the page scale is applied at a layer
2404 // above the clip layer.
2405 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2406 host_impl_->active_tree()->DidBecomeActive();
2407 host_impl_->SetViewportSize(viewport_size);
2408 DrawFrame();
2410 LayerImpl* root_scroll =
2411 host_impl_->active_tree()->InnerViewportScrollLayer();
2412 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2414 gfx::Vector2d scroll_delta(0, 10);
2415 gfx::Vector2d expected_scroll_delta = scroll_delta;
2416 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2417 EXPECT_EQ(InputHandler::ScrollStarted,
2418 host_impl_->ScrollBegin(gfx::Point(5, 5),
2419 InputHandler::Wheel));
2420 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2421 host_impl_->ScrollEnd();
2423 // Set new page scale from main thread.
2424 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2425 page_scale,
2426 page_scale);
2428 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2429 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2431 // The scroll range should also have been updated.
2432 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2434 // The page scale delta remains constant because the impl thread did not
2435 // scale.
2436 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2439 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
2440 gfx::Size surface_size(20, 20);
2441 gfx::Size viewport_size(10, 10);
2442 float page_scale = 2.f;
2443 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2444 scoped_ptr<LayerImpl> root_clip =
2445 LayerImpl::Create(host_impl_->active_tree(), 2);
2446 scoped_ptr<LayerImpl> root_scrolling =
2447 CreateScrollableLayer(3, surface_size, root_clip.get());
2448 EXPECT_EQ(viewport_size, root_clip->bounds());
2449 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2450 root_clip->AddChild(root_scrolling.Pass());
2451 root->AddChild(root_clip.Pass());
2452 host_impl_->active_tree()->SetRootLayer(root.Pass());
2453 // The behaviour in this test assumes the page scale is applied at a layer
2454 // above the clip layer.
2455 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2456 host_impl_->active_tree()->DidBecomeActive();
2457 host_impl_->SetViewportSize(viewport_size);
2458 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
2459 DrawFrame();
2461 LayerImpl* root_scroll =
2462 host_impl_->active_tree()->InnerViewportScrollLayer();
2463 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2465 gfx::Vector2d scroll_delta(0, 10);
2466 gfx::Vector2d expected_scroll_delta = scroll_delta;
2467 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2468 EXPECT_EQ(InputHandler::ScrollStarted,
2469 host_impl_->ScrollBegin(gfx::Point(5, 5),
2470 InputHandler::Wheel));
2471 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2472 host_impl_->ScrollEnd();
2474 // Set new page scale on impl thread by pinching.
2475 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2476 host_impl_->PinchGestureBegin();
2477 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
2478 host_impl_->PinchGestureEnd();
2479 host_impl_->ScrollEnd();
2480 DrawOneFrame();
2482 // The scroll delta is not scaled because the main thread did not scale.
2483 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2484 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2486 // The scroll range should also have been updated.
2487 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2489 // The page scale delta should match the new scale on the impl side.
2490 EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
2493 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
2494 gfx::Size surface_size(10, 10);
2495 float default_page_scale = 1.f;
2496 gfx::Transform default_page_scale_matrix;
2497 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
2499 float new_page_scale = 2.f;
2500 gfx::Transform new_page_scale_matrix;
2501 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
2503 // Create a normal scrollable root layer and another scrollable child layer.
2504 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
2505 LayerImpl* root = host_impl_->active_tree()->root_layer();
2506 LayerImpl* child = scroll->children()[0];
2508 scoped_ptr<LayerImpl> scrollable_child_clip =
2509 LayerImpl::Create(host_impl_->active_tree(), 6);
2510 scoped_ptr<LayerImpl> scrollable_child =
2511 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
2512 scrollable_child_clip->AddChild(scrollable_child.Pass());
2513 child->AddChild(scrollable_child_clip.Pass());
2514 LayerImpl* grand_child = child->children()[0];
2516 // Set new page scale on impl thread by pinching.
2517 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2518 host_impl_->PinchGestureBegin();
2519 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
2520 host_impl_->PinchGestureEnd();
2521 host_impl_->ScrollEnd();
2522 DrawOneFrame();
2524 EXPECT_EQ(1.f, root->contents_scale_x());
2525 EXPECT_EQ(1.f, root->contents_scale_y());
2526 EXPECT_EQ(1.f, scroll->contents_scale_x());
2527 EXPECT_EQ(1.f, scroll->contents_scale_y());
2528 EXPECT_EQ(1.f, child->contents_scale_x());
2529 EXPECT_EQ(1.f, child->contents_scale_y());
2530 EXPECT_EQ(1.f, grand_child->contents_scale_x());
2531 EXPECT_EQ(1.f, grand_child->contents_scale_y());
2533 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
2534 // the page scale delta on the root layer is applied hierarchically.
2535 LayerTreeHostImpl::FrameData frame;
2536 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2537 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2538 host_impl_->DidDrawAllLayers(frame);
2540 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
2541 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
2542 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
2543 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
2544 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
2545 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
2546 EXPECT_EQ(new_page_scale,
2547 grand_child->draw_transform().matrix().getDouble(0, 0));
2548 EXPECT_EQ(new_page_scale,
2549 grand_child->draw_transform().matrix().getDouble(1, 1));
2552 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
2553 gfx::Size surface_size(30, 30);
2554 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2555 root->SetBounds(gfx::Size(5, 5));
2556 scoped_ptr<LayerImpl> root_scrolling =
2557 LayerImpl::Create(host_impl_->active_tree(), 2);
2558 root_scrolling->SetBounds(surface_size);
2559 root_scrolling->SetContentBounds(surface_size);
2560 root_scrolling->SetScrollClipLayer(root->id());
2561 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2562 LayerImpl* root_scrolling_ptr = root_scrolling.get();
2563 root->AddChild(root_scrolling.Pass());
2564 int child_scroll_layer_id = 3;
2565 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
2566 child_scroll_layer_id, surface_size, root_scrolling_ptr);
2567 LayerImpl* child = child_scrolling.get();
2568 root_scrolling_ptr->AddChild(child_scrolling.Pass());
2569 host_impl_->active_tree()->SetRootLayer(root.Pass());
2570 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2571 host_impl_->active_tree()->DidBecomeActive();
2572 host_impl_->SetViewportSize(surface_size);
2573 DrawFrame();
2575 gfx::Vector2d scroll_delta(0, 10);
2576 gfx::Vector2d expected_scroll_delta(scroll_delta);
2577 gfx::Vector2d expected_max_scroll(child->MaxScrollOffset());
2578 EXPECT_EQ(InputHandler::ScrollStarted,
2579 host_impl_->ScrollBegin(gfx::Point(5, 5),
2580 InputHandler::Wheel));
2581 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2582 host_impl_->ScrollEnd();
2584 float page_scale = 2.f;
2585 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2586 1.f,
2587 page_scale);
2589 DrawOneFrame();
2591 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2592 ExpectContains(
2593 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
2595 // The scroll range should not have changed.
2596 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
2598 // The page scale delta remains constant because the impl thread did not
2599 // scale.
2600 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2603 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
2604 // Scroll a child layer beyond its maximum scroll range and make sure the
2605 // parent layer is scrolled on the axis on which the child was unable to
2606 // scroll.
2607 gfx::Size surface_size(10, 10);
2608 gfx::Size content_size(20, 20);
2609 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2610 root->SetBounds(surface_size);
2612 scoped_ptr<LayerImpl> grand_child =
2613 CreateScrollableLayer(3, content_size, root.get());
2615 scoped_ptr<LayerImpl> child =
2616 CreateScrollableLayer(2, content_size, root.get());
2617 LayerImpl* grand_child_layer = grand_child.get();
2618 child->AddChild(grand_child.Pass());
2620 LayerImpl* child_layer = child.get();
2621 root->AddChild(child.Pass());
2622 host_impl_->active_tree()->SetRootLayer(root.Pass());
2623 host_impl_->active_tree()->DidBecomeActive();
2624 host_impl_->SetViewportSize(surface_size);
2625 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 5));
2626 child_layer->SetScrollOffset(gfx::Vector2d(3, 0));
2628 DrawFrame();
2630 gfx::Vector2d scroll_delta(-8, -7);
2631 EXPECT_EQ(InputHandler::ScrollStarted,
2632 host_impl_->ScrollBegin(gfx::Point(),
2633 InputHandler::Wheel));
2634 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2635 host_impl_->ScrollEnd();
2637 scoped_ptr<ScrollAndScaleSet> scroll_info =
2638 host_impl_->ProcessScrollDeltas();
2640 // The grand child should have scrolled up to its limit.
2641 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2642 LayerImpl* grand_child = child->children()[0];
2643 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
2645 // The child should have only scrolled on the other axis.
2646 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
2650 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
2651 // Scroll a child layer beyond its maximum scroll range and make sure the
2652 // the scroll doesn't bubble up to the parent layer.
2653 gfx::Size surface_size(20, 20);
2654 gfx::Size viewport_size(10, 10);
2655 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2656 scoped_ptr<LayerImpl> root_scrolling =
2657 CreateScrollableLayer(2, surface_size, root.get());
2658 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2660 scoped_ptr<LayerImpl> grand_child =
2661 CreateScrollableLayer(4, surface_size, root.get());
2663 scoped_ptr<LayerImpl> child =
2664 CreateScrollableLayer(3, surface_size, root.get());
2665 LayerImpl* grand_child_layer = grand_child.get();
2666 child->AddChild(grand_child.Pass());
2668 LayerImpl* child_layer = child.get();
2669 root_scrolling->AddChild(child.Pass());
2670 root->AddChild(root_scrolling.Pass());
2671 EXPECT_EQ(viewport_size, root->bounds());
2672 host_impl_->active_tree()->SetRootLayer(root.Pass());
2673 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2674 host_impl_->active_tree()->DidBecomeActive();
2675 host_impl_->SetViewportSize(viewport_size);
2677 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
2678 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
2680 DrawFrame();
2682 gfx::Vector2d scroll_delta(0, -10);
2683 EXPECT_EQ(InputHandler::ScrollStarted,
2684 host_impl_->ScrollBegin(gfx::Point(),
2685 InputHandler::NonBubblingGesture));
2686 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2687 host_impl_->ScrollEnd();
2689 scoped_ptr<ScrollAndScaleSet> scroll_info =
2690 host_impl_->ProcessScrollDeltas();
2692 // The grand child should have scrolled up to its limit.
2693 LayerImpl* child =
2694 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
2695 LayerImpl* grand_child = child->children()[0];
2696 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2698 // The child should not have scrolled.
2699 ExpectNone(*scroll_info.get(), child->id());
2701 // The next time we scroll we should only scroll the parent.
2702 scroll_delta = gfx::Vector2d(0, -3);
2703 EXPECT_EQ(InputHandler::ScrollStarted,
2704 host_impl_->ScrollBegin(gfx::Point(5, 5),
2705 InputHandler::NonBubblingGesture));
2706 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2707 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2708 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
2709 host_impl_->ScrollEnd();
2711 scroll_info = host_impl_->ProcessScrollDeltas();
2713 // The child should have scrolled up to its limit.
2714 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2716 // The grand child should not have scrolled.
2717 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2719 // After scrolling the parent, another scroll on the opposite direction
2720 // should still scroll the child.
2721 scroll_delta = gfx::Vector2d(0, 7);
2722 EXPECT_EQ(InputHandler::ScrollStarted,
2723 host_impl_->ScrollBegin(gfx::Point(5, 5),
2724 InputHandler::NonBubblingGesture));
2725 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2726 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2727 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2728 host_impl_->ScrollEnd();
2730 scroll_info = host_impl_->ProcessScrollDeltas();
2732 // The grand child should have scrolled.
2733 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
2735 // The child should not have scrolled.
2736 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2739 // Scrolling should be adjusted from viewport space.
2740 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
2741 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2743 scroll_delta = gfx::Vector2d(0, -2);
2744 EXPECT_EQ(InputHandler::ScrollStarted,
2745 host_impl_->ScrollBegin(gfx::Point(1, 1),
2746 InputHandler::NonBubblingGesture));
2747 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
2748 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2749 host_impl_->ScrollEnd();
2751 scroll_info = host_impl_->ProcessScrollDeltas();
2753 // Should have scrolled by half the amount in layer space (5 - 2/2)
2754 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
2757 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
2758 // When we try to scroll a non-scrollable child layer, the scroll delta
2759 // should be applied to one of its ancestors if possible.
2760 gfx::Size surface_size(10, 10);
2761 gfx::Size content_size(20, 20);
2762 scoped_ptr<LayerImpl> root_clip =
2763 LayerImpl::Create(host_impl_->active_tree(), 3);
2764 scoped_ptr<LayerImpl> root =
2765 CreateScrollableLayer(1, content_size, root_clip.get());
2766 // Make 'root' the clip layer for child: since they have the same sizes the
2767 // child will have zero max_scroll_offset and scrolls will bubble.
2768 scoped_ptr<LayerImpl> child =
2769 CreateScrollableLayer(2, content_size, root.get());
2770 child->SetIsContainerForFixedPositionLayers(true);
2771 root->SetBounds(content_size);
2773 int root_scroll_id = root->id();
2774 root->AddChild(child.Pass());
2775 root_clip->AddChild(root.Pass());
2777 host_impl_->SetViewportSize(surface_size);
2778 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2779 host_impl_->active_tree()->SetViewportLayersFromIds(3, 2, Layer::INVALID_ID);
2780 host_impl_->active_tree()->DidBecomeActive();
2781 DrawFrame();
2783 gfx::Vector2d scroll_delta(0, 4);
2784 EXPECT_EQ(InputHandler::ScrollStarted,
2785 host_impl_->ScrollBegin(gfx::Point(5, 5),
2786 InputHandler::Wheel));
2787 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2788 host_impl_->ScrollEnd();
2790 scoped_ptr<ScrollAndScaleSet> scroll_info =
2791 host_impl_->ProcessScrollDeltas();
2793 // Only the root scroll should have scrolled.
2794 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
2795 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
2799 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
2800 gfx::Size surface_size(10, 10);
2801 scoped_ptr<LayerImpl> root_clip =
2802 LayerImpl::Create(host_impl_->active_tree(), 1);
2803 scoped_ptr<LayerImpl> root_scroll =
2804 CreateScrollableLayer(2, surface_size, root_clip.get());
2805 root_scroll->SetIsContainerForFixedPositionLayers(true);
2806 root_clip->AddChild(root_scroll.Pass());
2807 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2808 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2809 host_impl_->active_tree()->DidBecomeActive();
2810 host_impl_->SetViewportSize(surface_size);
2812 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
2813 // synchronization.
2814 DrawFrame();
2815 host_impl_->active_tree()->DetachLayerTree();
2816 scoped_ptr<LayerImpl> root_clip2 =
2817 LayerImpl::Create(host_impl_->active_tree(), 3);
2818 scoped_ptr<LayerImpl> root_scroll2 =
2819 CreateScrollableLayer(4, surface_size, root_clip2.get());
2820 root_scroll2->SetIsContainerForFixedPositionLayers(true);
2821 root_clip2->AddChild(root_scroll2.Pass());
2822 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
2823 host_impl_->active_tree()->SetViewportLayersFromIds(3, 4, Layer::INVALID_ID);
2824 host_impl_->active_tree()->DidBecomeActive();
2826 // Scrolling should still work even though we did not draw yet.
2827 EXPECT_EQ(InputHandler::ScrollStarted,
2828 host_impl_->ScrollBegin(gfx::Point(5, 5),
2829 InputHandler::Wheel));
2832 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
2833 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2835 // Rotate the root layer 90 degrees counter-clockwise about its center.
2836 gfx::Transform rotate_transform;
2837 rotate_transform.Rotate(-90.0);
2838 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
2840 gfx::Size surface_size(50, 50);
2841 host_impl_->SetViewportSize(surface_size);
2842 DrawFrame();
2844 // Scroll to the right in screen coordinates with a gesture.
2845 gfx::Vector2d gesture_scroll_delta(10, 0);
2846 EXPECT_EQ(InputHandler::ScrollStarted,
2847 host_impl_->ScrollBegin(gfx::Point(),
2848 InputHandler::Gesture));
2849 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2850 host_impl_->ScrollEnd();
2852 // The layer should have scrolled down in its local coordinates.
2853 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2854 ExpectContains(*scroll_info.get(),
2855 scroll_layer->id(),
2856 gfx::Vector2d(0, gesture_scroll_delta.x()));
2858 // Reset and scroll down with the wheel.
2859 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2860 gfx::Vector2d wheel_scroll_delta(0, 10);
2861 EXPECT_EQ(InputHandler::ScrollStarted,
2862 host_impl_->ScrollBegin(gfx::Point(),
2863 InputHandler::Wheel));
2864 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2865 host_impl_->ScrollEnd();
2867 // The layer should have scrolled down in its local coordinates.
2868 scroll_info = host_impl_->ProcessScrollDeltas();
2869 ExpectContains(*scroll_info.get(),
2870 scroll_layer->id(),
2871 wheel_scroll_delta);
2874 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
2875 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2876 int child_clip_layer_id = 6;
2877 int child_layer_id = 7;
2878 float child_layer_angle = -20.f;
2880 // Create a child layer that is rotated to a non-axis-aligned angle.
2881 scoped_ptr<LayerImpl> clip_layer =
2882 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
2883 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
2884 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
2885 gfx::Transform rotate_transform;
2886 rotate_transform.Translate(-50.0, -50.0);
2887 rotate_transform.Rotate(child_layer_angle);
2888 rotate_transform.Translate(50.0, 50.0);
2889 clip_layer->SetTransform(rotate_transform);
2891 // Only allow vertical scrolling.
2892 clip_layer->SetBounds(
2893 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
2894 // The rotation depends on the layer's transform origin, and the child layer
2895 // is a different size than the clip, so make sure the clip layer's origin
2896 // lines up over the child.
2897 clip_layer->SetTransformOrigin(gfx::Point3F(
2898 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
2899 LayerImpl* child_ptr = child.get();
2900 clip_layer->AddChild(child.Pass());
2901 scroll_layer->AddChild(clip_layer.Pass());
2903 gfx::Size surface_size(50, 50);
2904 host_impl_->SetViewportSize(surface_size);
2905 DrawFrame();
2907 // Scroll down in screen coordinates with a gesture.
2908 gfx::Vector2d gesture_scroll_delta(0, 10);
2909 EXPECT_EQ(InputHandler::ScrollStarted,
2910 host_impl_->ScrollBegin(gfx::Point(1, 1),
2911 InputHandler::Gesture));
2912 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2913 host_impl_->ScrollEnd();
2915 // The child layer should have scrolled down in its local coordinates an
2916 // amount proportional to the angle between it and the input scroll delta.
2917 gfx::Vector2d expected_scroll_delta(
2919 gesture_scroll_delta.y() *
2920 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
2921 scoped_ptr<ScrollAndScaleSet> scroll_info =
2922 host_impl_->ProcessScrollDeltas();
2923 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2925 // The root scroll layer should not have scrolled, because the input delta
2926 // was close to the layer's axis of movement.
2927 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
2930 // Now reset and scroll the same amount horizontally.
2931 child_ptr->SetScrollDelta(gfx::Vector2dF());
2932 gfx::Vector2d gesture_scroll_delta(10, 0);
2933 EXPECT_EQ(InputHandler::ScrollStarted,
2934 host_impl_->ScrollBegin(gfx::Point(1, 1),
2935 InputHandler::Gesture));
2936 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2937 host_impl_->ScrollEnd();
2939 // The child layer should have scrolled down in its local coordinates an
2940 // amount proportional to the angle between it and the input scroll delta.
2941 gfx::Vector2d expected_scroll_delta(
2943 -gesture_scroll_delta.x() *
2944 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
2945 scoped_ptr<ScrollAndScaleSet> scroll_info =
2946 host_impl_->ProcessScrollDeltas();
2947 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2949 // The root scroll layer should have scrolled more, since the input scroll
2950 // delta was mostly orthogonal to the child layer's vertical scroll axis.
2951 gfx::Vector2d expected_root_scroll_delta(
2952 gesture_scroll_delta.x() *
2953 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
2955 ExpectContains(*scroll_info.get(),
2956 scroll_layer->id(),
2957 expected_root_scroll_delta);
2961 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
2962 LayerImpl* scroll_layer =
2963 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2965 // Scale the layer to twice its normal size.
2966 int scale = 2;
2967 gfx::Transform scale_transform;
2968 scale_transform.Scale(scale, scale);
2969 scroll_layer->SetTransform(scale_transform);
2971 gfx::Size surface_size(50, 50);
2972 host_impl_->SetViewportSize(surface_size);
2973 DrawFrame();
2975 // Scroll down in screen coordinates with a gesture.
2976 gfx::Vector2d scroll_delta(0, 10);
2977 EXPECT_EQ(InputHandler::ScrollStarted,
2978 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2979 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2980 host_impl_->ScrollEnd();
2982 // The layer should have scrolled down in its local coordinates, but half the
2983 // amount.
2984 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2985 ExpectContains(*scroll_info.get(),
2986 scroll_layer->id(),
2987 gfx::Vector2d(0, scroll_delta.y() / scale));
2989 // Reset and scroll down with the wheel.
2990 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2991 gfx::Vector2d wheel_scroll_delta(0, 10);
2992 EXPECT_EQ(InputHandler::ScrollStarted,
2993 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2994 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2995 host_impl_->ScrollEnd();
2997 // The scale should not have been applied to the scroll delta.
2998 scroll_info = host_impl_->ProcessScrollDeltas();
2999 ExpectContains(*scroll_info.get(),
3000 scroll_layer->id(),
3001 wheel_scroll_delta);
3004 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
3005 public:
3006 TestScrollOffsetDelegate()
3007 : page_scale_factor_(0.f),
3008 min_page_scale_factor_(-1.f),
3009 max_page_scale_factor_(-1.f) {}
3011 virtual ~TestScrollOffsetDelegate() {}
3013 virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
3014 return getter_return_value_;
3017 virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
3019 virtual void UpdateRootLayerState(const gfx::Vector2dF& total_scroll_offset,
3020 const gfx::Vector2dF& max_scroll_offset,
3021 const gfx::SizeF& scrollable_size,
3022 float page_scale_factor,
3023 float min_page_scale_factor,
3024 float max_page_scale_factor) OVERRIDE {
3025 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
3026 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
3027 last_set_scroll_offset_ = total_scroll_offset;
3028 max_scroll_offset_ = max_scroll_offset;
3029 scrollable_size_ = scrollable_size;
3030 page_scale_factor_ = page_scale_factor;
3031 min_page_scale_factor_ = min_page_scale_factor;
3032 max_page_scale_factor_ = max_page_scale_factor;
3035 gfx::Vector2dF last_set_scroll_offset() {
3036 return last_set_scroll_offset_;
3039 void set_getter_return_value(const gfx::Vector2dF& value) {
3040 getter_return_value_ = value;
3043 gfx::Vector2dF max_scroll_offset() const {
3044 return max_scroll_offset_;
3047 gfx::SizeF scrollable_size() const {
3048 return scrollable_size_;
3051 float page_scale_factor() const {
3052 return page_scale_factor_;
3055 float min_page_scale_factor() const {
3056 return min_page_scale_factor_;
3059 float max_page_scale_factor() const {
3060 return max_page_scale_factor_;
3063 private:
3064 gfx::Vector2dF last_set_scroll_offset_;
3065 gfx::Vector2dF getter_return_value_;
3066 gfx::Vector2dF max_scroll_offset_;
3067 gfx::SizeF scrollable_size_;
3068 float page_scale_factor_;
3069 float min_page_scale_factor_;
3070 float max_page_scale_factor_;
3073 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
3074 TestScrollOffsetDelegate scroll_delegate;
3075 host_impl_->SetViewportSize(gfx::Size(10, 20));
3076 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3077 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3078 clip_layer->SetBounds(gfx::Size(10, 20));
3080 // Setting the delegate results in the current scroll offset being set.
3081 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
3082 scroll_layer->SetScrollOffset(gfx::Vector2d());
3083 scroll_layer->SetScrollDelta(initial_scroll_delta);
3084 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3085 EXPECT_EQ(initial_scroll_delta.ToString(),
3086 scroll_delegate.last_set_scroll_offset().ToString());
3088 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3089 // page_scale_factor and {min|max}_page_scale_factor being set.
3090 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
3091 EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
3092 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3093 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
3094 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
3096 // Updating page scale immediately updates the delegate.
3097 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
3098 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
3099 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3100 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3101 host_impl_->active_tree()->SetPageScaleDelta(1.5f);
3102 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
3103 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3104 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3105 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3106 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3107 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3108 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3109 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3111 // The pinch gesture doesn't put the delegate into a state where the scroll
3112 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3113 // delegate).
3114 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3115 host_impl_->PinchGestureBegin();
3116 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
3117 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
3118 host_impl_->PinchGestureEnd();
3119 host_impl_->ScrollEnd();
3121 // Scrolling should be relative to the offset as returned by the delegate.
3122 gfx::Vector2dF scroll_delta(0.f, 10.f);
3123 gfx::Vector2dF current_offset(7.f, 8.f);
3125 scroll_delegate.set_getter_return_value(current_offset);
3126 EXPECT_EQ(InputHandler::ScrollStarted,
3127 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3129 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3130 EXPECT_EQ(current_offset + scroll_delta,
3131 scroll_delegate.last_set_scroll_offset());
3133 current_offset = gfx::Vector2dF(42.f, 41.f);
3134 scroll_delegate.set_getter_return_value(current_offset);
3135 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3136 EXPECT_EQ(current_offset + scroll_delta,
3137 scroll_delegate.last_set_scroll_offset());
3138 host_impl_->ScrollEnd();
3139 scroll_delegate.set_getter_return_value(gfx::Vector2dF());
3141 // Forces a full tree synchronization and ensures that the scroll delegate
3142 // sees the correct size of the new tree.
3143 gfx::Size new_size(42, 24);
3144 host_impl_->CreatePendingTree();
3145 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
3146 host_impl_->ActivatePendingTree();
3147 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
3149 // Un-setting the delegate should propagate the delegate's current offset to
3150 // the root scrollable layer.
3151 current_offset = gfx::Vector2dF(13.f, 12.f);
3152 scroll_delegate.set_getter_return_value(current_offset);
3153 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3155 EXPECT_EQ(current_offset.ToString(),
3156 scroll_layer->TotalScrollOffset().ToString());
3159 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
3160 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3161 host_impl_->SetViewportSize(gfx::Size(50, 50));
3162 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3163 DrawFrame();
3164 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3166 // In-bounds scrolling does not affect overscroll.
3167 EXPECT_EQ(InputHandler::ScrollStarted,
3168 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3169 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3170 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3172 // Overscroll events are reflected immediately.
3173 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
3174 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3176 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
3177 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
3178 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3179 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
3180 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3181 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
3182 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3183 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
3184 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
3185 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
3186 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
3187 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
3188 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3190 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
3191 // as no scroll occurs.
3192 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3193 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
3194 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3195 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
3196 // Overscroll resets on valid scroll.
3197 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3198 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3199 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3200 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3201 host_impl_->ScrollEnd();
3205 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
3206 // Scroll child layers beyond their maximum scroll range and make sure root
3207 // overscroll does not accumulate.
3208 gfx::Size surface_size(10, 10);
3209 scoped_ptr<LayerImpl> root_clip =
3210 LayerImpl::Create(host_impl_->active_tree(), 4);
3211 scoped_ptr<LayerImpl> root =
3212 CreateScrollableLayer(1, surface_size, root_clip.get());
3214 scoped_ptr<LayerImpl> grand_child =
3215 CreateScrollableLayer(3, surface_size, root_clip.get());
3217 scoped_ptr<LayerImpl> child =
3218 CreateScrollableLayer(2, surface_size, root_clip.get());
3219 LayerImpl* grand_child_layer = grand_child.get();
3220 child->AddChild(grand_child.Pass());
3222 LayerImpl* child_layer = child.get();
3223 root->AddChild(child.Pass());
3224 root_clip->AddChild(root.Pass());
3225 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
3226 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
3227 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3228 host_impl_->active_tree()->DidBecomeActive();
3229 host_impl_->SetViewportSize(surface_size);
3230 DrawFrame();
3232 gfx::Vector2d scroll_delta(0, -10);
3233 EXPECT_EQ(InputHandler::ScrollStarted,
3234 host_impl_->ScrollBegin(gfx::Point(),
3235 InputHandler::NonBubblingGesture));
3236 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3237 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3238 host_impl_->ScrollEnd();
3240 // The next time we scroll we should only scroll the parent, but overscroll
3241 // should still not reach the root layer.
3242 scroll_delta = gfx::Vector2d(0, -30);
3243 EXPECT_EQ(InputHandler::ScrollStarted,
3244 host_impl_->ScrollBegin(gfx::Point(5, 5),
3245 InputHandler::NonBubblingGesture));
3246 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3247 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3248 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3249 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
3250 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3251 host_impl_->ScrollEnd();
3253 // After scrolling the parent, another scroll on the opposite direction
3254 // should scroll the child.
3255 scroll_delta = gfx::Vector2d(0, 70);
3256 EXPECT_EQ(InputHandler::ScrollStarted,
3257 host_impl_->ScrollBegin(gfx::Point(5, 5),
3258 InputHandler::NonBubblingGesture));
3259 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3260 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3261 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3262 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3263 host_impl_->ScrollEnd();
3267 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
3268 // When we try to scroll a non-scrollable child layer, the scroll delta
3269 // should be applied to one of its ancestors if possible. Overscroll should
3270 // be reflected only when it has bubbled up to the root scrolling layer.
3271 gfx::Size surface_size(10, 10);
3272 gfx::Size content_size(20, 20);
3273 scoped_ptr<LayerImpl> root_clip =
3274 LayerImpl::Create(host_impl_->active_tree(), 3);
3275 scoped_ptr<LayerImpl> root =
3276 CreateScrollableLayer(1, content_size, root_clip.get());
3277 root->SetIsContainerForFixedPositionLayers(true);
3278 scoped_ptr<LayerImpl> child =
3279 CreateScrollableLayer(2, content_size, root_clip.get());
3281 child->SetScrollClipLayer(Layer::INVALID_ID);
3282 root->AddChild(child.Pass());
3283 root_clip->AddChild(root.Pass());
3285 host_impl_->SetViewportSize(surface_size);
3286 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3287 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3288 host_impl_->active_tree()->DidBecomeActive();
3289 DrawFrame();
3291 gfx::Vector2d scroll_delta(0, 8);
3292 EXPECT_EQ(InputHandler::ScrollStarted,
3293 host_impl_->ScrollBegin(gfx::Point(5, 5),
3294 InputHandler::Wheel));
3295 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3296 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3297 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3298 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
3299 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3300 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
3301 host_impl_->ScrollEnd();
3305 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
3306 LayerTreeSettings settings;
3307 CreateHostImpl(settings, CreateOutputSurface());
3309 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
3310 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3311 clip_layer->SetBounds(gfx::Size(50, 50));
3312 host_impl_->SetViewportSize(gfx::Size(50, 50));
3313 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3314 DrawFrame();
3315 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3317 // Even though the layer can't scroll the overscroll still happens.
3318 EXPECT_EQ(InputHandler::ScrollStarted,
3319 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3320 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3321 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3324 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
3325 gfx::Size surface_size(980, 1439);
3326 gfx::Size content_size(980, 1438);
3327 float device_scale_factor = 1.5f;
3328 scoped_ptr<LayerImpl> root_clip =
3329 LayerImpl::Create(host_impl_->active_tree(), 3);
3330 scoped_ptr<LayerImpl> root =
3331 CreateScrollableLayer(1, content_size, root_clip.get());
3332 root->SetIsContainerForFixedPositionLayers(true);
3333 scoped_ptr<LayerImpl> child =
3334 CreateScrollableLayer(2, content_size, root_clip.get());
3335 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
3336 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
3337 0.326531f, 0.326531f, 5.f);
3338 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3339 child->SetScrollClipLayer(Layer::INVALID_ID);
3340 root->AddChild(child.Pass());
3341 root_clip->AddChild(root.Pass());
3343 host_impl_->SetViewportSize(surface_size);
3344 host_impl_->SetDeviceScaleFactor(device_scale_factor);
3345 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3346 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3347 host_impl_->active_tree()->DidBecomeActive();
3348 DrawFrame();
3350 // Horizontal & Vertical GlowEffect should not be applied when
3351 // content size is less then view port size. For Example Horizontal &
3352 // vertical GlowEffect should not be applied in about:blank page.
3353 EXPECT_EQ(InputHandler::ScrollStarted,
3354 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3355 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
3356 EXPECT_EQ(gfx::Vector2dF().ToString(),
3357 host_impl_->accumulated_root_overscroll().ToString());
3359 host_impl_->ScrollEnd();
3363 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
3364 gfx::Size surface_size(100, 100);
3365 gfx::Size content_size(200, 200);
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());
3374 child->SetScrollClipLayer(Layer::INVALID_ID);
3375 root->AddChild(child.Pass());
3376 root_clip->AddChild(root.Pass());
3378 host_impl_->SetViewportSize(surface_size);
3379 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3380 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3381 host_impl_->active_tree()->DidBecomeActive();
3382 DrawFrame();
3384 // Edge glow effect should be applicable only upon reaching Edges
3385 // of the content. unnecessary glow effect calls shouldn't be
3386 // called while scrolling up without reaching the edge of the content.
3387 EXPECT_EQ(InputHandler::ScrollStarted,
3388 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3389 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
3390 EXPECT_EQ(gfx::Vector2dF().ToString(),
3391 host_impl_->accumulated_root_overscroll().ToString());
3392 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
3393 EXPECT_EQ(gfx::Vector2dF().ToString(),
3394 host_impl_->accumulated_root_overscroll().ToString());
3395 host_impl_->ScrollEnd();
3396 // unusedrootDelta should be subtracted from applied delta so that
3397 // unwanted glow effect calls are not called.
3398 EXPECT_EQ(InputHandler::ScrollStarted,
3399 host_impl_->ScrollBegin(gfx::Point(0, 0),
3400 InputHandler::NonBubblingGesture));
3401 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
3402 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
3403 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3404 host_impl_->accumulated_root_overscroll().ToString());
3406 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
3407 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3408 host_impl_->accumulated_root_overscroll().ToString());
3409 host_impl_->ScrollEnd();
3410 // TestCase to check kEpsilon, which prevents minute values to trigger
3411 // gloweffect without reaching edge.
3412 EXPECT_EQ(InputHandler::ScrollStarted,
3413 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3414 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
3415 EXPECT_EQ(gfx::Vector2dF().ToString(),
3416 host_impl_->accumulated_root_overscroll().ToString());
3417 host_impl_->ScrollEnd();
3421 class BlendStateCheckLayer : public LayerImpl {
3422 public:
3423 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
3424 int id,
3425 ResourceProvider* resource_provider) {
3426 return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(tree_impl,
3428 resource_provider));
3431 virtual void AppendQuads(QuadSink* quad_sink,
3432 AppendQuadsData* append_quads_data) OVERRIDE {
3433 quads_appended_ = true;
3435 gfx::Rect opaque_rect;
3436 if (contents_opaque())
3437 opaque_rect = quad_rect_;
3438 else
3439 opaque_rect = opaque_content_rect_;
3440 gfx::Rect visible_quad_rect = quad_rect_;
3442 SharedQuadState* shared_quad_state = quad_sink->CreateSharedQuadState();
3443 PopulateSharedQuadState(shared_quad_state);
3445 scoped_ptr<TileDrawQuad> test_blending_draw_quad = TileDrawQuad::Create();
3446 test_blending_draw_quad->SetNew(shared_quad_state,
3447 quad_rect_,
3448 opaque_rect,
3449 visible_quad_rect,
3450 resource_id_,
3451 gfx::RectF(0.f, 0.f, 1.f, 1.f),
3452 gfx::Size(1, 1),
3453 false);
3454 test_blending_draw_quad->visible_rect = quad_visible_rect_;
3455 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
3456 EXPECT_EQ(has_render_surface_, !!render_surface());
3457 quad_sink->Append(test_blending_draw_quad.PassAs<DrawQuad>());
3460 void SetExpectation(bool blend, bool has_render_surface) {
3461 blend_ = blend;
3462 has_render_surface_ = has_render_surface;
3463 quads_appended_ = false;
3466 bool quads_appended() const { return quads_appended_; }
3468 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
3469 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
3470 void SetOpaqueContentRect(const gfx::Rect& rect) {
3471 opaque_content_rect_ = rect;
3474 private:
3475 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
3476 int id,
3477 ResourceProvider* resource_provider)
3478 : LayerImpl(tree_impl, id),
3479 blend_(false),
3480 has_render_surface_(false),
3481 quads_appended_(false),
3482 quad_rect_(5, 5, 5, 5),
3483 quad_visible_rect_(5, 5, 5, 5),
3484 resource_id_(resource_provider->CreateResource(
3485 gfx::Size(1, 1),
3486 GL_CLAMP_TO_EDGE,
3487 ResourceProvider::TextureUsageAny,
3488 RGBA_8888)) {
3489 resource_provider->AllocateForTesting(resource_id_);
3490 SetBounds(gfx::Size(10, 10));
3491 SetContentBounds(gfx::Size(10, 10));
3492 SetDrawsContent(true);
3495 bool blend_;
3496 bool has_render_surface_;
3497 bool quads_appended_;
3498 gfx::Rect quad_rect_;
3499 gfx::Rect opaque_content_rect_;
3500 gfx::Rect quad_visible_rect_;
3501 ResourceProvider::ResourceId resource_id_;
3504 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
3506 scoped_ptr<LayerImpl> root =
3507 LayerImpl::Create(host_impl_->active_tree(), 1);
3508 root->SetBounds(gfx::Size(10, 10));
3509 root->SetContentBounds(root->bounds());
3510 root->SetDrawsContent(false);
3511 host_impl_->active_tree()->SetRootLayer(root.Pass());
3513 LayerImpl* root = host_impl_->active_tree()->root_layer();
3515 root->AddChild(
3516 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3518 host_impl_->resource_provider()));
3519 BlendStateCheckLayer* layer1 =
3520 static_cast<BlendStateCheckLayer*>(root->children()[0]);
3521 layer1->SetPosition(gfx::PointF(2.f, 2.f));
3523 LayerTreeHostImpl::FrameData frame;
3525 // Opaque layer, drawn without blending.
3526 layer1->SetContentsOpaque(true);
3527 layer1->SetExpectation(false, false);
3528 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3529 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3530 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3531 EXPECT_TRUE(layer1->quads_appended());
3532 host_impl_->DidDrawAllLayers(frame);
3534 // Layer with translucent content and painting, so drawn with blending.
3535 layer1->SetContentsOpaque(false);
3536 layer1->SetExpectation(true, false);
3537 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3538 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3539 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3540 EXPECT_TRUE(layer1->quads_appended());
3541 host_impl_->DidDrawAllLayers(frame);
3543 // Layer with translucent opacity, drawn with blending.
3544 layer1->SetContentsOpaque(true);
3545 layer1->SetOpacity(0.5f);
3546 layer1->SetExpectation(true, false);
3547 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3548 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3549 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3550 EXPECT_TRUE(layer1->quads_appended());
3551 host_impl_->DidDrawAllLayers(frame);
3553 // Layer with translucent opacity and painting, drawn with blending.
3554 layer1->SetContentsOpaque(true);
3555 layer1->SetOpacity(0.5f);
3556 layer1->SetExpectation(true, false);
3557 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3558 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3559 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3560 EXPECT_TRUE(layer1->quads_appended());
3561 host_impl_->DidDrawAllLayers(frame);
3563 layer1->AddChild(
3564 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3566 host_impl_->resource_provider()));
3567 BlendStateCheckLayer* layer2 =
3568 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
3569 layer2->SetPosition(gfx::PointF(4.f, 4.f));
3571 // 2 opaque layers, drawn without blending.
3572 layer1->SetContentsOpaque(true);
3573 layer1->SetOpacity(1.f);
3574 layer1->SetExpectation(false, false);
3575 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3576 layer2->SetContentsOpaque(true);
3577 layer2->SetOpacity(1.f);
3578 layer2->SetExpectation(false, false);
3579 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3580 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3581 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3582 EXPECT_TRUE(layer1->quads_appended());
3583 EXPECT_TRUE(layer2->quads_appended());
3584 host_impl_->DidDrawAllLayers(frame);
3586 // Parent layer with translucent content, drawn with blending.
3587 // Child layer with opaque content, drawn without blending.
3588 layer1->SetContentsOpaque(false);
3589 layer1->SetExpectation(true, false);
3590 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3591 layer2->SetExpectation(false, false);
3592 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3593 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3594 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3595 EXPECT_TRUE(layer1->quads_appended());
3596 EXPECT_TRUE(layer2->quads_appended());
3597 host_impl_->DidDrawAllLayers(frame);
3599 // Parent layer with translucent content but opaque painting, drawn without
3600 // blending.
3601 // Child layer with opaque content, drawn without blending.
3602 layer1->SetContentsOpaque(true);
3603 layer1->SetExpectation(false, false);
3604 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3605 layer2->SetExpectation(false, false);
3606 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3607 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3608 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3609 EXPECT_TRUE(layer1->quads_appended());
3610 EXPECT_TRUE(layer2->quads_appended());
3611 host_impl_->DidDrawAllLayers(frame);
3613 // Parent layer with translucent opacity and opaque content. Since it has a
3614 // drawing child, it's drawn to a render surface which carries the opacity,
3615 // so it's itself drawn without blending.
3616 // Child layer with opaque content, drawn without blending (parent surface
3617 // carries the inherited opacity).
3618 layer1->SetContentsOpaque(true);
3619 layer1->SetOpacity(0.5f);
3620 layer1->SetExpectation(false, true);
3621 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3622 layer2->SetExpectation(false, false);
3623 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3624 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3625 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3626 EXPECT_TRUE(layer1->quads_appended());
3627 EXPECT_TRUE(layer2->quads_appended());
3628 host_impl_->DidDrawAllLayers(frame);
3630 // Draw again, but with child non-opaque, to make sure
3631 // layer1 not culled.
3632 layer1->SetContentsOpaque(true);
3633 layer1->SetOpacity(1.f);
3634 layer1->SetExpectation(false, false);
3635 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3636 layer2->SetContentsOpaque(true);
3637 layer2->SetOpacity(0.5f);
3638 layer2->SetExpectation(true, false);
3639 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3640 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3641 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3642 EXPECT_TRUE(layer1->quads_appended());
3643 EXPECT_TRUE(layer2->quads_appended());
3644 host_impl_->DidDrawAllLayers(frame);
3646 // A second way of making the child non-opaque.
3647 layer1->SetContentsOpaque(true);
3648 layer1->SetOpacity(1.f);
3649 layer1->SetExpectation(false, false);
3650 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3651 layer2->SetContentsOpaque(false);
3652 layer2->SetOpacity(1.f);
3653 layer2->SetExpectation(true, false);
3654 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3655 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3656 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3657 EXPECT_TRUE(layer1->quads_appended());
3658 EXPECT_TRUE(layer2->quads_appended());
3659 host_impl_->DidDrawAllLayers(frame);
3661 // And when the layer says its not opaque but is painted opaque, it is not
3662 // blended.
3663 layer1->SetContentsOpaque(true);
3664 layer1->SetOpacity(1.f);
3665 layer1->SetExpectation(false, false);
3666 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3667 layer2->SetContentsOpaque(true);
3668 layer2->SetOpacity(1.f);
3669 layer2->SetExpectation(false, false);
3670 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3671 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3672 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3673 EXPECT_TRUE(layer1->quads_appended());
3674 EXPECT_TRUE(layer2->quads_appended());
3675 host_impl_->DidDrawAllLayers(frame);
3677 // Layer with partially opaque contents, drawn with blending.
3678 layer1->SetContentsOpaque(false);
3679 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3680 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
3681 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3682 layer1->SetExpectation(true, false);
3683 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3684 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3685 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3686 EXPECT_TRUE(layer1->quads_appended());
3687 host_impl_->DidDrawAllLayers(frame);
3689 // Layer with partially opaque contents partially culled, drawn with blending.
3690 layer1->SetContentsOpaque(false);
3691 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3692 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
3693 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3694 layer1->SetExpectation(true, false);
3695 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3696 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3697 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3698 EXPECT_TRUE(layer1->quads_appended());
3699 host_impl_->DidDrawAllLayers(frame);
3701 // Layer with partially opaque contents culled, drawn with blending.
3702 layer1->SetContentsOpaque(false);
3703 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3704 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
3705 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3706 layer1->SetExpectation(true, false);
3707 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3708 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3709 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3710 EXPECT_TRUE(layer1->quads_appended());
3711 host_impl_->DidDrawAllLayers(frame);
3713 // Layer with partially opaque contents and translucent contents culled, drawn
3714 // without blending.
3715 layer1->SetContentsOpaque(false);
3716 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3717 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
3718 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3719 layer1->SetExpectation(false, false);
3720 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3721 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3722 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3723 EXPECT_TRUE(layer1->quads_appended());
3724 host_impl_->DidDrawAllLayers(frame);
3727 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
3728 protected:
3729 LayerTreeHostImplViewportCoveredTest() :
3730 gutter_quad_material_(DrawQuad::SOLID_COLOR),
3731 child_(NULL),
3732 did_activate_pending_tree_(false) {}
3734 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
3735 if (always_draw) {
3736 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
3737 .PassAs<OutputSurface>();
3739 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
3742 void SetupActiveTreeLayers() {
3743 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
3744 host_impl_->active_tree()->SetRootLayer(
3745 LayerImpl::Create(host_impl_->active_tree(), 1));
3746 host_impl_->active_tree()->root_layer()->AddChild(
3747 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3749 host_impl_->resource_provider()));
3750 child_ = static_cast<BlendStateCheckLayer*>(
3751 host_impl_->active_tree()->root_layer()->children()[0]);
3752 child_->SetExpectation(false, false);
3753 child_->SetContentsOpaque(true);
3756 // Expect no gutter rects.
3757 void TestLayerCoversFullViewport() {
3758 gfx::Rect layer_rect(viewport_size_);
3759 child_->SetPosition(layer_rect.origin());
3760 child_->SetBounds(layer_rect.size());
3761 child_->SetContentBounds(layer_rect.size());
3762 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3763 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3765 LayerTreeHostImpl::FrameData frame;
3766 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3767 ASSERT_EQ(1u, frame.render_passes.size());
3769 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3770 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3771 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3773 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3774 host_impl_->DidDrawAllLayers(frame);
3777 // Expect fullscreen gutter rect.
3778 void TestEmptyLayer() {
3779 gfx::Rect layer_rect(0, 0, 0, 0);
3780 child_->SetPosition(layer_rect.origin());
3781 child_->SetBounds(layer_rect.size());
3782 child_->SetContentBounds(layer_rect.size());
3783 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3784 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3786 LayerTreeHostImpl::FrameData frame;
3787 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3788 ASSERT_EQ(1u, frame.render_passes.size());
3790 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
3791 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3792 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3794 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3795 host_impl_->DidDrawAllLayers(frame);
3798 // Expect four surrounding gutter rects.
3799 void TestLayerInMiddleOfViewport() {
3800 gfx::Rect layer_rect(500, 500, 200, 200);
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(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
3812 EXPECT_EQ(5u, 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 no gutter rects.
3820 void TestLayerIsLargerThanViewport() {
3821 gfx::Rect layer_rect(viewport_size_.width() + 10,
3822 viewport_size_.height() + 10);
3823 child_->SetPosition(layer_rect.origin());
3824 child_->SetBounds(layer_rect.size());
3825 child_->SetContentBounds(layer_rect.size());
3826 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3827 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3829 LayerTreeHostImpl::FrameData frame;
3830 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3831 ASSERT_EQ(1u, frame.render_passes.size());
3833 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3834 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3835 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3837 host_impl_->DidDrawAllLayers(frame);
3840 virtual void DidActivatePendingTree() OVERRIDE {
3841 did_activate_pending_tree_ = true;
3844 void set_gutter_quad_material(DrawQuad::Material material) {
3845 gutter_quad_material_ = material;
3847 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
3848 gutter_texture_size_ = gutter_texture_size;
3851 protected:
3852 size_t CountGutterQuads(const QuadList& quad_list) {
3853 size_t num_gutter_quads = 0;
3854 for (size_t i = 0; i < quad_list.size(); ++i) {
3855 num_gutter_quads += (quad_list[i]->material ==
3856 gutter_quad_material_) ? 1 : 0;
3858 return num_gutter_quads;
3861 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
3862 LayerTestCommon::VerifyQuadsExactlyCoverRect(
3863 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
3866 // Make sure that the texture coordinates match their expectations.
3867 void ValidateTextureDrawQuads(const QuadList& quad_list) {
3868 for (size_t i = 0; i < quad_list.size(); ++i) {
3869 if (quad_list[i]->material != DrawQuad::TEXTURE_CONTENT)
3870 continue;
3871 const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(quad_list[i]);
3872 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
3873 gutter_texture_size_, host_impl_->device_scale_factor());
3874 EXPECT_EQ(quad->uv_top_left.x(),
3875 quad->rect.x() / gutter_texture_size_pixels.width());
3876 EXPECT_EQ(quad->uv_top_left.y(),
3877 quad->rect.y() / gutter_texture_size_pixels.height());
3878 EXPECT_EQ(quad->uv_bottom_right.x(),
3879 quad->rect.right() / gutter_texture_size_pixels.width());
3880 EXPECT_EQ(quad->uv_bottom_right.y(),
3881 quad->rect.bottom() / gutter_texture_size_pixels.height());
3885 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
3886 return gfx::ToRoundedSize(
3887 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
3890 DrawQuad::Material gutter_quad_material_;
3891 gfx::Size gutter_texture_size_;
3892 gfx::Size viewport_size_;
3893 BlendStateCheckLayer* child_;
3894 bool did_activate_pending_tree_;
3897 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
3898 viewport_size_ = gfx::Size(1000, 1000);
3900 bool always_draw = false;
3901 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3903 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3904 SetupActiveTreeLayers();
3905 TestLayerCoversFullViewport();
3906 TestEmptyLayer();
3907 TestLayerInMiddleOfViewport();
3908 TestLayerIsLargerThanViewport();
3911 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
3912 viewport_size_ = gfx::Size(1000, 1000);
3914 bool always_draw = false;
3915 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3917 host_impl_->SetDeviceScaleFactor(2.f);
3918 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3919 SetupActiveTreeLayers();
3920 TestLayerCoversFullViewport();
3921 TestEmptyLayer();
3922 TestLayerInMiddleOfViewport();
3923 TestLayerIsLargerThanViewport();
3926 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
3927 viewport_size_ = gfx::Size(1000, 1000);
3929 bool always_draw = false;
3930 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3932 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3933 SetupActiveTreeLayers();
3935 // Specify an overhang bitmap to use.
3936 bool is_opaque = false;
3937 UIResourceBitmap ui_resource_bitmap(gfx::Size(2, 2), is_opaque);
3938 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
3939 UIResourceId ui_resource_id = 12345;
3940 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
3941 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
3942 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
3943 set_gutter_texture_size(gfx::Size(32, 32));
3945 TestLayerCoversFullViewport();
3946 TestEmptyLayer();
3947 TestLayerInMiddleOfViewport();
3948 TestLayerIsLargerThanViewport();
3950 // Change the resource size.
3951 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
3952 set_gutter_texture_size(gfx::Size(128, 16));
3954 TestLayerCoversFullViewport();
3955 TestEmptyLayer();
3956 TestLayerInMiddleOfViewport();
3957 TestLayerIsLargerThanViewport();
3959 // Change the device scale factor
3960 host_impl_->SetDeviceScaleFactor(2.f);
3961 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3963 TestLayerCoversFullViewport();
3964 TestEmptyLayer();
3965 TestLayerInMiddleOfViewport();
3966 TestLayerIsLargerThanViewport();
3969 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
3970 viewport_size_ = gfx::Size(1000, 1000);
3972 bool always_draw = true;
3973 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3975 // Pending tree to force active_tree size invalid. Not used otherwise.
3976 host_impl_->CreatePendingTree();
3977 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3978 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3980 SetupActiveTreeLayers();
3981 TestEmptyLayer();
3982 TestLayerInMiddleOfViewport();
3983 TestLayerIsLargerThanViewport();
3986 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
3987 viewport_size_ = gfx::Size(1000, 1000);
3989 bool always_draw = true;
3990 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3992 // Set larger viewport and activate it to active tree.
3993 host_impl_->CreatePendingTree();
3994 gfx::Size larger_viewport(viewport_size_.width() + 100,
3995 viewport_size_.height() + 100);
3996 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
3997 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3998 host_impl_->ActivatePendingTree();
3999 EXPECT_TRUE(did_activate_pending_tree_);
4000 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
4002 // Shrink pending tree viewport without activating.
4003 host_impl_->CreatePendingTree();
4004 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4005 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4007 SetupActiveTreeLayers();
4008 TestEmptyLayer();
4009 TestLayerInMiddleOfViewport();
4010 TestLayerIsLargerThanViewport();
4013 class FakeDrawableLayerImpl: public LayerImpl {
4014 public:
4015 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4016 return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(tree_impl, id));
4018 protected:
4019 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
4020 : LayerImpl(tree_impl, id) {}
4023 // Only reshape when we know we are going to draw. Otherwise, the reshape
4024 // can leave the window at the wrong size if we never draw and the proper
4025 // viewport size is never set.
4026 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
4027 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4028 scoped_ptr<OutputSurface> output_surface(
4029 FakeOutputSurface::Create3d(provider));
4030 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4032 scoped_ptr<LayerImpl> root =
4033 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4034 root->SetBounds(gfx::Size(10, 10));
4035 root->SetContentBounds(gfx::Size(10, 10));
4036 root->SetDrawsContent(true);
4037 host_impl_->active_tree()->SetRootLayer(root.Pass());
4038 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
4039 provider->TestContext3d()->clear_reshape_called();
4041 LayerTreeHostImpl::FrameData frame;
4042 host_impl_->SetViewportSize(gfx::Size(10, 10));
4043 host_impl_->SetDeviceScaleFactor(1.f);
4044 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4045 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4046 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4047 EXPECT_EQ(provider->TestContext3d()->width(), 10);
4048 EXPECT_EQ(provider->TestContext3d()->height(), 10);
4049 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4050 host_impl_->DidDrawAllLayers(frame);
4051 provider->TestContext3d()->clear_reshape_called();
4053 host_impl_->SetViewportSize(gfx::Size(20, 30));
4054 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4055 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4056 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4057 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4058 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4059 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4060 host_impl_->DidDrawAllLayers(frame);
4061 provider->TestContext3d()->clear_reshape_called();
4063 host_impl_->SetDeviceScaleFactor(2.f);
4064 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4065 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4066 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4067 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4068 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4069 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
4070 host_impl_->DidDrawAllLayers(frame);
4071 provider->TestContext3d()->clear_reshape_called();
4074 // Make sure damage tracking propagates all the way to the graphics context,
4075 // where it should request to swap only the sub-buffer that is damaged.
4076 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
4077 scoped_refptr<TestContextProvider> context_provider(
4078 TestContextProvider::Create());
4079 context_provider->BindToCurrentThread();
4080 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
4082 scoped_ptr<OutputSurface> output_surface(
4083 FakeOutputSurface::Create3d(context_provider));
4085 // This test creates its own LayerTreeHostImpl, so
4086 // that we can force partial swap enabled.
4087 LayerTreeSettings settings;
4088 settings.partial_swap_enabled = true;
4089 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4090 new TestSharedBitmapManager());
4091 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
4092 LayerTreeHostImpl::Create(settings,
4093 this,
4094 &proxy_,
4095 &stats_instrumentation_,
4096 shared_bitmap_manager.get(),
4098 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
4099 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
4101 scoped_ptr<LayerImpl> root =
4102 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
4103 scoped_ptr<LayerImpl> child =
4104 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
4105 child->SetPosition(gfx::PointF(12.f, 13.f));
4106 child->SetBounds(gfx::Size(14, 15));
4107 child->SetContentBounds(gfx::Size(14, 15));
4108 child->SetDrawsContent(true);
4109 root->SetBounds(gfx::Size(500, 500));
4110 root->SetContentBounds(gfx::Size(500, 500));
4111 root->SetDrawsContent(true);
4112 root->AddChild(child.Pass());
4113 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
4115 LayerTreeHostImpl::FrameData frame;
4117 // First frame, the entire screen should get swapped.
4118 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4119 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4120 layer_tree_host_impl->DidDrawAllLayers(frame);
4121 layer_tree_host_impl->SwapBuffers(frame);
4122 EXPECT_EQ(TestContextSupport::SWAP,
4123 context_provider->support()->last_swap_type());
4125 // Second frame, only the damaged area should get swapped. Damage should be
4126 // the union of old and new child rects.
4127 // expected damage rect: gfx::Rect(26, 28);
4128 // expected swap rect: vertically flipped, with origin at bottom left corner.
4129 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
4130 gfx::PointF());
4131 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4132 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4133 host_impl_->DidDrawAllLayers(frame);
4134 layer_tree_host_impl->SwapBuffers(frame);
4136 // Make sure that partial swap is constrained to the viewport dimensions
4137 // expected damage rect: gfx::Rect(500, 500);
4138 // expected swap rect: flipped damage rect, but also clamped to viewport
4139 EXPECT_EQ(TestContextSupport::PARTIAL_SWAP,
4140 context_provider->support()->last_swap_type());
4141 gfx::Rect expected_swap_rect(0, 500-28, 26, 28);
4142 EXPECT_EQ(expected_swap_rect.ToString(),
4143 context_provider->support()->
4144 last_partial_swap_rect().ToString());
4146 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
4147 // This will damage everything.
4148 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
4149 SK_ColorBLACK);
4150 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4151 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4152 host_impl_->DidDrawAllLayers(frame);
4153 layer_tree_host_impl->SwapBuffers(frame);
4155 EXPECT_EQ(TestContextSupport::SWAP,
4156 context_provider->support()->last_swap_type());
4159 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
4160 scoped_ptr<LayerImpl> root =
4161 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4162 scoped_ptr<LayerImpl> child =
4163 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
4164 child->SetBounds(gfx::Size(10, 10));
4165 child->SetContentBounds(gfx::Size(10, 10));
4166 child->SetDrawsContent(true);
4167 root->SetBounds(gfx::Size(10, 10));
4168 root->SetContentBounds(gfx::Size(10, 10));
4169 root->SetDrawsContent(true);
4170 root->SetForceRenderSurface(true);
4171 root->AddChild(child.Pass());
4173 host_impl_->active_tree()->SetRootLayer(root.Pass());
4175 LayerTreeHostImpl::FrameData frame;
4177 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4178 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
4179 EXPECT_EQ(1u, frame.render_passes.size());
4180 host_impl_->DidDrawAllLayers(frame);
4183 class FakeLayerWithQuads : public LayerImpl {
4184 public:
4185 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4186 return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(tree_impl, id));
4189 virtual void AppendQuads(QuadSink* quad_sink,
4190 AppendQuadsData* append_quads_data) OVERRIDE {
4191 SharedQuadState* shared_quad_state = quad_sink->CreateSharedQuadState();
4192 PopulateSharedQuadState(shared_quad_state);
4194 SkColor gray = SkColorSetRGB(100, 100, 100);
4195 gfx::Rect quad_rect(content_bounds());
4196 gfx::Rect visible_quad_rect(quad_rect);
4197 scoped_ptr<SolidColorDrawQuad> my_quad = SolidColorDrawQuad::Create();
4198 my_quad->SetNew(
4199 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
4200 quad_sink->Append(my_quad.PassAs<DrawQuad>());
4203 private:
4204 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
4205 : LayerImpl(tree_impl, id) {}
4208 class MockContext : public TestWebGraphicsContext3D {
4209 public:
4210 MOCK_METHOD1(useProgram, void(GLuint program));
4211 MOCK_METHOD5(uniform4f, void(GLint location,
4212 GLfloat x,
4213 GLfloat y,
4214 GLfloat z,
4215 GLfloat w));
4216 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
4217 GLsizei count,
4218 GLboolean transpose,
4219 const GLfloat* value));
4220 MOCK_METHOD4(drawElements, void(GLenum mode,
4221 GLsizei count,
4222 GLenum type,
4223 GLintptr offset));
4224 MOCK_METHOD1(enable, void(GLenum cap));
4225 MOCK_METHOD1(disable, void(GLenum cap));
4226 MOCK_METHOD4(scissor, void(GLint x,
4227 GLint y,
4228 GLsizei width,
4229 GLsizei height));
4232 class MockContextHarness {
4233 private:
4234 MockContext* context_;
4236 public:
4237 explicit MockContextHarness(MockContext* context)
4238 : context_(context) {
4239 context_->set_have_post_sub_buffer(true);
4241 // Catch "uninteresting" calls
4242 EXPECT_CALL(*context_, useProgram(_))
4243 .Times(0);
4245 EXPECT_CALL(*context_, drawElements(_, _, _, _))
4246 .Times(0);
4248 // These are not asserted
4249 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
4250 .WillRepeatedly(Return());
4252 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
4253 .WillRepeatedly(Return());
4255 // Any un-sanctioned calls to enable() are OK
4256 EXPECT_CALL(*context_, enable(_))
4257 .WillRepeatedly(Return());
4259 // Any un-sanctioned calls to disable() are OK
4260 EXPECT_CALL(*context_, disable(_))
4261 .WillRepeatedly(Return());
4264 void MustDrawSolidQuad() {
4265 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
4266 .WillOnce(Return())
4267 .RetiresOnSaturation();
4269 EXPECT_CALL(*context_, useProgram(_))
4270 .WillOnce(Return())
4271 .RetiresOnSaturation();
4274 void MustSetScissor(int x, int y, int width, int height) {
4275 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4276 .WillRepeatedly(Return());
4278 EXPECT_CALL(*context_, scissor(x, y, width, height))
4279 .Times(AtLeast(1))
4280 .WillRepeatedly(Return());
4283 void MustSetNoScissor() {
4284 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
4285 .WillRepeatedly(Return());
4287 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4288 .Times(0);
4290 EXPECT_CALL(*context_, scissor(_, _, _, _))
4291 .Times(0);
4295 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
4296 scoped_ptr<MockContext> mock_context_owned(new MockContext);
4297 MockContext* mock_context = mock_context_owned.get();
4299 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4300 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4301 MockContextHarness harness(mock_context);
4303 // Run test case
4304 LayerTreeSettings settings = DefaultSettings();
4305 settings.partial_swap_enabled = false;
4306 CreateHostImpl(settings, output_surface.Pass());
4307 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4309 // Without partial swap, and no clipping, no scissor is set.
4310 harness.MustDrawSolidQuad();
4311 harness.MustSetNoScissor();
4313 LayerTreeHostImpl::FrameData frame;
4314 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4315 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4316 host_impl_->DidDrawAllLayers(frame);
4318 Mock::VerifyAndClearExpectations(&mock_context);
4320 // Without partial swap, but a layer does clip its subtree, one scissor is
4321 // set.
4322 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
4323 harness.MustDrawSolidQuad();
4324 harness.MustSetScissor(0, 0, 10, 10);
4326 LayerTreeHostImpl::FrameData frame;
4327 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4328 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4329 host_impl_->DidDrawAllLayers(frame);
4331 Mock::VerifyAndClearExpectations(&mock_context);
4334 TEST_F(LayerTreeHostImplTest, PartialSwap) {
4335 scoped_ptr<MockContext> context_owned(new MockContext);
4336 MockContext* mock_context = context_owned.get();
4337 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4338 context_owned.PassAs<TestWebGraphicsContext3D>()));
4339 MockContextHarness harness(mock_context);
4341 LayerTreeSettings settings = DefaultSettings();
4342 settings.partial_swap_enabled = true;
4343 CreateHostImpl(settings, output_surface.Pass());
4344 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4346 // The first frame is not a partially-swapped one.
4347 harness.MustSetScissor(0, 0, 10, 10);
4348 harness.MustDrawSolidQuad();
4350 LayerTreeHostImpl::FrameData frame;
4351 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4352 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4353 host_impl_->DidDrawAllLayers(frame);
4355 Mock::VerifyAndClearExpectations(&mock_context);
4357 // Damage a portion of the frame.
4358 host_impl_->active_tree()->root_layer()->SetUpdateRect(
4359 gfx::Rect(0, 0, 2, 3));
4361 // The second frame will be partially-swapped (the y coordinates are flipped).
4362 harness.MustSetScissor(0, 7, 2, 3);
4363 harness.MustDrawSolidQuad();
4365 LayerTreeHostImpl::FrameData frame;
4366 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4367 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4368 host_impl_->DidDrawAllLayers(frame);
4370 Mock::VerifyAndClearExpectations(&mock_context);
4373 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
4374 bool partial_swap,
4375 LayerTreeHostImplClient* client,
4376 Proxy* proxy,
4377 SharedBitmapManager* manager,
4378 RenderingStatsInstrumentation* stats_instrumentation) {
4379 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4380 scoped_ptr<OutputSurface> output_surface(
4381 FakeOutputSurface::Create3d(provider));
4382 provider->BindToCurrentThread();
4383 provider->TestContext3d()->set_have_post_sub_buffer(true);
4385 LayerTreeSettings settings;
4386 settings.partial_swap_enabled = partial_swap;
4387 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
4388 settings, client, proxy, stats_instrumentation, manager, 0);
4389 my_host_impl->InitializeRenderer(output_surface.Pass());
4390 my_host_impl->SetViewportSize(gfx::Size(100, 100));
4393 Layers are created as follows:
4395 +--------------------+
4396 | 1 |
4397 | +-----------+ |
4398 | | 2 | |
4399 | | +-------------------+
4400 | | | 3 |
4401 | | +-------------------+
4402 | | | |
4403 | +-----------+ |
4406 +--------------------+
4408 Layers 1, 2 have render surfaces
4410 scoped_ptr<LayerImpl> root =
4411 LayerImpl::Create(my_host_impl->active_tree(), 1);
4412 scoped_ptr<LayerImpl> child =
4413 LayerImpl::Create(my_host_impl->active_tree(), 2);
4414 scoped_ptr<LayerImpl> grand_child =
4415 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
4417 gfx::Rect root_rect(0, 0, 100, 100);
4418 gfx::Rect child_rect(10, 10, 50, 50);
4419 gfx::Rect grand_child_rect(5, 5, 150, 150);
4421 root->CreateRenderSurface();
4422 root->SetPosition(root_rect.origin());
4423 root->SetBounds(root_rect.size());
4424 root->SetContentBounds(root->bounds());
4425 root->draw_properties().visible_content_rect = root_rect;
4426 root->SetDrawsContent(false);
4427 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
4429 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
4430 child->SetOpacity(0.5f);
4431 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
4432 child->SetContentBounds(child->bounds());
4433 child->draw_properties().visible_content_rect = child_rect;
4434 child->SetDrawsContent(false);
4435 child->SetForceRenderSurface(true);
4437 grand_child->SetPosition(grand_child_rect.origin());
4438 grand_child->SetBounds(grand_child_rect.size());
4439 grand_child->SetContentBounds(grand_child->bounds());
4440 grand_child->draw_properties().visible_content_rect = grand_child_rect;
4441 grand_child->SetDrawsContent(true);
4443 child->AddChild(grand_child.Pass());
4444 root->AddChild(child.Pass());
4446 my_host_impl->active_tree()->SetRootLayer(root.Pass());
4447 return my_host_impl.Pass();
4450 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
4451 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4452 new TestSharedBitmapManager());
4453 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4454 SetupLayersForOpacity(true,
4455 this,
4456 &proxy_,
4457 shared_bitmap_manager.get(),
4458 &stats_instrumentation_);
4460 LayerTreeHostImpl::FrameData frame;
4461 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4463 // Verify all quads have been computed
4464 ASSERT_EQ(2U, frame.render_passes.size());
4465 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4466 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4467 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4468 frame.render_passes[0]->quad_list[0]->material);
4469 EXPECT_EQ(DrawQuad::RENDER_PASS,
4470 frame.render_passes[1]->quad_list[0]->material);
4472 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4473 my_host_impl->DidDrawAllLayers(frame);
4477 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
4478 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4479 new TestSharedBitmapManager());
4480 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4481 SetupLayersForOpacity(false,
4482 this,
4483 &proxy_,
4484 shared_bitmap_manager.get(),
4485 &stats_instrumentation_);
4487 LayerTreeHostImpl::FrameData frame;
4488 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4490 // Verify all quads have been computed
4491 ASSERT_EQ(2U, frame.render_passes.size());
4492 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4493 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4494 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4495 frame.render_passes[0]->quad_list[0]->material);
4496 EXPECT_EQ(DrawQuad::RENDER_PASS,
4497 frame.render_passes[1]->quad_list[0]->material);
4499 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4500 my_host_impl->DidDrawAllLayers(frame);
4504 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
4505 scoped_ptr<TestWebGraphicsContext3D> context =
4506 TestWebGraphicsContext3D::Create();
4507 TestWebGraphicsContext3D* context3d = context.get();
4508 scoped_ptr<OutputSurface> output_surface(
4509 FakeOutputSurface::Create3d(context.Pass()));
4510 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4512 scoped_ptr<LayerImpl> root_layer =
4513 LayerImpl::Create(host_impl_->active_tree(), 1);
4514 root_layer->SetBounds(gfx::Size(10, 10));
4516 scoped_refptr<VideoFrame> softwareFrame =
4517 media::VideoFrame::CreateColorFrame(
4518 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
4519 FakeVideoFrameProvider provider;
4520 provider.set_frame(softwareFrame);
4521 scoped_ptr<VideoLayerImpl> video_layer =
4522 VideoLayerImpl::Create(host_impl_->active_tree(), 4, &provider);
4523 video_layer->SetBounds(gfx::Size(10, 10));
4524 video_layer->SetContentBounds(gfx::Size(10, 10));
4525 video_layer->SetDrawsContent(true);
4526 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
4528 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
4529 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
4530 io_surface_layer->SetBounds(gfx::Size(10, 10));
4531 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
4532 io_surface_layer->SetDrawsContent(true);
4533 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
4534 root_layer->AddChild(io_surface_layer.PassAs<LayerImpl>());
4536 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
4538 EXPECT_EQ(0u, context3d->NumTextures());
4540 LayerTreeHostImpl::FrameData frame;
4541 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4542 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4543 host_impl_->DidDrawAllLayers(frame);
4544 host_impl_->SwapBuffers(frame);
4546 EXPECT_GT(context3d->NumTextures(), 0u);
4548 // Kill the layer tree.
4549 host_impl_->active_tree()->SetRootLayer(
4550 LayerImpl::Create(host_impl_->active_tree(), 100));
4551 // There should be no textures left in use after.
4552 EXPECT_EQ(0u, context3d->NumTextures());
4555 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
4556 public:
4557 MOCK_METHOD1(useProgram, void(GLuint program));
4558 MOCK_METHOD4(drawElements, void(GLenum mode,
4559 GLsizei count,
4560 GLenum type,
4561 GLintptr offset));
4564 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
4565 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
4566 new MockDrawQuadsToFillScreenContext);
4567 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
4569 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4570 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4572 // Run test case
4573 LayerTreeSettings settings = DefaultSettings();
4574 settings.partial_swap_enabled = false;
4575 CreateHostImpl(settings, output_surface.Pass());
4576 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
4577 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
4579 // Verify one quad is drawn when transparent background set is not set.
4580 host_impl_->active_tree()->set_has_transparent_background(false);
4581 EXPECT_CALL(*mock_context, useProgram(_))
4582 .Times(1);
4583 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
4584 .Times(1);
4585 LayerTreeHostImpl::FrameData frame;
4586 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4587 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4588 host_impl_->DidDrawAllLayers(frame);
4589 Mock::VerifyAndClearExpectations(&mock_context);
4591 // Verify no quads are drawn when transparent background is set.
4592 host_impl_->active_tree()->set_has_transparent_background(true);
4593 host_impl_->SetFullRootLayerDamage();
4594 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4595 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4596 host_impl_->DidDrawAllLayers(frame);
4597 Mock::VerifyAndClearExpectations(&mock_context);
4600 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
4601 set_reduce_memory_result(false);
4603 // If changing the memory limit wouldn't result in changing what was
4604 // committed, then no commit should be requested.
4605 set_reduce_memory_result(false);
4606 host_impl_->set_max_memory_needed_bytes(
4607 host_impl_->memory_allocation_limit_bytes() - 1);
4608 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4609 host_impl_->memory_allocation_limit_bytes() - 1));
4610 EXPECT_FALSE(did_request_commit_);
4611 did_request_commit_ = false;
4613 // If changing the memory limit would result in changing what was
4614 // committed, then a commit should be requested, even though nothing was
4615 // evicted.
4616 set_reduce_memory_result(false);
4617 host_impl_->set_max_memory_needed_bytes(
4618 host_impl_->memory_allocation_limit_bytes());
4619 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4620 host_impl_->memory_allocation_limit_bytes() - 1));
4621 EXPECT_TRUE(did_request_commit_);
4622 did_request_commit_ = false;
4624 // Especially if changing the memory limit caused evictions, we need
4625 // to re-commit.
4626 set_reduce_memory_result(true);
4627 host_impl_->set_max_memory_needed_bytes(1);
4628 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4629 host_impl_->memory_allocation_limit_bytes() - 1));
4630 EXPECT_TRUE(did_request_commit_);
4631 did_request_commit_ = false;
4633 // But if we set it to the same value that it was before, we shouldn't
4634 // re-commit.
4635 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4636 host_impl_->memory_allocation_limit_bytes()));
4637 EXPECT_FALSE(did_request_commit_);
4640 class LayerTreeHostImplTestWithDelegatingRenderer
4641 : public LayerTreeHostImplTest {
4642 protected:
4643 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
4644 return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
4647 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
4648 bool expect_to_draw = !expected_damage.IsEmpty();
4650 LayerTreeHostImpl::FrameData frame;
4651 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4653 if (!expect_to_draw) {
4654 // With no damage, we don't draw, and no quads are created.
4655 ASSERT_EQ(0u, frame.render_passes.size());
4656 } else {
4657 ASSERT_EQ(1u, frame.render_passes.size());
4659 // Verify the damage rect for the root render pass.
4660 const RenderPass* root_render_pass = frame.render_passes.back();
4661 EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
4663 // Verify the root and child layers' quads are generated and not being
4664 // culled.
4665 ASSERT_EQ(2u, root_render_pass->quad_list.size());
4667 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
4668 gfx::RectF expected_child_visible_rect(child->content_bounds());
4669 EXPECT_RECT_EQ(expected_child_visible_rect,
4670 root_render_pass->quad_list[0]->visible_rect);
4672 LayerImpl* root = host_impl_->active_tree()->root_layer();
4673 gfx::RectF expected_root_visible_rect(root->content_bounds());
4674 EXPECT_RECT_EQ(expected_root_visible_rect,
4675 root_render_pass->quad_list[1]->visible_rect);
4678 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4679 host_impl_->DidDrawAllLayers(frame);
4680 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
4684 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
4685 scoped_ptr<SolidColorLayerImpl> root =
4686 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4687 root->SetPosition(gfx::PointF());
4688 root->SetBounds(gfx::Size(10, 10));
4689 root->SetContentBounds(gfx::Size(10, 10));
4690 root->SetDrawsContent(true);
4692 // Child layer is in the bottom right corner.
4693 scoped_ptr<SolidColorLayerImpl> child =
4694 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
4695 child->SetPosition(gfx::PointF(9.f, 9.f));
4696 child->SetBounds(gfx::Size(1, 1));
4697 child->SetContentBounds(gfx::Size(1, 1));
4698 child->SetDrawsContent(true);
4699 root->AddChild(child.PassAs<LayerImpl>());
4701 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
4703 // Draw a frame. In the first frame, the entire viewport should be damaged.
4704 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
4705 DrawFrameAndTestDamage(full_frame_damage);
4707 // The second frame has damage that doesn't touch the child layer. Its quads
4708 // should still be generated.
4709 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
4710 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
4711 DrawFrameAndTestDamage(small_damage);
4713 // The third frame should have no damage, so no quads should be generated.
4714 gfx::Rect no_damage;
4715 DrawFrameAndTestDamage(no_damage);
4718 // TODO(reveman): Remove this test and the ability to prevent on demand raster
4719 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
4720 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
4721 LayerTreeSettings settings;
4722 CreateHostImpl(settings, CreateOutputSurface());
4723 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
4726 class FakeMaskLayerImpl : public LayerImpl {
4727 public:
4728 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
4729 int id) {
4730 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
4733 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
4734 return 0;
4737 private:
4738 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
4739 : LayerImpl(tree_impl, id) {}
4742 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
4743 LayerTreeSettings settings;
4744 settings.layer_transforms_should_scale_layer_contents = true;
4745 CreateHostImpl(settings, CreateOutputSurface());
4747 // Root
4748 // |
4749 // +-- Scaling Layer (adds a 2x scale)
4750 // |
4751 // +-- Content Layer
4752 // +--Mask
4753 scoped_ptr<LayerImpl> scoped_root =
4754 LayerImpl::Create(host_impl_->active_tree(), 1);
4755 LayerImpl* root = scoped_root.get();
4756 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4758 scoped_ptr<LayerImpl> scoped_scaling_layer =
4759 LayerImpl::Create(host_impl_->active_tree(), 2);
4760 LayerImpl* scaling_layer = scoped_scaling_layer.get();
4761 root->AddChild(scoped_scaling_layer.Pass());
4763 scoped_ptr<LayerImpl> scoped_content_layer =
4764 LayerImpl::Create(host_impl_->active_tree(), 3);
4765 LayerImpl* content_layer = scoped_content_layer.get();
4766 scaling_layer->AddChild(scoped_content_layer.Pass());
4768 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4769 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4770 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4771 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4773 gfx::Size root_size(100, 100);
4774 root->SetBounds(root_size);
4775 root->SetContentBounds(root_size);
4776 root->SetPosition(gfx::PointF());
4778 gfx::Size scaling_layer_size(50, 50);
4779 scaling_layer->SetBounds(scaling_layer_size);
4780 scaling_layer->SetContentBounds(scaling_layer_size);
4781 scaling_layer->SetPosition(gfx::PointF());
4782 gfx::Transform scale;
4783 scale.Scale(2.f, 2.f);
4784 scaling_layer->SetTransform(scale);
4786 content_layer->SetBounds(scaling_layer_size);
4787 content_layer->SetContentBounds(scaling_layer_size);
4788 content_layer->SetPosition(gfx::PointF());
4789 content_layer->SetDrawsContent(true);
4791 mask_layer->SetBounds(scaling_layer_size);
4792 mask_layer->SetContentBounds(scaling_layer_size);
4793 mask_layer->SetPosition(gfx::PointF());
4794 mask_layer->SetDrawsContent(true);
4797 // Check that the tree scaling is correctly taken into account for the mask,
4798 // that should fully map onto the quad.
4799 float device_scale_factor = 1.f;
4800 host_impl_->SetViewportSize(root_size);
4801 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4803 LayerTreeHostImpl::FrameData frame;
4804 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4806 ASSERT_EQ(1u, frame.render_passes.size());
4807 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4808 ASSERT_EQ(DrawQuad::RENDER_PASS,
4809 frame.render_passes[0]->quad_list[0]->material);
4810 const RenderPassDrawQuad* render_pass_quad =
4811 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4812 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4813 render_pass_quad->rect.ToString());
4814 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4815 render_pass_quad->mask_uv_rect.ToString());
4817 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4818 host_impl_->DidDrawAllLayers(frame);
4822 // Applying a DSF should change the render surface size, but won't affect
4823 // which part of the mask is used.
4824 device_scale_factor = 2.f;
4825 gfx::Size device_viewport =
4826 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4827 host_impl_->SetViewportSize(device_viewport);
4828 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4829 host_impl_->active_tree()->set_needs_update_draw_properties();
4831 LayerTreeHostImpl::FrameData frame;
4832 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4834 ASSERT_EQ(1u, frame.render_passes.size());
4835 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4836 ASSERT_EQ(DrawQuad::RENDER_PASS,
4837 frame.render_passes[0]->quad_list[0]->material);
4838 const RenderPassDrawQuad* render_pass_quad =
4839 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4840 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4841 render_pass_quad->rect.ToString());
4842 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4843 render_pass_quad->mask_uv_rect.ToString());
4845 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4846 host_impl_->DidDrawAllLayers(frame);
4850 // Applying an equivalent content scale on the content layer and the mask
4851 // should still result in the same part of the mask being used.
4852 gfx::Size content_bounds =
4853 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
4854 device_scale_factor));
4855 content_layer->SetContentBounds(content_bounds);
4856 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4857 mask_layer->SetContentBounds(content_bounds);
4858 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4859 host_impl_->active_tree()->set_needs_update_draw_properties();
4861 LayerTreeHostImpl::FrameData frame;
4862 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4864 ASSERT_EQ(1u, frame.render_passes.size());
4865 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4866 ASSERT_EQ(DrawQuad::RENDER_PASS,
4867 frame.render_passes[0]->quad_list[0]->material);
4868 const RenderPassDrawQuad* render_pass_quad =
4869 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4870 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4871 render_pass_quad->rect.ToString());
4872 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4873 render_pass_quad->mask_uv_rect.ToString());
4875 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4876 host_impl_->DidDrawAllLayers(frame);
4880 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
4881 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4882 // 50x50.
4884 scoped_ptr<LayerImpl> scoped_root =
4885 LayerImpl::Create(host_impl_->active_tree(), 1);
4886 LayerImpl* root = scoped_root.get();
4887 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4889 scoped_ptr<LayerImpl> scoped_content_layer =
4890 LayerImpl::Create(host_impl_->active_tree(), 3);
4891 LayerImpl* content_layer = scoped_content_layer.get();
4892 root->AddChild(scoped_content_layer.Pass());
4894 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4895 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4896 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4897 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4899 gfx::Size root_size(100, 100);
4900 root->SetBounds(root_size);
4901 root->SetContentBounds(root_size);
4902 root->SetPosition(gfx::PointF());
4904 gfx::Size layer_size(50, 50);
4905 content_layer->SetBounds(layer_size);
4906 content_layer->SetContentBounds(layer_size);
4907 content_layer->SetPosition(gfx::PointF());
4908 content_layer->SetDrawsContent(true);
4910 gfx::Size mask_size(100, 100);
4911 mask_layer->SetBounds(mask_size);
4912 mask_layer->SetContentBounds(mask_size);
4913 mask_layer->SetPosition(gfx::PointF());
4914 mask_layer->SetDrawsContent(true);
4916 // Check that the mask fills the surface.
4917 float device_scale_factor = 1.f;
4918 host_impl_->SetViewportSize(root_size);
4919 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4921 LayerTreeHostImpl::FrameData frame;
4922 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4924 ASSERT_EQ(1u, frame.render_passes.size());
4925 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4926 ASSERT_EQ(DrawQuad::RENDER_PASS,
4927 frame.render_passes[0]->quad_list[0]->material);
4928 const RenderPassDrawQuad* render_pass_quad =
4929 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4930 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4931 render_pass_quad->rect.ToString());
4932 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4933 render_pass_quad->mask_uv_rect.ToString());
4935 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4936 host_impl_->DidDrawAllLayers(frame);
4939 // Applying a DSF should change the render surface size, but won't affect
4940 // which part of the mask is used.
4941 device_scale_factor = 2.f;
4942 gfx::Size device_viewport =
4943 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4944 host_impl_->SetViewportSize(device_viewport);
4945 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4946 host_impl_->active_tree()->set_needs_update_draw_properties();
4948 LayerTreeHostImpl::FrameData frame;
4949 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4951 ASSERT_EQ(1u, frame.render_passes.size());
4952 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4953 ASSERT_EQ(DrawQuad::RENDER_PASS,
4954 frame.render_passes[0]->quad_list[0]->material);
4955 const RenderPassDrawQuad* render_pass_quad =
4956 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4957 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4958 render_pass_quad->rect.ToString());
4959 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4960 render_pass_quad->mask_uv_rect.ToString());
4962 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4963 host_impl_->DidDrawAllLayers(frame);
4966 // Applying an equivalent content scale on the content layer and the mask
4967 // should still result in the same part of the mask being used.
4968 gfx::Size layer_size_large =
4969 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
4970 content_layer->SetContentBounds(layer_size_large);
4971 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4972 gfx::Size mask_size_large =
4973 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
4974 mask_layer->SetContentBounds(mask_size_large);
4975 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4976 host_impl_->active_tree()->set_needs_update_draw_properties();
4978 LayerTreeHostImpl::FrameData frame;
4979 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4981 ASSERT_EQ(1u, frame.render_passes.size());
4982 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4983 ASSERT_EQ(DrawQuad::RENDER_PASS,
4984 frame.render_passes[0]->quad_list[0]->material);
4985 const RenderPassDrawQuad* render_pass_quad =
4986 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4987 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4988 render_pass_quad->rect.ToString());
4989 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4990 render_pass_quad->mask_uv_rect.ToString());
4992 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4993 host_impl_->DidDrawAllLayers(frame);
4996 // Applying a different contents scale to the mask layer means it will have
4997 // a larger texture, but it should use the same tex coords to cover the
4998 // layer it masks.
4999 mask_layer->SetContentBounds(mask_size);
5000 mask_layer->SetContentsScale(1.f, 1.f);
5001 host_impl_->active_tree()->set_needs_update_draw_properties();
5003 LayerTreeHostImpl::FrameData frame;
5004 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5006 ASSERT_EQ(1u, frame.render_passes.size());
5007 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5008 ASSERT_EQ(DrawQuad::RENDER_PASS,
5009 frame.render_passes[0]->quad_list[0]->material);
5010 const RenderPassDrawQuad* render_pass_quad =
5011 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5012 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5013 render_pass_quad->rect.ToString());
5014 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5015 render_pass_quad->mask_uv_rect.ToString());
5017 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5018 host_impl_->DidDrawAllLayers(frame);
5022 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
5023 // The replica's mask layer has bounds 100x100 but the replica is of a
5024 // layer with bounds 50x50.
5026 scoped_ptr<LayerImpl> scoped_root =
5027 LayerImpl::Create(host_impl_->active_tree(), 1);
5028 LayerImpl* root = scoped_root.get();
5029 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5031 scoped_ptr<LayerImpl> scoped_content_layer =
5032 LayerImpl::Create(host_impl_->active_tree(), 3);
5033 LayerImpl* content_layer = scoped_content_layer.get();
5034 root->AddChild(scoped_content_layer.Pass());
5036 scoped_ptr<LayerImpl> scoped_replica_layer =
5037 LayerImpl::Create(host_impl_->active_tree(), 2);
5038 LayerImpl* replica_layer = scoped_replica_layer.get();
5039 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5041 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5042 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5043 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5044 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5046 gfx::Size root_size(100, 100);
5047 root->SetBounds(root_size);
5048 root->SetContentBounds(root_size);
5049 root->SetPosition(gfx::PointF());
5051 gfx::Size layer_size(50, 50);
5052 content_layer->SetBounds(layer_size);
5053 content_layer->SetContentBounds(layer_size);
5054 content_layer->SetPosition(gfx::PointF());
5055 content_layer->SetDrawsContent(true);
5057 gfx::Size mask_size(100, 100);
5058 mask_layer->SetBounds(mask_size);
5059 mask_layer->SetContentBounds(mask_size);
5060 mask_layer->SetPosition(gfx::PointF());
5061 mask_layer->SetDrawsContent(true);
5063 // Check that the mask fills the surface.
5064 float device_scale_factor = 1.f;
5065 host_impl_->SetViewportSize(root_size);
5066 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5068 LayerTreeHostImpl::FrameData frame;
5069 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5071 ASSERT_EQ(1u, frame.render_passes.size());
5072 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5073 ASSERT_EQ(DrawQuad::RENDER_PASS,
5074 frame.render_passes[0]->quad_list[1]->material);
5075 const RenderPassDrawQuad* replica_quad =
5076 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5077 EXPECT_TRUE(replica_quad->is_replica);
5078 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5079 replica_quad->rect.ToString());
5080 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5081 replica_quad->mask_uv_rect.ToString());
5083 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5084 host_impl_->DidDrawAllLayers(frame);
5087 // Applying a DSF should change the render surface size, but won't affect
5088 // which part of the mask is used.
5089 device_scale_factor = 2.f;
5090 gfx::Size device_viewport =
5091 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5092 host_impl_->SetViewportSize(device_viewport);
5093 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5094 host_impl_->active_tree()->set_needs_update_draw_properties();
5096 LayerTreeHostImpl::FrameData frame;
5097 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5099 ASSERT_EQ(1u, frame.render_passes.size());
5100 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5101 ASSERT_EQ(DrawQuad::RENDER_PASS,
5102 frame.render_passes[0]->quad_list[1]->material);
5103 const RenderPassDrawQuad* replica_quad =
5104 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5105 EXPECT_TRUE(replica_quad->is_replica);
5106 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5107 replica_quad->rect.ToString());
5108 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5109 replica_quad->mask_uv_rect.ToString());
5111 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5112 host_impl_->DidDrawAllLayers(frame);
5115 // Applying an equivalent content scale on the content layer and the mask
5116 // should still result in the same part of the mask being used.
5117 gfx::Size layer_size_large =
5118 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5119 content_layer->SetContentBounds(layer_size_large);
5120 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5121 gfx::Size mask_size_large =
5122 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5123 mask_layer->SetContentBounds(mask_size_large);
5124 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5125 host_impl_->active_tree()->set_needs_update_draw_properties();
5127 LayerTreeHostImpl::FrameData frame;
5128 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5130 ASSERT_EQ(1u, frame.render_passes.size());
5131 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5132 ASSERT_EQ(DrawQuad::RENDER_PASS,
5133 frame.render_passes[0]->quad_list[1]->material);
5134 const RenderPassDrawQuad* replica_quad =
5135 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5136 EXPECT_TRUE(replica_quad->is_replica);
5137 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5138 replica_quad->rect.ToString());
5139 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5140 replica_quad->mask_uv_rect.ToString());
5142 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5143 host_impl_->DidDrawAllLayers(frame);
5146 // Applying a different contents scale to the mask layer means it will have
5147 // a larger texture, but it should use the same tex coords to cover the
5148 // layer it masks.
5149 mask_layer->SetContentBounds(mask_size);
5150 mask_layer->SetContentsScale(1.f, 1.f);
5151 host_impl_->active_tree()->set_needs_update_draw_properties();
5153 LayerTreeHostImpl::FrameData frame;
5154 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5156 ASSERT_EQ(1u, frame.render_passes.size());
5157 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5158 ASSERT_EQ(DrawQuad::RENDER_PASS,
5159 frame.render_passes[0]->quad_list[1]->material);
5160 const RenderPassDrawQuad* replica_quad =
5161 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5162 EXPECT_TRUE(replica_quad->is_replica);
5163 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5164 replica_quad->rect.ToString());
5165 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5166 replica_quad->mask_uv_rect.ToString());
5168 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5169 host_impl_->DidDrawAllLayers(frame);
5173 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
5174 // The replica is of a layer with bounds 50x50, but it has a child that causes
5175 // the surface bounds to be larger.
5177 scoped_ptr<LayerImpl> scoped_root =
5178 LayerImpl::Create(host_impl_->active_tree(), 1);
5179 LayerImpl* root = scoped_root.get();
5180 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5182 scoped_ptr<LayerImpl> scoped_content_layer =
5183 LayerImpl::Create(host_impl_->active_tree(), 2);
5184 LayerImpl* content_layer = scoped_content_layer.get();
5185 root->AddChild(scoped_content_layer.Pass());
5187 scoped_ptr<LayerImpl> scoped_content_child_layer =
5188 LayerImpl::Create(host_impl_->active_tree(), 3);
5189 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5190 content_layer->AddChild(scoped_content_child_layer.Pass());
5192 scoped_ptr<LayerImpl> scoped_replica_layer =
5193 LayerImpl::Create(host_impl_->active_tree(), 4);
5194 LayerImpl* replica_layer = scoped_replica_layer.get();
5195 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5197 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5198 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
5199 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5200 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5202 gfx::Size root_size(100, 100);
5203 root->SetBounds(root_size);
5204 root->SetContentBounds(root_size);
5205 root->SetPosition(gfx::PointF());
5207 gfx::Size layer_size(50, 50);
5208 content_layer->SetBounds(layer_size);
5209 content_layer->SetContentBounds(layer_size);
5210 content_layer->SetPosition(gfx::PointF());
5211 content_layer->SetDrawsContent(true);
5213 gfx::Size child_size(50, 50);
5214 content_child_layer->SetBounds(child_size);
5215 content_child_layer->SetContentBounds(child_size);
5216 content_child_layer->SetPosition(gfx::Point(50, 0));
5217 content_child_layer->SetDrawsContent(true);
5219 gfx::Size mask_size(50, 50);
5220 mask_layer->SetBounds(mask_size);
5221 mask_layer->SetContentBounds(mask_size);
5222 mask_layer->SetPosition(gfx::PointF());
5223 mask_layer->SetDrawsContent(true);
5225 float device_scale_factor = 1.f;
5226 host_impl_->SetViewportSize(root_size);
5227 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5229 LayerTreeHostImpl::FrameData frame;
5230 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5232 ASSERT_EQ(1u, frame.render_passes.size());
5233 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5235 // The surface is 100x50.
5236 ASSERT_EQ(DrawQuad::RENDER_PASS,
5237 frame.render_passes[0]->quad_list[0]->material);
5238 const RenderPassDrawQuad* render_pass_quad =
5239 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5240 EXPECT_FALSE(render_pass_quad->is_replica);
5241 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5242 render_pass_quad->rect.ToString());
5244 // The mask covers the owning layer only.
5245 ASSERT_EQ(DrawQuad::RENDER_PASS,
5246 frame.render_passes[0]->quad_list[1]->material);
5247 const RenderPassDrawQuad* replica_quad =
5248 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5249 EXPECT_TRUE(replica_quad->is_replica);
5250 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5251 replica_quad->rect.ToString());
5252 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
5253 replica_quad->mask_uv_rect.ToString());
5255 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5256 host_impl_->DidDrawAllLayers(frame);
5259 // Move the child to (-50, 0) instead. Now the mask should be moved to still
5260 // cover the layer being replicated.
5261 content_child_layer->SetPosition(gfx::Point(-50, 0));
5263 LayerTreeHostImpl::FrameData frame;
5264 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5266 ASSERT_EQ(1u, frame.render_passes.size());
5267 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5269 // The surface is 100x50 with its origin at (-50, 0).
5270 ASSERT_EQ(DrawQuad::RENDER_PASS,
5271 frame.render_passes[0]->quad_list[0]->material);
5272 const RenderPassDrawQuad* render_pass_quad =
5273 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5274 EXPECT_FALSE(render_pass_quad->is_replica);
5275 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5276 render_pass_quad->rect.ToString());
5278 // The mask covers the owning layer only.
5279 ASSERT_EQ(DrawQuad::RENDER_PASS,
5280 frame.render_passes[0]->quad_list[1]->material);
5281 const RenderPassDrawQuad* replica_quad =
5282 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5283 EXPECT_TRUE(replica_quad->is_replica);
5284 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5285 replica_quad->rect.ToString());
5286 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
5287 replica_quad->mask_uv_rect.ToString());
5289 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5290 host_impl_->DidDrawAllLayers(frame);
5294 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
5295 // The masked layer has bounds 50x50, but it has a child that causes
5296 // the surface bounds to be larger. It also has a parent that clips the
5297 // masked layer and its surface.
5299 scoped_ptr<LayerImpl> scoped_root =
5300 LayerImpl::Create(host_impl_->active_tree(), 1);
5301 LayerImpl* root = scoped_root.get();
5302 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5304 scoped_ptr<LayerImpl> scoped_clipping_layer =
5305 LayerImpl::Create(host_impl_->active_tree(), 2);
5306 LayerImpl* clipping_layer = scoped_clipping_layer.get();
5307 root->AddChild(scoped_clipping_layer.Pass());
5309 scoped_ptr<LayerImpl> scoped_content_layer =
5310 LayerImpl::Create(host_impl_->active_tree(), 3);
5311 LayerImpl* content_layer = scoped_content_layer.get();
5312 clipping_layer->AddChild(scoped_content_layer.Pass());
5314 scoped_ptr<LayerImpl> scoped_content_child_layer =
5315 LayerImpl::Create(host_impl_->active_tree(), 4);
5316 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5317 content_layer->AddChild(scoped_content_child_layer.Pass());
5319 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5320 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
5321 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5322 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5324 gfx::Size root_size(100, 100);
5325 root->SetBounds(root_size);
5326 root->SetContentBounds(root_size);
5327 root->SetPosition(gfx::PointF());
5329 gfx::Rect clipping_rect(20, 10, 10, 20);
5330 clipping_layer->SetBounds(clipping_rect.size());
5331 clipping_layer->SetContentBounds(clipping_rect.size());
5332 clipping_layer->SetPosition(clipping_rect.origin());
5333 clipping_layer->SetMasksToBounds(true);
5335 gfx::Size layer_size(50, 50);
5336 content_layer->SetBounds(layer_size);
5337 content_layer->SetContentBounds(layer_size);
5338 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
5339 content_layer->SetDrawsContent(true);
5341 gfx::Size child_size(50, 50);
5342 content_child_layer->SetBounds(child_size);
5343 content_child_layer->SetContentBounds(child_size);
5344 content_child_layer->SetPosition(gfx::Point(50, 0));
5345 content_child_layer->SetDrawsContent(true);
5347 gfx::Size mask_size(100, 100);
5348 mask_layer->SetBounds(mask_size);
5349 mask_layer->SetContentBounds(mask_size);
5350 mask_layer->SetPosition(gfx::PointF());
5351 mask_layer->SetDrawsContent(true);
5353 float device_scale_factor = 1.f;
5354 host_impl_->SetViewportSize(root_size);
5355 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5357 LayerTreeHostImpl::FrameData frame;
5358 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5360 ASSERT_EQ(1u, frame.render_passes.size());
5361 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5363 // The surface is clipped to 10x20.
5364 ASSERT_EQ(DrawQuad::RENDER_PASS,
5365 frame.render_passes[0]->quad_list[0]->material);
5366 const RenderPassDrawQuad* render_pass_quad =
5367 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5368 EXPECT_FALSE(render_pass_quad->is_replica);
5369 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
5370 render_pass_quad->rect.ToString());
5372 // The masked layer is 50x50, but the surface size is 10x20. So the texture
5373 // coords in the mask are scaled by 10/50 and 20/50.
5374 // The surface is clipped to (20,10) so the mask texture coords are offset
5375 // by 20/50 and 10/50
5376 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f),
5377 1.f / 50.f).ToString(),
5378 render_pass_quad->mask_uv_rect.ToString());
5380 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5381 host_impl_->DidDrawAllLayers(frame);
5385 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
5386 public:
5387 using GLRenderer::SetupQuadForAntialiasing;
5390 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
5391 // Due to precision issues (especially on Android), sometimes far
5392 // away quads can end up thinking they need AA.
5393 float device_scale_factor = 4.f / 3.f;
5394 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5395 gfx::Size root_size(2000, 1000);
5396 gfx::Size device_viewport_size =
5397 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
5398 host_impl_->SetViewportSize(device_viewport_size);
5400 host_impl_->CreatePendingTree();
5401 host_impl_->pending_tree()
5402 ->SetPageScaleFactorAndLimits(1.f, 1.f / 16.f, 16.f);
5404 scoped_ptr<LayerImpl> scoped_root =
5405 LayerImpl::Create(host_impl_->pending_tree(), 1);
5406 LayerImpl* root = scoped_root.get();
5408 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
5410 scoped_ptr<LayerImpl> scoped_scrolling_layer =
5411 LayerImpl::Create(host_impl_->pending_tree(), 2);
5412 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
5413 root->AddChild(scoped_scrolling_layer.Pass());
5415 gfx::Size content_layer_bounds(100000, 100);
5416 gfx::Size pile_tile_size(3000, 3000);
5417 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
5418 pile_tile_size, content_layer_bounds));
5420 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
5421 FakePictureLayerImpl::CreateWithPile(host_impl_->pending_tree(), 3, pile);
5422 LayerImpl* content_layer = scoped_content_layer.get();
5423 scrolling_layer->AddChild(scoped_content_layer.PassAs<LayerImpl>());
5424 content_layer->SetBounds(content_layer_bounds);
5425 content_layer->SetDrawsContent(true);
5427 root->SetBounds(root_size);
5429 gfx::Vector2d scroll_offset(100000, 0);
5430 scrolling_layer->SetScrollClipLayer(root->id());
5431 scrolling_layer->SetScrollOffset(scroll_offset);
5433 host_impl_->ActivatePendingTree();
5435 host_impl_->active_tree()->UpdateDrawProperties();
5436 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
5438 LayerTreeHostImpl::FrameData frame;
5439 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5441 ASSERT_EQ(1u, frame.render_passes.size());
5442 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
5443 const DrawQuad* quad = frame.render_passes[0]->quad_list[0];
5445 float edge[24];
5446 gfx::QuadF device_layer_quad;
5447 bool antialiased =
5448 GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
5449 quad->quadTransform(), quad, &device_layer_quad, edge);
5450 EXPECT_FALSE(antialiased);
5452 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5453 host_impl_->DidDrawAllLayers(frame);
5457 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
5458 public:
5459 CompositorFrameMetadataTest()
5460 : swap_buffers_complete_(0) {}
5462 virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {
5463 swap_buffers_complete_++;
5466 int swap_buffers_complete_;
5469 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
5470 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5472 LayerTreeHostImpl::FrameData frame;
5473 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5474 host_impl_->DrawLayers(&frame, base::TimeTicks());
5475 host_impl_->DidDrawAllLayers(frame);
5477 CompositorFrameAck ack;
5478 host_impl_->ReclaimResources(&ack);
5479 host_impl_->DidSwapBuffersComplete();
5480 EXPECT_EQ(swap_buffers_complete_, 1);
5483 class CountingSoftwareDevice : public SoftwareOutputDevice {
5484 public:
5485 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5487 virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
5488 ++frames_began_;
5489 return SoftwareOutputDevice::BeginPaint(damage_rect);
5491 virtual void EndPaint(SoftwareFrameData* frame_data) OVERRIDE {
5492 ++frames_ended_;
5493 SoftwareOutputDevice::EndPaint(frame_data);
5496 int frames_began_, frames_ended_;
5499 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
5500 // No main thread evictions in resourceless software mode.
5501 set_reduce_memory_result(false);
5502 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
5503 bool delegated_rendering = false;
5504 FakeOutputSurface* output_surface =
5505 FakeOutputSurface::CreateDeferredGL(
5506 scoped_ptr<SoftwareOutputDevice>(software_device),
5507 delegated_rendering).release();
5508 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5509 scoped_ptr<OutputSurface>(output_surface)));
5510 host_impl_->SetViewportSize(gfx::Size(50, 50));
5512 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5514 output_surface->set_forced_draw_to_software_device(true);
5515 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5517 EXPECT_EQ(0, software_device->frames_began_);
5518 EXPECT_EQ(0, software_device->frames_ended_);
5520 DrawFrame();
5522 EXPECT_EQ(1, software_device->frames_began_);
5523 EXPECT_EQ(1, software_device->frames_ended_);
5525 // Call other API methods that are likely to hit NULL pointer in this mode.
5526 EXPECT_TRUE(host_impl_->AsValue());
5527 EXPECT_TRUE(host_impl_->ActivationStateAsValue());
5530 TEST_F(LayerTreeHostImplTest,
5531 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
5532 set_reduce_memory_result(false);
5533 bool delegated_rendering = false;
5534 FakeOutputSurface* output_surface =
5535 FakeOutputSurface::CreateDeferredGL(
5536 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5537 delegated_rendering).release();
5538 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5539 scoped_ptr<OutputSurface>(output_surface)));
5541 output_surface->set_forced_draw_to_software_device(true);
5542 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5544 // SolidColorLayerImpl will be drawn.
5545 scoped_ptr<SolidColorLayerImpl> root_layer =
5546 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5548 // VideoLayerImpl will not be drawn.
5549 FakeVideoFrameProvider provider;
5550 scoped_ptr<VideoLayerImpl> video_layer =
5551 VideoLayerImpl::Create(host_impl_->active_tree(), 2, &provider);
5552 video_layer->SetBounds(gfx::Size(10, 10));
5553 video_layer->SetContentBounds(gfx::Size(10, 10));
5554 video_layer->SetDrawsContent(true);
5555 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
5556 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5558 LayerTreeHostImpl::FrameData frame;
5559 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5560 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5561 host_impl_->DidDrawAllLayers(frame);
5563 EXPECT_EQ(1u, frame.will_draw_layers.size());
5564 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
5567 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
5568 protected:
5569 virtual void SetUp() OVERRIDE {
5570 LayerTreeHostImplTest::SetUp();
5572 set_reduce_memory_result(false);
5574 bool delegated_rendering = false;
5575 scoped_ptr<FakeOutputSurface> output_surface(
5576 FakeOutputSurface::CreateDeferredGL(
5577 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5578 delegated_rendering));
5579 output_surface_ = output_surface.get();
5581 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5582 output_surface.PassAs<OutputSurface>()));
5584 scoped_ptr<SolidColorLayerImpl> root_layer =
5585 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5586 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5588 onscreen_context_provider_ = TestContextProvider::Create();
5591 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {
5592 did_update_renderer_capabilities_ = true;
5595 FakeOutputSurface* output_surface_;
5596 scoped_refptr<TestContextProvider> onscreen_context_provider_;
5597 bool did_update_renderer_capabilities_;
5601 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
5602 // Software draw.
5603 DrawFrame();
5605 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5607 // DeferredInitialize and hardware draw.
5608 did_update_renderer_capabilities_ = false;
5609 EXPECT_TRUE(
5610 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5611 EXPECT_EQ(onscreen_context_provider_,
5612 host_impl_->output_surface()->context_provider());
5613 EXPECT_TRUE(did_update_renderer_capabilities_);
5615 // Defer intialized GL draw.
5616 DrawFrame();
5618 // Revert back to software.
5619 did_update_renderer_capabilities_ = false;
5620 output_surface_->ReleaseGL();
5621 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5622 EXPECT_TRUE(did_update_renderer_capabilities_);
5624 // Software draw again.
5625 DrawFrame();
5628 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails) {
5629 // Software draw.
5630 DrawFrame();
5632 // Fail initialization of the onscreen context before the OutputSurface binds
5633 // it to the thread.
5634 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5636 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5638 // DeferredInitialize fails.
5639 did_update_renderer_capabilities_ = false;
5640 EXPECT_FALSE(
5641 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5642 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5643 EXPECT_FALSE(did_update_renderer_capabilities_);
5645 // Software draw again.
5646 DrawFrame();
5649 // Checks that we have a non-0 default allocation if we pass a context that
5650 // doesn't support memory management extensions.
5651 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5652 LayerTreeSettings settings;
5653 host_impl_ = LayerTreeHostImpl::Create(settings,
5654 this,
5655 &proxy_,
5656 &stats_instrumentation_,
5657 shared_bitmap_manager_.get(),
5660 scoped_ptr<OutputSurface> output_surface(
5661 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5662 host_impl_->InitializeRenderer(output_surface.Pass());
5663 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5666 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5667 ManagedMemoryPolicy policy1(
5668 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5669 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5670 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5671 int allow_nice_to_have_cutoff_value =
5672 ManagedMemoryPolicy::PriorityCutoffToValue(
5673 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
5674 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5675 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5677 // GPU rasterization should be disabled by default on the tree(s)
5678 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
5679 EXPECT_TRUE(host_impl_->pending_tree() == NULL);
5681 host_impl_->SetVisible(true);
5682 host_impl_->SetMemoryPolicy(policy1);
5683 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5684 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5686 host_impl_->SetVisible(false);
5687 EXPECT_EQ(0u, current_limit_bytes_);
5688 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5690 host_impl_->SetVisible(true);
5691 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5692 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5694 // Now enable GPU rasterization and test if we get nice to have cutoff,
5695 // when visible.
5696 LayerTreeSettings settings;
5697 settings.gpu_rasterization_enabled = true;
5698 host_impl_ = LayerTreeHostImpl::Create(
5699 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
5700 host_impl_->SetUseGpuRasterization(true);
5701 host_impl_->SetVisible(true);
5702 host_impl_->SetMemoryPolicy(policy1);
5703 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5704 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
5706 host_impl_->SetVisible(false);
5707 EXPECT_EQ(0u, current_limit_bytes_);
5708 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5711 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
5712 ASSERT_TRUE(host_impl_->active_tree());
5714 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5715 host_impl_->SetVisible(false);
5716 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5717 host_impl_->SetVisible(true);
5718 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5719 host_impl_->SetVisible(false);
5720 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5722 host_impl_->CreatePendingTree();
5723 host_impl_->ActivatePendingTree();
5725 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5726 host_impl_->SetVisible(true);
5727 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5730 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
5731 ASSERT_TRUE(host_impl_->active_tree());
5732 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
5734 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5735 host_impl_->SetUseGpuRasterization(false);
5736 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5737 host_impl_->SetUseGpuRasterization(true);
5738 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5739 host_impl_->SetUseGpuRasterization(false);
5740 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5742 host_impl_->CreatePendingTree();
5743 host_impl_->ActivatePendingTree();
5745 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5746 host_impl_->SetUseGpuRasterization(true);
5747 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5750 class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
5751 public:
5752 virtual void SetUp() OVERRIDE {
5753 LayerTreeSettings settings;
5754 settings.impl_side_painting = true;
5756 fake_host_impl_ = new FakeLayerTreeHostImpl(
5757 settings, &proxy_, shared_bitmap_manager_.get());
5758 host_impl_.reset(fake_host_impl_);
5759 host_impl_->InitializeRenderer(CreateOutputSurface());
5760 host_impl_->SetViewportSize(gfx::Size(10, 10));
5763 FakeLayerTreeHostImpl* fake_host_impl_;
5766 TEST_F(LayerTreeHostImplTestManageTiles, ManageTilesWhenInvisible) {
5767 fake_host_impl_->DidModifyTilePriorities();
5768 EXPECT_TRUE(fake_host_impl_->manage_tiles_needed());
5769 fake_host_impl_->SetVisible(false);
5770 EXPECT_FALSE(fake_host_impl_->manage_tiles_needed());
5773 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
5774 scoped_ptr<TestWebGraphicsContext3D> context =
5775 TestWebGraphicsContext3D::Create();
5776 TestWebGraphicsContext3D* context3d = context.get();
5777 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5778 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5780 EXPECT_EQ(0u, context3d->NumTextures());
5782 UIResourceId ui_resource_id = 1;
5783 bool is_opaque = false;
5784 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
5785 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5786 EXPECT_EQ(1u, context3d->NumTextures());
5787 ResourceProvider::ResourceId id1 =
5788 host_impl_->ResourceIdForUIResource(ui_resource_id);
5789 EXPECT_NE(0u, id1);
5791 // Multiple requests with the same id is allowed. The previous texture is
5792 // deleted.
5793 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5794 EXPECT_EQ(1u, context3d->NumTextures());
5795 ResourceProvider::ResourceId id2 =
5796 host_impl_->ResourceIdForUIResource(ui_resource_id);
5797 EXPECT_NE(0u, id2);
5798 EXPECT_NE(id1, id2);
5800 // Deleting invalid UIResourceId is allowed and does not change state.
5801 host_impl_->DeleteUIResource(-1);
5802 EXPECT_EQ(1u, context3d->NumTextures());
5804 // Should return zero for invalid UIResourceId. Number of textures should
5805 // not change.
5806 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
5807 EXPECT_EQ(1u, context3d->NumTextures());
5809 host_impl_->DeleteUIResource(ui_resource_id);
5810 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
5811 EXPECT_EQ(0u, context3d->NumTextures());
5813 // Should not change state for multiple deletion on one UIResourceId
5814 host_impl_->DeleteUIResource(ui_resource_id);
5815 EXPECT_EQ(0u, context3d->NumTextures());
5818 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
5819 scoped_ptr<TestWebGraphicsContext3D> context =
5820 TestWebGraphicsContext3D::Create();
5821 TestWebGraphicsContext3D* context3d = context.get();
5822 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5823 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5825 EXPECT_EQ(0u, context3d->NumTextures());
5827 gfx::Size size(4, 4);
5828 // SkImageInfo has no support for ETC1. The |info| below contains the right
5829 // total pixel size for the bitmap but not the right height and width. The
5830 // correct width/height are passed directly to UIResourceBitmap.
5831 SkImageInfo info =
5832 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
5833 skia::RefPtr<SkPixelRef> pixel_ref =
5834 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
5835 pixel_ref->setImmutable();
5836 UIResourceBitmap bitmap(pixel_ref, size);
5837 UIResourceId ui_resource_id = 1;
5838 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5839 EXPECT_EQ(1u, context3d->NumTextures());
5840 ResourceProvider::ResourceId id1 =
5841 host_impl_->ResourceIdForUIResource(ui_resource_id);
5842 EXPECT_NE(0u, id1);
5845 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
5848 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
5849 scoped_refptr<TestContextProvider> context_provider =
5850 TestContextProvider::Create();
5852 CreateHostImpl(
5853 DefaultSettings(),
5854 FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>());
5856 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5858 ScopedPtrVector<CopyOutputRequest> requests;
5859 requests.push_back(CopyOutputRequest::CreateRequest(
5860 base::Bind(&ShutdownReleasesContext_Callback)));
5862 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
5864 LayerTreeHostImpl::FrameData frame;
5865 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5866 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5867 host_impl_->DidDrawAllLayers(frame);
5869 // The CopyOutputResult's callback has a ref on the ContextProvider and a
5870 // texture in a texture mailbox.
5871 EXPECT_FALSE(context_provider->HasOneRef());
5872 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
5874 host_impl_.reset();
5876 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
5877 // released, and the texture deleted.
5878 EXPECT_TRUE(context_provider->HasOneRef());
5879 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
5882 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
5883 // When flinging via touch, only the child should scroll (we should not
5884 // bubble).
5885 gfx::Size surface_size(10, 10);
5886 gfx::Size content_size(20, 20);
5887 scoped_ptr<LayerImpl> root_clip =
5888 LayerImpl::Create(host_impl_->active_tree(), 3);
5889 scoped_ptr<LayerImpl> root =
5890 CreateScrollableLayer(1, content_size, root_clip.get());
5891 root->SetIsContainerForFixedPositionLayers(true);
5892 scoped_ptr<LayerImpl> child =
5893 CreateScrollableLayer(2, content_size, root_clip.get());
5895 root->AddChild(child.Pass());
5896 int root_id = root->id();
5897 root_clip->AddChild(root.Pass());
5899 host_impl_->SetViewportSize(surface_size);
5900 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
5901 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
5902 host_impl_->active_tree()->DidBecomeActive();
5903 DrawFrame();
5905 EXPECT_EQ(InputHandler::ScrollStarted,
5906 host_impl_->ScrollBegin(gfx::Point(),
5907 InputHandler::Gesture));
5909 EXPECT_EQ(InputHandler::ScrollStarted,
5910 host_impl_->FlingScrollBegin());
5912 gfx::Vector2d scroll_delta(0, 100);
5913 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5914 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5916 host_impl_->ScrollEnd();
5918 scoped_ptr<ScrollAndScaleSet> scroll_info =
5919 host_impl_->ProcessScrollDeltas();
5921 // Only the child should have scrolled.
5922 ASSERT_EQ(1u, scroll_info->scrolls.size());
5923 ExpectNone(*scroll_info.get(), root_id);
5927 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
5928 // Scroll a child layer beyond its maximum scroll range and make sure the
5929 // the scroll doesn't bubble up to the parent layer.
5930 gfx::Size surface_size(10, 10);
5931 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
5932 scoped_ptr<LayerImpl> root_scrolling =
5933 CreateScrollableLayer(2, surface_size, root.get());
5935 scoped_ptr<LayerImpl> grand_child =
5936 CreateScrollableLayer(4, surface_size, root.get());
5937 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
5939 scoped_ptr<LayerImpl> child =
5940 CreateScrollableLayer(3, surface_size, root.get());
5941 child->SetScrollOffset(gfx::Vector2d(0, 4));
5942 child->AddChild(grand_child.Pass());
5944 root_scrolling->AddChild(child.Pass());
5945 root->AddChild(root_scrolling.Pass());
5946 host_impl_->active_tree()->SetRootLayer(root.Pass());
5947 host_impl_->active_tree()->DidBecomeActive();
5948 host_impl_->SetViewportSize(surface_size);
5949 DrawFrame();
5951 scoped_ptr<ScrollAndScaleSet> scroll_info;
5952 LayerImpl* child =
5953 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
5954 LayerImpl* grand_child = child->children()[0];
5956 gfx::Vector2d scroll_delta(0, -2);
5957 EXPECT_EQ(InputHandler::ScrollStarted,
5958 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
5959 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5961 // The grand child should have scrolled up to its limit.
5962 scroll_info = host_impl_->ProcessScrollDeltas();
5963 ASSERT_EQ(1u, scroll_info->scrolls.size());
5964 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5965 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
5967 // The child should have received the bubbled delta, but the locked
5968 // scrolling layer should remain set as the grand child.
5969 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5970 scroll_info = host_impl_->ProcessScrollDeltas();
5971 ASSERT_EQ(2u, scroll_info->scrolls.size());
5972 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5973 ExpectContains(*scroll_info, child->id(), scroll_delta);
5974 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
5976 // The first |ScrollBy| after the fling should re-lock the scrolling
5977 // layer to the first layer that scrolled, which is the child.
5978 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
5979 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5980 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
5982 // The child should have scrolled up to its limit.
5983 scroll_info = host_impl_->ProcessScrollDeltas();
5984 ASSERT_EQ(2u, scroll_info->scrolls.size());
5985 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5986 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
5988 // As the locked layer is at it's limit, no further scrolling can occur.
5989 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5990 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
5991 host_impl_->ScrollEnd();
5995 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
5996 // When flinging via wheel, the root should eventually scroll (we should
5997 // bubble).
5998 gfx::Size surface_size(10, 10);
5999 gfx::Size content_size(20, 20);
6000 scoped_ptr<LayerImpl> root_clip =
6001 LayerImpl::Create(host_impl_->active_tree(), 3);
6002 scoped_ptr<LayerImpl> root_scroll =
6003 CreateScrollableLayer(1, content_size, root_clip.get());
6004 int root_scroll_id = root_scroll->id();
6005 scoped_ptr<LayerImpl> child =
6006 CreateScrollableLayer(2, content_size, root_clip.get());
6008 root_scroll->AddChild(child.Pass());
6009 root_clip->AddChild(root_scroll.Pass());
6011 host_impl_->SetViewportSize(surface_size);
6012 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6013 host_impl_->active_tree()->DidBecomeActive();
6014 DrawFrame();
6016 EXPECT_EQ(InputHandler::ScrollStarted,
6017 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6019 EXPECT_EQ(InputHandler::ScrollStarted,
6020 host_impl_->FlingScrollBegin());
6022 gfx::Vector2d scroll_delta(0, 100);
6023 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6024 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6026 host_impl_->ScrollEnd();
6028 scoped_ptr<ScrollAndScaleSet> scroll_info =
6029 host_impl_->ProcessScrollDeltas();
6031 // The root should have scrolled.
6032 ASSERT_EQ(2u, scroll_info->scrolls.size());
6033 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
6037 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6038 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6039 // we should return ScrollUnknown.
6040 gfx::Size content_size(100, 100);
6041 SetupScrollAndContentsLayers(content_size);
6043 int scroll_layer_id = 2;
6044 LayerImpl* scroll_layer =
6045 host_impl_->active_tree()->LayerById(scroll_layer_id);
6046 scroll_layer->SetDrawsContent(true);
6048 int page_scale_layer_id = 5;
6049 LayerImpl* page_scale_layer =
6050 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6052 int occluder_layer_id = 6;
6053 scoped_ptr<LayerImpl> occluder_layer =
6054 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6055 occluder_layer->SetDrawsContent(true);
6056 occluder_layer->SetBounds(content_size);
6057 occluder_layer->SetContentBounds(content_size);
6058 occluder_layer->SetPosition(gfx::PointF());
6060 // The parent of the occluder is *above* the scroller.
6061 page_scale_layer->AddChild(occluder_layer.Pass());
6063 DrawFrame();
6065 EXPECT_EQ(InputHandler::ScrollUnknown,
6066 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6069 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6070 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6071 // is not the first scroller we encounter when walking up from the layer, we
6072 // should also return ScrollUnknown.
6073 gfx::Size content_size(100, 100);
6074 SetupScrollAndContentsLayers(content_size);
6076 int scroll_layer_id = 2;
6077 LayerImpl* scroll_layer =
6078 host_impl_->active_tree()->LayerById(scroll_layer_id);
6079 scroll_layer->SetDrawsContent(true);
6081 int occluder_layer_id = 6;
6082 scoped_ptr<LayerImpl> occluder_layer =
6083 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6084 occluder_layer->SetDrawsContent(true);
6085 occluder_layer->SetBounds(content_size);
6086 occluder_layer->SetContentBounds(content_size);
6087 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6089 int child_scroll_clip_layer_id = 7;
6090 scoped_ptr<LayerImpl> child_scroll_clip =
6091 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6093 int child_scroll_layer_id = 8;
6094 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6095 child_scroll_layer_id, content_size, child_scroll_clip.get());
6097 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6099 child_scroll->AddChild(occluder_layer.Pass());
6100 scroll_layer->AddChild(child_scroll.Pass());
6102 DrawFrame();
6104 EXPECT_EQ(InputHandler::ScrollUnknown,
6105 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6108 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) {
6109 gfx::Size content_size(100, 100);
6110 SetupScrollAndContentsLayers(content_size);
6112 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6114 int scroll_layer_id = 2;
6115 LayerImpl* scroll_layer =
6116 host_impl_->active_tree()->LayerById(scroll_layer_id);
6118 int child_scroll_layer_id = 7;
6119 scoped_ptr<LayerImpl> child_scroll =
6120 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6121 child_scroll->SetDrawsContent(false);
6123 scroll_layer->AddChild(child_scroll.Pass());
6125 DrawFrame();
6127 // We should not have scrolled |child_scroll| even though we technically "hit"
6128 // it. The reason for this is that if the scrolling the scroll would not move
6129 // any layer that is a drawn RSLL member, then we can ignore the hit.
6131 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6132 // overscrolling the inner viewport.
6133 EXPECT_EQ(InputHandler::ScrollStarted,
6134 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6136 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6139 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6140 // This test case is very similar to the one above with one key difference:
6141 // the invisible scroller has a scroll child that is indeed draw contents.
6142 // If we attempt to initiate a gesture scroll off of the visible scroll child
6143 // we should still start the scroll child.
6144 gfx::Size content_size(100, 100);
6145 SetupScrollAndContentsLayers(content_size);
6147 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6149 int scroll_layer_id = 2;
6150 LayerImpl* scroll_layer =
6151 host_impl_->active_tree()->LayerById(scroll_layer_id);
6153 int scroll_child_id = 6;
6154 scoped_ptr<LayerImpl> scroll_child =
6155 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6156 scroll_child->SetDrawsContent(true);
6157 scroll_child->SetBounds(content_size);
6158 scroll_child->SetContentBounds(content_size);
6159 // Move the scroll child so it's not hit by our test point.
6160 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6162 int invisible_scroll_layer_id = 7;
6163 scoped_ptr<LayerImpl> invisible_scroll =
6164 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6165 invisible_scroll->SetDrawsContent(false);
6167 int container_id = 8;
6168 scoped_ptr<LayerImpl> container =
6169 LayerImpl::Create(host_impl_->active_tree(), container_id);
6171 scoped_ptr<std::set<LayerImpl*> > scroll_children(new std::set<LayerImpl*>());
6172 scroll_children->insert(scroll_child.get());
6173 invisible_scroll->SetScrollChildren(scroll_children.release());
6175 scroll_child->SetScrollParent(invisible_scroll.get());
6177 container->AddChild(invisible_scroll.Pass());
6178 container->AddChild(scroll_child.Pass());
6180 scroll_layer->AddChild(container.Pass());
6182 DrawFrame();
6184 // We should not have scrolled |child_scroll| even though we technically "hit"
6185 // it. The reason for this is that if the scrolling the scroll would not move
6186 // any layer that is a drawn RSLL member, then we can ignore the hit.
6188 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6189 // overscrolling the inner viewport.
6190 EXPECT_EQ(InputHandler::ScrollStarted,
6191 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6193 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6196 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6197 // to CompositorFrameMetadata after SwapBuffers();
6198 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6199 scoped_ptr<SolidColorLayerImpl> root =
6200 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6201 root->SetPosition(gfx::PointF());
6202 root->SetBounds(gfx::Size(10, 10));
6203 root->SetContentBounds(gfx::Size(10, 10));
6204 root->SetDrawsContent(true);
6206 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
6208 FakeOutputSurface* fake_output_surface =
6209 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6211 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6212 fake_output_surface->last_sent_frame().metadata.latency_info;
6213 EXPECT_TRUE(metadata_latency_before.empty());
6215 ui::LatencyInfo latency_info;
6216 latency_info.AddLatencyNumber(
6217 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6218 scoped_ptr<SwapPromise> swap_promise(
6219 new LatencyInfoSwapPromise(latency_info));
6220 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
6221 host_impl_->SetNeedsRedraw();
6223 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6224 LayerTreeHostImpl::FrameData frame;
6225 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6226 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6227 host_impl_->DidDrawAllLayers(frame);
6228 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6230 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6231 fake_output_surface->last_sent_frame().metadata.latency_info;
6232 EXPECT_EQ(1u, metadata_latency_after.size());
6233 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6234 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6237 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
6238 public:
6239 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
6240 LayerTreeHostImpl* layer_tree_host_impl,
6241 int* set_needs_commit_count,
6242 int* set_needs_redraw_count)
6243 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
6244 set_needs_commit_count_(set_needs_commit_count),
6245 set_needs_redraw_count_(set_needs_redraw_count) {}
6247 virtual ~SimpleSwapPromiseMonitor() {}
6249 virtual void OnSetNeedsCommitOnMain() OVERRIDE {
6250 (*set_needs_commit_count_)++;
6253 virtual void OnSetNeedsRedrawOnImpl() OVERRIDE {
6254 (*set_needs_redraw_count_)++;
6257 private:
6258 int* set_needs_commit_count_;
6259 int* set_needs_redraw_count_;
6262 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
6263 int set_needs_commit_count = 0;
6264 int set_needs_redraw_count = 0;
6267 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6268 new SimpleSwapPromiseMonitor(NULL,
6269 host_impl_.get(),
6270 &set_needs_commit_count,
6271 &set_needs_redraw_count));
6272 host_impl_->SetNeedsRedraw();
6273 EXPECT_EQ(0, set_needs_commit_count);
6274 EXPECT_EQ(1, set_needs_redraw_count);
6277 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6278 // monitored.
6279 host_impl_->SetNeedsRedraw();
6280 EXPECT_EQ(0, set_needs_commit_count);
6281 EXPECT_EQ(1, set_needs_redraw_count);
6284 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6285 new SimpleSwapPromiseMonitor(NULL,
6286 host_impl_.get(),
6287 &set_needs_commit_count,
6288 &set_needs_redraw_count));
6289 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
6290 EXPECT_EQ(0, set_needs_commit_count);
6291 EXPECT_EQ(2, set_needs_redraw_count);
6295 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6296 new SimpleSwapPromiseMonitor(NULL,
6297 host_impl_.get(),
6298 &set_needs_commit_count,
6299 &set_needs_redraw_count));
6300 // Empty damage rect won't signal the monitor.
6301 host_impl_->SetNeedsRedrawRect(gfx::Rect());
6302 EXPECT_EQ(0, set_needs_commit_count);
6303 EXPECT_EQ(2, set_needs_redraw_count);
6307 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
6308 public:
6309 virtual void SetUp() OVERRIDE {
6310 LayerTreeSettings settings = DefaultSettings();
6311 settings.calculate_top_controls_position = true;
6312 settings.top_controls_height = top_controls_height_;
6313 CreateHostImpl(settings, CreateOutputSurface());
6316 protected:
6317 static const int top_controls_height_;
6320 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
6322 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
6323 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6324 ->SetScrollOffset(gfx::Vector2d(0, 10));
6325 host_impl_->Animate(base::TimeTicks());
6326 EXPECT_FALSE(did_request_redraw_);
6329 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
6330 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6331 ->SetScrollOffset(gfx::Vector2d(0, 10));
6332 host_impl_->DidChangeTopControlsPosition();
6333 EXPECT_TRUE(did_request_animate_);
6334 EXPECT_TRUE(did_request_redraw_);
6337 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
6338 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6339 host_impl_->SetViewportSize(gfx::Size(100, 100));
6340 DrawFrame();
6342 EXPECT_EQ(InputHandler::ScrollStarted,
6343 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6344 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6345 EXPECT_EQ(gfx::Vector2dF().ToString(),
6346 scroll_layer->TotalScrollOffset().ToString());
6348 // Scroll just the top controls and verify that the scroll succeeds.
6349 const float residue = 10;
6350 float offset = top_controls_height_ - residue;
6351 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6352 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->controls_top_offset());
6353 EXPECT_EQ(gfx::Vector2dF().ToString(),
6354 scroll_layer->TotalScrollOffset().ToString());
6356 // Scroll across the boundary
6357 const float content_scroll = 20;
6358 offset = residue + content_scroll;
6359 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6360 EXPECT_EQ(-top_controls_height_,
6361 host_impl_->top_controls_manager()->controls_top_offset());
6362 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
6363 scroll_layer->TotalScrollOffset().ToString());
6365 // Now scroll back to the top of the content
6366 offset = -content_scroll;
6367 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6368 EXPECT_EQ(-top_controls_height_,
6369 host_impl_->top_controls_manager()->controls_top_offset());
6370 EXPECT_EQ(gfx::Vector2dF().ToString(),
6371 scroll_layer->TotalScrollOffset().ToString());
6373 // And scroll the top controls completely into view
6374 offset = -top_controls_height_;
6375 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6376 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6377 EXPECT_EQ(gfx::Vector2dF().ToString(),
6378 scroll_layer->TotalScrollOffset().ToString());
6380 // And attempt to scroll past the end
6381 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6382 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6383 EXPECT_EQ(gfx::Vector2dF().ToString(),
6384 scroll_layer->TotalScrollOffset().ToString());
6386 host_impl_->ScrollEnd();
6389 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
6390 public:
6391 void SetupVirtualViewportLayers(const gfx::Size& content_size,
6392 const gfx::Size& outer_viewport,
6393 const gfx::Size& inner_viewport) {
6394 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
6395 const int kOuterViewportClipLayerId = 6;
6396 const int kOuterViewportScrollLayerId = 7;
6397 const int kInnerViewportScrollLayerId = 2;
6398 const int kInnerViewportClipLayerId = 4;
6399 const int kPageScaleLayerId = 5;
6401 scoped_ptr<LayerImpl> inner_scroll =
6402 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
6403 inner_scroll->SetIsContainerForFixedPositionLayers(true);
6404 inner_scroll->SetScrollOffset(gfx::Vector2d());
6406 scoped_ptr<LayerImpl> inner_clip =
6407 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
6408 inner_clip->SetBounds(inner_viewport);
6410 scoped_ptr<LayerImpl> page_scale =
6411 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
6413 inner_scroll->SetScrollClipLayer(inner_clip->id());
6414 inner_scroll->SetBounds(outer_viewport);
6415 inner_scroll->SetContentBounds(outer_viewport);
6416 inner_scroll->SetPosition(gfx::PointF());
6418 scoped_ptr<LayerImpl> outer_clip =
6419 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
6420 outer_clip->SetBounds(outer_viewport);
6421 outer_clip->SetIsContainerForFixedPositionLayers(true);
6423 scoped_ptr<LayerImpl> outer_scroll =
6424 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
6425 outer_scroll->SetScrollClipLayer(outer_clip->id());
6426 outer_scroll->SetScrollOffset(gfx::Vector2d());
6427 outer_scroll->SetBounds(content_size);
6428 outer_scroll->SetContentBounds(content_size);
6429 outer_scroll->SetPosition(gfx::PointF());
6431 scoped_ptr<LayerImpl> contents =
6432 LayerImpl::Create(layer_tree_impl, 8);
6433 contents->SetDrawsContent(true);
6434 contents->SetBounds(content_size);
6435 contents->SetContentBounds(content_size);
6436 contents->SetPosition(gfx::PointF());
6438 outer_scroll->AddChild(contents.Pass());
6439 outer_clip->AddChild(outer_scroll.Pass());
6440 inner_scroll->AddChild(outer_clip.Pass());
6441 page_scale->AddChild(inner_scroll.Pass());
6442 inner_clip->AddChild(page_scale.Pass());
6444 layer_tree_impl->SetRootLayer(inner_clip.Pass());
6445 layer_tree_impl->SetViewportLayersFromIds(kPageScaleLayerId,
6446 kInnerViewportScrollLayerId, kOuterViewportScrollLayerId);
6448 host_impl_->active_tree()->DidBecomeActive();
6452 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
6453 gfx::Size content_size = gfx::Size(100, 160);
6454 gfx::Size outer_viewport = gfx::Size(50, 80);
6455 gfx::Size inner_viewport = gfx::Size(25, 40);
6457 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
6459 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
6460 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
6461 DrawFrame();
6463 gfx::Vector2dF inner_expected;
6464 gfx::Vector2dF outer_expected;
6465 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6466 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6468 // Make sure the fling goes to the outer viewport first
6469 EXPECT_EQ(InputHandler::ScrollStarted,
6470 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6471 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6473 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
6474 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6475 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6477 host_impl_->ScrollEnd();
6479 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6480 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6482 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
6483 EXPECT_EQ(InputHandler::ScrollStarted,
6484 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6485 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6487 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6488 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6490 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6491 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6493 host_impl_->ScrollEnd();
6495 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6496 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6500 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
6501 public:
6502 virtual void SetUp() OVERRIDE {
6503 LayerTreeSettings settings = DefaultSettings();
6504 settings.max_memory_for_prepaint_percentage = 50;
6505 CreateHostImpl(settings, CreateOutputSurface());
6509 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
6510 // Set up a memory policy and percentages which could cause
6511 // 32-bit integer overflows.
6512 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
6514 // Verify implicit limits are calculated correctly with no overflows
6515 host_impl_->SetMemoryPolicy(mem_policy);
6516 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
6517 300u * 1024u * 1024u);
6518 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
6519 150u * 1024u * 1024u);
6522 TEST_F(LayerTreeHostImplTest, UpdateTilesForMasksWithNoVisibleContent) {
6523 gfx::Size bounds(100000, 100);
6525 host_impl_->CreatePendingTree();
6527 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->pending_tree(), 1);
6529 scoped_ptr<FakePictureLayerImpl> layer_with_mask =
6530 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 2);
6532 layer_with_mask->SetBounds(bounds);
6534 scoped_ptr<FakePictureLayerImpl> mask =
6535 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 3);
6537 mask->SetIsMask(true);
6538 mask->SetBounds(bounds);
6540 FakePictureLayerImpl* pending_mask_content = mask.get();
6541 layer_with_mask->SetMaskLayer(mask.PassAs<LayerImpl>());
6543 scoped_ptr<FakePictureLayerImpl> child_of_layer_with_mask =
6544 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 4);
6546 child_of_layer_with_mask->SetBounds(bounds);
6547 child_of_layer_with_mask->SetDrawsContent(true);
6549 layer_with_mask->AddChild(child_of_layer_with_mask.PassAs<LayerImpl>());
6551 root->AddChild(layer_with_mask.PassAs<LayerImpl>());
6553 host_impl_->pending_tree()->SetRootLayer(root.Pass());
6555 gfx::Rect r1 = pending_mask_content->visible_rect_for_tile_priority();
6556 ASSERT_EQ(0, r1.x());
6557 ASSERT_EQ(0, r1.y());
6558 ASSERT_EQ(0, r1.width());
6559 ASSERT_EQ(0, r1.height());
6561 host_impl_->ActivatePendingTree();
6563 host_impl_->active_tree()->UpdateDrawProperties();
6565 ASSERT_EQ(2u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
6567 FakePictureLayerImpl* active_mask_content =
6568 static_cast<FakePictureLayerImpl*>(
6569 host_impl_->active_tree()->root_layer()->children()[0]->mask_layer());
6570 gfx::Rect r2 = active_mask_content->visible_rect_for_tile_priority();
6572 ASSERT_TRUE(!r2.IsEmpty());
6575 } // namespace
6576 } // namespace cc