IndexedDB: fsync after transactions.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blob479754128250cf59c2ba6c131b9b3bcb16035141
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/delegated_renderer_layer_impl.h"
18 #include "cc/layers/heads_up_display_layer_impl.h"
19 #include "cc/layers/io_surface_layer_impl.h"
20 #include "cc/layers/layer_impl.h"
21 #include "cc/layers/painted_scrollbar_layer_impl.h"
22 #include "cc/layers/quad_sink.h"
23 #include "cc/layers/render_surface_impl.h"
24 #include "cc/layers/solid_color_layer_impl.h"
25 #include "cc/layers/texture_layer_impl.h"
26 #include "cc/layers/tiled_layer_impl.h"
27 #include "cc/layers/video_layer_impl.h"
28 #include "cc/output/begin_frame_args.h"
29 #include "cc/output/compositor_frame_ack.h"
30 #include "cc/output/compositor_frame_metadata.h"
31 #include "cc/output/copy_output_request.h"
32 #include "cc/output/copy_output_result.h"
33 #include "cc/output/gl_renderer.h"
34 #include "cc/quads/render_pass_draw_quad.h"
35 #include "cc/quads/solid_color_draw_quad.h"
36 #include "cc/quads/texture_draw_quad.h"
37 #include "cc/quads/tile_draw_quad.h"
38 #include "cc/resources/layer_tiling_data.h"
39 #include "cc/test/animation_test_common.h"
40 #include "cc/test/fake_layer_tree_host_impl.h"
41 #include "cc/test/fake_output_surface.h"
42 #include "cc/test/fake_output_surface_client.h"
43 #include "cc/test/fake_picture_layer_impl.h"
44 #include "cc/test/fake_picture_pile_impl.h"
45 #include "cc/test/fake_proxy.h"
46 #include "cc/test/fake_rendering_stats_instrumentation.h"
47 #include "cc/test/fake_video_frame_provider.h"
48 #include "cc/test/geometry_test_utils.h"
49 #include "cc/test/layer_test_common.h"
50 #include "cc/test/render_pass_test_common.h"
51 #include "cc/test/test_web_graphics_context_3d.h"
52 #include "cc/trees/layer_tree_impl.h"
53 #include "cc/trees/single_thread_proxy.h"
54 #include "media/base/media.h"
55 #include "testing/gmock/include/gmock/gmock.h"
56 #include "testing/gtest/include/gtest/gtest.h"
57 #include "third_party/skia/include/core/SkMallocPixelRef.h"
58 #include "ui/gfx/frame_time.h"
59 #include "ui/gfx/rect_conversions.h"
60 #include "ui/gfx/size_conversions.h"
61 #include "ui/gfx/vector2d_conversions.h"
63 using ::testing::Mock;
64 using ::testing::Return;
65 using ::testing::AnyNumber;
66 using ::testing::AtLeast;
67 using ::testing::_;
68 using media::VideoFrame;
70 namespace cc {
71 namespace {
73 class LayerTreeHostImplTest : public testing::Test,
74 public LayerTreeHostImplClient {
75 public:
76 LayerTreeHostImplTest()
77 : proxy_(),
78 always_impl_thread_(&proxy_),
79 always_main_thread_blocked_(&proxy_),
80 on_can_draw_state_changed_called_(false),
81 did_notify_ready_to_activate_(false),
82 did_request_commit_(false),
83 did_request_redraw_(false),
84 did_request_manage_tiles_(false),
85 did_upload_visible_tile_(false),
86 reduce_memory_result_(true),
87 current_limit_bytes_(0),
88 current_priority_cutoff_value_(0) {
89 media::InitializeMediaLibraryForTesting();
92 LayerTreeSettings DefaultSettings() {
93 LayerTreeSettings settings;
94 settings.minimum_occlusion_tracking_size = gfx::Size();
95 settings.impl_side_painting = true;
96 settings.texture_id_allocation_chunk_size = 1;
97 return settings;
100 virtual void SetUp() OVERRIDE {
101 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
104 virtual void TearDown() OVERRIDE {}
106 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
107 virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
108 virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {}
109 virtual void BeginImplFrame(const BeginFrameArgs& args) OVERRIDE {}
110 virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
111 on_can_draw_state_changed_called_ = true;
113 virtual void NotifyReadyToActivate() OVERRIDE {
114 did_notify_ready_to_activate_ = true;
115 host_impl_->ActivatePendingTree();
117 virtual void SetNeedsRedrawOnImplThread() OVERRIDE {
118 did_request_redraw_ = true;
120 virtual void SetNeedsRedrawRectOnImplThread(
121 const gfx::Rect& damage_rect) OVERRIDE {
122 did_request_redraw_ = true;
124 virtual void SetNeedsManageTilesOnImplThread() OVERRIDE {
125 did_request_manage_tiles_ = true;
127 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {
128 did_upload_visible_tile_ = true;
130 virtual void SetNeedsCommitOnImplThread() OVERRIDE {
131 did_request_commit_ = true;
133 virtual void PostAnimationEventsToMainThreadOnImplThread(
134 scoped_ptr<AnimationEventsVector> events,
135 base::Time wall_clock_time) OVERRIDE {}
136 virtual bool ReduceContentsTextureMemoryOnImplThread(
137 size_t limit_bytes, int priority_cutoff) OVERRIDE {
138 current_limit_bytes_ = limit_bytes;
139 current_priority_cutoff_value_ = priority_cutoff;
140 return reduce_memory_result_;
142 virtual void SendManagedMemoryStats() OVERRIDE {}
143 virtual bool IsInsideDraw() OVERRIDE { return false; }
144 virtual void RenewTreePriority() OVERRIDE {}
145 virtual void RequestScrollbarAnimationOnImplThread(base::TimeDelta delay)
146 OVERRIDE { requested_scrollbar_animation_delay_ = delay; }
147 virtual void DidActivatePendingTree() OVERRIDE {}
148 virtual void DidManageTiles() OVERRIDE {}
150 void set_reduce_memory_result(bool reduce_memory_result) {
151 reduce_memory_result_ = reduce_memory_result;
154 bool CreateHostImpl(const LayerTreeSettings& settings,
155 scoped_ptr<OutputSurface> output_surface) {
156 host_impl_ = LayerTreeHostImpl::Create(
157 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
158 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
159 host_impl_->SetViewportSize(gfx::Size(10, 10));
160 return init;
163 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
164 root->SetAnchorPoint(gfx::PointF());
165 root->SetPosition(gfx::PointF());
166 root->SetBounds(gfx::Size(10, 10));
167 root->SetContentBounds(gfx::Size(10, 10));
168 root->SetDrawsContent(true);
169 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
170 host_impl_->active_tree()->SetRootLayer(root.Pass());
173 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
174 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
175 for (size_t i = 0; i < layer->children().size(); ++i)
176 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
179 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
180 int id,
181 gfx::Vector2d scroll_delta) {
182 int times_encountered = 0;
184 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
185 if (scroll_info.scrolls[i].layer_id != id)
186 continue;
187 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
188 times_encountered++;
191 ASSERT_EQ(1, times_encountered);
194 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
195 int times_encountered = 0;
197 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
198 if (scroll_info.scrolls[i].layer_id != id)
199 continue;
200 times_encountered++;
203 ASSERT_EQ(0, times_encountered);
206 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
207 gfx::Size content_size) {
208 scoped_ptr<LayerImpl> root =
209 LayerImpl::Create(layer_tree_impl, 1);
210 root->SetBounds(content_size);
211 root->SetContentBounds(content_size);
212 root->SetPosition(gfx::PointF());
213 root->SetAnchorPoint(gfx::PointF());
215 scoped_ptr<LayerImpl> scroll =
216 LayerImpl::Create(layer_tree_impl, 2);
217 LayerImpl* scroll_layer = scroll.get();
218 scroll->SetScrollable(true);
219 scroll->SetScrollOffset(gfx::Vector2d());
220 scroll->SetMaxScrollOffset(gfx::Vector2d(content_size.width(),
221 content_size.height()));
222 scroll->SetBounds(content_size);
223 scroll->SetContentBounds(content_size);
224 scroll->SetPosition(gfx::PointF());
225 scroll->SetAnchorPoint(gfx::PointF());
227 scoped_ptr<LayerImpl> contents =
228 LayerImpl::Create(layer_tree_impl, 3);
229 contents->SetDrawsContent(true);
230 contents->SetBounds(content_size);
231 contents->SetContentBounds(content_size);
232 contents->SetPosition(gfx::PointF());
233 contents->SetAnchorPoint(gfx::PointF());
235 scroll->AddChild(contents.Pass());
236 root->AddChild(scroll.Pass());
238 layer_tree_impl->SetRootLayer(root.Pass());
239 return scroll_layer;
242 LayerImpl* SetupScrollAndContentsLayers(gfx::Size content_size) {
243 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
244 host_impl_->active_tree(), content_size);
245 host_impl_->active_tree()->DidBecomeActive();
246 return scroll_layer;
249 scoped_ptr<LayerImpl> CreateScrollableLayer(int id, gfx::Size size) {
250 scoped_ptr<LayerImpl> layer =
251 LayerImpl::Create(host_impl_->active_tree(), id);
252 layer->SetScrollable(true);
253 layer->SetDrawsContent(true);
254 layer->SetBounds(size);
255 layer->SetContentBounds(size);
256 layer->SetMaxScrollOffset(gfx::Vector2d(size.width() * 2,
257 size.height() * 2));
258 return layer.Pass();
261 void DrawFrame() {
262 LayerTreeHostImpl::FrameData frame;
263 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
264 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
265 host_impl_->DidDrawAllLayers(frame);
268 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
269 void pinch_zoom_pan_viewport_test(float device_scale_factor);
270 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
271 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
272 float device_scale_factor);
274 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
275 // Note: It is not possible to disable the renderer once it has been set,
276 // so we do not need to test that disabling the renderer notifies us
277 // that can_draw changed.
278 EXPECT_FALSE(host_impl_->CanDraw());
279 on_can_draw_state_changed_called_ = false;
281 // Set up the root layer, which allows us to draw.
282 SetupScrollAndContentsLayers(gfx::Size(100, 100));
283 EXPECT_TRUE(host_impl_->CanDraw());
284 EXPECT_TRUE(on_can_draw_state_changed_called_);
285 on_can_draw_state_changed_called_ = false;
287 // Toggle the root layer to make sure it toggles can_draw
288 host_impl_->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
289 EXPECT_FALSE(host_impl_->CanDraw());
290 EXPECT_TRUE(on_can_draw_state_changed_called_);
291 on_can_draw_state_changed_called_ = false;
293 SetupScrollAndContentsLayers(gfx::Size(100, 100));
294 EXPECT_TRUE(host_impl_->CanDraw());
295 EXPECT_TRUE(on_can_draw_state_changed_called_);
296 on_can_draw_state_changed_called_ = false;
298 // Toggle the device viewport size to make sure it toggles can_draw.
299 host_impl_->SetViewportSize(gfx::Size());
300 if (always_draw) {
301 EXPECT_TRUE(host_impl_->CanDraw());
302 } else {
303 EXPECT_FALSE(host_impl_->CanDraw());
305 EXPECT_TRUE(on_can_draw_state_changed_called_);
306 on_can_draw_state_changed_called_ = false;
308 host_impl_->SetViewportSize(gfx::Size(100, 100));
309 EXPECT_TRUE(host_impl_->CanDraw());
310 EXPECT_TRUE(on_can_draw_state_changed_called_);
311 on_can_draw_state_changed_called_ = false;
313 // Toggle contents textures purged without causing any evictions,
314 // and make sure that it does not change can_draw.
315 set_reduce_memory_result(false);
316 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
317 host_impl_->memory_allocation_limit_bytes() - 1));
318 EXPECT_TRUE(host_impl_->CanDraw());
319 EXPECT_FALSE(on_can_draw_state_changed_called_);
320 on_can_draw_state_changed_called_ = false;
322 // Toggle contents textures purged to make sure it toggles can_draw.
323 set_reduce_memory_result(true);
324 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
325 host_impl_->memory_allocation_limit_bytes() - 1));
326 if (always_draw) {
327 EXPECT_TRUE(host_impl_->CanDraw());
328 } else {
329 EXPECT_FALSE(host_impl_->CanDraw());
331 EXPECT_TRUE(on_can_draw_state_changed_called_);
332 on_can_draw_state_changed_called_ = false;
334 host_impl_->active_tree()->ResetContentsTexturesPurged();
335 EXPECT_TRUE(host_impl_->CanDraw());
336 EXPECT_TRUE(on_can_draw_state_changed_called_);
337 on_can_draw_state_changed_called_ = false;
340 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
342 protected:
343 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
344 return CreateFakeOutputSurface();
347 void DrawOneFrame() {
348 LayerTreeHostImpl::FrameData frame_data;
349 host_impl_->PrepareToDraw(&frame_data, gfx::Rect());
350 host_impl_->DidDrawAllLayers(frame_data);
353 FakeProxy proxy_;
354 DebugScopedSetImplThread always_impl_thread_;
355 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
357 scoped_ptr<LayerTreeHostImpl> host_impl_;
358 FakeRenderingStatsInstrumentation stats_instrumentation_;
359 bool on_can_draw_state_changed_called_;
360 bool did_notify_ready_to_activate_;
361 bool did_request_commit_;
362 bool did_request_redraw_;
363 bool did_request_manage_tiles_;
364 bool did_upload_visible_tile_;
365 bool reduce_memory_result_;
366 base::TimeDelta requested_scrollbar_animation_delay_;
367 size_t current_limit_bytes_;
368 int current_priority_cutoff_value_;
371 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
372 bool always_draw = false;
373 CheckNotifyCalledIfCanDrawChanged(always_draw);
376 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
377 scoped_ptr<FakeOutputSurface> output_surface(
378 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
379 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
381 bool always_draw = true;
382 CheckNotifyCalledIfCanDrawChanged(always_draw);
385 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
386 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
388 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
389 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
392 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
394 scoped_ptr<LayerImpl> root =
395 LayerImpl::Create(host_impl_->active_tree(), 1);
396 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
397 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
398 root->children()[1]->AddChild(
399 LayerImpl::Create(host_impl_->active_tree(), 4));
400 root->children()[1]->AddChild(
401 LayerImpl::Create(host_impl_->active_tree(), 5));
402 root->children()[1]->children()[0]->AddChild(
403 LayerImpl::Create(host_impl_->active_tree(), 6));
404 host_impl_->active_tree()->SetRootLayer(root.Pass());
406 LayerImpl* root = host_impl_->active_tree()->root_layer();
408 ExpectClearedScrollDeltasRecursive(root);
410 scoped_ptr<ScrollAndScaleSet> scroll_info;
412 scroll_info = host_impl_->ProcessScrollDeltas();
413 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
414 ExpectClearedScrollDeltasRecursive(root);
416 scroll_info = host_impl_->ProcessScrollDeltas();
417 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
418 ExpectClearedScrollDeltasRecursive(root);
421 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
422 gfx::Vector2d scroll_offset(20, 30);
423 gfx::Vector2d scroll_delta(11, -15);
425 scoped_ptr<LayerImpl> root =
426 LayerImpl::Create(host_impl_->active_tree(), 1);
427 root->SetMaxScrollOffset(gfx::Vector2d(100, 100));
428 root->SetScrollOffset(scroll_offset);
429 root->SetScrollable(true);
430 root->ScrollBy(scroll_delta);
431 host_impl_->active_tree()->SetRootLayer(root.Pass());
433 LayerImpl* root = host_impl_->active_tree()->root_layer();
435 scoped_ptr<ScrollAndScaleSet> scroll_info;
437 scroll_info = host_impl_->ProcessScrollDeltas();
438 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
439 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta);
440 ExpectContains(*scroll_info, root->id(), scroll_delta);
442 gfx::Vector2d scroll_delta2(-5, 27);
443 root->ScrollBy(scroll_delta2);
444 scroll_info = host_impl_->ProcessScrollDeltas();
445 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
446 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
447 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
449 root->ScrollBy(gfx::Vector2d());
450 scroll_info = host_impl_->ProcessScrollDeltas();
451 EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
454 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
455 SetupScrollAndContentsLayers(gfx::Size(100, 100));
456 host_impl_->SetViewportSize(gfx::Size(50, 50));
457 DrawFrame();
459 EXPECT_EQ(InputHandler::ScrollStarted,
460 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
461 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
462 host_impl_->ScrollEnd();
463 EXPECT_TRUE(did_request_redraw_);
464 EXPECT_TRUE(did_request_commit_);
467 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
468 // We should not crash when trying to scroll an empty layer tree.
469 EXPECT_EQ(InputHandler::ScrollIgnored,
470 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
473 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
474 scoped_ptr<TestWebGraphicsContext3D> context_owned =
475 TestWebGraphicsContext3D::Create();
476 context_owned->set_context_lost(true);
478 scoped_ptr<FakeOutputSurface> output_surface(FakeOutputSurface::Create3d(
479 context_owned.Pass()));
481 // Initialization will fail.
482 EXPECT_FALSE(CreateHostImpl(DefaultSettings(),
483 output_surface.PassAs<OutputSurface>()));
485 SetupScrollAndContentsLayers(gfx::Size(100, 100));
487 // We should not crash when trying to scroll after the renderer initialization
488 // fails.
489 EXPECT_EQ(InputHandler::ScrollIgnored,
490 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
493 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
494 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
495 host_impl_->SetViewportSize(gfx::Size(50, 50));
496 DrawFrame();
498 // We should not crash if the tree is replaced while we are scrolling.
499 EXPECT_EQ(InputHandler::ScrollStarted,
500 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
501 host_impl_->active_tree()->DetachLayerTree();
503 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
505 // We should still be scrolling, because the scrolled layer also exists in the
506 // new tree.
507 gfx::Vector2d scroll_delta(0, 10);
508 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
509 host_impl_->ScrollEnd();
510 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
511 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
514 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
515 SetupScrollAndContentsLayers(gfx::Size(100, 100));
516 host_impl_->SetViewportSize(gfx::Size(50, 50));
517 DrawFrame();
519 // We should be able to scroll even if the root layer loses its render surface
520 // after the most recent render.
521 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
522 host_impl_->active_tree()->set_needs_update_draw_properties();
524 EXPECT_EQ(InputHandler::ScrollStarted,
525 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
528 TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
529 SetupScrollAndContentsLayers(gfx::Size(100, 100));
530 host_impl_->SetViewportSize(gfx::Size(50, 50));
531 DrawFrame();
532 LayerImpl* root = host_impl_->active_tree()->root_layer();
534 root->SetHaveWheelEventHandlers(true);
536 // With registered event handlers, wheel scrolls have to go to the main
537 // thread.
538 EXPECT_EQ(InputHandler::ScrollOnMainThread,
539 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
541 // But gesture scrolls can still be handled.
542 EXPECT_EQ(InputHandler::ScrollStarted,
543 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
546 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
547 SetupScrollAndContentsLayers(gfx::Size(100, 100));
548 host_impl_->SetViewportSize(gfx::Size(50, 50));
549 DrawFrame();
551 // Ignore the fling since no layer is being scrolled
552 EXPECT_EQ(InputHandler::ScrollIgnored,
553 host_impl_->FlingScrollBegin());
555 // Start scrolling a layer
556 EXPECT_EQ(InputHandler::ScrollStarted,
557 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
559 // Now the fling should go ahead since we've started scrolling a layer
560 EXPECT_EQ(InputHandler::ScrollStarted,
561 host_impl_->FlingScrollBegin());
564 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
565 SetupScrollAndContentsLayers(gfx::Size(100, 100));
566 host_impl_->SetViewportSize(gfx::Size(50, 50));
567 DrawFrame();
569 // Ignore the fling since no layer is being scrolled
570 EXPECT_EQ(InputHandler::ScrollIgnored,
571 host_impl_->FlingScrollBegin());
573 // Start scrolling a layer
574 EXPECT_EQ(InputHandler::ScrollStarted,
575 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
577 // Now the fling should go ahead since we've started scrolling a layer
578 EXPECT_EQ(InputHandler::ScrollStarted,
579 host_impl_->FlingScrollBegin());
582 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
583 SetupScrollAndContentsLayers(gfx::Size(100, 100));
584 host_impl_->SetViewportSize(gfx::Size(50, 50));
585 DrawFrame();
586 LayerImpl* root = host_impl_->active_tree()->root_layer();
588 root->SetShouldScrollOnMainThread(true);
590 // Start scrolling a layer
591 EXPECT_EQ(InputHandler::ScrollOnMainThread,
592 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
594 // The fling should be ignored since there's no layer being scrolled impl-side
595 EXPECT_EQ(InputHandler::ScrollIgnored,
596 host_impl_->FlingScrollBegin());
599 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
600 SetupScrollAndContentsLayers(gfx::Size(100, 100));
601 host_impl_->SetViewportSize(gfx::Size(50, 50));
602 DrawFrame();
603 LayerImpl* root = host_impl_->active_tree()->root_layer();
605 root->SetShouldScrollOnMainThread(true);
607 EXPECT_EQ(InputHandler::ScrollOnMainThread,
608 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
609 EXPECT_EQ(InputHandler::ScrollOnMainThread,
610 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
613 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
614 SetupScrollAndContentsLayers(gfx::Size(200, 200));
615 host_impl_->SetViewportSize(gfx::Size(100, 100));
617 LayerImpl* root = host_impl_->active_tree()->root_layer();
618 root->SetContentsScale(2.f, 2.f);
619 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
621 DrawFrame();
623 // All scroll types inside the non-fast scrollable region should fail.
624 EXPECT_EQ(InputHandler::ScrollOnMainThread,
625 host_impl_->ScrollBegin(gfx::Point(25, 25),
626 InputHandler::Wheel));
627 EXPECT_EQ(InputHandler::ScrollOnMainThread,
628 host_impl_->ScrollBegin(gfx::Point(25, 25),
629 InputHandler::Gesture));
631 // All scroll types outside this region should succeed.
632 EXPECT_EQ(InputHandler::ScrollStarted,
633 host_impl_->ScrollBegin(gfx::Point(75, 75),
634 InputHandler::Wheel));
635 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
636 host_impl_->ScrollEnd();
637 EXPECT_EQ(InputHandler::ScrollStarted,
638 host_impl_->ScrollBegin(gfx::Point(75, 75),
639 InputHandler::Gesture));
640 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
641 host_impl_->ScrollEnd();
644 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
645 SetupScrollAndContentsLayers(gfx::Size(200, 200));
646 host_impl_->SetViewportSize(gfx::Size(100, 100));
648 LayerImpl* root = host_impl_->active_tree()->root_layer();
649 root->SetContentsScale(2.f, 2.f);
650 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
651 root->SetPosition(gfx::PointF(-25.f, 0.f));
653 DrawFrame();
655 // This point would fall into the non-fast scrollable region except that we've
656 // moved the layer down by 25 pixels.
657 EXPECT_EQ(InputHandler::ScrollStarted,
658 host_impl_->ScrollBegin(gfx::Point(40, 10),
659 InputHandler::Wheel));
660 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
661 host_impl_->ScrollEnd();
663 // This point is still inside the non-fast region.
664 EXPECT_EQ(InputHandler::ScrollOnMainThread,
665 host_impl_->ScrollBegin(gfx::Point(10, 10),
666 InputHandler::Wheel));
669 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
670 SetupScrollAndContentsLayers(gfx::Size(200, 200));
671 host_impl_->SetViewportSize(gfx::Size(100, 100));
673 DrawFrame();
675 EXPECT_EQ(InputHandler::ScrollStarted,
676 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
678 // Trying to scroll to the left/top will not succeed.
679 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
680 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
681 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
683 // Scrolling to the right/bottom will succeed.
684 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
685 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
686 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
688 // Scrolling to left/top will now succeed.
689 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
690 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
691 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
693 // Scrolling diagonally against an edge will succeed.
694 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
695 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
696 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
698 // Trying to scroll more than the available space will also succeed.
699 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
702 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
703 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
704 host_impl_->SetViewportSize(gfx::Size(100, 1000));
706 DrawFrame();
708 EXPECT_EQ(InputHandler::ScrollStarted,
709 host_impl_->ScrollBegin(gfx::Point(),
710 InputHandler::Wheel));
712 // Trying to scroll without a vertical scrollbar will fail.
713 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
714 gfx::Point(), SCROLL_FORWARD));
715 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
716 gfx::Point(), SCROLL_BACKWARD));
718 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
719 PaintedScrollbarLayerImpl::Create(
720 host_impl_->active_tree(),
722 VERTICAL));
723 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
724 host_impl_->RootScrollLayer()->SetVerticalScrollbarLayer(
725 vertical_scrollbar.get());
727 // Trying to scroll with a vertical scrollbar will succeed.
728 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
729 gfx::Point(), SCROLL_FORWARD));
730 EXPECT_FLOAT_EQ(875.f, host_impl_->RootScrollLayer()->ScrollDelta().y());
731 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
732 gfx::Point(), SCROLL_BACKWARD));
735 // The user-scrollability breaks for zoomed-in pages. So disable this.
736 // http://crbug.com/322223
737 TEST_F(LayerTreeHostImplTest, DISABLED_ScrollWithUserUnscrollableLayers) {
738 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
739 host_impl_->SetViewportSize(gfx::Size(100, 100));
741 gfx::Size overflow_size(400, 400);
742 ASSERT_EQ(1u, scroll_layer->children().size());
743 LayerImpl* overflow = scroll_layer->children()[0];
744 overflow->SetBounds(overflow_size);
745 overflow->SetContentBounds(overflow_size);
746 overflow->SetScrollable(true);
747 overflow->SetMaxScrollOffset(gfx::Vector2d(overflow_size.width(),
748 overflow_size.height()));
749 overflow->SetScrollOffset(gfx::Vector2d());
750 overflow->SetPosition(gfx::PointF());
751 overflow->SetAnchorPoint(gfx::PointF());
753 DrawFrame();
754 gfx::Point scroll_position(10, 10);
756 EXPECT_EQ(InputHandler::ScrollStarted,
757 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
758 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
759 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->TotalScrollOffset());
761 gfx::Vector2dF scroll_delta(10, 10);
762 host_impl_->ScrollBy(scroll_position, scroll_delta);
763 host_impl_->ScrollEnd();
764 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
765 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
767 overflow->set_user_scrollable_horizontal(false);
769 EXPECT_EQ(InputHandler::ScrollStarted,
770 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
771 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
772 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
774 host_impl_->ScrollBy(scroll_position, scroll_delta);
775 host_impl_->ScrollEnd();
776 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
777 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
779 overflow->set_user_scrollable_vertical(false);
781 EXPECT_EQ(InputHandler::ScrollStarted,
782 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
783 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
784 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
786 host_impl_->ScrollBy(scroll_position, scroll_delta);
787 host_impl_->ScrollEnd();
788 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->TotalScrollOffset());
789 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
792 TEST_F(LayerTreeHostImplTest,
793 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
794 SetupScrollAndContentsLayers(gfx::Size(100, 100));
795 host_impl_->SetViewportSize(gfx::Size(50, 50));
796 DrawFrame();
798 // We should be able to hit test for touch event handlers even if the root
799 // layer loses its render surface after the most recent render.
800 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
801 host_impl_->active_tree()->set_needs_update_draw_properties();
803 EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
806 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
807 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
808 host_impl_->SetViewportSize(gfx::Size(50, 50));
809 DrawFrame();
811 EXPECT_EQ(scroll_layer, host_impl_->RootScrollLayer());
813 float min_page_scale = 1.f, max_page_scale = 4.f;
815 // The impl-based pinch zoom should adjust the max scroll position.
817 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
818 min_page_scale,
819 max_page_scale);
820 host_impl_->active_tree()->SetPageScaleDelta(1.f);
821 scroll_layer->SetScrollDelta(gfx::Vector2d());
823 float page_scale_delta = 2.f;
824 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
825 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
826 host_impl_->PinchGestureEnd();
827 host_impl_->ScrollEnd();
828 EXPECT_TRUE(did_request_redraw_);
829 EXPECT_TRUE(did_request_commit_);
831 scoped_ptr<ScrollAndScaleSet> scroll_info =
832 host_impl_->ProcessScrollDeltas();
833 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
835 EXPECT_EQ(gfx::Vector2d(75, 75).ToString(),
836 scroll_layer->max_scroll_offset().ToString());
839 // Scrolling after a pinch gesture should always be in local space. The
840 // scroll deltas do not have the page scale factor applied.
842 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
843 min_page_scale,
844 max_page_scale);
845 host_impl_->active_tree()->SetPageScaleDelta(1.f);
846 scroll_layer->SetScrollDelta(gfx::Vector2d());
848 float page_scale_delta = 2.f;
849 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
850 host_impl_->PinchGestureBegin();
851 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
852 host_impl_->PinchGestureEnd();
853 host_impl_->ScrollEnd();
855 gfx::Vector2d scroll_delta(0, 10);
856 EXPECT_EQ(InputHandler::ScrollStarted,
857 host_impl_->ScrollBegin(gfx::Point(5, 5),
858 InputHandler::Wheel));
859 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
860 host_impl_->ScrollEnd();
862 scoped_ptr<ScrollAndScaleSet> scroll_info =
863 host_impl_->ProcessScrollDeltas();
864 ExpectContains(*scroll_info.get(),
865 scroll_layer->id(),
866 scroll_delta);
870 TEST_F(LayerTreeHostImplTest, PinchGesture) {
871 SetupScrollAndContentsLayers(gfx::Size(100, 100));
872 host_impl_->SetViewportSize(gfx::Size(50, 50));
873 DrawFrame();
875 LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
876 DCHECK(scroll_layer);
878 float min_page_scale = 1.f;
879 float max_page_scale = 4.f;
881 // Basic pinch zoom in gesture
883 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
884 min_page_scale,
885 max_page_scale);
886 scroll_layer->SetScrollDelta(gfx::Vector2d());
888 float page_scale_delta = 2.f;
889 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
890 host_impl_->PinchGestureBegin();
891 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
892 host_impl_->PinchGestureEnd();
893 host_impl_->ScrollEnd();
894 EXPECT_TRUE(did_request_redraw_);
895 EXPECT_TRUE(did_request_commit_);
897 scoped_ptr<ScrollAndScaleSet> scroll_info =
898 host_impl_->ProcessScrollDeltas();
899 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
902 // Zoom-in clamping
904 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
905 min_page_scale,
906 max_page_scale);
907 scroll_layer->SetScrollDelta(gfx::Vector2d());
908 float page_scale_delta = 10.f;
910 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
911 host_impl_->PinchGestureBegin();
912 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
913 host_impl_->PinchGestureEnd();
914 host_impl_->ScrollEnd();
916 scoped_ptr<ScrollAndScaleSet> scroll_info =
917 host_impl_->ProcessScrollDeltas();
918 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
921 // Zoom-out clamping
923 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
924 min_page_scale,
925 max_page_scale);
926 scroll_layer->SetScrollDelta(gfx::Vector2d());
927 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
929 float page_scale_delta = 0.1f;
930 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
931 host_impl_->PinchGestureBegin();
932 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
933 host_impl_->PinchGestureEnd();
934 host_impl_->ScrollEnd();
936 scoped_ptr<ScrollAndScaleSet> scroll_info =
937 host_impl_->ProcessScrollDeltas();
938 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
940 EXPECT_TRUE(scroll_info->scrolls.empty());
943 // Two-finger panning should not happen based on pinch events only
945 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
946 min_page_scale,
947 max_page_scale);
948 scroll_layer->SetScrollDelta(gfx::Vector2d());
949 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
951 float page_scale_delta = 1.f;
952 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
953 host_impl_->PinchGestureBegin();
954 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
955 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
956 host_impl_->PinchGestureEnd();
957 host_impl_->ScrollEnd();
959 scoped_ptr<ScrollAndScaleSet> scroll_info =
960 host_impl_->ProcessScrollDeltas();
961 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
962 EXPECT_TRUE(scroll_info->scrolls.empty());
965 // Two-finger panning should work with interleaved scroll events
967 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
968 min_page_scale,
969 max_page_scale);
970 scroll_layer->SetScrollDelta(gfx::Vector2d());
971 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
973 float page_scale_delta = 1.f;
974 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
975 host_impl_->PinchGestureBegin();
976 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
977 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
978 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
979 host_impl_->PinchGestureEnd();
980 host_impl_->ScrollEnd();
982 scoped_ptr<ScrollAndScaleSet> scroll_info =
983 host_impl_->ProcessScrollDeltas();
984 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
985 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
988 // Two-finger panning should work when starting fully zoomed out.
990 host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
991 0.5f,
992 4.f);
993 scroll_layer->SetScrollDelta(gfx::Vector2d());
994 scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
995 host_impl_->active_tree()->UpdateMaxScrollOffset();
997 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
998 host_impl_->PinchGestureBegin();
999 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1000 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1001 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1002 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1003 host_impl_->PinchGestureEnd();
1004 host_impl_->ScrollEnd();
1006 scoped_ptr<ScrollAndScaleSet> scroll_info =
1007 host_impl_->ProcessScrollDeltas();
1008 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1009 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1013 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1014 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1015 host_impl_->SetViewportSize(gfx::Size(50, 50));
1016 DrawFrame();
1018 LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
1019 DCHECK(scroll_layer);
1021 float min_page_scale = 0.5f;
1022 float max_page_scale = 4.f;
1023 base::TimeTicks start_time = base::TimeTicks() +
1024 base::TimeDelta::FromSeconds(1);
1025 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1026 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1027 base::TimeTicks end_time = start_time + duration;
1029 // Non-anchor zoom-in
1031 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1032 min_page_scale,
1033 max_page_scale);
1034 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1036 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), false, 2.f, duration);
1037 did_request_redraw_ = false;
1038 host_impl_->Animate(start_time, base::Time());
1039 EXPECT_TRUE(did_request_redraw_);
1041 did_request_redraw_ = false;
1042 host_impl_->Animate(halfway_through_animation, base::Time());
1043 EXPECT_TRUE(did_request_redraw_);
1045 did_request_redraw_ = false;
1046 did_request_commit_ = false;
1047 host_impl_->Animate(end_time, base::Time());
1048 EXPECT_TRUE(did_request_commit_);
1050 scoped_ptr<ScrollAndScaleSet> scroll_info =
1051 host_impl_->ProcessScrollDeltas();
1052 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1053 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1056 // Anchor zoom-out
1058 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1059 min_page_scale,
1060 max_page_scale);
1061 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1063 host_impl_->StartPageScaleAnimation(
1064 gfx::Vector2d(25, 25), true, min_page_scale, duration);
1065 did_request_redraw_ = false;
1066 host_impl_->Animate(start_time, base::Time());
1067 EXPECT_TRUE(did_request_redraw_);
1069 did_request_redraw_ = false;
1070 did_request_commit_ = false;
1071 host_impl_->Animate(end_time, base::Time());
1072 EXPECT_TRUE(did_request_redraw_);
1073 EXPECT_TRUE(did_request_commit_);
1075 scoped_ptr<ScrollAndScaleSet> scroll_info =
1076 host_impl_->ProcessScrollDeltas();
1077 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1078 // Pushed to (0,0) via clamping against contents layer size.
1079 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1083 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1084 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1085 host_impl_->SetViewportSize(gfx::Size(50, 50));
1086 DrawFrame();
1088 LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
1089 DCHECK(scroll_layer);
1091 float min_page_scale = 0.5f;
1092 float max_page_scale = 4.f;
1093 base::TimeTicks start_time = base::TimeTicks() +
1094 base::TimeDelta::FromSeconds(1);
1095 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1096 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1097 base::TimeTicks end_time = start_time + duration;
1099 // Anchor zoom with unchanged page scale should not change scroll or scale.
1101 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1102 min_page_scale,
1103 max_page_scale);
1104 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1106 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), true, 1.f, duration);
1107 host_impl_->Animate(start_time, base::Time());
1108 host_impl_->Animate(halfway_through_animation, base::Time());
1109 EXPECT_TRUE(did_request_redraw_);
1110 host_impl_->Animate(end_time, base::Time());
1111 EXPECT_TRUE(did_request_commit_);
1113 scoped_ptr<ScrollAndScaleSet> scroll_info =
1114 host_impl_->ProcessScrollDeltas();
1115 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1116 ExpectNone(*scroll_info, scroll_layer->id());
1120 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1121 public:
1122 LayerTreeHostImplOverridePhysicalTime(
1123 const LayerTreeSettings& settings,
1124 LayerTreeHostImplClient* client,
1125 Proxy* proxy,
1126 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1127 : LayerTreeHostImpl(settings,
1128 client,
1129 proxy,
1130 rendering_stats_instrumentation,
1131 NULL,
1132 0) {}
1134 virtual base::TimeTicks CurrentPhysicalTimeTicks() const OVERRIDE {
1135 return fake_current_physical_time_;
1138 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1139 fake_current_physical_time_ = fake_now;
1142 private:
1143 base::TimeTicks fake_current_physical_time_;
1146 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1147 LayerTreeSettings settings;
1148 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1149 settings.scrollbar_linear_fade_delay_ms = 20;
1150 settings.scrollbar_linear_fade_length_ms = 20;
1152 gfx::Size viewport_size(10, 10);
1153 gfx::Size content_size(100, 100);
1155 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
1156 new LayerTreeHostImplOverridePhysicalTime(
1157 settings, this, &proxy_, &stats_instrumentation_);
1158 host_impl_ = make_scoped_ptr(host_impl_override_time);
1159 host_impl_->InitializeRenderer(CreateOutputSurface());
1160 host_impl_->SetViewportSize(viewport_size);
1162 scoped_ptr<LayerImpl> root =
1163 LayerImpl::Create(host_impl_->active_tree(), 1);
1164 root->SetBounds(viewport_size);
1166 scoped_ptr<LayerImpl> scroll =
1167 LayerImpl::Create(host_impl_->active_tree(), 2);
1168 scroll->SetScrollable(true);
1169 scroll->SetScrollOffset(gfx::Vector2d());
1170 scroll->SetMaxScrollOffset(gfx::Vector2d(content_size.width(),
1171 content_size.height()));
1172 scroll->SetBounds(content_size);
1173 scroll->SetContentBounds(content_size);
1175 scoped_ptr<LayerImpl> contents =
1176 LayerImpl::Create(host_impl_->active_tree(), 3);
1177 contents->SetDrawsContent(true);
1178 contents->SetBounds(content_size);
1179 contents->SetContentBounds(content_size);
1181 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1182 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 4, VERTICAL);
1183 scroll->SetVerticalScrollbarLayer(scrollbar.get());
1185 scroll->AddChild(contents.Pass());
1186 root->AddChild(scroll.Pass());
1187 root->AddChild(scrollbar.PassAs<LayerImpl>());
1189 host_impl_->active_tree()->SetRootLayer(root.Pass());
1190 host_impl_->active_tree()->DidBecomeActive();
1191 DrawFrame();
1193 base::TimeTicks fake_now = gfx::FrameTime::Now();
1194 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1196 // If no scroll happened recently, StartScrollbarAnimation should have no
1197 // effect.
1198 host_impl_->StartScrollbarAnimation();
1199 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1200 EXPECT_FALSE(did_request_redraw_);
1202 // If no scroll happened during a scroll gesture, StartScrollbarAnimation
1203 // should have no effect.
1204 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1205 host_impl_->ScrollEnd();
1206 host_impl_->StartScrollbarAnimation();
1207 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1208 EXPECT_FALSE(did_request_redraw_);
1210 // After a scroll, a fade animation should be scheduled about 20ms from now.
1211 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1212 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1213 host_impl_->ScrollEnd();
1214 did_request_redraw_ = false;
1215 host_impl_->StartScrollbarAnimation();
1216 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1217 requested_scrollbar_animation_delay_);
1218 EXPECT_FALSE(did_request_redraw_);
1219 requested_scrollbar_animation_delay_ = base::TimeDelta();
1221 // After the fade begins, we should start getting redraws instead of a
1222 // scheduled animation.
1223 fake_now += base::TimeDelta::FromMilliseconds(25);
1224 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1225 host_impl_->StartScrollbarAnimation();
1226 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1227 EXPECT_TRUE(did_request_redraw_);
1228 did_request_redraw_ = false;
1230 // If no scroll happened recently, StartScrollbarAnimation should have no
1231 // effect.
1232 fake_now += base::TimeDelta::FromMilliseconds(25);
1233 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1234 host_impl_->StartScrollbarAnimation();
1235 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1236 EXPECT_FALSE(did_request_redraw_);
1238 // Setting the scroll offset outside a scroll should also cause the scrollbar
1239 // to appear and to schedule a fade.
1240 host_impl_->RootScrollLayer()->SetScrollOffset(gfx::Vector2d(5, 5));
1241 host_impl_->StartScrollbarAnimation();
1242 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1243 requested_scrollbar_animation_delay_);
1244 EXPECT_FALSE(did_request_redraw_);
1245 requested_scrollbar_animation_delay_ = base::TimeDelta();
1247 // None of the above should have called CurrentFrameTimeTicks, so if we call
1248 // it now we should get the current time.
1249 fake_now += base::TimeDelta::FromMilliseconds(10);
1250 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1251 EXPECT_EQ(fake_now, host_impl_->CurrentFrameTimeTicks());
1254 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1255 float device_scale_factor) {
1256 LayerTreeSettings settings;
1257 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1259 gfx::Size viewport_size(300, 200);
1260 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1261 gfx::ScaleSize(viewport_size, device_scale_factor));
1262 gfx::Size content_size(1000, 1000);
1264 CreateHostImpl(settings, CreateOutputSurface());
1265 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1266 host_impl_->SetViewportSize(device_viewport_size);
1268 scoped_ptr<LayerImpl> root =
1269 LayerImpl::Create(host_impl_->active_tree(), 1);
1270 root->SetBounds(viewport_size);
1272 scoped_ptr<LayerImpl> scroll =
1273 LayerImpl::Create(host_impl_->active_tree(), 2);
1274 scroll->SetScrollable(true);
1275 scroll->SetScrollOffset(gfx::Vector2d());
1276 scroll->SetMaxScrollOffset(gfx::Vector2d(content_size.width(),
1277 content_size.height()));
1278 scroll->SetBounds(content_size);
1279 scroll->SetContentBounds(content_size);
1281 scoped_ptr<LayerImpl> contents =
1282 LayerImpl::Create(host_impl_->active_tree(), 3);
1283 contents->SetDrawsContent(true);
1284 contents->SetBounds(content_size);
1285 contents->SetContentBounds(content_size);
1287 // The scrollbar is on the right side.
1288 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1289 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1290 scrollbar->SetDrawsContent(true);
1291 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1292 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1293 scrollbar->SetPosition(gfx::Point(285, 0));
1294 scroll->SetVerticalScrollbarLayer(scrollbar.get());
1296 scroll->AddChild(contents.Pass());
1297 root->AddChild(scroll.Pass());
1298 root->AddChild(scrollbar.PassAs<LayerImpl>());
1300 host_impl_->active_tree()->SetRootLayer(root.Pass());
1301 host_impl_->active_tree()->DidBecomeActive();
1302 DrawFrame();
1304 LayerImpl* root_scroll = host_impl_->active_tree()->RootScrollLayer();
1305 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1306 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1307 static_cast<ScrollbarAnimationControllerThinning*>(
1308 root_scroll->scrollbar_animation_controller());
1309 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1311 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1312 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1314 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1315 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1317 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1318 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1320 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1321 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1322 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1324 did_request_redraw_ = false;
1325 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1326 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1327 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1328 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1329 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1330 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1331 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1334 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1335 SetupMouseMoveAtWithDeviceScale(1.f);
1338 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1339 SetupMouseMoveAtWithDeviceScale(2.f);
1342 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1343 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1344 host_impl_->SetViewportSize(gfx::Size(50, 50));
1345 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
1346 DrawFrame();
1348 CompositorFrameMetadata metadata =
1349 host_impl_->MakeCompositorFrameMetadata();
1350 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1351 EXPECT_EQ(1.f, metadata.page_scale_factor);
1352 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.viewport_size);
1353 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1354 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1355 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1358 // Scrolling should update metadata immediately.
1359 EXPECT_EQ(InputHandler::ScrollStarted,
1360 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1361 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1363 CompositorFrameMetadata metadata =
1364 host_impl_->MakeCompositorFrameMetadata();
1365 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1367 host_impl_->ScrollEnd();
1369 CompositorFrameMetadata metadata =
1370 host_impl_->MakeCompositorFrameMetadata();
1371 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1374 // Page scale should update metadata correctly (shrinking only the viewport).
1375 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1376 host_impl_->PinchGestureBegin();
1377 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1378 host_impl_->PinchGestureEnd();
1379 host_impl_->ScrollEnd();
1381 CompositorFrameMetadata metadata =
1382 host_impl_->MakeCompositorFrameMetadata();
1383 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1384 EXPECT_EQ(2.f, metadata.page_scale_factor);
1385 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.viewport_size);
1386 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1387 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1388 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1391 // Likewise if set from the main thread.
1392 host_impl_->ProcessScrollDeltas();
1393 host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
1394 host_impl_->active_tree()->SetPageScaleDelta(1.f);
1396 CompositorFrameMetadata metadata =
1397 host_impl_->MakeCompositorFrameMetadata();
1398 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1399 EXPECT_EQ(4.f, metadata.page_scale_factor);
1400 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.viewport_size);
1401 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1402 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1403 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1407 class DidDrawCheckLayer : public TiledLayerImpl {
1408 public:
1409 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1410 return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(tree_impl, id));
1413 virtual bool WillDraw(DrawMode draw_mode, ResourceProvider* provider)
1414 OVERRIDE {
1415 will_draw_called_ = true;
1416 if (will_draw_returns_false_)
1417 return false;
1418 return TiledLayerImpl::WillDraw(draw_mode, provider);
1421 virtual void AppendQuads(QuadSink* quad_sink,
1422 AppendQuadsData* append_quads_data) OVERRIDE {
1423 append_quads_called_ = true;
1424 TiledLayerImpl::AppendQuads(quad_sink, append_quads_data);
1427 virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
1428 did_draw_called_ = true;
1429 TiledLayerImpl::DidDraw(provider);
1432 bool will_draw_called() const { return will_draw_called_; }
1433 bool append_quads_called() const { return append_quads_called_; }
1434 bool did_draw_called() const { return did_draw_called_; }
1436 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1438 void ClearDidDrawCheck() {
1439 will_draw_called_ = false;
1440 append_quads_called_ = false;
1441 did_draw_called_ = false;
1444 protected:
1445 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1446 : TiledLayerImpl(tree_impl, id),
1447 will_draw_returns_false_(false),
1448 will_draw_called_(false),
1449 append_quads_called_(false),
1450 did_draw_called_(false) {
1451 SetAnchorPoint(gfx::PointF());
1452 SetBounds(gfx::Size(10, 10));
1453 SetContentBounds(gfx::Size(10, 10));
1454 SetDrawsContent(true);
1455 set_skips_draw(false);
1456 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1458 scoped_ptr<LayerTilingData> tiler =
1459 LayerTilingData::Create(gfx::Size(100, 100),
1460 LayerTilingData::HAS_BORDER_TEXELS);
1461 tiler->SetBounds(content_bounds());
1462 SetTilingData(*tiler.get());
1465 private:
1466 bool will_draw_returns_false_;
1467 bool will_draw_called_;
1468 bool append_quads_called_;
1469 bool did_draw_called_;
1472 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1473 // The root layer is always drawn, so run this test on a child layer that
1474 // will be masked out by the root layer's bounds.
1475 host_impl_->active_tree()->SetRootLayer(
1476 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1477 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1478 host_impl_->active_tree()->root_layer());
1480 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1481 DidDrawCheckLayer* layer =
1482 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1485 LayerTreeHostImpl::FrameData frame;
1486 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
1487 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1488 host_impl_->DidDrawAllLayers(frame);
1490 EXPECT_TRUE(layer->will_draw_called());
1491 EXPECT_TRUE(layer->append_quads_called());
1492 EXPECT_TRUE(layer->did_draw_called());
1496 LayerTreeHostImpl::FrameData frame;
1498 layer->set_will_draw_returns_false();
1499 layer->ClearDidDrawCheck();
1501 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
1502 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1503 host_impl_->DidDrawAllLayers(frame);
1505 EXPECT_TRUE(layer->will_draw_called());
1506 EXPECT_FALSE(layer->append_quads_called());
1507 EXPECT_FALSE(layer->did_draw_called());
1511 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1512 // The root layer is always drawn, so run this test on a child layer that
1513 // will be masked out by the root layer's bounds.
1514 host_impl_->active_tree()->SetRootLayer(
1515 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1516 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1517 host_impl_->active_tree()->root_layer());
1518 root->SetMasksToBounds(true);
1520 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1521 DidDrawCheckLayer* layer =
1522 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1523 // Ensure visible_content_rect for layer is empty.
1524 layer->SetPosition(gfx::PointF(100.f, 100.f));
1525 layer->SetBounds(gfx::Size(10, 10));
1526 layer->SetContentBounds(gfx::Size(10, 10));
1528 LayerTreeHostImpl::FrameData frame;
1530 EXPECT_FALSE(layer->will_draw_called());
1531 EXPECT_FALSE(layer->did_draw_called());
1533 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1534 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1535 host_impl_->DidDrawAllLayers(frame);
1537 EXPECT_FALSE(layer->will_draw_called());
1538 EXPECT_FALSE(layer->did_draw_called());
1540 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1542 // Ensure visible_content_rect for layer is not empty
1543 layer->SetPosition(gfx::PointF());
1545 EXPECT_FALSE(layer->will_draw_called());
1546 EXPECT_FALSE(layer->did_draw_called());
1548 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1549 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1550 host_impl_->DidDrawAllLayers(frame);
1552 EXPECT_TRUE(layer->will_draw_called());
1553 EXPECT_TRUE(layer->did_draw_called());
1555 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1558 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1559 gfx::Size big_size(1000, 1000);
1560 host_impl_->SetViewportSize(big_size);
1562 host_impl_->active_tree()->SetRootLayer(
1563 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1564 DidDrawCheckLayer* root =
1565 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1567 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1568 DidDrawCheckLayer* occluded_layer =
1569 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1571 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1572 DidDrawCheckLayer* top_layer =
1573 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1574 // This layer covers the occluded_layer above. Make this layer large so it can
1575 // occlude.
1576 top_layer->SetBounds(big_size);
1577 top_layer->SetContentBounds(big_size);
1578 top_layer->SetContentsOpaque(true);
1580 LayerTreeHostImpl::FrameData frame;
1582 EXPECT_FALSE(occluded_layer->will_draw_called());
1583 EXPECT_FALSE(occluded_layer->did_draw_called());
1584 EXPECT_FALSE(top_layer->will_draw_called());
1585 EXPECT_FALSE(top_layer->did_draw_called());
1587 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1588 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1589 host_impl_->DidDrawAllLayers(frame);
1591 EXPECT_FALSE(occluded_layer->will_draw_called());
1592 EXPECT_FALSE(occluded_layer->did_draw_called());
1593 EXPECT_TRUE(top_layer->will_draw_called());
1594 EXPECT_TRUE(top_layer->did_draw_called());
1597 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1598 host_impl_->active_tree()->SetRootLayer(
1599 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1600 DidDrawCheckLayer* root =
1601 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1603 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1604 DidDrawCheckLayer* layer1 =
1605 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1607 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1608 DidDrawCheckLayer* layer2 =
1609 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1611 layer1->SetOpacity(0.3f);
1612 layer1->SetPreserves3d(false);
1614 EXPECT_FALSE(root->did_draw_called());
1615 EXPECT_FALSE(layer1->did_draw_called());
1616 EXPECT_FALSE(layer2->did_draw_called());
1618 LayerTreeHostImpl::FrameData frame;
1619 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1620 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1621 host_impl_->DidDrawAllLayers(frame);
1623 EXPECT_TRUE(root->did_draw_called());
1624 EXPECT_TRUE(layer1->did_draw_called());
1625 EXPECT_TRUE(layer2->did_draw_called());
1627 EXPECT_NE(root->render_surface(), layer1->render_surface());
1628 EXPECT_TRUE(!!layer1->render_surface());
1631 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1632 public:
1633 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1634 int id,
1635 bool tile_missing,
1636 bool skips_draw,
1637 bool animating,
1638 ResourceProvider* resource_provider) {
1639 return scoped_ptr<LayerImpl>(new MissingTextureAnimatingLayer(
1640 tree_impl,
1642 tile_missing,
1643 skips_draw,
1644 animating,
1645 resource_provider));
1648 private:
1649 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1650 int id,
1651 bool tile_missing,
1652 bool skips_draw,
1653 bool animating,
1654 ResourceProvider* resource_provider)
1655 : DidDrawCheckLayer(tree_impl, id) {
1656 scoped_ptr<LayerTilingData> tiling_data =
1657 LayerTilingData::Create(gfx::Size(10, 10),
1658 LayerTilingData::NO_BORDER_TEXELS);
1659 tiling_data->SetBounds(bounds());
1660 SetTilingData(*tiling_data.get());
1661 set_skips_draw(skips_draw);
1662 if (!tile_missing) {
1663 ResourceProvider::ResourceId resource =
1664 resource_provider->CreateResource(gfx::Size(1, 1),
1665 GL_CLAMP_TO_EDGE,
1666 ResourceProvider::TextureUsageAny,
1667 RGBA_8888);
1668 resource_provider->AllocateForTesting(resource);
1669 PushTileProperties(0, 0, resource, gfx::Rect(), false);
1671 if (animating)
1672 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1676 TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
1677 // When the texture is not missing, we draw as usual.
1678 host_impl_->active_tree()->SetRootLayer(
1679 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1680 DidDrawCheckLayer* root =
1681 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1682 root->AddChild(
1683 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1685 false,
1686 false,
1687 true,
1688 host_impl_->resource_provider()));
1690 LayerTreeHostImpl::FrameData frame;
1692 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1693 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1694 host_impl_->DidDrawAllLayers(frame);
1696 // When a texture is missing and we're not animating, we draw as usual with
1697 // checkerboarding.
1698 host_impl_->active_tree()->SetRootLayer(
1699 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1700 root =
1701 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1702 root->AddChild(
1703 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1705 true,
1706 false,
1707 false,
1708 host_impl_->resource_provider()));
1710 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1711 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1712 host_impl_->DidDrawAllLayers(frame);
1714 // When a texture is missing and we're animating, we don't want to draw
1715 // anything.
1716 host_impl_->active_tree()->SetRootLayer(
1717 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
1718 root =
1719 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1720 root->AddChild(
1721 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1723 true,
1724 false,
1725 true,
1726 host_impl_->resource_provider()));
1728 EXPECT_FALSE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1729 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1730 host_impl_->DidDrawAllLayers(frame);
1732 // When the layer skips draw and we're animating, we still draw the frame.
1733 host_impl_->active_tree()->SetRootLayer(
1734 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
1735 root =
1736 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1737 root->AddChild(
1738 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1740 false,
1741 true,
1742 true,
1743 host_impl_->resource_provider()));
1745 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1746 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1747 host_impl_->DidDrawAllLayers(frame);
1750 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
1751 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1752 root->SetScrollable(false);
1753 host_impl_->active_tree()->SetRootLayer(root.Pass());
1754 DrawFrame();
1756 // Scroll event is ignored because layer is not scrollable.
1757 EXPECT_EQ(InputHandler::ScrollIgnored,
1758 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1759 EXPECT_FALSE(did_request_redraw_);
1760 EXPECT_FALSE(did_request_commit_);
1763 TEST_F(LayerTreeHostImplTest, ScrollNonScrollableRootWithTopControls) {
1764 LayerTreeSettings settings;
1765 settings.calculate_top_controls_position = true;
1766 settings.top_controls_height = 50;
1768 CreateHostImpl(settings, CreateOutputSurface());
1770 gfx::Size layer_size(5, 5);
1771 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1772 root->SetScrollable(true);
1773 root->SetMaxScrollOffset(gfx::Vector2d(layer_size.width(),
1774 layer_size.height()));
1775 root->SetBounds(layer_size);
1776 root->SetContentBounds(layer_size);
1777 root->SetPosition(gfx::PointF());
1778 root->SetAnchorPoint(gfx::PointF());
1779 root->SetDrawsContent(false);
1780 host_impl_->active_tree()->SetRootLayer(root.Pass());
1781 host_impl_->active_tree()->FindRootScrollLayer();
1782 DrawFrame();
1784 EXPECT_EQ(InputHandler::ScrollStarted,
1785 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
1787 host_impl_->top_controls_manager()->ScrollBegin();
1788 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
1789 host_impl_->top_controls_manager()->ScrollEnd();
1790 EXPECT_EQ(host_impl_->top_controls_manager()->content_top_offset(), 0.f);
1792 host_impl_->ScrollEnd();
1794 EXPECT_EQ(InputHandler::ScrollStarted,
1795 host_impl_->ScrollBegin(gfx::Point(),
1796 InputHandler::Gesture));
1799 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
1800 // Test the configuration where a non-composited root layer is embedded in a
1801 // scrollable outer layer.
1802 gfx::Size surface_size(10, 10);
1804 scoped_ptr<LayerImpl> content_layer =
1805 LayerImpl::Create(host_impl_->active_tree(), 1);
1806 content_layer->SetDrawsContent(true);
1807 content_layer->SetPosition(gfx::PointF());
1808 content_layer->SetAnchorPoint(gfx::PointF());
1809 content_layer->SetBounds(surface_size);
1810 content_layer->SetContentBounds(gfx::Size(surface_size.width() * 2,
1811 surface_size.height() * 2));
1812 content_layer->SetContentsScale(2.f, 2.f);
1814 scoped_ptr<LayerImpl> scroll_layer =
1815 LayerImpl::Create(host_impl_->active_tree(), 2);
1816 scroll_layer->SetScrollable(true);
1817 scroll_layer->SetMaxScrollOffset(gfx::Vector2d(surface_size.width(),
1818 surface_size.height()));
1819 scroll_layer->SetBounds(surface_size);
1820 scroll_layer->SetContentBounds(surface_size);
1821 scroll_layer->SetPosition(gfx::PointF());
1822 scroll_layer->SetAnchorPoint(gfx::PointF());
1823 scroll_layer->AddChild(content_layer.Pass());
1825 host_impl_->active_tree()->SetRootLayer(scroll_layer.Pass());
1826 host_impl_->SetViewportSize(surface_size);
1827 DrawFrame();
1829 EXPECT_EQ(InputHandler::ScrollStarted,
1830 host_impl_->ScrollBegin(gfx::Point(5, 5),
1831 InputHandler::Wheel));
1832 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1833 host_impl_->ScrollEnd();
1834 EXPECT_TRUE(did_request_redraw_);
1835 EXPECT_TRUE(did_request_commit_);
1838 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
1839 gfx::Size surface_size(10, 10);
1840 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1841 root->SetBounds(surface_size);
1842 root->SetContentBounds(surface_size);
1843 root->AddChild(CreateScrollableLayer(2, surface_size));
1844 host_impl_->active_tree()->SetRootLayer(root.Pass());
1845 host_impl_->SetViewportSize(surface_size);
1846 DrawFrame();
1848 EXPECT_EQ(InputHandler::ScrollStarted,
1849 host_impl_->ScrollBegin(gfx::Point(5, 5),
1850 InputHandler::Wheel));
1851 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1852 host_impl_->ScrollEnd();
1853 EXPECT_TRUE(did_request_redraw_);
1854 EXPECT_TRUE(did_request_commit_);
1857 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
1858 gfx::Size surface_size(10, 10);
1859 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1860 root->AddChild(CreateScrollableLayer(2, surface_size));
1861 host_impl_->active_tree()->SetRootLayer(root.Pass());
1862 host_impl_->SetViewportSize(surface_size);
1863 DrawFrame();
1865 // Scroll event is ignored because the input coordinate is outside the layer
1866 // boundaries.
1867 EXPECT_EQ(InputHandler::ScrollIgnored,
1868 host_impl_->ScrollBegin(gfx::Point(15, 5),
1869 InputHandler::Wheel));
1870 EXPECT_FALSE(did_request_redraw_);
1871 EXPECT_FALSE(did_request_commit_);
1874 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
1875 gfx::Size surface_size(10, 10);
1876 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1877 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, surface_size);
1878 host_impl_->SetViewportSize(surface_size);
1880 gfx::Transform matrix;
1881 matrix.RotateAboutXAxis(180.0);
1882 child->SetTransform(matrix);
1883 child->SetDoubleSided(false);
1885 root->AddChild(child.Pass());
1886 host_impl_->active_tree()->SetRootLayer(root.Pass());
1887 DrawFrame();
1889 // Scroll event is ignored because the scrollable layer is not facing the
1890 // viewer and there is nothing scrollable behind it.
1891 EXPECT_EQ(InputHandler::ScrollIgnored,
1892 host_impl_->ScrollBegin(gfx::Point(5, 5),
1893 InputHandler::Wheel));
1894 EXPECT_FALSE(did_request_redraw_);
1895 EXPECT_FALSE(did_request_commit_);
1898 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
1899 gfx::Size surface_size(10, 10);
1900 scoped_ptr<LayerImpl> content_layer = CreateScrollableLayer(1, surface_size);
1901 content_layer->SetShouldScrollOnMainThread(true);
1902 content_layer->SetScrollable(false);
1904 scoped_ptr<LayerImpl> scroll_layer = CreateScrollableLayer(2, surface_size);
1905 scroll_layer->AddChild(content_layer.Pass());
1907 host_impl_->active_tree()->SetRootLayer(scroll_layer.Pass());
1908 host_impl_->SetViewportSize(surface_size);
1909 DrawFrame();
1911 // Scrolling fails because the content layer is asking to be scrolled on the
1912 // main thread.
1913 EXPECT_EQ(InputHandler::ScrollOnMainThread,
1914 host_impl_->ScrollBegin(gfx::Point(5, 5),
1915 InputHandler::Wheel));
1918 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
1919 gfx::Size surface_size(10, 10);
1920 float page_scale = 2.f;
1921 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1922 scoped_ptr<LayerImpl> root_scrolling = CreateScrollableLayer(2, surface_size);
1923 root->AddChild(root_scrolling.Pass());
1924 host_impl_->active_tree()->SetRootLayer(root.Pass());
1925 host_impl_->active_tree()->DidBecomeActive();
1926 host_impl_->SetViewportSize(surface_size);
1927 DrawFrame();
1929 LayerImpl* root_scroll = host_impl_->active_tree()->RootScrollLayer();
1931 gfx::Vector2d scroll_delta(0, 10);
1932 gfx::Vector2d expected_scroll_delta = scroll_delta;
1933 gfx::Vector2d expected_max_scroll = root_scroll->max_scroll_offset();
1934 EXPECT_EQ(InputHandler::ScrollStarted,
1935 host_impl_->ScrollBegin(gfx::Point(5, 5),
1936 InputHandler::Wheel));
1937 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
1938 host_impl_->ScrollEnd();
1940 // Set new page scale from main thread.
1941 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
1942 page_scale,
1943 page_scale);
1945 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
1946 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
1948 // The scroll range should also have been updated.
1949 EXPECT_EQ(expected_max_scroll, root_scroll->max_scroll_offset());
1951 // The page scale delta remains constant because the impl thread did not
1952 // scale.
1953 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
1956 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
1957 gfx::Size surface_size(10, 10);
1958 float page_scale = 2.f;
1959 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1960 scoped_ptr<LayerImpl> root_scrolling = CreateScrollableLayer(2, surface_size);
1961 root->AddChild(root_scrolling.Pass());
1962 host_impl_->active_tree()->SetRootLayer(root.Pass());
1963 host_impl_->active_tree()->DidBecomeActive();
1964 host_impl_->SetViewportSize(surface_size);
1965 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
1966 DrawFrame();
1968 LayerImpl* root_scroll = host_impl_->active_tree()->RootScrollLayer();
1970 gfx::Vector2d scroll_delta(0, 10);
1971 gfx::Vector2d expected_scroll_delta = scroll_delta;
1972 gfx::Vector2d expected_max_scroll = root_scroll->max_scroll_offset();
1973 EXPECT_EQ(InputHandler::ScrollStarted,
1974 host_impl_->ScrollBegin(gfx::Point(5, 5),
1975 InputHandler::Wheel));
1976 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
1977 host_impl_->ScrollEnd();
1979 // Set new page scale on impl thread by pinching.
1980 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1981 host_impl_->PinchGestureBegin();
1982 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
1983 host_impl_->PinchGestureEnd();
1984 host_impl_->ScrollEnd();
1985 DrawOneFrame();
1987 // The scroll delta is not scaled because the main thread did not scale.
1988 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
1989 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
1991 // The scroll range should also have been updated.
1992 EXPECT_EQ(expected_max_scroll, root_scroll->max_scroll_offset());
1994 // The page scale delta should match the new scale on the impl side.
1995 EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
1998 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
1999 gfx::Size surface_size(10, 10);
2000 float default_page_scale = 1.f;
2001 gfx::Transform default_page_scale_matrix;
2002 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
2004 float new_page_scale = 2.f;
2005 gfx::Transform new_page_scale_matrix;
2006 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
2008 // Create a normal scrollable root layer and another scrollable child layer.
2009 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
2010 LayerImpl* root = host_impl_->active_tree()->root_layer();
2011 LayerImpl* child = scroll->children()[0];
2013 scoped_ptr<LayerImpl> scrollable_child =
2014 CreateScrollableLayer(4, surface_size);
2015 child->AddChild(scrollable_child.Pass());
2016 LayerImpl* grand_child = child->children()[0];
2018 // Set new page scale on impl thread by pinching.
2019 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2020 host_impl_->PinchGestureBegin();
2021 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
2022 host_impl_->PinchGestureEnd();
2023 host_impl_->ScrollEnd();
2024 DrawOneFrame();
2026 EXPECT_EQ(1.f, root->contents_scale_x());
2027 EXPECT_EQ(1.f, root->contents_scale_y());
2028 EXPECT_EQ(1.f, scroll->contents_scale_x());
2029 EXPECT_EQ(1.f, scroll->contents_scale_y());
2030 EXPECT_EQ(1.f, child->contents_scale_x());
2031 EXPECT_EQ(1.f, child->contents_scale_y());
2032 EXPECT_EQ(1.f, grand_child->contents_scale_x());
2033 EXPECT_EQ(1.f, grand_child->contents_scale_y());
2035 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
2036 // the page scale delta on the root layer is applied hierarchically.
2037 LayerTreeHostImpl::FrameData frame;
2038 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2039 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2040 host_impl_->DidDrawAllLayers(frame);
2042 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
2043 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
2044 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
2045 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
2046 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
2047 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
2048 EXPECT_EQ(new_page_scale,
2049 grand_child->draw_transform().matrix().getDouble(0, 0));
2050 EXPECT_EQ(new_page_scale,
2051 grand_child->draw_transform().matrix().getDouble(1, 1));
2054 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
2055 gfx::Size surface_size(10, 10);
2056 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2057 scoped_ptr<LayerImpl> root_scrolling =
2058 LayerImpl::Create(host_impl_->active_tree(), 2);
2059 root_scrolling->SetBounds(surface_size);
2060 root_scrolling->SetContentBounds(surface_size);
2061 root_scrolling->SetScrollable(true);
2062 root->AddChild(root_scrolling.Pass());
2063 int child_scroll_layer_id = 3;
2064 scoped_ptr<LayerImpl> child_scrolling =
2065 CreateScrollableLayer(child_scroll_layer_id, surface_size);
2066 LayerImpl* child = child_scrolling.get();
2067 root->AddChild(child_scrolling.Pass());
2068 host_impl_->active_tree()->SetRootLayer(root.Pass());
2069 host_impl_->active_tree()->DidBecomeActive();
2070 host_impl_->SetViewportSize(surface_size);
2071 DrawFrame();
2073 gfx::Vector2d scroll_delta(0, 10);
2074 gfx::Vector2d expected_scroll_delta(scroll_delta);
2075 gfx::Vector2d expected_max_scroll(child->max_scroll_offset());
2076 EXPECT_EQ(InputHandler::ScrollStarted,
2077 host_impl_->ScrollBegin(gfx::Point(5, 5),
2078 InputHandler::Wheel));
2079 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2080 host_impl_->ScrollEnd();
2082 float page_scale = 2.f;
2083 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2084 1.f,
2085 page_scale);
2087 DrawOneFrame();
2089 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2090 ExpectContains(
2091 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
2093 // The scroll range should not have changed.
2094 EXPECT_EQ(child->max_scroll_offset(), expected_max_scroll);
2096 // The page scale delta remains constant because the impl thread did not
2097 // scale.
2098 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2101 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
2102 // Scroll a child layer beyond its maximum scroll range and make sure the
2103 // parent layer is scrolled on the axis on which the child was unable to
2104 // scroll.
2105 gfx::Size surface_size(10, 10);
2106 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, surface_size);
2108 scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(3, surface_size);
2109 grand_child->SetScrollOffset(gfx::Vector2d(0, 5));
2111 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, surface_size);
2112 child->SetScrollOffset(gfx::Vector2d(3, 0));
2113 child->AddChild(grand_child.Pass());
2115 root->AddChild(child.Pass());
2116 host_impl_->active_tree()->SetRootLayer(root.Pass());
2117 host_impl_->active_tree()->DidBecomeActive();
2118 host_impl_->SetViewportSize(surface_size);
2119 DrawFrame();
2121 gfx::Vector2d scroll_delta(-8, -7);
2122 EXPECT_EQ(InputHandler::ScrollStarted,
2123 host_impl_->ScrollBegin(gfx::Point(),
2124 InputHandler::Wheel));
2125 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2126 host_impl_->ScrollEnd();
2128 scoped_ptr<ScrollAndScaleSet> scroll_info =
2129 host_impl_->ProcessScrollDeltas();
2131 // The grand child should have scrolled up to its limit.
2132 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2133 LayerImpl* grand_child = child->children()[0];
2134 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
2136 // The child should have only scrolled on the other axis.
2137 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
2141 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
2142 // Scroll a child layer beyond its maximum scroll range and make sure the
2143 // the scroll doesn't bubble up to the parent layer.
2144 gfx::Size surface_size(10, 10);
2145 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2146 scoped_ptr<LayerImpl> root_scrolling = CreateScrollableLayer(2, surface_size);
2148 scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(4, surface_size);
2149 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
2151 scoped_ptr<LayerImpl> child = CreateScrollableLayer(3, surface_size);
2152 child->SetScrollOffset(gfx::Vector2d(0, 3));
2153 child->AddChild(grand_child.Pass());
2155 root_scrolling->AddChild(child.Pass());
2156 root->AddChild(root_scrolling.Pass());
2157 host_impl_->active_tree()->SetRootLayer(root.Pass());
2158 host_impl_->active_tree()->DidBecomeActive();
2159 host_impl_->SetViewportSize(surface_size);
2160 DrawFrame();
2162 gfx::Vector2d scroll_delta(0, -10);
2163 EXPECT_EQ(InputHandler::ScrollStarted,
2164 host_impl_->ScrollBegin(gfx::Point(),
2165 InputHandler::NonBubblingGesture));
2166 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2167 host_impl_->ScrollEnd();
2169 scoped_ptr<ScrollAndScaleSet> scroll_info =
2170 host_impl_->ProcessScrollDeltas();
2172 // The grand child should have scrolled up to its limit.
2173 LayerImpl* child =
2174 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
2175 LayerImpl* grand_child = child->children()[0];
2176 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2178 // The child should not have scrolled.
2179 ExpectNone(*scroll_info.get(), child->id());
2181 // The next time we scroll we should only scroll the parent.
2182 scroll_delta = gfx::Vector2d(0, -3);
2183 EXPECT_EQ(InputHandler::ScrollStarted,
2184 host_impl_->ScrollBegin(gfx::Point(5, 5),
2185 InputHandler::NonBubblingGesture));
2186 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2187 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2188 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
2189 host_impl_->ScrollEnd();
2191 scroll_info = host_impl_->ProcessScrollDeltas();
2193 // The child should have scrolled up to its limit.
2194 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2196 // The grand child should not have scrolled.
2197 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2199 // After scrolling the parent, another scroll on the opposite direction
2200 // should still scroll the child.
2201 scroll_delta = gfx::Vector2d(0, 7);
2202 EXPECT_EQ(InputHandler::ScrollStarted,
2203 host_impl_->ScrollBegin(gfx::Point(5, 5),
2204 InputHandler::NonBubblingGesture));
2205 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2206 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2207 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2208 host_impl_->ScrollEnd();
2210 scroll_info = host_impl_->ProcessScrollDeltas();
2212 // The grand child should have scrolled.
2213 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
2215 // The child should not have scrolled.
2216 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2219 // Scrolling should be adjusted from viewport space.
2220 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
2221 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2223 scroll_delta = gfx::Vector2d(0, -2);
2224 EXPECT_EQ(InputHandler::ScrollStarted,
2225 host_impl_->ScrollBegin(gfx::Point(1, 1),
2226 InputHandler::NonBubblingGesture));
2227 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
2228 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2229 host_impl_->ScrollEnd();
2231 scroll_info = host_impl_->ProcessScrollDeltas();
2233 // Should have scrolled by half the amount in layer space (5 - 2/2)
2234 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
2238 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
2239 // When we try to scroll a non-scrollable child layer, the scroll delta
2240 // should be applied to one of its ancestors if possible.
2241 gfx::Size surface_size(10, 10);
2242 gfx::Size content_size(20, 20);
2243 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
2244 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
2246 child->SetScrollable(false);
2247 root->AddChild(child.Pass());
2249 host_impl_->SetViewportSize(surface_size);
2250 host_impl_->active_tree()->SetRootLayer(root.Pass());
2251 host_impl_->active_tree()->DidBecomeActive();
2252 DrawFrame();
2254 gfx::Vector2d scroll_delta(0, 4);
2255 EXPECT_EQ(InputHandler::ScrollStarted,
2256 host_impl_->ScrollBegin(gfx::Point(5, 5),
2257 InputHandler::Wheel));
2258 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2259 host_impl_->ScrollEnd();
2261 scoped_ptr<ScrollAndScaleSet> scroll_info =
2262 host_impl_->ProcessScrollDeltas();
2264 // Only the root should have scrolled.
2265 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
2266 ExpectContains(*scroll_info.get(),
2267 host_impl_->active_tree()->root_layer()->id(),
2268 scroll_delta);
2272 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
2273 gfx::Size surface_size(10, 10);
2274 host_impl_->active_tree()->SetRootLayer(
2275 CreateScrollableLayer(1, surface_size));
2276 host_impl_->active_tree()->DidBecomeActive();
2277 host_impl_->SetViewportSize(surface_size);
2279 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
2280 // synchronization.
2281 DrawFrame();
2282 host_impl_->active_tree()->DetachLayerTree();
2283 host_impl_->active_tree()->SetRootLayer(
2284 CreateScrollableLayer(2, surface_size));
2285 host_impl_->active_tree()->DidBecomeActive();
2287 // Scrolling should still work even though we did not draw yet.
2288 EXPECT_EQ(InputHandler::ScrollStarted,
2289 host_impl_->ScrollBegin(gfx::Point(5, 5),
2290 InputHandler::Wheel));
2293 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
2294 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2296 // Rotate the root layer 90 degrees counter-clockwise about its center.
2297 gfx::Transform rotate_transform;
2298 rotate_transform.Rotate(-90.0);
2299 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
2301 gfx::Size surface_size(50, 50);
2302 host_impl_->SetViewportSize(surface_size);
2303 DrawFrame();
2305 // Scroll to the right in screen coordinates with a gesture.
2306 gfx::Vector2d gesture_scroll_delta(10, 0);
2307 EXPECT_EQ(InputHandler::ScrollStarted,
2308 host_impl_->ScrollBegin(gfx::Point(),
2309 InputHandler::Gesture));
2310 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2311 host_impl_->ScrollEnd();
2313 // The layer should have scrolled down in its local coordinates.
2314 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2315 ExpectContains(*scroll_info.get(),
2316 scroll_layer->id(),
2317 gfx::Vector2d(0, gesture_scroll_delta.x()));
2319 // Reset and scroll down with the wheel.
2320 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2321 gfx::Vector2d wheel_scroll_delta(0, 10);
2322 EXPECT_EQ(InputHandler::ScrollStarted,
2323 host_impl_->ScrollBegin(gfx::Point(),
2324 InputHandler::Wheel));
2325 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2326 host_impl_->ScrollEnd();
2328 // The layer should have scrolled down in its local coordinates.
2329 scroll_info = host_impl_->ProcessScrollDeltas();
2330 ExpectContains(*scroll_info.get(),
2331 scroll_layer->id(),
2332 wheel_scroll_delta);
2335 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
2336 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2337 int child_layer_id = 4;
2338 float child_layer_angle = -20.f;
2340 // Create a child layer that is rotated to a non-axis-aligned angle.
2341 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
2342 child_layer_id,
2343 scroll_layer->content_bounds());
2344 gfx::Transform rotate_transform;
2345 rotate_transform.Translate(-50.0, -50.0);
2346 rotate_transform.Rotate(child_layer_angle);
2347 rotate_transform.Translate(50.0, 50.0);
2348 child->SetTransform(rotate_transform);
2350 // Only allow vertical scrolling.
2351 child->SetMaxScrollOffset(gfx::Vector2d(0, child->content_bounds().height()));
2352 scroll_layer->AddChild(child.Pass());
2354 gfx::Size surface_size(50, 50);
2355 host_impl_->SetViewportSize(surface_size);
2356 DrawFrame();
2358 // Scroll down in screen coordinates with a gesture.
2359 gfx::Vector2d gesture_scroll_delta(0, 10);
2360 EXPECT_EQ(InputHandler::ScrollStarted,
2361 host_impl_->ScrollBegin(gfx::Point(1, 1),
2362 InputHandler::Gesture));
2363 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2364 host_impl_->ScrollEnd();
2366 // The child layer should have scrolled down in its local coordinates an
2367 // amount proportional to the angle between it and the input scroll delta.
2368 gfx::Vector2d expected_scroll_delta(
2370 gesture_scroll_delta.y() *
2371 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
2372 scoped_ptr<ScrollAndScaleSet> scroll_info =
2373 host_impl_->ProcessScrollDeltas();
2374 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2376 // The root scroll layer should not have scrolled, because the input delta
2377 // was close to the layer's axis of movement.
2378 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
2381 // Now reset and scroll the same amount horizontally.
2382 scroll_layer->children()[1]->SetScrollDelta(
2383 gfx::Vector2dF());
2384 gfx::Vector2d gesture_scroll_delta(10, 0);
2385 EXPECT_EQ(InputHandler::ScrollStarted,
2386 host_impl_->ScrollBegin(gfx::Point(1, 1),
2387 InputHandler::Gesture));
2388 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2389 host_impl_->ScrollEnd();
2391 // The child layer should have scrolled down in its local coordinates an
2392 // amount proportional to the angle between it and the input scroll delta.
2393 gfx::Vector2d expected_scroll_delta(
2395 -gesture_scroll_delta.x() *
2396 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
2397 scoped_ptr<ScrollAndScaleSet> scroll_info =
2398 host_impl_->ProcessScrollDeltas();
2399 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2401 // The root scroll layer should have scrolled more, since the input scroll
2402 // delta was mostly orthogonal to the child layer's vertical scroll axis.
2403 gfx::Vector2d expected_root_scroll_delta(
2404 gesture_scroll_delta.x() *
2405 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
2407 ExpectContains(*scroll_info.get(),
2408 scroll_layer->id(),
2409 expected_root_scroll_delta);
2413 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
2414 LayerImpl* scroll_layer =
2415 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2417 // Scale the layer to twice its normal size.
2418 int scale = 2;
2419 gfx::Transform scale_transform;
2420 scale_transform.Scale(scale, scale);
2421 scroll_layer->SetTransform(scale_transform);
2423 gfx::Size surface_size(50, 50);
2424 host_impl_->SetViewportSize(surface_size);
2425 DrawFrame();
2427 // Scroll down in screen coordinates with a gesture.
2428 gfx::Vector2d scroll_delta(0, 10);
2429 EXPECT_EQ(InputHandler::ScrollStarted,
2430 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2431 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2432 host_impl_->ScrollEnd();
2434 // The layer should have scrolled down in its local coordinates, but half the
2435 // amount.
2436 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2437 ExpectContains(*scroll_info.get(),
2438 scroll_layer->id(),
2439 gfx::Vector2d(0, scroll_delta.y() / scale));
2441 // Reset and scroll down with the wheel.
2442 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2443 gfx::Vector2d wheel_scroll_delta(0, 10);
2444 EXPECT_EQ(InputHandler::ScrollStarted,
2445 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2446 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2447 host_impl_->ScrollEnd();
2449 // The scale should not have been applied to the scroll delta.
2450 scroll_info = host_impl_->ProcessScrollDeltas();
2451 ExpectContains(*scroll_info.get(),
2452 scroll_layer->id(),
2453 wheel_scroll_delta);
2456 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
2457 public:
2458 TestScrollOffsetDelegate() : page_scale_factor_(0.f) {}
2460 virtual ~TestScrollOffsetDelegate() {}
2462 virtual void SetMaxScrollOffset(
2463 const gfx::Vector2dF& max_scroll_offset) OVERRIDE {
2464 max_scroll_offset_ = max_scroll_offset;
2467 virtual void SetTotalScrollOffset(const gfx::Vector2dF& new_value) OVERRIDE {
2468 last_set_scroll_offset_ = new_value;
2471 virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
2472 return getter_return_value_;
2475 virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
2477 virtual void SetTotalPageScaleFactor(float page_scale_factor) OVERRIDE {
2478 page_scale_factor_ = page_scale_factor;
2481 virtual void SetScrollableSize(const gfx::SizeF& scrollable_size) OVERRIDE {
2482 scrollable_size_ = scrollable_size;
2485 gfx::Vector2dF last_set_scroll_offset() {
2486 return last_set_scroll_offset_;
2489 void set_getter_return_value(const gfx::Vector2dF& value) {
2490 getter_return_value_ = value;
2493 gfx::Vector2dF max_scroll_offset() const {
2494 return max_scroll_offset_;
2497 gfx::SizeF scrollable_size() const {
2498 return scrollable_size_;
2501 float page_scale_factor() const {
2502 return page_scale_factor_;
2505 private:
2506 gfx::Vector2dF last_set_scroll_offset_;
2507 gfx::Vector2dF getter_return_value_;
2508 gfx::Vector2dF max_scroll_offset_;
2509 gfx::SizeF scrollable_size_;
2510 float page_scale_factor_;
2513 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
2514 TestScrollOffsetDelegate scroll_delegate;
2515 host_impl_->SetViewportSize(gfx::Size(10, 20));
2516 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2518 // Setting the delegate results in the current scroll offset being set.
2519 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
2520 scroll_layer->SetScrollOffset(gfx::Vector2d());
2521 scroll_layer->SetScrollDelta(initial_scroll_delta);
2522 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
2523 EXPECT_EQ(initial_scroll_delta.ToString(),
2524 scroll_delegate.last_set_scroll_offset().ToString());
2526 // Setting the delegate results in the scrollable_size, max_scroll_offset and
2527 // page_scale being set.
2528 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
2529 EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
2530 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
2532 // Updating page scale immediately updates the delegate.
2533 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
2534 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
2535 host_impl_->active_tree()->SetPageScaleDelta(1.5f);
2536 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
2537 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2538 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
2539 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
2541 // Scrolling should be relative to the offset as returned by the delegate.
2542 gfx::Vector2dF scroll_delta(0.f, 10.f);
2543 gfx::Vector2dF current_offset(7.f, 8.f);
2545 scroll_delegate.set_getter_return_value(current_offset);
2546 EXPECT_EQ(InputHandler::ScrollStarted,
2547 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2549 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2550 EXPECT_EQ(current_offset + scroll_delta,
2551 scroll_delegate.last_set_scroll_offset());
2553 current_offset = gfx::Vector2dF(42.f, 41.f);
2554 scroll_delegate.set_getter_return_value(current_offset);
2555 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2556 EXPECT_EQ(current_offset + scroll_delta,
2557 scroll_delegate.last_set_scroll_offset());
2558 host_impl_->ScrollEnd();
2560 // Forces a full tree synchronization and ensures that the scroll delegate
2561 // sees the correct size of the new tree.
2562 gfx::Size new_size(42, 24);
2563 host_impl_->CreatePendingTree();
2564 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
2565 host_impl_->ActivatePendingTree();
2566 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
2568 // Un-setting the delegate should propagate the delegate's current offset to
2569 // the root scrollable layer.
2570 current_offset = gfx::Vector2dF(13.f, 12.f);
2571 scroll_delegate.set_getter_return_value(current_offset);
2572 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
2574 EXPECT_EQ(current_offset.ToString(),
2575 scroll_layer->TotalScrollOffset().ToString());
2578 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
2579 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2580 host_impl_->SetViewportSize(gfx::Size(50, 50));
2581 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
2582 DrawFrame();
2583 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2584 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2586 // In-bounds scrolling does not affect overscroll.
2587 EXPECT_EQ(InputHandler::ScrollStarted,
2588 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2589 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2590 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2591 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2593 // Overscroll events are reflected immediately.
2594 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
2595 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
2596 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2598 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
2599 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
2600 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
2601 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
2602 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
2603 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
2604 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
2605 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
2606 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
2607 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
2608 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
2609 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
2610 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
2612 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
2613 // as no scroll occurs.
2614 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
2615 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
2616 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
2617 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
2618 // Overscroll resets on valid scroll.
2619 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2620 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
2621 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
2622 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
2623 host_impl_->ScrollEnd();
2625 EXPECT_EQ(InputHandler::ScrollStarted,
2626 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2627 // Fling velocity is reflected immediately.
2628 host_impl_->NotifyCurrentFlingVelocity(gfx::Vector2dF(10, 0));
2629 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
2630 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
2631 EXPECT_EQ(gfx::Vector2dF(0, -20), host_impl_->accumulated_root_overscroll());
2632 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
2636 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
2637 // Scroll child layers beyond their maximum scroll range and make sure root
2638 // overscroll does not accumulate.
2639 gfx::Size surface_size(10, 10);
2640 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, surface_size);
2642 scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(3, surface_size);
2643 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
2645 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, surface_size);
2646 child->SetScrollOffset(gfx::Vector2d(0, 3));
2647 child->AddChild(grand_child.Pass());
2649 root->AddChild(child.Pass());
2650 host_impl_->active_tree()->SetRootLayer(root.Pass());
2651 host_impl_->active_tree()->DidBecomeActive();
2652 host_impl_->SetViewportSize(surface_size);
2653 DrawFrame();
2655 gfx::Vector2d scroll_delta(0, -10);
2656 EXPECT_EQ(InputHandler::ScrollStarted,
2657 host_impl_->ScrollBegin(gfx::Point(),
2658 InputHandler::NonBubblingGesture));
2659 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2660 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2661 host_impl_->ScrollEnd();
2663 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2664 LayerImpl* grand_child = child->children()[0];
2666 // The next time we scroll we should only scroll the parent, but overscroll
2667 // should still not reach the root layer.
2668 scroll_delta = gfx::Vector2d(0, -30);
2669 EXPECT_EQ(InputHandler::ScrollStarted,
2670 host_impl_->ScrollBegin(gfx::Point(5, 5),
2671 InputHandler::NonBubblingGesture));
2672 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2673 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2674 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2675 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
2676 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2677 host_impl_->ScrollEnd();
2679 // After scrolling the parent, another scroll on the opposite direction
2680 // should scroll the child, resetting the fling velocity.
2681 scroll_delta = gfx::Vector2d(0, 70);
2682 host_impl_->NotifyCurrentFlingVelocity(gfx::Vector2dF(10, 0));
2683 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
2684 EXPECT_EQ(InputHandler::ScrollStarted,
2685 host_impl_->ScrollBegin(gfx::Point(5, 5),
2686 InputHandler::NonBubblingGesture));
2687 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2688 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2689 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2690 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2691 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2692 host_impl_->ScrollEnd();
2696 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
2697 // When we try to scroll a non-scrollable child layer, the scroll delta
2698 // should be applied to one of its ancestors if possible. Overscroll should
2699 // be reflected only when it has bubbled up to the root scrolling layer.
2700 gfx::Size surface_size(10, 10);
2701 gfx::Size content_size(20, 20);
2702 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
2703 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
2705 child->SetScrollable(false);
2706 root->AddChild(child.Pass());
2708 host_impl_->SetViewportSize(surface_size);
2709 host_impl_->active_tree()->SetRootLayer(root.Pass());
2710 host_impl_->active_tree()->DidBecomeActive();
2711 DrawFrame();
2713 gfx::Vector2d scroll_delta(0, 8);
2714 EXPECT_EQ(InputHandler::ScrollStarted,
2715 host_impl_->ScrollBegin(gfx::Point(5, 5),
2716 InputHandler::Wheel));
2717 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2718 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2719 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2720 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
2721 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2722 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
2723 host_impl_->ScrollEnd();
2727 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
2728 LayerTreeSettings settings;
2729 CreateHostImpl(settings, CreateOutputSurface());
2731 SetupScrollAndContentsLayers(gfx::Size(50, 50));
2732 host_impl_->SetViewportSize(gfx::Size(50, 50));
2733 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
2734 DrawFrame();
2735 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2736 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2738 // Even though the layer can't scroll the overscroll still happens.
2739 EXPECT_EQ(InputHandler::ScrollStarted,
2740 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2741 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2742 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
2743 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2746 class BlendStateCheckLayer : public LayerImpl {
2747 public:
2748 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
2749 int id,
2750 ResourceProvider* resource_provider) {
2751 return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(tree_impl,
2753 resource_provider));
2756 virtual void AppendQuads(QuadSink* quad_sink,
2757 AppendQuadsData* append_quads_data) OVERRIDE {
2758 quads_appended_ = true;
2760 gfx::Rect opaque_rect;
2761 if (contents_opaque())
2762 opaque_rect = quad_rect_;
2763 else
2764 opaque_rect = opaque_content_rect_;
2766 SharedQuadState* shared_quad_state =
2767 quad_sink->UseSharedQuadState(CreateSharedQuadState());
2768 scoped_ptr<TileDrawQuad> test_blending_draw_quad = TileDrawQuad::Create();
2769 test_blending_draw_quad->SetNew(shared_quad_state,
2770 quad_rect_,
2771 opaque_rect,
2772 resource_id_,
2773 gfx::RectF(0.f, 0.f, 1.f, 1.f),
2774 gfx::Size(1, 1),
2775 false);
2776 test_blending_draw_quad->visible_rect = quad_visible_rect_;
2777 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
2778 EXPECT_EQ(has_render_surface_, !!render_surface());
2779 quad_sink->Append(test_blending_draw_quad.PassAs<DrawQuad>(),
2780 append_quads_data);
2783 void SetExpectation(bool blend, bool has_render_surface) {
2784 blend_ = blend;
2785 has_render_surface_ = has_render_surface;
2786 quads_appended_ = false;
2789 bool quads_appended() const { return quads_appended_; }
2791 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
2792 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
2793 void SetOpaqueContentRect(const gfx::Rect& rect) {
2794 opaque_content_rect_ = rect;
2797 private:
2798 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
2799 int id,
2800 ResourceProvider* resource_provider)
2801 : LayerImpl(tree_impl, id),
2802 blend_(false),
2803 has_render_surface_(false),
2804 quads_appended_(false),
2805 quad_rect_(5, 5, 5, 5),
2806 quad_visible_rect_(5, 5, 5, 5),
2807 resource_id_(resource_provider->CreateResource(
2808 gfx::Size(1, 1),
2809 GL_CLAMP_TO_EDGE,
2810 ResourceProvider::TextureUsageAny,
2811 RGBA_8888)) {
2812 resource_provider->AllocateForTesting(resource_id_);
2813 SetAnchorPoint(gfx::PointF());
2814 SetBounds(gfx::Size(10, 10));
2815 SetContentBounds(gfx::Size(10, 10));
2816 SetDrawsContent(true);
2819 bool blend_;
2820 bool has_render_surface_;
2821 bool quads_appended_;
2822 gfx::Rect quad_rect_;
2823 gfx::Rect opaque_content_rect_;
2824 gfx::Rect quad_visible_rect_;
2825 ResourceProvider::ResourceId resource_id_;
2828 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
2830 scoped_ptr<LayerImpl> root =
2831 LayerImpl::Create(host_impl_->active_tree(), 1);
2832 root->SetAnchorPoint(gfx::PointF());
2833 root->SetBounds(gfx::Size(10, 10));
2834 root->SetContentBounds(root->bounds());
2835 root->SetDrawsContent(false);
2836 host_impl_->active_tree()->SetRootLayer(root.Pass());
2838 LayerImpl* root = host_impl_->active_tree()->root_layer();
2840 root->AddChild(
2841 BlendStateCheckLayer::Create(host_impl_->active_tree(),
2843 host_impl_->resource_provider()));
2844 BlendStateCheckLayer* layer1 =
2845 static_cast<BlendStateCheckLayer*>(root->children()[0]);
2846 layer1->SetPosition(gfx::PointF(2.f, 2.f));
2848 LayerTreeHostImpl::FrameData frame;
2850 // Opaque layer, drawn without blending.
2851 layer1->SetContentsOpaque(true);
2852 layer1->SetExpectation(false, false);
2853 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2854 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2855 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2856 EXPECT_TRUE(layer1->quads_appended());
2857 host_impl_->DidDrawAllLayers(frame);
2859 // Layer with translucent content and painting, so drawn with blending.
2860 layer1->SetContentsOpaque(false);
2861 layer1->SetExpectation(true, false);
2862 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2863 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2864 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2865 EXPECT_TRUE(layer1->quads_appended());
2866 host_impl_->DidDrawAllLayers(frame);
2868 // Layer with translucent opacity, drawn with blending.
2869 layer1->SetContentsOpaque(true);
2870 layer1->SetOpacity(0.5f);
2871 layer1->SetExpectation(true, false);
2872 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2873 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2874 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2875 EXPECT_TRUE(layer1->quads_appended());
2876 host_impl_->DidDrawAllLayers(frame);
2878 // Layer with translucent opacity and painting, drawn with blending.
2879 layer1->SetContentsOpaque(true);
2880 layer1->SetOpacity(0.5f);
2881 layer1->SetExpectation(true, false);
2882 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2883 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2884 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2885 EXPECT_TRUE(layer1->quads_appended());
2886 host_impl_->DidDrawAllLayers(frame);
2888 layer1->AddChild(
2889 BlendStateCheckLayer::Create(host_impl_->active_tree(),
2891 host_impl_->resource_provider()));
2892 BlendStateCheckLayer* layer2 =
2893 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
2894 layer2->SetPosition(gfx::PointF(4.f, 4.f));
2896 // 2 opaque layers, drawn without blending.
2897 layer1->SetContentsOpaque(true);
2898 layer1->SetOpacity(1.f);
2899 layer1->SetExpectation(false, false);
2900 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2901 layer2->SetContentsOpaque(true);
2902 layer2->SetOpacity(1.f);
2903 layer2->SetExpectation(false, false);
2904 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2905 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2906 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2907 EXPECT_TRUE(layer1->quads_appended());
2908 EXPECT_TRUE(layer2->quads_appended());
2909 host_impl_->DidDrawAllLayers(frame);
2911 // Parent layer with translucent content, drawn with blending.
2912 // Child layer with opaque content, drawn without blending.
2913 layer1->SetContentsOpaque(false);
2914 layer1->SetExpectation(true, false);
2915 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2916 layer2->SetExpectation(false, false);
2917 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2918 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2919 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2920 EXPECT_TRUE(layer1->quads_appended());
2921 EXPECT_TRUE(layer2->quads_appended());
2922 host_impl_->DidDrawAllLayers(frame);
2924 // Parent layer with translucent content but opaque painting, drawn without
2925 // blending.
2926 // Child layer with opaque content, drawn without blending.
2927 layer1->SetContentsOpaque(true);
2928 layer1->SetExpectation(false, false);
2929 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2930 layer2->SetExpectation(false, false);
2931 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2932 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2933 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2934 EXPECT_TRUE(layer1->quads_appended());
2935 EXPECT_TRUE(layer2->quads_appended());
2936 host_impl_->DidDrawAllLayers(frame);
2938 // Parent layer with translucent opacity and opaque content. Since it has a
2939 // drawing child, it's drawn to a render surface which carries the opacity,
2940 // so it's itself drawn without blending.
2941 // Child layer with opaque content, drawn without blending (parent surface
2942 // carries the inherited opacity).
2943 layer1->SetContentsOpaque(true);
2944 layer1->SetOpacity(0.5f);
2945 layer1->SetExpectation(false, true);
2946 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2947 layer2->SetExpectation(false, false);
2948 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2949 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2950 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2951 EXPECT_TRUE(layer1->quads_appended());
2952 EXPECT_TRUE(layer2->quads_appended());
2953 host_impl_->DidDrawAllLayers(frame);
2955 // Draw again, but with child non-opaque, to make sure
2956 // layer1 not culled.
2957 layer1->SetContentsOpaque(true);
2958 layer1->SetOpacity(1.f);
2959 layer1->SetExpectation(false, false);
2960 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2961 layer2->SetContentsOpaque(true);
2962 layer2->SetOpacity(0.5f);
2963 layer2->SetExpectation(true, false);
2964 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2965 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2966 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2967 EXPECT_TRUE(layer1->quads_appended());
2968 EXPECT_TRUE(layer2->quads_appended());
2969 host_impl_->DidDrawAllLayers(frame);
2971 // A second way of making the child non-opaque.
2972 layer1->SetContentsOpaque(true);
2973 layer1->SetOpacity(1.f);
2974 layer1->SetExpectation(false, false);
2975 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2976 layer2->SetContentsOpaque(false);
2977 layer2->SetOpacity(1.f);
2978 layer2->SetExpectation(true, false);
2979 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2980 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2981 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2982 EXPECT_TRUE(layer1->quads_appended());
2983 EXPECT_TRUE(layer2->quads_appended());
2984 host_impl_->DidDrawAllLayers(frame);
2986 // And when the layer says its not opaque but is painted opaque, it is not
2987 // blended.
2988 layer1->SetContentsOpaque(true);
2989 layer1->SetOpacity(1.f);
2990 layer1->SetExpectation(false, false);
2991 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2992 layer2->SetContentsOpaque(true);
2993 layer2->SetOpacity(1.f);
2994 layer2->SetExpectation(false, false);
2995 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
2996 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2997 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2998 EXPECT_TRUE(layer1->quads_appended());
2999 EXPECT_TRUE(layer2->quads_appended());
3000 host_impl_->DidDrawAllLayers(frame);
3002 // Layer with partially opaque contents, drawn with blending.
3003 layer1->SetContentsOpaque(false);
3004 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3005 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
3006 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3007 layer1->SetExpectation(true, false);
3008 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3009 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3010 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3011 EXPECT_TRUE(layer1->quads_appended());
3012 host_impl_->DidDrawAllLayers(frame);
3014 // Layer with partially opaque contents partially culled, drawn with blending.
3015 layer1->SetContentsOpaque(false);
3016 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3017 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
3018 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3019 layer1->SetExpectation(true, false);
3020 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3021 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3022 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3023 EXPECT_TRUE(layer1->quads_appended());
3024 host_impl_->DidDrawAllLayers(frame);
3026 // Layer with partially opaque contents culled, drawn with blending.
3027 layer1->SetContentsOpaque(false);
3028 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3029 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
3030 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3031 layer1->SetExpectation(true, false);
3032 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3033 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3034 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3035 EXPECT_TRUE(layer1->quads_appended());
3036 host_impl_->DidDrawAllLayers(frame);
3038 // Layer with partially opaque contents and translucent contents culled, drawn
3039 // without blending.
3040 layer1->SetContentsOpaque(false);
3041 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3042 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
3043 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3044 layer1->SetExpectation(false, false);
3045 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3046 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3047 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3048 EXPECT_TRUE(layer1->quads_appended());
3049 host_impl_->DidDrawAllLayers(frame);
3052 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
3053 protected:
3054 LayerTreeHostImplViewportCoveredTest() :
3055 gutter_quad_material_(DrawQuad::SOLID_COLOR),
3056 child_(NULL),
3057 did_activate_pending_tree_(false) {}
3059 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
3060 if (always_draw) {
3061 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
3062 .PassAs<OutputSurface>();
3064 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
3067 void SetupActiveTreeLayers() {
3068 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
3069 host_impl_->active_tree()->SetRootLayer(
3070 LayerImpl::Create(host_impl_->active_tree(), 1));
3071 host_impl_->active_tree()->root_layer()->AddChild(
3072 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3074 host_impl_->resource_provider()));
3075 child_ = static_cast<BlendStateCheckLayer*>(
3076 host_impl_->active_tree()->root_layer()->children()[0]);
3077 child_->SetExpectation(false, false);
3078 child_->SetContentsOpaque(true);
3081 // Expect no gutter rects.
3082 void TestLayerCoversFullViewport() {
3083 gfx::Rect layer_rect(viewport_size_);
3084 child_->SetPosition(layer_rect.origin());
3085 child_->SetBounds(layer_rect.size());
3086 child_->SetContentBounds(layer_rect.size());
3087 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3088 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3090 LayerTreeHostImpl::FrameData frame;
3091 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3092 ASSERT_EQ(1u, frame.render_passes.size());
3094 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3095 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3096 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3098 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3099 host_impl_->DidDrawAllLayers(frame);
3102 // Expect fullscreen gutter rect.
3103 void TestEmptyLayer() {
3104 gfx::Rect layer_rect(0, 0, 0, 0);
3105 child_->SetPosition(layer_rect.origin());
3106 child_->SetBounds(layer_rect.size());
3107 child_->SetContentBounds(layer_rect.size());
3108 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3109 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3111 LayerTreeHostImpl::FrameData frame;
3112 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3113 ASSERT_EQ(1u, frame.render_passes.size());
3115 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
3116 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3117 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3119 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3120 host_impl_->DidDrawAllLayers(frame);
3123 // Expect four surrounding gutter rects.
3124 void TestLayerInMiddleOfViewport() {
3125 gfx::Rect layer_rect(500, 500, 200, 200);
3126 child_->SetPosition(layer_rect.origin());
3127 child_->SetBounds(layer_rect.size());
3128 child_->SetContentBounds(layer_rect.size());
3129 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3130 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3132 LayerTreeHostImpl::FrameData frame;
3133 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3134 ASSERT_EQ(1u, frame.render_passes.size());
3136 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
3137 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
3138 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3140 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3141 host_impl_->DidDrawAllLayers(frame);
3144 // Expect no gutter rects.
3145 void TestLayerIsLargerThanViewport() {
3146 gfx::Rect layer_rect(viewport_size_.width() + 10,
3147 viewport_size_.height() + 10);
3148 child_->SetPosition(layer_rect.origin());
3149 child_->SetBounds(layer_rect.size());
3150 child_->SetContentBounds(layer_rect.size());
3151 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3152 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3154 LayerTreeHostImpl::FrameData frame;
3155 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3156 ASSERT_EQ(1u, frame.render_passes.size());
3158 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3159 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3160 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3162 host_impl_->DidDrawAllLayers(frame);
3165 virtual void DidActivatePendingTree() OVERRIDE {
3166 did_activate_pending_tree_ = true;
3169 void set_gutter_quad_material(DrawQuad::Material material) {
3170 gutter_quad_material_ = material;
3172 void set_gutter_texture_size(gfx::Size gutter_texture_size) {
3173 gutter_texture_size_ = gutter_texture_size;
3176 protected:
3177 size_t CountGutterQuads(const QuadList& quad_list) {
3178 size_t num_gutter_quads = 0;
3179 for (size_t i = 0; i < quad_list.size(); ++i) {
3180 num_gutter_quads += (quad_list[i]->material ==
3181 gutter_quad_material_) ? 1 : 0;
3183 return num_gutter_quads;
3186 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
3187 LayerTestCommon::VerifyQuadsExactlyCoverRect(
3188 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
3191 // Make sure that the texture coordinates match their expectations.
3192 void ValidateTextureDrawQuads(const QuadList& quad_list) {
3193 for (size_t i = 0; i < quad_list.size(); ++i) {
3194 if (quad_list[i]->material != DrawQuad::TEXTURE_CONTENT)
3195 continue;
3196 const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(quad_list[i]);
3197 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
3198 gutter_texture_size_, host_impl_->device_scale_factor());
3199 EXPECT_EQ(quad->uv_top_left.x(),
3200 quad->rect.x() / gutter_texture_size_pixels.width());
3201 EXPECT_EQ(quad->uv_top_left.y(),
3202 quad->rect.y() / gutter_texture_size_pixels.height());
3203 EXPECT_EQ(quad->uv_bottom_right.x(),
3204 quad->rect.right() / gutter_texture_size_pixels.width());
3205 EXPECT_EQ(quad->uv_bottom_right.y(),
3206 quad->rect.bottom() / gutter_texture_size_pixels.height());
3210 gfx::Size DipSizeToPixelSize(gfx::Size size) {
3211 return gfx::ToRoundedSize(
3212 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
3215 DrawQuad::Material gutter_quad_material_;
3216 gfx::Size gutter_texture_size_;
3217 gfx::Size viewport_size_;
3218 BlendStateCheckLayer* child_;
3219 bool did_activate_pending_tree_;
3222 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
3223 viewport_size_ = gfx::Size(1000, 1000);
3225 bool always_draw = false;
3226 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3228 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3229 SetupActiveTreeLayers();
3230 TestLayerCoversFullViewport();
3231 TestEmptyLayer();
3232 TestLayerInMiddleOfViewport();
3233 TestLayerIsLargerThanViewport();
3236 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
3237 viewport_size_ = gfx::Size(1000, 1000);
3239 bool always_draw = false;
3240 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3242 host_impl_->SetDeviceScaleFactor(2.f);
3243 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3244 SetupActiveTreeLayers();
3245 TestLayerCoversFullViewport();
3246 TestEmptyLayer();
3247 TestLayerInMiddleOfViewport();
3248 TestLayerIsLargerThanViewport();
3251 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
3252 viewport_size_ = gfx::Size(1000, 1000);
3254 bool always_draw = false;
3255 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3257 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3258 SetupActiveTreeLayers();
3260 SkBitmap skbitmap;
3261 skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
3262 skbitmap.allocPixels();
3263 skbitmap.setImmutable();
3265 // Specify an overhang bitmap to use.
3266 UIResourceBitmap ui_resource_bitmap(skbitmap);
3267 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
3268 UIResourceId ui_resource_id = 12345;
3269 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
3270 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
3271 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
3272 set_gutter_texture_size(gfx::Size(32, 32));
3274 TestLayerCoversFullViewport();
3275 TestEmptyLayer();
3276 TestLayerInMiddleOfViewport();
3277 TestLayerIsLargerThanViewport();
3279 // Change the resource size.
3280 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
3281 set_gutter_texture_size(gfx::Size(128, 16));
3283 TestLayerCoversFullViewport();
3284 TestEmptyLayer();
3285 TestLayerInMiddleOfViewport();
3286 TestLayerIsLargerThanViewport();
3288 // Change the device scale factor
3289 host_impl_->SetDeviceScaleFactor(2.f);
3290 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3292 TestLayerCoversFullViewport();
3293 TestEmptyLayer();
3294 TestLayerInMiddleOfViewport();
3295 TestLayerIsLargerThanViewport();
3298 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
3299 viewport_size_ = gfx::Size(1000, 1000);
3301 bool always_draw = true;
3302 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3304 // Pending tree to force active_tree size invalid. Not used otherwise.
3305 host_impl_->CreatePendingTree();
3306 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3307 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3309 SetupActiveTreeLayers();
3310 TestEmptyLayer();
3311 TestLayerInMiddleOfViewport();
3312 TestLayerIsLargerThanViewport();
3315 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
3316 viewport_size_ = gfx::Size(1000, 1000);
3318 bool always_draw = true;
3319 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3321 // Set larger viewport and activate it to active tree.
3322 host_impl_->CreatePendingTree();
3323 gfx::Size larger_viewport(viewport_size_.width() + 100,
3324 viewport_size_.height() + 100);
3325 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
3326 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3327 host_impl_->ActivatePendingTree();
3328 EXPECT_TRUE(did_activate_pending_tree_);
3329 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
3331 // Shrink pending tree viewport without activating.
3332 host_impl_->CreatePendingTree();
3333 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3334 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3336 SetupActiveTreeLayers();
3337 TestEmptyLayer();
3338 TestLayerInMiddleOfViewport();
3339 TestLayerIsLargerThanViewport();
3342 class FakeDrawableLayerImpl: public LayerImpl {
3343 public:
3344 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
3345 return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(tree_impl, id));
3347 protected:
3348 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
3349 : LayerImpl(tree_impl, id) {}
3352 // Only reshape when we know we are going to draw. Otherwise, the reshape
3353 // can leave the window at the wrong size if we never draw and the proper
3354 // viewport size is never set.
3355 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
3356 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
3357 scoped_ptr<OutputSurface> output_surface(
3358 FakeOutputSurface::Create3d(provider));
3359 CreateHostImpl(DefaultSettings(), output_surface.Pass());
3361 scoped_ptr<LayerImpl> root =
3362 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
3363 root->SetAnchorPoint(gfx::PointF());
3364 root->SetBounds(gfx::Size(10, 10));
3365 root->SetContentBounds(gfx::Size(10, 10));
3366 root->SetDrawsContent(true);
3367 host_impl_->active_tree()->SetRootLayer(root.Pass());
3368 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
3369 provider->TestContext3d()->clear_reshape_called();
3371 LayerTreeHostImpl::FrameData frame;
3372 host_impl_->SetViewportSize(gfx::Size(10, 10));
3373 host_impl_->SetDeviceScaleFactor(1.f);
3374 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3375 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3376 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
3377 EXPECT_EQ(provider->TestContext3d()->width(), 10);
3378 EXPECT_EQ(provider->TestContext3d()->height(), 10);
3379 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
3380 host_impl_->DidDrawAllLayers(frame);
3381 provider->TestContext3d()->clear_reshape_called();
3383 host_impl_->SetViewportSize(gfx::Size(20, 30));
3384 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3385 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3386 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
3387 EXPECT_EQ(provider->TestContext3d()->width(), 20);
3388 EXPECT_EQ(provider->TestContext3d()->height(), 30);
3389 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
3390 host_impl_->DidDrawAllLayers(frame);
3391 provider->TestContext3d()->clear_reshape_called();
3393 host_impl_->SetDeviceScaleFactor(2.f);
3394 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3395 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3396 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
3397 EXPECT_EQ(provider->TestContext3d()->width(), 20);
3398 EXPECT_EQ(provider->TestContext3d()->height(), 30);
3399 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
3400 host_impl_->DidDrawAllLayers(frame);
3401 provider->TestContext3d()->clear_reshape_called();
3404 // Make sure damage tracking propagates all the way to the graphics context,
3405 // where it should request to swap only the sub-buffer that is damaged.
3406 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
3407 scoped_refptr<TestContextProvider> context_provider(
3408 TestContextProvider::Create());
3409 context_provider->BindToCurrentThread();
3410 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
3412 scoped_ptr<OutputSurface> output_surface(
3413 FakeOutputSurface::Create3d(context_provider));
3415 // This test creates its own LayerTreeHostImpl, so
3416 // that we can force partial swap enabled.
3417 LayerTreeSettings settings;
3418 settings.partial_swap_enabled = true;
3419 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
3420 LayerTreeHostImpl::Create(
3421 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
3422 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
3423 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
3425 scoped_ptr<LayerImpl> root =
3426 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
3427 scoped_ptr<LayerImpl> child =
3428 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
3429 child->SetPosition(gfx::PointF(12.f, 13.f));
3430 child->SetAnchorPoint(gfx::PointF());
3431 child->SetBounds(gfx::Size(14, 15));
3432 child->SetContentBounds(gfx::Size(14, 15));
3433 child->SetDrawsContent(true);
3434 root->SetAnchorPoint(gfx::PointF());
3435 root->SetBounds(gfx::Size(500, 500));
3436 root->SetContentBounds(gfx::Size(500, 500));
3437 root->SetDrawsContent(true);
3438 root->AddChild(child.Pass());
3439 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
3441 LayerTreeHostImpl::FrameData frame;
3443 // First frame, the entire screen should get swapped.
3444 EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3445 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3446 layer_tree_host_impl->DidDrawAllLayers(frame);
3447 layer_tree_host_impl->SwapBuffers(frame);
3448 EXPECT_EQ(TestContextSupport::SWAP,
3449 context_provider->support()->last_swap_type());
3451 // Second frame, only the damaged area should get swapped. Damage should be
3452 // the union of old and new child rects.
3453 // expected damage rect: gfx::Rect(26, 28);
3454 // expected swap rect: vertically flipped, with origin at bottom left corner.
3455 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
3456 gfx::PointF());
3457 EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3458 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3459 host_impl_->DidDrawAllLayers(frame);
3460 layer_tree_host_impl->SwapBuffers(frame);
3462 // Make sure that partial swap is constrained to the viewport dimensions
3463 // expected damage rect: gfx::Rect(500, 500);
3464 // expected swap rect: flipped damage rect, but also clamped to viewport
3465 EXPECT_EQ(TestContextSupport::PARTIAL_SWAP,
3466 context_provider->support()->last_swap_type());
3467 gfx::Rect expected_swap_rect(0, 500-28, 26, 28);
3468 EXPECT_EQ(expected_swap_rect.ToString(),
3469 context_provider->support()->
3470 last_partial_swap_rect().ToString());
3472 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
3473 // This will damage everything.
3474 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
3475 SK_ColorBLACK);
3476 EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3477 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3478 host_impl_->DidDrawAllLayers(frame);
3479 layer_tree_host_impl->SwapBuffers(frame);
3481 EXPECT_EQ(TestContextSupport::SWAP,
3482 context_provider->support()->last_swap_type());
3485 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
3486 scoped_ptr<LayerImpl> root =
3487 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
3488 scoped_ptr<LayerImpl> child =
3489 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
3490 child->SetAnchorPoint(gfx::PointF());
3491 child->SetBounds(gfx::Size(10, 10));
3492 child->SetContentBounds(gfx::Size(10, 10));
3493 child->SetDrawsContent(true);
3494 root->SetAnchorPoint(gfx::PointF());
3495 root->SetBounds(gfx::Size(10, 10));
3496 root->SetContentBounds(gfx::Size(10, 10));
3497 root->SetDrawsContent(true);
3498 root->SetForceRenderSurface(true);
3499 root->AddChild(child.Pass());
3501 host_impl_->active_tree()->SetRootLayer(root.Pass());
3503 LayerTreeHostImpl::FrameData frame;
3505 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3506 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
3507 EXPECT_EQ(1u, frame.render_passes.size());
3508 host_impl_->DidDrawAllLayers(frame);
3511 class FakeLayerWithQuads : public LayerImpl {
3512 public:
3513 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
3514 return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(tree_impl, id));
3517 virtual void AppendQuads(QuadSink* quad_sink,
3518 AppendQuadsData* append_quads_data) OVERRIDE {
3519 SharedQuadState* shared_quad_state =
3520 quad_sink->UseSharedQuadState(CreateSharedQuadState());
3522 SkColor gray = SkColorSetRGB(100, 100, 100);
3523 gfx::Rect quad_rect(content_bounds());
3524 scoped_ptr<SolidColorDrawQuad> my_quad = SolidColorDrawQuad::Create();
3525 my_quad->SetNew(shared_quad_state, quad_rect, gray, false);
3526 quad_sink->Append(my_quad.PassAs<DrawQuad>(), append_quads_data);
3529 private:
3530 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
3531 : LayerImpl(tree_impl, id) {}
3534 class MockContext : public TestWebGraphicsContext3D {
3535 public:
3536 MOCK_METHOD1(useProgram, void(GLuint program));
3537 MOCK_METHOD5(uniform4f, void(GLint location,
3538 GLfloat x,
3539 GLfloat y,
3540 GLfloat z,
3541 GLfloat w));
3542 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
3543 GLsizei count,
3544 GLboolean transpose,
3545 const GLfloat* value));
3546 MOCK_METHOD4(drawElements, void(GLenum mode,
3547 GLsizei count,
3548 GLenum type,
3549 GLintptr offset));
3550 MOCK_METHOD1(enable, void(GLenum cap));
3551 MOCK_METHOD1(disable, void(GLenum cap));
3552 MOCK_METHOD4(scissor, void(GLint x,
3553 GLint y,
3554 GLsizei width,
3555 GLsizei height));
3558 class MockContextHarness {
3559 private:
3560 MockContext* context_;
3562 public:
3563 explicit MockContextHarness(MockContext* context)
3564 : context_(context) {
3565 context_->set_have_post_sub_buffer(true);
3567 // Catch "uninteresting" calls
3568 EXPECT_CALL(*context_, useProgram(_))
3569 .Times(0);
3571 EXPECT_CALL(*context_, drawElements(_, _, _, _))
3572 .Times(0);
3574 // These are not asserted
3575 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
3576 .WillRepeatedly(Return());
3578 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
3579 .WillRepeatedly(Return());
3581 // Any un-sanctioned calls to enable() are OK
3582 EXPECT_CALL(*context_, enable(_))
3583 .WillRepeatedly(Return());
3585 // Any un-sanctioned calls to disable() are OK
3586 EXPECT_CALL(*context_, disable(_))
3587 .WillRepeatedly(Return());
3590 void MustDrawSolidQuad() {
3591 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
3592 .WillOnce(Return())
3593 .RetiresOnSaturation();
3595 EXPECT_CALL(*context_, useProgram(_))
3596 .WillOnce(Return())
3597 .RetiresOnSaturation();
3600 void MustSetScissor(int x, int y, int width, int height) {
3601 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
3602 .WillRepeatedly(Return());
3604 EXPECT_CALL(*context_, scissor(x, y, width, height))
3605 .Times(AtLeast(1))
3606 .WillRepeatedly(Return());
3609 void MustSetNoScissor() {
3610 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
3611 .WillRepeatedly(Return());
3613 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
3614 .Times(0);
3616 EXPECT_CALL(*context_, scissor(_, _, _, _))
3617 .Times(0);
3621 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
3622 scoped_ptr<MockContext> mock_context_owned(new MockContext);
3623 MockContext* mock_context = mock_context_owned.get();
3625 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3626 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
3627 MockContextHarness harness(mock_context);
3629 // Run test case
3630 LayerTreeSettings settings = DefaultSettings();
3631 settings.partial_swap_enabled = false;
3632 CreateHostImpl(settings, output_surface.Pass());
3633 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
3635 // Without partial swap, and no clipping, no scissor is set.
3636 harness.MustDrawSolidQuad();
3637 harness.MustSetNoScissor();
3639 LayerTreeHostImpl::FrameData frame;
3640 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3641 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3642 host_impl_->DidDrawAllLayers(frame);
3644 Mock::VerifyAndClearExpectations(&mock_context);
3646 // Without partial swap, but a layer does clip its subtree, one scissor is
3647 // set.
3648 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
3649 harness.MustDrawSolidQuad();
3650 harness.MustSetScissor(0, 0, 10, 10);
3652 LayerTreeHostImpl::FrameData frame;
3653 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3654 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3655 host_impl_->DidDrawAllLayers(frame);
3657 Mock::VerifyAndClearExpectations(&mock_context);
3660 TEST_F(LayerTreeHostImplTest, PartialSwap) {
3661 scoped_ptr<MockContext> context_owned(new MockContext);
3662 MockContext* mock_context = context_owned.get();
3663 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3664 context_owned.PassAs<TestWebGraphicsContext3D>()));
3665 MockContextHarness harness(mock_context);
3667 LayerTreeSettings settings = DefaultSettings();
3668 settings.partial_swap_enabled = true;
3669 CreateHostImpl(settings, output_surface.Pass());
3670 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
3672 // The first frame is not a partially-swapped one.
3673 harness.MustSetScissor(0, 0, 10, 10);
3674 harness.MustDrawSolidQuad();
3676 LayerTreeHostImpl::FrameData frame;
3677 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3678 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3679 host_impl_->DidDrawAllLayers(frame);
3681 Mock::VerifyAndClearExpectations(&mock_context);
3683 // Damage a portion of the frame.
3684 host_impl_->active_tree()->root_layer()->SetUpdateRect(
3685 gfx::Rect(0, 0, 2, 3));
3687 // The second frame will be partially-swapped (the y coordinates are flipped).
3688 harness.MustSetScissor(0, 7, 2, 3);
3689 harness.MustDrawSolidQuad();
3691 LayerTreeHostImpl::FrameData frame;
3692 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3693 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3694 host_impl_->DidDrawAllLayers(frame);
3696 Mock::VerifyAndClearExpectations(&mock_context);
3699 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
3700 bool partial_swap,
3701 LayerTreeHostImplClient* client,
3702 Proxy* proxy,
3703 RenderingStatsInstrumentation* stats_instrumentation) {
3704 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
3705 scoped_ptr<OutputSurface> output_surface(
3706 FakeOutputSurface::Create3d(provider));
3707 provider->BindToCurrentThread();
3708 provider->TestContext3d()->set_have_post_sub_buffer(true);
3710 LayerTreeSettings settings;
3711 settings.partial_swap_enabled = partial_swap;
3712 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
3713 settings, client, proxy, stats_instrumentation, NULL, 0);
3714 my_host_impl->InitializeRenderer(output_surface.Pass());
3715 my_host_impl->SetViewportSize(gfx::Size(100, 100));
3718 Layers are created as follows:
3720 +--------------------+
3721 | 1 |
3722 | +-----------+ |
3723 | | 2 | |
3724 | | +-------------------+
3725 | | | 3 |
3726 | | +-------------------+
3727 | | | |
3728 | +-----------+ |
3731 +--------------------+
3733 Layers 1, 2 have render surfaces
3735 scoped_ptr<LayerImpl> root =
3736 LayerImpl::Create(my_host_impl->active_tree(), 1);
3737 scoped_ptr<LayerImpl> child =
3738 LayerImpl::Create(my_host_impl->active_tree(), 2);
3739 scoped_ptr<LayerImpl> grand_child =
3740 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
3742 gfx::Rect root_rect(0, 0, 100, 100);
3743 gfx::Rect child_rect(10, 10, 50, 50);
3744 gfx::Rect grand_child_rect(5, 5, 150, 150);
3746 root->CreateRenderSurface();
3747 root->SetAnchorPoint(gfx::PointF());
3748 root->SetPosition(root_rect.origin());
3749 root->SetBounds(root_rect.size());
3750 root->SetContentBounds(root->bounds());
3751 root->draw_properties().visible_content_rect = root_rect;
3752 root->SetDrawsContent(false);
3753 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
3755 child->SetAnchorPoint(gfx::PointF());
3756 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
3757 child->SetOpacity(0.5f);
3758 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
3759 child->SetContentBounds(child->bounds());
3760 child->draw_properties().visible_content_rect = child_rect;
3761 child->SetDrawsContent(false);
3762 child->SetForceRenderSurface(true);
3764 grand_child->SetAnchorPoint(gfx::PointF());
3765 grand_child->SetPosition(grand_child_rect.origin());
3766 grand_child->SetBounds(grand_child_rect.size());
3767 grand_child->SetContentBounds(grand_child->bounds());
3768 grand_child->draw_properties().visible_content_rect = grand_child_rect;
3769 grand_child->SetDrawsContent(true);
3771 child->AddChild(grand_child.Pass());
3772 root->AddChild(child.Pass());
3774 my_host_impl->active_tree()->SetRootLayer(root.Pass());
3775 return my_host_impl.Pass();
3778 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
3779 scoped_ptr<LayerTreeHostImpl> my_host_impl =
3780 SetupLayersForOpacity(true, this, &proxy_, &stats_instrumentation_);
3782 LayerTreeHostImpl::FrameData frame;
3783 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3785 // Verify all quads have been computed
3786 ASSERT_EQ(2U, frame.render_passes.size());
3787 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
3788 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
3789 EXPECT_EQ(DrawQuad::SOLID_COLOR,
3790 frame.render_passes[0]->quad_list[0]->material);
3791 EXPECT_EQ(DrawQuad::RENDER_PASS,
3792 frame.render_passes[1]->quad_list[0]->material);
3794 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3795 my_host_impl->DidDrawAllLayers(frame);
3799 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
3800 scoped_ptr<LayerTreeHostImpl> my_host_impl =
3801 SetupLayersForOpacity(false, this, &proxy_, &stats_instrumentation_);
3803 LayerTreeHostImpl::FrameData frame;
3804 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3806 // Verify all quads have been computed
3807 ASSERT_EQ(2U, frame.render_passes.size());
3808 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
3809 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
3810 EXPECT_EQ(DrawQuad::SOLID_COLOR,
3811 frame.render_passes[0]->quad_list[0]->material);
3812 EXPECT_EQ(DrawQuad::RENDER_PASS,
3813 frame.render_passes[1]->quad_list[0]->material);
3815 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3816 my_host_impl->DidDrawAllLayers(frame);
3820 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
3821 scoped_ptr<TestWebGraphicsContext3D> context =
3822 TestWebGraphicsContext3D::Create();
3823 TestWebGraphicsContext3D* context3d = context.get();
3824 scoped_ptr<OutputSurface> output_surface(
3825 FakeOutputSurface::Create3d(context.Pass()));
3826 CreateHostImpl(DefaultSettings(), output_surface.Pass());
3828 scoped_ptr<LayerImpl> root_layer =
3829 LayerImpl::Create(host_impl_->active_tree(), 1);
3830 root_layer->SetBounds(gfx::Size(10, 10));
3831 root_layer->SetAnchorPoint(gfx::PointF());
3833 scoped_refptr<VideoFrame> softwareFrame =
3834 media::VideoFrame::CreateColorFrame(
3835 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
3836 FakeVideoFrameProvider provider;
3837 provider.set_frame(softwareFrame);
3838 scoped_ptr<VideoLayerImpl> video_layer =
3839 VideoLayerImpl::Create(host_impl_->active_tree(), 4, &provider);
3840 video_layer->SetBounds(gfx::Size(10, 10));
3841 video_layer->SetAnchorPoint(gfx::PointF());
3842 video_layer->SetContentBounds(gfx::Size(10, 10));
3843 video_layer->SetDrawsContent(true);
3844 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
3846 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
3847 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
3848 io_surface_layer->SetBounds(gfx::Size(10, 10));
3849 io_surface_layer->SetAnchorPoint(gfx::PointF());
3850 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
3851 io_surface_layer->SetDrawsContent(true);
3852 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
3853 root_layer->AddChild(io_surface_layer.PassAs<LayerImpl>());
3855 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
3857 EXPECT_EQ(0u, context3d->NumTextures());
3859 LayerTreeHostImpl::FrameData frame;
3860 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3861 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3862 host_impl_->DidDrawAllLayers(frame);
3863 host_impl_->SwapBuffers(frame);
3865 EXPECT_GT(context3d->NumTextures(), 0u);
3867 // Kill the layer tree.
3868 host_impl_->active_tree()->SetRootLayer(
3869 LayerImpl::Create(host_impl_->active_tree(), 100));
3870 // There should be no textures left in use after.
3871 EXPECT_EQ(0u, context3d->NumTextures());
3874 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
3875 public:
3876 MOCK_METHOD1(useProgram, void(GLuint program));
3877 MOCK_METHOD4(drawElements, void(GLenum mode,
3878 GLsizei count,
3879 GLenum type,
3880 GLintptr offset));
3883 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
3884 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
3885 new MockDrawQuadsToFillScreenContext);
3886 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
3888 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3889 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
3891 // Run test case
3892 LayerTreeSettings settings = DefaultSettings();
3893 settings.partial_swap_enabled = false;
3894 CreateHostImpl(settings, output_surface.Pass());
3895 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
3896 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
3898 // Verify one quad is drawn when transparent background set is not set.
3899 host_impl_->active_tree()->set_has_transparent_background(false);
3900 EXPECT_CALL(*mock_context, useProgram(_))
3901 .Times(1);
3902 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
3903 .Times(1);
3904 LayerTreeHostImpl::FrameData frame;
3905 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3906 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3907 host_impl_->DidDrawAllLayers(frame);
3908 Mock::VerifyAndClearExpectations(&mock_context);
3910 // Verify no quads are drawn when transparent background is set.
3911 host_impl_->active_tree()->set_has_transparent_background(true);
3912 host_impl_->SetFullRootLayerDamage();
3913 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3914 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3915 host_impl_->DidDrawAllLayers(frame);
3916 Mock::VerifyAndClearExpectations(&mock_context);
3919 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
3920 set_reduce_memory_result(false);
3922 // If changing the memory limit wouldn't result in changing what was
3923 // committed, then no commit should be requested.
3924 set_reduce_memory_result(false);
3925 host_impl_->set_max_memory_needed_bytes(
3926 host_impl_->memory_allocation_limit_bytes() - 1);
3927 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
3928 host_impl_->memory_allocation_limit_bytes() - 1));
3929 EXPECT_FALSE(did_request_commit_);
3930 did_request_commit_ = false;
3932 // If changing the memory limit would result in changing what was
3933 // committed, then a commit should be requested, even though nothing was
3934 // evicted.
3935 set_reduce_memory_result(false);
3936 host_impl_->set_max_memory_needed_bytes(
3937 host_impl_->memory_allocation_limit_bytes());
3938 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
3939 host_impl_->memory_allocation_limit_bytes() - 1));
3940 EXPECT_TRUE(did_request_commit_);
3941 did_request_commit_ = false;
3943 // Especially if changing the memory limit caused evictions, we need
3944 // to re-commit.
3945 set_reduce_memory_result(true);
3946 host_impl_->set_max_memory_needed_bytes(1);
3947 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
3948 host_impl_->memory_allocation_limit_bytes() - 1));
3949 EXPECT_TRUE(did_request_commit_);
3950 did_request_commit_ = false;
3952 // But if we set it to the same value that it was before, we shouldn't
3953 // re-commit.
3954 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
3955 host_impl_->memory_allocation_limit_bytes()));
3956 EXPECT_FALSE(did_request_commit_);
3959 class LayerTreeHostImplTestWithDelegatingRenderer
3960 : public LayerTreeHostImplTest {
3961 protected:
3962 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
3963 return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
3966 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
3967 bool expect_to_draw = !expected_damage.IsEmpty();
3969 LayerTreeHostImpl::FrameData frame;
3970 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3972 if (!expect_to_draw) {
3973 // With no damage, we don't draw, and no quads are created.
3974 ASSERT_EQ(0u, frame.render_passes.size());
3975 } else {
3976 ASSERT_EQ(1u, frame.render_passes.size());
3978 // Verify the damage rect for the root render pass.
3979 const RenderPass* root_render_pass = frame.render_passes.back();
3980 EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
3982 // Verify the root and child layers' quads are generated and not being
3983 // culled.
3984 ASSERT_EQ(2u, root_render_pass->quad_list.size());
3986 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
3987 gfx::RectF expected_child_visible_rect(child->content_bounds());
3988 EXPECT_RECT_EQ(expected_child_visible_rect,
3989 root_render_pass->quad_list[0]->visible_rect);
3991 LayerImpl* root = host_impl_->active_tree()->root_layer();
3992 gfx::RectF expected_root_visible_rect(root->content_bounds());
3993 EXPECT_RECT_EQ(expected_root_visible_rect,
3994 root_render_pass->quad_list[1]->visible_rect);
3997 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3998 host_impl_->DidDrawAllLayers(frame);
3999 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
4003 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
4004 scoped_ptr<SolidColorLayerImpl> root =
4005 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4006 root->SetAnchorPoint(gfx::PointF());
4007 root->SetPosition(gfx::PointF());
4008 root->SetBounds(gfx::Size(10, 10));
4009 root->SetContentBounds(gfx::Size(10, 10));
4010 root->SetDrawsContent(true);
4012 // Child layer is in the bottom right corner.
4013 scoped_ptr<SolidColorLayerImpl> child =
4014 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
4015 child->SetAnchorPoint(gfx::PointF(0.f, 0.f));
4016 child->SetPosition(gfx::PointF(9.f, 9.f));
4017 child->SetBounds(gfx::Size(1, 1));
4018 child->SetContentBounds(gfx::Size(1, 1));
4019 child->SetDrawsContent(true);
4020 root->AddChild(child.PassAs<LayerImpl>());
4022 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
4024 // Draw a frame. In the first frame, the entire viewport should be damaged.
4025 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
4026 DrawFrameAndTestDamage(full_frame_damage);
4028 // The second frame has damage that doesn't touch the child layer. Its quads
4029 // should still be generated.
4030 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
4031 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
4032 DrawFrameAndTestDamage(small_damage);
4034 // The third frame should have no damage, so no quads should be generated.
4035 gfx::Rect no_damage;
4036 DrawFrameAndTestDamage(no_damage);
4039 class FakeMaskLayerImpl : public LayerImpl {
4040 public:
4041 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
4042 int id) {
4043 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
4046 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
4047 return 0;
4050 private:
4051 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
4052 : LayerImpl(tree_impl, id) {}
4055 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
4056 LayerTreeSettings settings;
4057 settings.layer_transforms_should_scale_layer_contents = true;
4058 CreateHostImpl(settings, CreateOutputSurface());
4060 // Root
4061 // |
4062 // +-- Scaling Layer (adds a 2x scale)
4063 // |
4064 // +-- Content Layer
4065 // +--Mask
4066 scoped_ptr<LayerImpl> scoped_root =
4067 LayerImpl::Create(host_impl_->active_tree(), 1);
4068 LayerImpl* root = scoped_root.get();
4069 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4071 scoped_ptr<LayerImpl> scoped_scaling_layer =
4072 LayerImpl::Create(host_impl_->active_tree(), 2);
4073 LayerImpl* scaling_layer = scoped_scaling_layer.get();
4074 root->AddChild(scoped_scaling_layer.Pass());
4076 scoped_ptr<LayerImpl> scoped_content_layer =
4077 LayerImpl::Create(host_impl_->active_tree(), 3);
4078 LayerImpl* content_layer = scoped_content_layer.get();
4079 scaling_layer->AddChild(scoped_content_layer.Pass());
4081 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4082 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4083 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4084 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4086 gfx::Size root_size(100, 100);
4087 root->SetBounds(root_size);
4088 root->SetContentBounds(root_size);
4089 root->SetPosition(gfx::PointF());
4090 root->SetAnchorPoint(gfx::PointF());
4092 gfx::Size scaling_layer_size(50, 50);
4093 scaling_layer->SetBounds(scaling_layer_size);
4094 scaling_layer->SetContentBounds(scaling_layer_size);
4095 scaling_layer->SetPosition(gfx::PointF());
4096 scaling_layer->SetAnchorPoint(gfx::PointF());
4097 gfx::Transform scale;
4098 scale.Scale(2.f, 2.f);
4099 scaling_layer->SetTransform(scale);
4101 content_layer->SetBounds(scaling_layer_size);
4102 content_layer->SetContentBounds(scaling_layer_size);
4103 content_layer->SetPosition(gfx::PointF());
4104 content_layer->SetAnchorPoint(gfx::PointF());
4105 content_layer->SetDrawsContent(true);
4107 mask_layer->SetBounds(scaling_layer_size);
4108 mask_layer->SetContentBounds(scaling_layer_size);
4109 mask_layer->SetPosition(gfx::PointF());
4110 mask_layer->SetAnchorPoint(gfx::PointF());
4111 mask_layer->SetDrawsContent(true);
4114 // Check that the tree scaling is correctly taken into account for the mask,
4115 // that should fully map onto the quad.
4116 float device_scale_factor = 1.f;
4117 host_impl_->SetViewportSize(root_size);
4118 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4120 LayerTreeHostImpl::FrameData frame;
4121 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4123 ASSERT_EQ(1u, frame.render_passes.size());
4124 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4125 ASSERT_EQ(DrawQuad::RENDER_PASS,
4126 frame.render_passes[0]->quad_list[0]->material);
4127 const RenderPassDrawQuad* render_pass_quad =
4128 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4129 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4130 render_pass_quad->rect.ToString());
4131 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4132 render_pass_quad->mask_uv_rect.ToString());
4134 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4135 host_impl_->DidDrawAllLayers(frame);
4139 // Applying a DSF should change the render surface size, but won't affect
4140 // which part of the mask is used.
4141 device_scale_factor = 2.f;
4142 gfx::Size device_viewport =
4143 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4144 host_impl_->SetViewportSize(device_viewport);
4145 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4146 host_impl_->active_tree()->set_needs_update_draw_properties();
4148 LayerTreeHostImpl::FrameData frame;
4149 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4151 ASSERT_EQ(1u, frame.render_passes.size());
4152 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4153 ASSERT_EQ(DrawQuad::RENDER_PASS,
4154 frame.render_passes[0]->quad_list[0]->material);
4155 const RenderPassDrawQuad* render_pass_quad =
4156 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4157 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4158 render_pass_quad->rect.ToString());
4159 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4160 render_pass_quad->mask_uv_rect.ToString());
4162 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4163 host_impl_->DidDrawAllLayers(frame);
4167 // Applying an equivalent content scale on the content layer and the mask
4168 // should still result in the same part of the mask being used.
4169 gfx::Size content_bounds =
4170 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
4171 device_scale_factor));
4172 content_layer->SetContentBounds(content_bounds);
4173 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4174 mask_layer->SetContentBounds(content_bounds);
4175 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4176 host_impl_->active_tree()->set_needs_update_draw_properties();
4178 LayerTreeHostImpl::FrameData frame;
4179 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4181 ASSERT_EQ(1u, frame.render_passes.size());
4182 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4183 ASSERT_EQ(DrawQuad::RENDER_PASS,
4184 frame.render_passes[0]->quad_list[0]->material);
4185 const RenderPassDrawQuad* render_pass_quad =
4186 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4187 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4188 render_pass_quad->rect.ToString());
4189 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4190 render_pass_quad->mask_uv_rect.ToString());
4192 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4193 host_impl_->DidDrawAllLayers(frame);
4197 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
4198 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4199 // 50x50.
4201 scoped_ptr<LayerImpl> scoped_root =
4202 LayerImpl::Create(host_impl_->active_tree(), 1);
4203 LayerImpl* root = scoped_root.get();
4204 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4206 scoped_ptr<LayerImpl> scoped_content_layer =
4207 LayerImpl::Create(host_impl_->active_tree(), 3);
4208 LayerImpl* content_layer = scoped_content_layer.get();
4209 root->AddChild(scoped_content_layer.Pass());
4211 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4212 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4213 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4214 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4216 gfx::Size root_size(100, 100);
4217 root->SetBounds(root_size);
4218 root->SetContentBounds(root_size);
4219 root->SetPosition(gfx::PointF());
4220 root->SetAnchorPoint(gfx::PointF());
4222 gfx::Size layer_size(50, 50);
4223 content_layer->SetBounds(layer_size);
4224 content_layer->SetContentBounds(layer_size);
4225 content_layer->SetPosition(gfx::PointF());
4226 content_layer->SetAnchorPoint(gfx::PointF());
4227 content_layer->SetDrawsContent(true);
4229 gfx::Size mask_size(100, 100);
4230 mask_layer->SetBounds(mask_size);
4231 mask_layer->SetContentBounds(mask_size);
4232 mask_layer->SetPosition(gfx::PointF());
4233 mask_layer->SetAnchorPoint(gfx::PointF());
4234 mask_layer->SetDrawsContent(true);
4236 // Check that the mask fills the surface.
4237 float device_scale_factor = 1.f;
4238 host_impl_->SetViewportSize(root_size);
4239 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4241 LayerTreeHostImpl::FrameData frame;
4242 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4244 ASSERT_EQ(1u, frame.render_passes.size());
4245 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4246 ASSERT_EQ(DrawQuad::RENDER_PASS,
4247 frame.render_passes[0]->quad_list[0]->material);
4248 const RenderPassDrawQuad* render_pass_quad =
4249 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4250 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4251 render_pass_quad->rect.ToString());
4252 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4253 render_pass_quad->mask_uv_rect.ToString());
4255 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4256 host_impl_->DidDrawAllLayers(frame);
4259 // Applying a DSF should change the render surface size, but won't affect
4260 // which part of the mask is used.
4261 device_scale_factor = 2.f;
4262 gfx::Size device_viewport =
4263 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4264 host_impl_->SetViewportSize(device_viewport);
4265 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4266 host_impl_->active_tree()->set_needs_update_draw_properties();
4268 LayerTreeHostImpl::FrameData frame;
4269 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4271 ASSERT_EQ(1u, frame.render_passes.size());
4272 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4273 ASSERT_EQ(DrawQuad::RENDER_PASS,
4274 frame.render_passes[0]->quad_list[0]->material);
4275 const RenderPassDrawQuad* render_pass_quad =
4276 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4277 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4278 render_pass_quad->rect.ToString());
4279 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4280 render_pass_quad->mask_uv_rect.ToString());
4282 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4283 host_impl_->DidDrawAllLayers(frame);
4286 // Applying an equivalent content scale on the content layer and the mask
4287 // should still result in the same part of the mask being used.
4288 gfx::Size layer_size_large =
4289 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
4290 content_layer->SetContentBounds(layer_size_large);
4291 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4292 gfx::Size mask_size_large =
4293 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
4294 mask_layer->SetContentBounds(mask_size_large);
4295 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4296 host_impl_->active_tree()->set_needs_update_draw_properties();
4298 LayerTreeHostImpl::FrameData frame;
4299 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4301 ASSERT_EQ(1u, frame.render_passes.size());
4302 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4303 ASSERT_EQ(DrawQuad::RENDER_PASS,
4304 frame.render_passes[0]->quad_list[0]->material);
4305 const RenderPassDrawQuad* render_pass_quad =
4306 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4307 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4308 render_pass_quad->rect.ToString());
4309 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4310 render_pass_quad->mask_uv_rect.ToString());
4312 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4313 host_impl_->DidDrawAllLayers(frame);
4316 // Applying a different contents scale to the mask layer means it will have
4317 // a larger texture, but it should use the same tex coords to cover the
4318 // layer it masks.
4319 mask_layer->SetContentBounds(mask_size);
4320 mask_layer->SetContentsScale(1.f, 1.f);
4321 host_impl_->active_tree()->set_needs_update_draw_properties();
4323 LayerTreeHostImpl::FrameData frame;
4324 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4326 ASSERT_EQ(1u, frame.render_passes.size());
4327 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4328 ASSERT_EQ(DrawQuad::RENDER_PASS,
4329 frame.render_passes[0]->quad_list[0]->material);
4330 const RenderPassDrawQuad* render_pass_quad =
4331 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4332 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4333 render_pass_quad->rect.ToString());
4334 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4335 render_pass_quad->mask_uv_rect.ToString());
4337 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4338 host_impl_->DidDrawAllLayers(frame);
4342 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
4343 // The replica's mask layer has bounds 100x100 but the replica is of a
4344 // layer with bounds 50x50.
4346 scoped_ptr<LayerImpl> scoped_root =
4347 LayerImpl::Create(host_impl_->active_tree(), 1);
4348 LayerImpl* root = scoped_root.get();
4349 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4351 scoped_ptr<LayerImpl> scoped_content_layer =
4352 LayerImpl::Create(host_impl_->active_tree(), 3);
4353 LayerImpl* content_layer = scoped_content_layer.get();
4354 root->AddChild(scoped_content_layer.Pass());
4356 scoped_ptr<LayerImpl> scoped_replica_layer =
4357 LayerImpl::Create(host_impl_->active_tree(), 2);
4358 LayerImpl* replica_layer = scoped_replica_layer.get();
4359 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
4361 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4362 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4363 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4364 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4366 gfx::Size root_size(100, 100);
4367 root->SetBounds(root_size);
4368 root->SetContentBounds(root_size);
4369 root->SetPosition(gfx::PointF());
4370 root->SetAnchorPoint(gfx::PointF());
4372 gfx::Size layer_size(50, 50);
4373 content_layer->SetBounds(layer_size);
4374 content_layer->SetContentBounds(layer_size);
4375 content_layer->SetPosition(gfx::PointF());
4376 content_layer->SetAnchorPoint(gfx::PointF());
4377 content_layer->SetDrawsContent(true);
4379 gfx::Size mask_size(100, 100);
4380 mask_layer->SetBounds(mask_size);
4381 mask_layer->SetContentBounds(mask_size);
4382 mask_layer->SetPosition(gfx::PointF());
4383 mask_layer->SetAnchorPoint(gfx::PointF());
4384 mask_layer->SetDrawsContent(true);
4386 // Check that the mask fills the surface.
4387 float device_scale_factor = 1.f;
4388 host_impl_->SetViewportSize(root_size);
4389 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4391 LayerTreeHostImpl::FrameData frame;
4392 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4394 ASSERT_EQ(1u, frame.render_passes.size());
4395 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4396 ASSERT_EQ(DrawQuad::RENDER_PASS,
4397 frame.render_passes[0]->quad_list[1]->material);
4398 const RenderPassDrawQuad* replica_quad =
4399 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4400 EXPECT_TRUE(replica_quad->is_replica);
4401 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4402 replica_quad->rect.ToString());
4403 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4404 replica_quad->mask_uv_rect.ToString());
4406 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4407 host_impl_->DidDrawAllLayers(frame);
4410 // Applying a DSF should change the render surface size, but won't affect
4411 // which part of the mask is used.
4412 device_scale_factor = 2.f;
4413 gfx::Size device_viewport =
4414 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4415 host_impl_->SetViewportSize(device_viewport);
4416 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4417 host_impl_->active_tree()->set_needs_update_draw_properties();
4419 LayerTreeHostImpl::FrameData frame;
4420 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4422 ASSERT_EQ(1u, frame.render_passes.size());
4423 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4424 ASSERT_EQ(DrawQuad::RENDER_PASS,
4425 frame.render_passes[0]->quad_list[1]->material);
4426 const RenderPassDrawQuad* replica_quad =
4427 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4428 EXPECT_TRUE(replica_quad->is_replica);
4429 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4430 replica_quad->rect.ToString());
4431 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4432 replica_quad->mask_uv_rect.ToString());
4434 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4435 host_impl_->DidDrawAllLayers(frame);
4438 // Applying an equivalent content scale on the content layer and the mask
4439 // should still result in the same part of the mask being used.
4440 gfx::Size layer_size_large =
4441 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
4442 content_layer->SetContentBounds(layer_size_large);
4443 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4444 gfx::Size mask_size_large =
4445 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
4446 mask_layer->SetContentBounds(mask_size_large);
4447 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4448 host_impl_->active_tree()->set_needs_update_draw_properties();
4450 LayerTreeHostImpl::FrameData frame;
4451 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4453 ASSERT_EQ(1u, frame.render_passes.size());
4454 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4455 ASSERT_EQ(DrawQuad::RENDER_PASS,
4456 frame.render_passes[0]->quad_list[1]->material);
4457 const RenderPassDrawQuad* replica_quad =
4458 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4459 EXPECT_TRUE(replica_quad->is_replica);
4460 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4461 replica_quad->rect.ToString());
4462 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4463 replica_quad->mask_uv_rect.ToString());
4465 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4466 host_impl_->DidDrawAllLayers(frame);
4469 // Applying a different contents scale to the mask layer means it will have
4470 // a larger texture, but it should use the same tex coords to cover the
4471 // layer it masks.
4472 mask_layer->SetContentBounds(mask_size);
4473 mask_layer->SetContentsScale(1.f, 1.f);
4474 host_impl_->active_tree()->set_needs_update_draw_properties();
4476 LayerTreeHostImpl::FrameData frame;
4477 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4479 ASSERT_EQ(1u, frame.render_passes.size());
4480 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4481 ASSERT_EQ(DrawQuad::RENDER_PASS,
4482 frame.render_passes[0]->quad_list[1]->material);
4483 const RenderPassDrawQuad* replica_quad =
4484 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4485 EXPECT_TRUE(replica_quad->is_replica);
4486 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4487 replica_quad->rect.ToString());
4488 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4489 replica_quad->mask_uv_rect.ToString());
4491 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4492 host_impl_->DidDrawAllLayers(frame);
4496 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
4497 // The replica is of a layer with bounds 50x50, but it has a child that causes
4498 // the surface bounds to be larger.
4500 scoped_ptr<LayerImpl> scoped_root =
4501 LayerImpl::Create(host_impl_->active_tree(), 1);
4502 LayerImpl* root = scoped_root.get();
4503 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4505 scoped_ptr<LayerImpl> scoped_content_layer =
4506 LayerImpl::Create(host_impl_->active_tree(), 2);
4507 LayerImpl* content_layer = scoped_content_layer.get();
4508 root->AddChild(scoped_content_layer.Pass());
4510 scoped_ptr<LayerImpl> scoped_content_child_layer =
4511 LayerImpl::Create(host_impl_->active_tree(), 3);
4512 LayerImpl* content_child_layer = scoped_content_child_layer.get();
4513 content_layer->AddChild(scoped_content_child_layer.Pass());
4515 scoped_ptr<LayerImpl> scoped_replica_layer =
4516 LayerImpl::Create(host_impl_->active_tree(), 4);
4517 LayerImpl* replica_layer = scoped_replica_layer.get();
4518 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
4520 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4521 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
4522 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4523 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4525 gfx::Size root_size(100, 100);
4526 root->SetBounds(root_size);
4527 root->SetContentBounds(root_size);
4528 root->SetPosition(gfx::PointF());
4529 root->SetAnchorPoint(gfx::PointF());
4531 gfx::Size layer_size(50, 50);
4532 content_layer->SetBounds(layer_size);
4533 content_layer->SetContentBounds(layer_size);
4534 content_layer->SetPosition(gfx::PointF());
4535 content_layer->SetAnchorPoint(gfx::PointF());
4536 content_layer->SetDrawsContent(true);
4538 gfx::Size child_size(50, 50);
4539 content_child_layer->SetBounds(child_size);
4540 content_child_layer->SetContentBounds(child_size);
4541 content_child_layer->SetPosition(gfx::Point(50, 0));
4542 content_child_layer->SetAnchorPoint(gfx::PointF());
4543 content_child_layer->SetDrawsContent(true);
4545 gfx::Size mask_size(50, 50);
4546 mask_layer->SetBounds(mask_size);
4547 mask_layer->SetContentBounds(mask_size);
4548 mask_layer->SetPosition(gfx::PointF());
4549 mask_layer->SetAnchorPoint(gfx::PointF());
4550 mask_layer->SetDrawsContent(true);
4552 float device_scale_factor = 1.f;
4553 host_impl_->SetViewportSize(root_size);
4554 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4556 LayerTreeHostImpl::FrameData frame;
4557 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4559 ASSERT_EQ(1u, frame.render_passes.size());
4560 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4562 // The surface is 100x50.
4563 ASSERT_EQ(DrawQuad::RENDER_PASS,
4564 frame.render_passes[0]->quad_list[0]->material);
4565 const RenderPassDrawQuad* render_pass_quad =
4566 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4567 EXPECT_FALSE(render_pass_quad->is_replica);
4568 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
4569 render_pass_quad->rect.ToString());
4571 // The mask covers the owning layer only.
4572 ASSERT_EQ(DrawQuad::RENDER_PASS,
4573 frame.render_passes[0]->quad_list[1]->material);
4574 const RenderPassDrawQuad* replica_quad =
4575 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4576 EXPECT_TRUE(replica_quad->is_replica);
4577 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
4578 replica_quad->rect.ToString());
4579 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
4580 replica_quad->mask_uv_rect.ToString());
4582 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4583 host_impl_->DidDrawAllLayers(frame);
4586 // Move the child to (-50, 0) instead. Now the mask should be moved to still
4587 // cover the layer being replicated.
4588 content_child_layer->SetPosition(gfx::Point(-50, 0));
4590 LayerTreeHostImpl::FrameData frame;
4591 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4593 ASSERT_EQ(1u, frame.render_passes.size());
4594 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4596 // The surface is 100x50 with its origin at (-50, 0).
4597 ASSERT_EQ(DrawQuad::RENDER_PASS,
4598 frame.render_passes[0]->quad_list[0]->material);
4599 const RenderPassDrawQuad* render_pass_quad =
4600 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4601 EXPECT_FALSE(render_pass_quad->is_replica);
4602 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
4603 render_pass_quad->rect.ToString());
4605 // The mask covers the owning layer only.
4606 ASSERT_EQ(DrawQuad::RENDER_PASS,
4607 frame.render_passes[0]->quad_list[1]->material);
4608 const RenderPassDrawQuad* replica_quad =
4609 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4610 EXPECT_TRUE(replica_quad->is_replica);
4611 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
4612 replica_quad->rect.ToString());
4613 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
4614 replica_quad->mask_uv_rect.ToString());
4616 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4617 host_impl_->DidDrawAllLayers(frame);
4621 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
4622 // The masked layer has bounds 50x50, but it has a child that causes
4623 // the surface bounds to be larger. It also has a parent that clips the
4624 // masked layer and its surface.
4626 scoped_ptr<LayerImpl> scoped_root =
4627 LayerImpl::Create(host_impl_->active_tree(), 1);
4628 LayerImpl* root = scoped_root.get();
4629 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4631 scoped_ptr<LayerImpl> scoped_clipping_layer =
4632 LayerImpl::Create(host_impl_->active_tree(), 2);
4633 LayerImpl* clipping_layer = scoped_clipping_layer.get();
4634 root->AddChild(scoped_clipping_layer.Pass());
4636 scoped_ptr<LayerImpl> scoped_content_layer =
4637 LayerImpl::Create(host_impl_->active_tree(), 3);
4638 LayerImpl* content_layer = scoped_content_layer.get();
4639 clipping_layer->AddChild(scoped_content_layer.Pass());
4641 scoped_ptr<LayerImpl> scoped_content_child_layer =
4642 LayerImpl::Create(host_impl_->active_tree(), 4);
4643 LayerImpl* content_child_layer = scoped_content_child_layer.get();
4644 content_layer->AddChild(scoped_content_child_layer.Pass());
4646 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4647 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
4648 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4649 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4651 gfx::Size root_size(100, 100);
4652 root->SetBounds(root_size);
4653 root->SetContentBounds(root_size);
4654 root->SetPosition(gfx::PointF());
4655 root->SetAnchorPoint(gfx::PointF());
4657 gfx::Rect clipping_rect(20, 10, 10, 20);
4658 clipping_layer->SetBounds(clipping_rect.size());
4659 clipping_layer->SetContentBounds(clipping_rect.size());
4660 clipping_layer->SetPosition(clipping_rect.origin());
4661 clipping_layer->SetAnchorPoint(gfx::PointF());
4662 clipping_layer->SetMasksToBounds(true);
4664 gfx::Size layer_size(50, 50);
4665 content_layer->SetBounds(layer_size);
4666 content_layer->SetContentBounds(layer_size);
4667 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
4668 content_layer->SetAnchorPoint(gfx::PointF());
4669 content_layer->SetDrawsContent(true);
4671 gfx::Size child_size(50, 50);
4672 content_child_layer->SetBounds(child_size);
4673 content_child_layer->SetContentBounds(child_size);
4674 content_child_layer->SetPosition(gfx::Point(50, 0));
4675 content_child_layer->SetAnchorPoint(gfx::PointF());
4676 content_child_layer->SetDrawsContent(true);
4678 gfx::Size mask_size(100, 100);
4679 mask_layer->SetBounds(mask_size);
4680 mask_layer->SetContentBounds(mask_size);
4681 mask_layer->SetPosition(gfx::PointF());
4682 mask_layer->SetAnchorPoint(gfx::PointF());
4683 mask_layer->SetDrawsContent(true);
4685 float device_scale_factor = 1.f;
4686 host_impl_->SetViewportSize(root_size);
4687 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4689 LayerTreeHostImpl::FrameData frame;
4690 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4692 ASSERT_EQ(1u, frame.render_passes.size());
4693 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4695 // The surface is clipped to 10x20.
4696 ASSERT_EQ(DrawQuad::RENDER_PASS,
4697 frame.render_passes[0]->quad_list[0]->material);
4698 const RenderPassDrawQuad* render_pass_quad =
4699 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4700 EXPECT_FALSE(render_pass_quad->is_replica);
4701 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
4702 render_pass_quad->rect.ToString());
4704 // The masked layer is 50x50, but the surface size is 10x20. So the texture
4705 // coords in the mask are scaled by 10/50 and 20/50.
4706 // The surface is clipped to (20,10) so the mask texture coords are offset
4707 // by 20/50 and 10/50
4708 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f),
4709 1.f / 50.f).ToString(),
4710 render_pass_quad->mask_uv_rect.ToString());
4712 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4713 host_impl_->DidDrawAllLayers(frame);
4717 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
4718 public:
4719 using GLRenderer::SetupQuadForAntialiasing;
4722 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
4723 // Due to precision issues (especially on Android), sometimes far
4724 // away quads can end up thinking they need AA.
4725 float device_scale_factor = 4.f / 3.f;
4726 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4727 gfx::Size root_size(2000, 1000);
4728 gfx::Size device_viewport_size =
4729 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
4730 host_impl_->SetViewportSize(device_viewport_size);
4732 host_impl_->CreatePendingTree();
4733 host_impl_->pending_tree()
4734 ->SetPageScaleFactorAndLimits(1.f, 1.f / 16.f, 16.f);
4736 scoped_ptr<LayerImpl> scoped_root =
4737 LayerImpl::Create(host_impl_->pending_tree(), 1);
4738 LayerImpl* root = scoped_root.get();
4740 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
4742 scoped_ptr<LayerImpl> scoped_scrolling_layer =
4743 LayerImpl::Create(host_impl_->pending_tree(), 2);
4744 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
4745 root->AddChild(scoped_scrolling_layer.Pass());
4747 gfx::Size content_layer_bounds(100000, 100);
4748 gfx::Size pile_tile_size(3000, 3000);
4749 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
4750 pile_tile_size, content_layer_bounds));
4752 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
4753 FakePictureLayerImpl::CreateWithPile(host_impl_->pending_tree(), 3, pile);
4754 LayerImpl* content_layer = scoped_content_layer.get();
4755 scrolling_layer->AddChild(scoped_content_layer.PassAs<LayerImpl>());
4756 content_layer->SetBounds(content_layer_bounds);
4757 content_layer->SetDrawsContent(true);
4759 root->SetBounds(root_size);
4761 gfx::Vector2d scroll_offset(100000, 0);
4762 scrolling_layer->SetScrollable(true);
4763 scrolling_layer->SetMaxScrollOffset(scroll_offset);
4764 scrolling_layer->SetScrollOffset(scroll_offset);
4766 host_impl_->ActivatePendingTree();
4768 host_impl_->active_tree()->UpdateDrawProperties();
4769 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
4771 LayerTreeHostImpl::FrameData frame;
4772 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4774 ASSERT_EQ(1u, frame.render_passes.size());
4775 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
4776 const DrawQuad* quad = frame.render_passes[0]->quad_list[0];
4778 float edge[24];
4779 gfx::QuadF device_layer_quad;
4780 bool antialiased =
4781 GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
4782 quad->quadTransform(), quad, &device_layer_quad, edge);
4783 EXPECT_FALSE(antialiased);
4785 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4786 host_impl_->DidDrawAllLayers(frame);
4790 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
4791 public:
4792 CompositorFrameMetadataTest()
4793 : swap_buffers_complete_(0) {}
4795 virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {
4796 swap_buffers_complete_++;
4799 int swap_buffers_complete_;
4802 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
4803 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4805 LayerTreeHostImpl::FrameData frame;
4806 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4807 host_impl_->DrawLayers(&frame, base::TimeTicks());
4808 host_impl_->DidDrawAllLayers(frame);
4810 CompositorFrameAck ack;
4811 host_impl_->ReclaimResources(&ack);
4812 host_impl_->OnSwapBuffersComplete();
4813 EXPECT_EQ(swap_buffers_complete_, 1);
4816 class CountingSoftwareDevice : public SoftwareOutputDevice {
4817 public:
4818 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
4820 virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
4821 ++frames_began_;
4822 return SoftwareOutputDevice::BeginPaint(damage_rect);
4824 virtual void EndPaint(SoftwareFrameData* frame_data) OVERRIDE {
4825 ++frames_ended_;
4826 SoftwareOutputDevice::EndPaint(frame_data);
4829 int frames_began_, frames_ended_;
4832 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
4833 // No main thread evictions in resourceless software mode.
4834 set_reduce_memory_result(false);
4835 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
4836 FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
4837 scoped_ptr<SoftwareOutputDevice>(software_device)).release();
4838 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
4839 scoped_ptr<OutputSurface>(output_surface)));
4840 host_impl_->SetViewportSize(gfx::Size(50, 50));
4842 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4844 output_surface->set_forced_draw_to_software_device(true);
4845 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
4847 EXPECT_EQ(0, software_device->frames_began_);
4848 EXPECT_EQ(0, software_device->frames_ended_);
4850 DrawFrame();
4852 EXPECT_EQ(1, software_device->frames_began_);
4853 EXPECT_EQ(1, software_device->frames_ended_);
4855 // Call other API methods that are likely to hit NULL pointer in this mode.
4856 EXPECT_TRUE(host_impl_->AsValue());
4857 EXPECT_TRUE(host_impl_->ActivationStateAsValue());
4860 TEST_F(LayerTreeHostImplTest,
4861 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
4862 set_reduce_memory_result(false);
4863 FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
4864 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())).release();
4865 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
4866 scoped_ptr<OutputSurface>(output_surface)));
4868 output_surface->set_forced_draw_to_software_device(true);
4869 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
4871 // SolidColorLayerImpl will be drawn.
4872 scoped_ptr<SolidColorLayerImpl> root_layer =
4873 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4875 // VideoLayerImpl will not be drawn.
4876 FakeVideoFrameProvider provider;
4877 scoped_ptr<VideoLayerImpl> video_layer =
4878 VideoLayerImpl::Create(host_impl_->active_tree(), 2, &provider);
4879 video_layer->SetBounds(gfx::Size(10, 10));
4880 video_layer->SetContentBounds(gfx::Size(10, 10));
4881 video_layer->SetDrawsContent(true);
4882 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
4883 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
4885 LayerTreeHostImpl::FrameData frame;
4886 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4887 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4888 host_impl_->DidDrawAllLayers(frame);
4890 EXPECT_EQ(1u, frame.will_draw_layers.size());
4891 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
4894 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
4895 protected:
4896 virtual void SetUp() OVERRIDE {
4897 LayerTreeHostImplTest::SetUp();
4899 set_reduce_memory_result(false);
4901 scoped_ptr<FakeOutputSurface> output_surface(
4902 FakeOutputSurface::CreateDeferredGL(
4903 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())));
4904 output_surface_ = output_surface.get();
4906 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
4907 output_surface.PassAs<OutputSurface>()));
4909 scoped_ptr<SolidColorLayerImpl> root_layer =
4910 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4911 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
4913 onscreen_context_provider_ = TestContextProvider::Create();
4914 offscreen_context_provider_ = TestContextProvider::Create();
4917 FakeOutputSurface* output_surface_;
4918 scoped_refptr<TestContextProvider> onscreen_context_provider_;
4919 scoped_refptr<TestContextProvider> offscreen_context_provider_;
4923 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
4924 // Software draw.
4925 DrawFrame();
4927 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
4928 EXPECT_FALSE(host_impl_->offscreen_context_provider());
4930 // DeferredInitialize and hardware draw.
4931 EXPECT_TRUE(output_surface_->InitializeAndSetContext3d(
4932 onscreen_context_provider_, offscreen_context_provider_));
4933 EXPECT_EQ(onscreen_context_provider_,
4934 host_impl_->output_surface()->context_provider());
4935 EXPECT_EQ(offscreen_context_provider_,
4936 host_impl_->offscreen_context_provider());
4938 // Defer intialized GL draw.
4939 DrawFrame();
4941 // Revert back to software.
4942 output_surface_->ReleaseGL();
4943 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
4944 EXPECT_FALSE(host_impl_->offscreen_context_provider());
4946 // Software draw again.
4947 DrawFrame();
4950 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_0) {
4951 // Software draw.
4952 DrawFrame();
4954 // Fail initialization of the onscreen context before the OutputSurface binds
4955 // it to the thread.
4956 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
4958 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
4959 EXPECT_FALSE(host_impl_->offscreen_context_provider());
4961 // DeferredInitialize fails.
4962 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
4963 onscreen_context_provider_, offscreen_context_provider_));
4964 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
4965 EXPECT_FALSE(host_impl_->offscreen_context_provider());
4967 // Software draw again.
4968 DrawFrame();
4971 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_1) {
4972 // Software draw.
4973 DrawFrame();
4975 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
4976 EXPECT_FALSE(host_impl_->offscreen_context_provider());
4978 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
4980 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
4981 // DeferredInitialize fails.
4982 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
4983 onscreen_context_provider_, offscreen_context_provider_));
4984 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
4985 EXPECT_FALSE(host_impl_->offscreen_context_provider());
4988 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_2) {
4989 // Software draw.
4990 DrawFrame();
4992 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
4993 EXPECT_FALSE(host_impl_->offscreen_context_provider());
4995 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
4997 // DeferredInitialize fails.
4998 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
4999 onscreen_context_provider_, offscreen_context_provider_));
5000 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5001 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5004 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OffscreenContext) {
5005 // Software draw.
5006 DrawFrame();
5008 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5009 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5011 // Fail initialization of the offscreen context.
5012 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5014 // DeferredInitialize fails.
5015 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5016 onscreen_context_provider_, offscreen_context_provider_));
5017 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5018 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5021 // Checks that we have a non-0 default allocation if we pass a context that
5022 // doesn't support memory management extensions.
5023 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5024 LayerTreeSettings settings;
5025 host_impl_ = LayerTreeHostImpl::Create(
5026 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
5028 scoped_ptr<OutputSurface> output_surface(
5029 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5030 host_impl_->InitializeRenderer(output_surface.Pass());
5031 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5034 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5035 ManagedMemoryPolicy policy1(
5036 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5037 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5038 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5039 int required_only_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5040 gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY);
5041 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5042 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5044 // GPU rasterization should be disabled by default.
5045 EXPECT_EQ(host_impl_->settings().gpu_rasterization, false);
5047 host_impl_->SetVisible(true);
5048 host_impl_->SetMemoryPolicy(policy1);
5049 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5050 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5052 host_impl_->SetVisible(false);
5053 EXPECT_EQ(0u, current_limit_bytes_);
5054 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5056 host_impl_->SetVisible(true);
5057 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5058 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5060 // Now enable GPU rasterization and test if we get required only cutoff,
5061 // when visible.
5062 LayerTreeSettings settings;
5063 settings.gpu_rasterization = true;
5064 host_impl_ = LayerTreeHostImpl::Create(
5065 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
5067 host_impl_->SetVisible(true);
5068 host_impl_->SetMemoryPolicy(policy1);
5069 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5070 EXPECT_EQ(required_only_cutoff_value, current_priority_cutoff_value_);
5072 host_impl_->SetVisible(false);
5073 EXPECT_EQ(0u, current_limit_bytes_);
5074 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5077 class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
5078 public:
5079 virtual void SetUp() OVERRIDE {
5080 LayerTreeSettings settings;
5081 settings.impl_side_painting = true;
5083 fake_host_impl_ = new FakeLayerTreeHostImpl(settings, &proxy_);
5084 host_impl_.reset(fake_host_impl_);
5085 host_impl_->InitializeRenderer(CreateOutputSurface());
5086 host_impl_->SetViewportSize(gfx::Size(10, 10));
5089 FakeLayerTreeHostImpl* fake_host_impl_;
5092 TEST_F(LayerTreeHostImplTestManageTiles, ManageTilesWhenInvisible) {
5093 fake_host_impl_->DidModifyTilePriorities();
5094 EXPECT_TRUE(fake_host_impl_->manage_tiles_needed());
5095 fake_host_impl_->SetVisible(false);
5096 EXPECT_FALSE(fake_host_impl_->manage_tiles_needed());
5099 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
5100 scoped_ptr<TestWebGraphicsContext3D> context =
5101 TestWebGraphicsContext3D::Create();
5102 TestWebGraphicsContext3D* context3d = context.get();
5103 scoped_ptr<OutputSurface> output_surface = CreateFakeOutputSurface();
5104 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5106 EXPECT_EQ(0u, context3d->NumTextures());
5108 SkBitmap skbitmap;
5109 skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
5110 skbitmap.allocPixels();
5111 skbitmap.setImmutable();
5113 UIResourceId ui_resource_id = 1;
5114 UIResourceBitmap bitmap(skbitmap);
5115 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5116 EXPECT_EQ(1u, context3d->NumTextures());
5117 ResourceProvider::ResourceId id1 =
5118 host_impl_->ResourceIdForUIResource(ui_resource_id);
5119 EXPECT_NE(0u, id1);
5121 // Multiple requests with the same id is allowed. The previous texture is
5122 // deleted.
5123 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5124 EXPECT_EQ(1u, context3d->NumTextures());
5125 ResourceProvider::ResourceId id2 =
5126 host_impl_->ResourceIdForUIResource(ui_resource_id);
5127 EXPECT_NE(0u, id2);
5128 EXPECT_NE(id1, id2);
5130 // Deleting invalid UIResourceId is allowed and does not change state.
5131 host_impl_->DeleteUIResource(-1);
5132 EXPECT_EQ(1u, context3d->NumTextures());
5134 // Should return zero for invalid UIResourceId. Number of textures should
5135 // not change.
5136 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
5137 EXPECT_EQ(1u, context3d->NumTextures());
5139 host_impl_->DeleteUIResource(ui_resource_id);
5140 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
5141 EXPECT_EQ(0u, context3d->NumTextures());
5143 // Should not change state for multiple deletion on one UIResourceId
5144 host_impl_->DeleteUIResource(ui_resource_id);
5145 EXPECT_EQ(0u, context3d->NumTextures());
5148 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
5149 scoped_ptr<TestWebGraphicsContext3D> context =
5150 TestWebGraphicsContext3D::Create();
5151 TestWebGraphicsContext3D* context3d = context.get();
5152 scoped_ptr<OutputSurface> output_surface = CreateFakeOutputSurface();
5153 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5155 EXPECT_EQ(0u, context3d->NumTextures());
5157 SkImageInfo info =
5158 SkImageInfo::Make(4, 4, kPMColor_SkColorType, kPremul_SkAlphaType);
5159 skia::RefPtr<SkPixelRef> pixel_ref =
5160 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
5161 pixel_ref->setImmutable();
5162 UIResourceBitmap bitmap(pixel_ref);
5163 UIResourceId ui_resource_id = 1;
5164 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5165 EXPECT_EQ(1u, context3d->NumTextures());
5166 ResourceProvider::ResourceId id1 =
5167 host_impl_->ResourceIdForUIResource(ui_resource_id);
5168 EXPECT_NE(0u, id1);
5171 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
5174 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
5175 scoped_refptr<TestContextProvider> context_provider =
5176 TestContextProvider::Create();
5178 CreateHostImpl(
5179 DefaultSettings(),
5180 FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>());
5182 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5184 ScopedPtrVector<CopyOutputRequest> requests;
5185 requests.push_back(CopyOutputRequest::CreateRequest(
5186 base::Bind(&ShutdownReleasesContext_Callback)));
5188 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
5190 LayerTreeHostImpl::FrameData frame;
5191 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5192 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5193 host_impl_->DidDrawAllLayers(frame);
5195 // The CopyOutputResult's callback has a ref on the ContextProvider and a
5196 // texture in a texture mailbox.
5197 EXPECT_FALSE(context_provider->HasOneRef());
5198 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
5200 host_impl_.reset();
5202 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
5203 // released, and the texture deleted.
5204 EXPECT_TRUE(context_provider->HasOneRef());
5205 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
5208 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
5209 // When flinging via touch, only the child should scroll (we should not
5210 // bubble).
5211 gfx::Size surface_size(10, 10);
5212 gfx::Size content_size(20, 20);
5213 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
5214 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
5216 root->AddChild(child.Pass());
5218 host_impl_->SetViewportSize(surface_size);
5219 host_impl_->active_tree()->SetRootLayer(root.Pass());
5220 host_impl_->active_tree()->DidBecomeActive();
5221 DrawFrame();
5223 EXPECT_EQ(InputHandler::ScrollStarted,
5224 host_impl_->ScrollBegin(gfx::Point(),
5225 InputHandler::Gesture));
5227 EXPECT_EQ(InputHandler::ScrollStarted,
5228 host_impl_->FlingScrollBegin());
5230 gfx::Vector2d scroll_delta(0, 100);
5231 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5232 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5234 host_impl_->ScrollEnd();
5236 scoped_ptr<ScrollAndScaleSet> scroll_info =
5237 host_impl_->ProcessScrollDeltas();
5239 // Only the child should have scrolled.
5240 ASSERT_EQ(1u, scroll_info->scrolls.size());
5241 ExpectNone(*scroll_info.get(),
5242 host_impl_->active_tree()->root_layer()->id());
5246 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
5247 // Scroll a child layer beyond its maximum scroll range and make sure the
5248 // the scroll doesn't bubble up to the parent layer.
5249 gfx::Size surface_size(10, 10);
5250 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
5251 scoped_ptr<LayerImpl> root_scrolling = CreateScrollableLayer(2, surface_size);
5253 scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(4, surface_size);
5254 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
5256 scoped_ptr<LayerImpl> child = CreateScrollableLayer(3, surface_size);
5257 child->SetScrollOffset(gfx::Vector2d(0, 4));
5258 child->AddChild(grand_child.Pass());
5260 root_scrolling->AddChild(child.Pass());
5261 root->AddChild(root_scrolling.Pass());
5262 host_impl_->active_tree()->SetRootLayer(root.Pass());
5263 host_impl_->active_tree()->DidBecomeActive();
5264 host_impl_->SetViewportSize(surface_size);
5265 DrawFrame();
5267 scoped_ptr<ScrollAndScaleSet> scroll_info;
5268 LayerImpl* child =
5269 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
5270 LayerImpl* grand_child = child->children()[0];
5272 gfx::Vector2d scroll_delta(0, -2);
5273 EXPECT_EQ(InputHandler::ScrollStarted,
5274 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
5275 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5277 // The grand child should have scrolled up to its limit.
5278 scroll_info = host_impl_->ProcessScrollDeltas();
5279 ASSERT_EQ(1u, scroll_info->scrolls.size());
5280 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5281 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
5283 // The child should have received the bubbled delta, but the locked
5284 // scrolling layer should remain set as the grand child.
5285 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5286 scroll_info = host_impl_->ProcessScrollDeltas();
5287 ASSERT_EQ(2u, scroll_info->scrolls.size());
5288 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5289 ExpectContains(*scroll_info, child->id(), scroll_delta);
5290 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
5292 // The first |ScrollBy| after the fling should re-lock the scrolling
5293 // layer to the first layer that scrolled, which is the child.
5294 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
5295 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5296 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
5298 // The child should have scrolled up to its limit.
5299 scroll_info = host_impl_->ProcessScrollDeltas();
5300 ASSERT_EQ(2u, scroll_info->scrolls.size());
5301 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
5302 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
5304 // As the locked layer is at it's limit, no further scrolling can occur.
5305 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
5306 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
5307 host_impl_->ScrollEnd();
5311 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
5312 // When flinging via wheel, the root should eventually scroll (we should
5313 // bubble).
5314 gfx::Size surface_size(10, 10);
5315 gfx::Size content_size(20, 20);
5316 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
5317 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
5319 root->AddChild(child.Pass());
5321 host_impl_->SetViewportSize(surface_size);
5322 host_impl_->active_tree()->SetRootLayer(root.Pass());
5323 host_impl_->active_tree()->DidBecomeActive();
5324 DrawFrame();
5326 EXPECT_EQ(InputHandler::ScrollStarted,
5327 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
5329 EXPECT_EQ(InputHandler::ScrollStarted,
5330 host_impl_->FlingScrollBegin());
5332 gfx::Vector2d scroll_delta(0, 100);
5333 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5334 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5336 host_impl_->ScrollEnd();
5338 scoped_ptr<ScrollAndScaleSet> scroll_info =
5339 host_impl_->ProcessScrollDeltas();
5341 // The root should have scrolled.
5342 ASSERT_EQ(2u, scroll_info->scrolls.size());
5343 ExpectContains(*scroll_info.get(),
5344 host_impl_->active_tree()->root_layer()->id(),
5345 gfx::Vector2d(0, 10));
5349 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
5350 // to CompositorFrameMetadata after SwapBuffers();
5351 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
5352 scoped_ptr<SolidColorLayerImpl> root =
5353 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5354 root->SetAnchorPoint(gfx::PointF());
5355 root->SetPosition(gfx::PointF());
5356 root->SetBounds(gfx::Size(10, 10));
5357 root->SetContentBounds(gfx::Size(10, 10));
5358 root->SetDrawsContent(true);
5360 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
5362 FakeOutputSurface* fake_output_surface =
5363 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
5365 const std::vector<ui::LatencyInfo>& metadata_latency_before =
5366 fake_output_surface->last_sent_frame().metadata.latency_info;
5367 EXPECT_TRUE(metadata_latency_before.empty());
5369 ui::LatencyInfo latency_info;
5370 latency_info.AddLatencyNumber(
5371 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
5372 scoped_ptr<SwapPromise> swap_promise(
5373 new LatencyInfoSwapPromise(latency_info));
5374 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
5375 host_impl_->SetNeedsRedraw();
5377 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
5378 LayerTreeHostImpl::FrameData frame;
5379 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5380 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5381 host_impl_->DidDrawAllLayers(frame);
5382 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
5384 const std::vector<ui::LatencyInfo>& metadata_latency_after =
5385 fake_output_surface->last_sent_frame().metadata.latency_info;
5386 EXPECT_EQ(1u, metadata_latency_after.size());
5387 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
5388 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
5391 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
5392 public:
5393 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
5394 LayerTreeHostImpl* layer_tree_host_impl,
5395 int* set_needs_commit_count,
5396 int* set_needs_redraw_count)
5397 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
5398 set_needs_commit_count_(set_needs_commit_count),
5399 set_needs_redraw_count_(set_needs_redraw_count) {}
5401 virtual ~SimpleSwapPromiseMonitor() {}
5403 virtual void OnSetNeedsCommitOnMain() OVERRIDE {
5404 (*set_needs_commit_count_)++;
5407 virtual void OnSetNeedsRedrawOnImpl() OVERRIDE {
5408 (*set_needs_redraw_count_)++;
5411 private:
5412 int* set_needs_commit_count_;
5413 int* set_needs_redraw_count_;
5416 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
5417 int set_needs_commit_count = 0;
5418 int set_needs_redraw_count = 0;
5421 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
5422 new SimpleSwapPromiseMonitor(NULL,
5423 host_impl_.get(),
5424 &set_needs_commit_count,
5425 &set_needs_redraw_count));
5426 host_impl_->SetNeedsRedraw();
5427 EXPECT_EQ(0, set_needs_commit_count);
5428 EXPECT_EQ(1, set_needs_redraw_count);
5431 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
5432 // monitored.
5433 host_impl_->SetNeedsRedraw();
5434 EXPECT_EQ(0, set_needs_commit_count);
5435 EXPECT_EQ(1, set_needs_redraw_count);
5438 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
5439 new SimpleSwapPromiseMonitor(NULL,
5440 host_impl_.get(),
5441 &set_needs_commit_count,
5442 &set_needs_redraw_count));
5443 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
5444 EXPECT_EQ(0, set_needs_commit_count);
5445 EXPECT_EQ(2, set_needs_redraw_count);
5449 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
5450 new SimpleSwapPromiseMonitor(NULL,
5451 host_impl_.get(),
5452 &set_needs_commit_count,
5453 &set_needs_redraw_count));
5454 // Empty damage rect won't signal the monitor.
5455 host_impl_->SetNeedsRedrawRect(gfx::Rect());
5456 EXPECT_EQ(0, set_needs_commit_count);
5457 EXPECT_EQ(2, set_needs_redraw_count);
5461 } // namespace
5462 } // namespace cc