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"
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/math_util.h"
15 #include "cc/input/top_controls_manager.h"
16 #include "cc/layers/delegated_renderer_layer_impl.h"
17 #include "cc/layers/heads_up_display_layer_impl.h"
18 #include "cc/layers/io_surface_layer_impl.h"
19 #include "cc/layers/layer_impl.h"
20 #include "cc/layers/painted_scrollbar_layer_impl.h"
21 #include "cc/layers/quad_sink.h"
22 #include "cc/layers/render_surface_impl.h"
23 #include "cc/layers/solid_color_layer_impl.h"
24 #include "cc/layers/texture_layer_impl.h"
25 #include "cc/layers/tiled_layer_impl.h"
26 #include "cc/layers/video_layer_impl.h"
27 #include "cc/output/begin_frame_args.h"
28 #include "cc/output/compositor_frame_ack.h"
29 #include "cc/output/compositor_frame_metadata.h"
30 #include "cc/output/copy_output_request.h"
31 #include "cc/output/copy_output_result.h"
32 #include "cc/output/gl_renderer.h"
33 #include "cc/quads/render_pass_draw_quad.h"
34 #include "cc/quads/solid_color_draw_quad.h"
35 #include "cc/quads/texture_draw_quad.h"
36 #include "cc/quads/tile_draw_quad.h"
37 #include "cc/resources/layer_tiling_data.h"
38 #include "cc/test/animation_test_common.h"
39 #include "cc/test/fake_layer_tree_host_impl.h"
40 #include "cc/test/fake_output_surface.h"
41 #include "cc/test/fake_output_surface_client.h"
42 #include "cc/test/fake_picture_layer_impl.h"
43 #include "cc/test/fake_picture_pile_impl.h"
44 #include "cc/test/fake_proxy.h"
45 #include "cc/test/fake_rendering_stats_instrumentation.h"
46 #include "cc/test/fake_video_frame_provider.h"
47 #include "cc/test/geometry_test_utils.h"
48 #include "cc/test/layer_test_common.h"
49 #include "cc/test/render_pass_test_common.h"
50 #include "cc/test/test_web_graphics_context_3d.h"
51 #include "cc/trees/layer_tree_impl.h"
52 #include "cc/trees/single_thread_proxy.h"
53 #include "media/base/media.h"
54 #include "testing/gmock/include/gmock/gmock.h"
55 #include "testing/gtest/include/gtest/gtest.h"
56 #include "ui/gfx/frame_time.h"
57 #include "ui/gfx/rect_conversions.h"
58 #include "ui/gfx/size_conversions.h"
59 #include "ui/gfx/vector2d_conversions.h"
61 using ::testing::Mock;
62 using ::testing::Return;
63 using ::testing::AnyNumber;
64 using ::testing::AtLeast;
66 using media::VideoFrame;
71 class LayerTreeHostImplTest : public testing::Test,
72 public LayerTreeHostImplClient {
74 LayerTreeHostImplTest()
76 always_impl_thread_(&proxy_),
77 always_main_thread_blocked_(&proxy_),
78 on_can_draw_state_changed_called_(false),
79 did_notify_ready_to_activate_(false),
80 did_request_commit_(false),
81 did_request_redraw_(false),
82 did_request_manage_tiles_(false),
83 did_upload_visible_tile_(false),
84 did_lose_output_surface_(false),
85 reduce_memory_result_(true),
86 current_limit_bytes_(0),
87 current_priority_cutoff_value_(0) {
88 media::InitializeMediaLibraryForTesting();
91 virtual void SetUp() OVERRIDE {
92 LayerTreeSettings settings;
93 settings.minimum_occlusion_tracking_size = gfx::Size();
94 settings.impl_side_painting = true;
95 settings.texture_id_allocation_chunk_size = 1;
97 host_impl_ = LayerTreeHostImpl::Create(
98 settings, this, &proxy_, &stats_instrumentation_, NULL);
99 host_impl_->InitializeRenderer(CreateOutputSurface());
100 host_impl_->SetViewportSize(gfx::Size(10, 10));
103 virtual void TearDown() OVERRIDE {}
105 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {
106 did_lose_output_surface_ = true;
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(gfx::Rect damage_rect) OVERRIDE {
121 did_request_redraw_ = true;
123 virtual void SetNeedsManageTilesOnImplThread() OVERRIDE {
124 did_request_manage_tiles_ = true;
126 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {
127 did_upload_visible_tile_ = true;
129 virtual void SetNeedsCommitOnImplThread() OVERRIDE {
130 did_request_commit_ = true;
132 virtual void PostAnimationEventsToMainThreadOnImplThread(
133 scoped_ptr<AnimationEventsVector> events,
134 base::Time wall_clock_time) OVERRIDE {}
135 virtual bool ReduceContentsTextureMemoryOnImplThread(
136 size_t limit_bytes, int priority_cutoff) OVERRIDE {
137 current_limit_bytes_ = limit_bytes;
138 current_priority_cutoff_value_ = priority_cutoff;
139 return reduce_memory_result_;
141 virtual void SendManagedMemoryStats() OVERRIDE {}
142 virtual bool IsInsideDraw() OVERRIDE { return false; }
143 virtual void RenewTreePriority() OVERRIDE {}
144 virtual void RequestScrollbarAnimationOnImplThread(base::TimeDelta delay)
145 OVERRIDE { requested_scrollbar_animation_delay_ = delay; }
146 virtual void DidActivatePendingTree() OVERRIDE {}
148 void set_reduce_memory_result(bool reduce_memory_result) {
149 reduce_memory_result_ = reduce_memory_result;
152 void CreateLayerTreeHost(bool partial_swap,
153 scoped_ptr<OutputSurface> output_surface) {
154 LayerTreeSettings settings;
155 settings.minimum_occlusion_tracking_size = gfx::Size();
156 settings.partial_swap_enabled = partial_swap;
158 host_impl_ = LayerTreeHostImpl::Create(
159 settings, this, &proxy_, &stats_instrumentation_, NULL);
161 host_impl_->InitializeRenderer(output_surface.Pass());
162 host_impl_->SetViewportSize(gfx::Size(10, 10));
165 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
166 root->SetAnchorPoint(gfx::PointF());
167 root->SetPosition(gfx::PointF());
168 root->SetBounds(gfx::Size(10, 10));
169 root->SetContentBounds(gfx::Size(10, 10));
170 root->SetDrawsContent(true);
171 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
172 host_impl_->active_tree()->SetRootLayer(root.Pass());
175 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
176 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
177 for (size_t i = 0; i < layer->children().size(); ++i)
178 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
181 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
183 gfx::Vector2d scroll_delta) {
184 int times_encountered = 0;
186 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
187 if (scroll_info.scrolls[i].layer_id != id)
189 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
193 ASSERT_EQ(1, times_encountered);
196 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
197 int times_encountered = 0;
199 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
200 if (scroll_info.scrolls[i].layer_id != id)
205 ASSERT_EQ(0, times_encountered);
208 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
209 gfx::Size content_size) {
210 scoped_ptr<LayerImpl> root =
211 LayerImpl::Create(layer_tree_impl, 1);
212 root->SetBounds(content_size);
213 root->SetContentBounds(content_size);
214 root->SetPosition(gfx::PointF());
215 root->SetAnchorPoint(gfx::PointF());
217 scoped_ptr<LayerImpl> scroll =
218 LayerImpl::Create(layer_tree_impl, 2);
219 LayerImpl* scroll_layer = scroll.get();
220 scroll->SetScrollable(true);
221 scroll->SetScrollOffset(gfx::Vector2d());
222 scroll->SetMaxScrollOffset(gfx::Vector2d(content_size.width(),
223 content_size.height()));
224 scroll->SetBounds(content_size);
225 scroll->SetContentBounds(content_size);
226 scroll->SetPosition(gfx::PointF());
227 scroll->SetAnchorPoint(gfx::PointF());
229 scoped_ptr<LayerImpl> contents =
230 LayerImpl::Create(layer_tree_impl, 3);
231 contents->SetDrawsContent(true);
232 contents->SetBounds(content_size);
233 contents->SetContentBounds(content_size);
234 contents->SetPosition(gfx::PointF());
235 contents->SetAnchorPoint(gfx::PointF());
237 scroll->AddChild(contents.Pass());
238 root->AddChild(scroll.Pass());
240 layer_tree_impl->SetRootLayer(root.Pass());
244 LayerImpl* SetupScrollAndContentsLayers(gfx::Size content_size) {
245 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
246 host_impl_->active_tree(), content_size);
247 host_impl_->active_tree()->DidBecomeActive();
251 scoped_ptr<LayerImpl> CreateScrollableLayer(int id, gfx::Size size) {
252 scoped_ptr<LayerImpl> layer =
253 LayerImpl::Create(host_impl_->active_tree(), id);
254 layer->SetScrollable(true);
255 layer->SetDrawsContent(true);
256 layer->SetBounds(size);
257 layer->SetContentBounds(size);
258 layer->SetMaxScrollOffset(gfx::Vector2d(size.width() * 2,
263 void InitializeRendererAndDrawFrame() {
264 host_impl_->InitializeRenderer(CreateOutputSurface());
269 LayerTreeHostImpl::FrameData frame;
270 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
271 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
272 host_impl_->DidDrawAllLayers(frame);
275 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
276 void pinch_zoom_pan_viewport_test(float device_scale_factor);
277 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
278 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
279 float device_scale_factor);
281 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
282 // Note: It is not possible to disable the renderer once it has been set,
283 // so we do not need to test that disabling the renderer notifies us
284 // that can_draw changed.
285 EXPECT_FALSE(host_impl_->CanDraw());
286 on_can_draw_state_changed_called_ = false;
288 // Set up the root layer, which allows us to draw.
289 SetupScrollAndContentsLayers(gfx::Size(100, 100));
290 EXPECT_TRUE(host_impl_->CanDraw());
291 EXPECT_TRUE(on_can_draw_state_changed_called_);
292 on_can_draw_state_changed_called_ = false;
294 // Toggle the root layer to make sure it toggles can_draw
295 host_impl_->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
296 EXPECT_FALSE(host_impl_->CanDraw());
297 EXPECT_TRUE(on_can_draw_state_changed_called_);
298 on_can_draw_state_changed_called_ = false;
300 SetupScrollAndContentsLayers(gfx::Size(100, 100));
301 EXPECT_TRUE(host_impl_->CanDraw());
302 EXPECT_TRUE(on_can_draw_state_changed_called_);
303 on_can_draw_state_changed_called_ = false;
305 // Toggle the device viewport size to make sure it toggles can_draw.
306 host_impl_->SetViewportSize(gfx::Size());
308 EXPECT_TRUE(host_impl_->CanDraw());
310 EXPECT_FALSE(host_impl_->CanDraw());
312 EXPECT_TRUE(on_can_draw_state_changed_called_);
313 on_can_draw_state_changed_called_ = false;
315 host_impl_->SetViewportSize(gfx::Size(100, 100));
316 EXPECT_TRUE(host_impl_->CanDraw());
317 EXPECT_TRUE(on_can_draw_state_changed_called_);
318 on_can_draw_state_changed_called_ = false;
320 // Toggle contents textures purged without causing any evictions,
321 // and make sure that it does not change can_draw.
322 set_reduce_memory_result(false);
323 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
324 host_impl_->memory_allocation_limit_bytes() - 1));
325 EXPECT_TRUE(host_impl_->CanDraw());
326 EXPECT_FALSE(on_can_draw_state_changed_called_);
327 on_can_draw_state_changed_called_ = false;
329 // Toggle contents textures purged to make sure it toggles can_draw.
330 set_reduce_memory_result(true);
331 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
332 host_impl_->memory_allocation_limit_bytes() - 1));
334 EXPECT_TRUE(host_impl_->CanDraw());
336 EXPECT_FALSE(host_impl_->CanDraw());
338 EXPECT_TRUE(on_can_draw_state_changed_called_);
339 on_can_draw_state_changed_called_ = false;
341 host_impl_->active_tree()->ResetContentsTexturesPurged();
342 EXPECT_TRUE(host_impl_->CanDraw());
343 EXPECT_TRUE(on_can_draw_state_changed_called_);
344 on_can_draw_state_changed_called_ = false;
347 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
350 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
351 return CreateFakeOutputSurface();
354 void DrawOneFrame() {
355 LayerTreeHostImpl::FrameData frame_data;
356 host_impl_->PrepareToDraw(&frame_data, gfx::Rect());
357 host_impl_->DidDrawAllLayers(frame_data);
361 DebugScopedSetImplThread always_impl_thread_;
362 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
364 scoped_ptr<LayerTreeHostImpl> host_impl_;
365 FakeRenderingStatsInstrumentation stats_instrumentation_;
366 bool on_can_draw_state_changed_called_;
367 bool did_notify_ready_to_activate_;
368 bool did_request_commit_;
369 bool did_request_redraw_;
370 bool did_request_manage_tiles_;
371 bool did_upload_visible_tile_;
372 bool did_lose_output_surface_;
373 bool reduce_memory_result_;
374 base::TimeDelta requested_scrollbar_animation_delay_;
375 size_t current_limit_bytes_;
376 int current_priority_cutoff_value_;
379 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
380 bool always_draw = false;
381 CheckNotifyCalledIfCanDrawChanged(always_draw);
384 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
385 LayerTreeSettings settings;
386 settings.impl_side_painting = true;
387 host_impl_ = LayerTreeHostImpl::Create(
388 settings, this, &proxy_, &stats_instrumentation_, NULL);
390 scoped_ptr<FakeOutputSurface> output_surface(
391 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
393 host_impl_->InitializeRenderer(
394 output_surface.PassAs<OutputSurface>());
395 host_impl_->SetViewportSize(gfx::Size(10, 10));
397 bool always_draw = true;
398 CheckNotifyCalledIfCanDrawChanged(always_draw);
401 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
402 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
404 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
405 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
408 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
410 scoped_ptr<LayerImpl> root =
411 LayerImpl::Create(host_impl_->active_tree(), 1);
412 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
413 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
414 root->children()[1]->AddChild(
415 LayerImpl::Create(host_impl_->active_tree(), 4));
416 root->children()[1]->AddChild(
417 LayerImpl::Create(host_impl_->active_tree(), 5));
418 root->children()[1]->children()[0]->AddChild(
419 LayerImpl::Create(host_impl_->active_tree(), 6));
420 host_impl_->active_tree()->SetRootLayer(root.Pass());
422 LayerImpl* root = host_impl_->active_tree()->root_layer();
424 ExpectClearedScrollDeltasRecursive(root);
426 scoped_ptr<ScrollAndScaleSet> scroll_info;
428 scroll_info = host_impl_->ProcessScrollDeltas();
429 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
430 ExpectClearedScrollDeltasRecursive(root);
432 scroll_info = host_impl_->ProcessScrollDeltas();
433 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
434 ExpectClearedScrollDeltasRecursive(root);
437 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
438 gfx::Vector2d scroll_offset(20, 30);
439 gfx::Vector2d scroll_delta(11, -15);
441 scoped_ptr<LayerImpl> root =
442 LayerImpl::Create(host_impl_->active_tree(), 1);
443 root->SetMaxScrollOffset(gfx::Vector2d(100, 100));
444 root->SetScrollOffset(scroll_offset);
445 root->SetScrollable(true);
446 root->ScrollBy(scroll_delta);
447 host_impl_->active_tree()->SetRootLayer(root.Pass());
449 LayerImpl* root = host_impl_->active_tree()->root_layer();
451 scoped_ptr<ScrollAndScaleSet> scroll_info;
453 scroll_info = host_impl_->ProcessScrollDeltas();
454 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
455 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta);
456 ExpectContains(*scroll_info, root->id(), scroll_delta);
458 gfx::Vector2d scroll_delta2(-5, 27);
459 root->ScrollBy(scroll_delta2);
460 scroll_info = host_impl_->ProcessScrollDeltas();
461 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
462 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
463 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
465 root->ScrollBy(gfx::Vector2d());
466 scroll_info = host_impl_->ProcessScrollDeltas();
467 EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
470 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
471 SetupScrollAndContentsLayers(gfx::Size(100, 100));
472 host_impl_->SetViewportSize(gfx::Size(50, 50));
473 InitializeRendererAndDrawFrame();
475 EXPECT_EQ(InputHandler::ScrollStarted,
476 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
477 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
478 host_impl_->ScrollEnd();
479 EXPECT_TRUE(did_request_redraw_);
480 EXPECT_TRUE(did_request_commit_);
483 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
484 // We should not crash when trying to scroll an empty layer tree.
485 EXPECT_EQ(InputHandler::ScrollIgnored,
486 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
489 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
490 LayerTreeSettings settings;
491 host_impl_ = LayerTreeHostImpl::Create(
492 settings, this, &proxy_, &stats_instrumentation_, NULL);
493 scoped_ptr<TestWebGraphicsContext3D> context_owned =
494 TestWebGraphicsContext3D::Create();
495 context_owned->set_times_make_current_succeeds(0);
497 scoped_ptr<FakeOutputSurface> output_surface(FakeOutputSurface::Create3d(
498 context_owned.Pass()));
500 // Initialization will fail here.
501 host_impl_->InitializeRenderer(output_surface.PassAs<OutputSurface>());
502 host_impl_->SetViewportSize(gfx::Size(10, 10));
504 SetupScrollAndContentsLayers(gfx::Size(100, 100));
506 // We should not crash when trying to scroll after the renderer initialization
508 EXPECT_EQ(InputHandler::ScrollIgnored,
509 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
512 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
513 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
514 host_impl_->SetViewportSize(gfx::Size(50, 50));
515 InitializeRendererAndDrawFrame();
517 // We should not crash if the tree is replaced while we are scrolling.
518 EXPECT_EQ(InputHandler::ScrollStarted,
519 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
520 host_impl_->active_tree()->DetachLayerTree();
522 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
524 // We should still be scrolling, because the scrolled layer also exists in the
526 gfx::Vector2d scroll_delta(0, 10);
527 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
528 host_impl_->ScrollEnd();
529 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
530 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
533 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
534 SetupScrollAndContentsLayers(gfx::Size(100, 100));
535 host_impl_->SetViewportSize(gfx::Size(50, 50));
536 InitializeRendererAndDrawFrame();
538 // We should be able to scroll even if the root layer loses its render surface
539 // after the most recent render.
540 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
541 host_impl_->active_tree()->set_needs_update_draw_properties();
543 EXPECT_EQ(InputHandler::ScrollStarted,
544 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
547 TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
548 SetupScrollAndContentsLayers(gfx::Size(100, 100));
549 host_impl_->SetViewportSize(gfx::Size(50, 50));
550 InitializeRendererAndDrawFrame();
551 LayerImpl* root = host_impl_->active_tree()->root_layer();
553 root->SetHaveWheelEventHandlers(true);
555 // With registered event handlers, wheel scrolls have to go to the main
557 EXPECT_EQ(InputHandler::ScrollOnMainThread,
558 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
560 // But gesture scrolls can still be handled.
561 EXPECT_EQ(InputHandler::ScrollStarted,
562 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
565 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
566 SetupScrollAndContentsLayers(gfx::Size(100, 100));
567 host_impl_->SetViewportSize(gfx::Size(50, 50));
568 InitializeRendererAndDrawFrame();
570 // Ignore the fling since no layer is being scrolled
571 EXPECT_EQ(InputHandler::ScrollIgnored,
572 host_impl_->FlingScrollBegin());
574 // Start scrolling a layer
575 EXPECT_EQ(InputHandler::ScrollStarted,
576 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
578 // Now the fling should go ahead since we've started scrolling a layer
579 EXPECT_EQ(InputHandler::ScrollStarted,
580 host_impl_->FlingScrollBegin());
583 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
584 SetupScrollAndContentsLayers(gfx::Size(100, 100));
585 host_impl_->SetViewportSize(gfx::Size(50, 50));
586 InitializeRendererAndDrawFrame();
588 // Ignore the fling since no layer is being scrolled
589 EXPECT_EQ(InputHandler::ScrollIgnored,
590 host_impl_->FlingScrollBegin());
592 // Start scrolling a layer
593 EXPECT_EQ(InputHandler::ScrollStarted,
594 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
596 // Now the fling should go ahead since we've started scrolling a layer
597 EXPECT_EQ(InputHandler::ScrollStarted,
598 host_impl_->FlingScrollBegin());
601 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
602 SetupScrollAndContentsLayers(gfx::Size(100, 100));
603 host_impl_->SetViewportSize(gfx::Size(50, 50));
604 InitializeRendererAndDrawFrame();
605 LayerImpl* root = host_impl_->active_tree()->root_layer();
607 root->SetShouldScrollOnMainThread(true);
609 // Start scrolling a layer
610 EXPECT_EQ(InputHandler::ScrollOnMainThread,
611 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
613 // The fling should be ignored since there's no layer being scrolled impl-side
614 EXPECT_EQ(InputHandler::ScrollIgnored,
615 host_impl_->FlingScrollBegin());
618 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
619 SetupScrollAndContentsLayers(gfx::Size(100, 100));
620 host_impl_->SetViewportSize(gfx::Size(50, 50));
621 InitializeRendererAndDrawFrame();
622 LayerImpl* root = host_impl_->active_tree()->root_layer();
624 root->SetShouldScrollOnMainThread(true);
626 EXPECT_EQ(InputHandler::ScrollOnMainThread,
627 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
628 EXPECT_EQ(InputHandler::ScrollOnMainThread,
629 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
632 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
633 SetupScrollAndContentsLayers(gfx::Size(200, 200));
634 host_impl_->SetViewportSize(gfx::Size(100, 100));
636 LayerImpl* root = host_impl_->active_tree()->root_layer();
637 root->SetContentsScale(2.f, 2.f);
638 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
640 InitializeRendererAndDrawFrame();
642 // All scroll types inside the non-fast scrollable region should fail.
643 EXPECT_EQ(InputHandler::ScrollOnMainThread,
644 host_impl_->ScrollBegin(gfx::Point(25, 25),
645 InputHandler::Wheel));
646 EXPECT_EQ(InputHandler::ScrollOnMainThread,
647 host_impl_->ScrollBegin(gfx::Point(25, 25),
648 InputHandler::Gesture));
650 // All scroll types outside this region should succeed.
651 EXPECT_EQ(InputHandler::ScrollStarted,
652 host_impl_->ScrollBegin(gfx::Point(75, 75),
653 InputHandler::Wheel));
654 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
655 host_impl_->ScrollEnd();
656 EXPECT_EQ(InputHandler::ScrollStarted,
657 host_impl_->ScrollBegin(gfx::Point(75, 75),
658 InputHandler::Gesture));
659 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
660 host_impl_->ScrollEnd();
663 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
664 SetupScrollAndContentsLayers(gfx::Size(200, 200));
665 host_impl_->SetViewportSize(gfx::Size(100, 100));
667 LayerImpl* root = host_impl_->active_tree()->root_layer();
668 root->SetContentsScale(2.f, 2.f);
669 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
670 root->SetPosition(gfx::PointF(-25.f, 0.f));
672 InitializeRendererAndDrawFrame();
674 // This point would fall into the non-fast scrollable region except that we've
675 // moved the layer down by 25 pixels.
676 EXPECT_EQ(InputHandler::ScrollStarted,
677 host_impl_->ScrollBegin(gfx::Point(40, 10),
678 InputHandler::Wheel));
679 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
680 host_impl_->ScrollEnd();
682 // This point is still inside the non-fast region.
683 EXPECT_EQ(InputHandler::ScrollOnMainThread,
684 host_impl_->ScrollBegin(gfx::Point(10, 10),
685 InputHandler::Wheel));
688 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
689 SetupScrollAndContentsLayers(gfx::Size(200, 200));
690 host_impl_->SetViewportSize(gfx::Size(100, 100));
692 InitializeRendererAndDrawFrame();
694 EXPECT_EQ(InputHandler::ScrollStarted,
695 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
697 // Trying to scroll to the left/top will not succeed.
698 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
699 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
700 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
702 // Scrolling to the right/bottom will succeed.
703 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
704 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
705 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
707 // Scrolling to left/top will now succeed.
708 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
709 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
710 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
712 // Scrolling diagonally against an edge will succeed.
713 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
714 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
715 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
717 // Trying to scroll more than the available space will also succeed.
718 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
721 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
722 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
723 host_impl_->SetViewportSize(gfx::Size(100, 1000));
725 InitializeRendererAndDrawFrame();
727 EXPECT_EQ(InputHandler::ScrollStarted,
728 host_impl_->ScrollBegin(gfx::Point(),
729 InputHandler::Wheel));
731 // Trying to scroll without a vertical scrollbar will fail.
732 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
733 gfx::Point(), SCROLL_FORWARD));
734 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
735 gfx::Point(), SCROLL_BACKWARD));
737 scoped_ptr<cc::PaintedScrollbarLayerImpl> vertical_scrollbar(
738 cc::PaintedScrollbarLayerImpl::Create(
739 host_impl_->active_tree(),
742 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
743 host_impl_->RootScrollLayer()->SetVerticalScrollbarLayer(
744 vertical_scrollbar.get());
746 // Trying to scroll with a vertical scrollbar will succeed.
747 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
748 gfx::Point(), SCROLL_FORWARD));
749 EXPECT_FLOAT_EQ(875.f, host_impl_->RootScrollLayer()->ScrollDelta().y());
750 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
751 gfx::Point(), SCROLL_BACKWARD));
754 TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
755 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
756 host_impl_->SetViewportSize(gfx::Size(100, 100));
758 gfx::Size overflow_size(400, 400);
759 ASSERT_EQ(1u, scroll_layer->children().size());
760 LayerImpl* overflow = scroll_layer->children()[0];
761 overflow->SetBounds(overflow_size);
762 overflow->SetContentBounds(overflow_size);
763 overflow->SetScrollable(true);
764 overflow->SetMaxScrollOffset(gfx::Vector2d(overflow_size.width(),
765 overflow_size.height()));
766 overflow->SetScrollOffset(gfx::Vector2d());
767 overflow->SetPosition(gfx::PointF());
768 overflow->SetAnchorPoint(gfx::PointF());
770 InitializeRendererAndDrawFrame();
771 gfx::Point scroll_position(10, 10);
773 EXPECT_EQ(InputHandler::ScrollStarted,
774 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
775 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
776 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->TotalScrollOffset());
778 gfx::Vector2dF scroll_delta(10, 10);
779 host_impl_->ScrollBy(scroll_position, scroll_delta);
780 host_impl_->ScrollEnd();
781 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
782 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
784 overflow->set_user_scrollable_horizontal(false);
786 EXPECT_EQ(InputHandler::ScrollStarted,
787 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
788 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
789 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
791 host_impl_->ScrollBy(scroll_position, scroll_delta);
792 host_impl_->ScrollEnd();
793 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
794 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
796 overflow->set_user_scrollable_vertical(false);
798 EXPECT_EQ(InputHandler::ScrollStarted,
799 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
800 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
801 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
803 host_impl_->ScrollBy(scroll_position, scroll_delta);
804 host_impl_->ScrollEnd();
805 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->TotalScrollOffset());
806 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
809 TEST_F(LayerTreeHostImplTest,
810 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
811 SetupScrollAndContentsLayers(gfx::Size(100, 100));
812 host_impl_->SetViewportSize(gfx::Size(50, 50));
813 InitializeRendererAndDrawFrame();
815 // We should be able to hit test for touch event handlers even if the root
816 // layer loses its render surface after the most recent render.
817 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
818 host_impl_->active_tree()->set_needs_update_draw_properties();
820 EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
823 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
824 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
825 host_impl_->SetViewportSize(gfx::Size(50, 50));
826 InitializeRendererAndDrawFrame();
828 EXPECT_EQ(scroll_layer, host_impl_->RootScrollLayer());
830 float min_page_scale = 1.f, max_page_scale = 4.f;
832 // The impl-based pinch zoom should adjust the max scroll position.
834 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
837 host_impl_->active_tree()->SetPageScaleDelta(1.f);
838 scroll_layer->SetScrollDelta(gfx::Vector2d());
840 float page_scale_delta = 2.f;
841 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
842 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
843 host_impl_->PinchGestureEnd();
844 host_impl_->ScrollEnd();
845 EXPECT_TRUE(did_request_redraw_);
846 EXPECT_TRUE(did_request_commit_);
848 scoped_ptr<ScrollAndScaleSet> scroll_info =
849 host_impl_->ProcessScrollDeltas();
850 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
852 EXPECT_EQ(gfx::Vector2d(75, 75).ToString(),
853 scroll_layer->max_scroll_offset().ToString());
856 // Scrolling after a pinch gesture should always be in local space. The
857 // scroll deltas do not have the page scale factor applied.
859 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
862 host_impl_->active_tree()->SetPageScaleDelta(1.f);
863 scroll_layer->SetScrollDelta(gfx::Vector2d());
865 float page_scale_delta = 2.f;
866 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
867 host_impl_->PinchGestureBegin();
868 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
869 host_impl_->PinchGestureEnd();
870 host_impl_->ScrollEnd();
872 gfx::Vector2d scroll_delta(0, 10);
873 EXPECT_EQ(InputHandler::ScrollStarted,
874 host_impl_->ScrollBegin(gfx::Point(5, 5),
875 InputHandler::Wheel));
876 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
877 host_impl_->ScrollEnd();
879 scoped_ptr<ScrollAndScaleSet> scroll_info =
880 host_impl_->ProcessScrollDeltas();
881 ExpectContains(*scroll_info.get(),
887 TEST_F(LayerTreeHostImplTest, PinchGesture) {
888 SetupScrollAndContentsLayers(gfx::Size(100, 100));
889 host_impl_->SetViewportSize(gfx::Size(50, 50));
890 InitializeRendererAndDrawFrame();
892 LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
893 DCHECK(scroll_layer);
895 float min_page_scale = 1.f;
896 float max_page_scale = 4.f;
898 // Basic pinch zoom in gesture
900 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
903 scroll_layer->SetScrollDelta(gfx::Vector2d());
905 float page_scale_delta = 2.f;
906 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
907 host_impl_->PinchGestureBegin();
908 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
909 host_impl_->PinchGestureEnd();
910 host_impl_->ScrollEnd();
911 EXPECT_TRUE(did_request_redraw_);
912 EXPECT_TRUE(did_request_commit_);
914 scoped_ptr<ScrollAndScaleSet> scroll_info =
915 host_impl_->ProcessScrollDeltas();
916 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
921 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
924 scroll_layer->SetScrollDelta(gfx::Vector2d());
925 float page_scale_delta = 10.f;
927 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
928 host_impl_->PinchGestureBegin();
929 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
930 host_impl_->PinchGestureEnd();
931 host_impl_->ScrollEnd();
933 scoped_ptr<ScrollAndScaleSet> scroll_info =
934 host_impl_->ProcessScrollDeltas();
935 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
940 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
943 scroll_layer->SetScrollDelta(gfx::Vector2d());
944 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
946 float page_scale_delta = 0.1f;
947 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
948 host_impl_->PinchGestureBegin();
949 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
950 host_impl_->PinchGestureEnd();
951 host_impl_->ScrollEnd();
953 scoped_ptr<ScrollAndScaleSet> scroll_info =
954 host_impl_->ProcessScrollDeltas();
955 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
957 EXPECT_TRUE(scroll_info->scrolls.empty());
960 // Two-finger panning should not happen based on pinch events only
962 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
965 scroll_layer->SetScrollDelta(gfx::Vector2d());
966 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
968 float page_scale_delta = 1.f;
969 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
970 host_impl_->PinchGestureBegin();
971 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
972 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
973 host_impl_->PinchGestureEnd();
974 host_impl_->ScrollEnd();
976 scoped_ptr<ScrollAndScaleSet> scroll_info =
977 host_impl_->ProcessScrollDeltas();
978 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
979 EXPECT_TRUE(scroll_info->scrolls.empty());
982 // Two-finger panning should work with interleaved scroll events
984 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
987 scroll_layer->SetScrollDelta(gfx::Vector2d());
988 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
990 float page_scale_delta = 1.f;
991 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
992 host_impl_->PinchGestureBegin();
993 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
994 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
995 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
996 host_impl_->PinchGestureEnd();
997 host_impl_->ScrollEnd();
999 scoped_ptr<ScrollAndScaleSet> scroll_info =
1000 host_impl_->ProcessScrollDeltas();
1001 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1002 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1005 // Two-finger panning should work when starting fully zoomed out.
1007 host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
1010 scroll_layer->SetScrollDelta(gfx::Vector2d());
1011 scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
1012 host_impl_->active_tree()->UpdateMaxScrollOffset();
1014 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
1015 host_impl_->PinchGestureBegin();
1016 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1017 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1018 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1019 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1020 host_impl_->PinchGestureEnd();
1021 host_impl_->ScrollEnd();
1023 scoped_ptr<ScrollAndScaleSet> scroll_info =
1024 host_impl_->ProcessScrollDeltas();
1025 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1026 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1030 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1031 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1032 host_impl_->SetViewportSize(gfx::Size(50, 50));
1033 InitializeRendererAndDrawFrame();
1035 LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
1036 DCHECK(scroll_layer);
1038 float min_page_scale = 0.5f;
1039 float max_page_scale = 4.f;
1040 base::TimeTicks start_time = base::TimeTicks() +
1041 base::TimeDelta::FromSeconds(1);
1042 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1043 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1044 base::TimeTicks end_time = start_time + duration;
1046 // Non-anchor zoom-in
1048 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1051 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1053 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), false, 2.f, duration);
1054 did_request_redraw_ = false;
1055 host_impl_->Animate(start_time, base::Time());
1056 EXPECT_TRUE(did_request_redraw_);
1058 did_request_redraw_ = false;
1059 host_impl_->Animate(halfway_through_animation, base::Time());
1060 EXPECT_TRUE(did_request_redraw_);
1062 did_request_redraw_ = false;
1063 did_request_commit_ = false;
1064 host_impl_->Animate(end_time, base::Time());
1065 EXPECT_TRUE(did_request_commit_);
1067 scoped_ptr<ScrollAndScaleSet> scroll_info =
1068 host_impl_->ProcessScrollDeltas();
1069 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1070 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1075 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1078 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1080 host_impl_->StartPageScaleAnimation(
1081 gfx::Vector2d(25, 25), true, min_page_scale, duration);
1082 did_request_redraw_ = false;
1083 host_impl_->Animate(start_time, base::Time());
1084 EXPECT_TRUE(did_request_redraw_);
1086 did_request_redraw_ = false;
1087 did_request_commit_ = false;
1088 host_impl_->Animate(end_time, base::Time());
1089 EXPECT_TRUE(did_request_redraw_);
1090 EXPECT_TRUE(did_request_commit_);
1092 scoped_ptr<ScrollAndScaleSet> scroll_info =
1093 host_impl_->ProcessScrollDeltas();
1094 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1095 // Pushed to (0,0) via clamping against contents layer size.
1096 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1100 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1101 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1102 host_impl_->SetViewportSize(gfx::Size(50, 50));
1103 InitializeRendererAndDrawFrame();
1105 LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
1106 DCHECK(scroll_layer);
1108 float min_page_scale = 0.5f;
1109 float max_page_scale = 4.f;
1110 base::TimeTicks start_time = base::TimeTicks() +
1111 base::TimeDelta::FromSeconds(1);
1112 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1113 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1114 base::TimeTicks end_time = start_time + duration;
1116 // Anchor zoom with unchanged page scale should not change scroll or scale.
1118 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1121 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1123 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), true, 1.f, duration);
1124 host_impl_->Animate(start_time, base::Time());
1125 host_impl_->Animate(halfway_through_animation, base::Time());
1126 EXPECT_TRUE(did_request_redraw_);
1127 host_impl_->Animate(end_time, base::Time());
1128 EXPECT_TRUE(did_request_commit_);
1130 scoped_ptr<ScrollAndScaleSet> scroll_info =
1131 host_impl_->ProcessScrollDeltas();
1132 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1133 ExpectNone(*scroll_info, scroll_layer->id());
1137 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1139 LayerTreeHostImplOverridePhysicalTime(
1140 const LayerTreeSettings& settings,
1141 LayerTreeHostImplClient* client,
1143 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1144 : LayerTreeHostImpl(settings,
1147 rendering_stats_instrumentation,
1150 virtual base::TimeTicks CurrentPhysicalTimeTicks() const OVERRIDE {
1151 return fake_current_physical_time_;
1154 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1155 fake_current_physical_time_ = fake_now;
1159 base::TimeTicks fake_current_physical_time_;
1162 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1163 LayerTreeSettings settings;
1164 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1165 settings.scrollbar_linear_fade_delay_ms = 20;
1166 settings.scrollbar_linear_fade_length_ms = 20;
1168 gfx::Size viewport_size(10, 10);
1169 gfx::Size content_size(100, 100);
1171 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
1172 new LayerTreeHostImplOverridePhysicalTime(
1173 settings, this, &proxy_, &stats_instrumentation_);
1174 host_impl_ = make_scoped_ptr<LayerTreeHostImpl>(host_impl_override_time);
1175 host_impl_->InitializeRenderer(CreateOutputSurface());
1176 host_impl_->SetViewportSize(viewport_size);
1178 scoped_ptr<LayerImpl> root =
1179 LayerImpl::Create(host_impl_->active_tree(), 1);
1180 root->SetBounds(viewport_size);
1182 scoped_ptr<LayerImpl> scroll =
1183 LayerImpl::Create(host_impl_->active_tree(), 2);
1184 scroll->SetScrollable(true);
1185 scroll->SetScrollOffset(gfx::Vector2d());
1186 scroll->SetMaxScrollOffset(gfx::Vector2d(content_size.width(),
1187 content_size.height()));
1188 scroll->SetBounds(content_size);
1189 scroll->SetContentBounds(content_size);
1191 scoped_ptr<LayerImpl> contents =
1192 LayerImpl::Create(host_impl_->active_tree(), 3);
1193 contents->SetDrawsContent(true);
1194 contents->SetBounds(content_size);
1195 contents->SetContentBounds(content_size);
1197 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1198 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 4, VERTICAL);
1199 scroll->SetVerticalScrollbarLayer(scrollbar.get());
1201 scroll->AddChild(contents.Pass());
1202 root->AddChild(scroll.Pass());
1203 root->AddChild(scrollbar.PassAs<LayerImpl>());
1205 host_impl_->active_tree()->SetRootLayer(root.Pass());
1206 host_impl_->active_tree()->DidBecomeActive();
1207 InitializeRendererAndDrawFrame();
1209 base::TimeTicks fake_now = gfx::FrameTime::Now();
1210 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1212 // If no scroll happened recently, StartScrollbarAnimation should have no
1214 host_impl_->StartScrollbarAnimation();
1215 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1216 EXPECT_FALSE(did_request_redraw_);
1218 // If no scroll happened during a scroll gesture, StartScrollbarAnimation
1219 // should have no effect.
1220 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1221 host_impl_->ScrollEnd();
1222 host_impl_->StartScrollbarAnimation();
1223 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1224 EXPECT_FALSE(did_request_redraw_);
1226 // After a scroll, a fade animation should be scheduled about 20ms from now.
1227 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1228 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1229 host_impl_->ScrollEnd();
1230 did_request_redraw_ = false;
1231 host_impl_->StartScrollbarAnimation();
1232 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1233 requested_scrollbar_animation_delay_);
1234 EXPECT_FALSE(did_request_redraw_);
1235 requested_scrollbar_animation_delay_ = base::TimeDelta();
1237 // After the fade begins, we should start getting redraws instead of a
1238 // scheduled animation.
1239 fake_now += base::TimeDelta::FromMilliseconds(25);
1240 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1241 host_impl_->StartScrollbarAnimation();
1242 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1243 EXPECT_TRUE(did_request_redraw_);
1244 did_request_redraw_ = false;
1246 // If no scroll happened recently, StartScrollbarAnimation should have no
1248 fake_now += base::TimeDelta::FromMilliseconds(25);
1249 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1250 host_impl_->StartScrollbarAnimation();
1251 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1252 EXPECT_FALSE(did_request_redraw_);
1254 // Setting the scroll offset outside a scroll should also cause the scrollbar
1255 // to appear and to schedule a fade.
1256 host_impl_->RootScrollLayer()->SetScrollOffset(gfx::Vector2d(5, 5));
1257 host_impl_->StartScrollbarAnimation();
1258 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1259 requested_scrollbar_animation_delay_);
1260 EXPECT_FALSE(did_request_redraw_);
1261 requested_scrollbar_animation_delay_ = base::TimeDelta();
1263 // None of the above should have called CurrentFrameTimeTicks, so if we call
1264 // it now we should get the current time.
1265 fake_now += base::TimeDelta::FromMilliseconds(10);
1266 host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
1267 EXPECT_EQ(fake_now, host_impl_->CurrentFrameTimeTicks());
1270 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1271 float device_scale_factor) {
1272 LayerTreeSettings settings;
1273 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1275 gfx::Size viewport_size(300, 200);
1276 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1277 gfx::ScaleSize(viewport_size, device_scale_factor));
1278 gfx::Size content_size(1000, 1000);
1280 host_impl_ = LayerTreeHostImpl::Create(
1281 settings, this, &proxy_, &stats_instrumentation_, NULL);
1282 host_impl_->InitializeRenderer(CreateOutputSurface());
1283 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1284 host_impl_->SetViewportSize(device_viewport_size);
1286 scoped_ptr<LayerImpl> root =
1287 LayerImpl::Create(host_impl_->active_tree(), 1);
1288 root->SetBounds(viewport_size);
1290 scoped_ptr<LayerImpl> scroll =
1291 LayerImpl::Create(host_impl_->active_tree(), 2);
1292 scroll->SetScrollable(true);
1293 scroll->SetScrollOffset(gfx::Vector2d());
1294 scroll->SetMaxScrollOffset(gfx::Vector2d(content_size.width(),
1295 content_size.height()));
1296 scroll->SetBounds(content_size);
1297 scroll->SetContentBounds(content_size);
1299 scoped_ptr<LayerImpl> contents =
1300 LayerImpl::Create(host_impl_->active_tree(), 3);
1301 contents->SetDrawsContent(true);
1302 contents->SetBounds(content_size);
1303 contents->SetContentBounds(content_size);
1305 // The scrollbar is on the right side.
1306 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1307 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1308 scrollbar->SetDrawsContent(true);
1309 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1310 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1311 scrollbar->SetPosition(gfx::Point(285, 0));
1312 scroll->SetVerticalScrollbarLayer(scrollbar.get());
1314 scroll->AddChild(contents.Pass());
1315 root->AddChild(scroll.Pass());
1316 root->AddChild(scrollbar.PassAs<LayerImpl>());
1318 host_impl_->active_tree()->SetRootLayer(root.Pass());
1319 host_impl_->active_tree()->DidBecomeActive();
1320 InitializeRendererAndDrawFrame();
1322 LayerImpl* root_scroll = host_impl_->active_tree()->RootScrollLayer();
1323 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1324 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1325 static_cast<ScrollbarAnimationControllerThinning*>(
1326 root_scroll->scrollbar_animation_controller());
1327 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1329 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1330 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1332 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1333 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1335 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1336 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1338 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1339 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1340 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1342 did_request_redraw_ = false;
1343 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1344 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1345 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1346 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1347 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1348 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1349 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1352 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1353 SetupMouseMoveAtWithDeviceScale(1.f);
1356 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1357 SetupMouseMoveAtWithDeviceScale(2.f);
1360 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1361 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1362 host_impl_->SetViewportSize(gfx::Size(50, 50));
1363 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
1364 InitializeRendererAndDrawFrame();
1366 CompositorFrameMetadata metadata =
1367 host_impl_->MakeCompositorFrameMetadata();
1368 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1369 EXPECT_EQ(1.f, metadata.page_scale_factor);
1370 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.viewport_size);
1371 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1372 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1373 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1376 // Scrolling should update metadata immediately.
1377 EXPECT_EQ(InputHandler::ScrollStarted,
1378 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1379 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1381 CompositorFrameMetadata metadata =
1382 host_impl_->MakeCompositorFrameMetadata();
1383 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1385 host_impl_->ScrollEnd();
1387 CompositorFrameMetadata metadata =
1388 host_impl_->MakeCompositorFrameMetadata();
1389 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1392 // Page scale should update metadata correctly (shrinking only the viewport).
1393 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1394 host_impl_->PinchGestureBegin();
1395 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1396 host_impl_->PinchGestureEnd();
1397 host_impl_->ScrollEnd();
1399 CompositorFrameMetadata metadata =
1400 host_impl_->MakeCompositorFrameMetadata();
1401 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1402 EXPECT_EQ(2.f, metadata.page_scale_factor);
1403 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.viewport_size);
1404 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1405 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1406 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1409 // Likewise if set from the main thread.
1410 host_impl_->ProcessScrollDeltas();
1411 host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
1412 host_impl_->active_tree()->SetPageScaleDelta(1.f);
1414 CompositorFrameMetadata metadata =
1415 host_impl_->MakeCompositorFrameMetadata();
1416 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1417 EXPECT_EQ(4.f, metadata.page_scale_factor);
1418 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.viewport_size);
1419 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1420 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1421 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1425 class DidDrawCheckLayer : public TiledLayerImpl {
1427 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1428 return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(tree_impl, id));
1431 virtual bool WillDraw(DrawMode draw_mode, ResourceProvider* provider)
1433 will_draw_called_ = true;
1434 if (will_draw_returns_false_)
1436 return TiledLayerImpl::WillDraw(draw_mode, provider);
1439 virtual void AppendQuads(QuadSink* quad_sink,
1440 AppendQuadsData* append_quads_data) OVERRIDE {
1441 append_quads_called_ = true;
1442 TiledLayerImpl::AppendQuads(quad_sink, append_quads_data);
1445 virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
1446 did_draw_called_ = true;
1447 TiledLayerImpl::DidDraw(provider);
1450 bool will_draw_called() const { return will_draw_called_; }
1451 bool append_quads_called() const { return append_quads_called_; }
1452 bool did_draw_called() const { return did_draw_called_; }
1454 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1456 void ClearDidDrawCheck() {
1457 will_draw_called_ = false;
1458 append_quads_called_ = false;
1459 did_draw_called_ = false;
1463 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1464 : TiledLayerImpl(tree_impl, id),
1465 will_draw_returns_false_(false),
1466 will_draw_called_(false),
1467 append_quads_called_(false),
1468 did_draw_called_(false) {
1469 SetAnchorPoint(gfx::PointF());
1470 SetBounds(gfx::Size(10, 10));
1471 SetContentBounds(gfx::Size(10, 10));
1472 SetDrawsContent(true);
1473 set_skips_draw(false);
1474 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1476 scoped_ptr<LayerTilingData> tiler =
1477 LayerTilingData::Create(gfx::Size(100, 100),
1478 LayerTilingData::HAS_BORDER_TEXELS);
1479 tiler->SetBounds(content_bounds());
1480 SetTilingData(*tiler.get());
1484 bool will_draw_returns_false_;
1485 bool will_draw_called_;
1486 bool append_quads_called_;
1487 bool did_draw_called_;
1490 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1491 // The root layer is always drawn, so run this test on a child layer that
1492 // will be masked out by the root layer's bounds.
1493 host_impl_->active_tree()->SetRootLayer(
1494 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1495 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1496 host_impl_->active_tree()->root_layer());
1498 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1499 DidDrawCheckLayer* layer =
1500 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1503 LayerTreeHostImpl::FrameData frame;
1504 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
1505 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1506 host_impl_->DidDrawAllLayers(frame);
1508 EXPECT_TRUE(layer->will_draw_called());
1509 EXPECT_TRUE(layer->append_quads_called());
1510 EXPECT_TRUE(layer->did_draw_called());
1514 LayerTreeHostImpl::FrameData frame;
1516 layer->set_will_draw_returns_false();
1517 layer->ClearDidDrawCheck();
1519 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
1520 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1521 host_impl_->DidDrawAllLayers(frame);
1523 EXPECT_TRUE(layer->will_draw_called());
1524 EXPECT_FALSE(layer->append_quads_called());
1525 EXPECT_FALSE(layer->did_draw_called());
1529 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1530 // The root layer is always drawn, so run this test on a child layer that
1531 // will be masked out by the root layer's bounds.
1532 host_impl_->active_tree()->SetRootLayer(
1533 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1534 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1535 host_impl_->active_tree()->root_layer());
1536 root->SetMasksToBounds(true);
1538 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1539 DidDrawCheckLayer* layer =
1540 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1541 // Ensure visible_content_rect for layer is empty.
1542 layer->SetPosition(gfx::PointF(100.f, 100.f));
1543 layer->SetBounds(gfx::Size(10, 10));
1544 layer->SetContentBounds(gfx::Size(10, 10));
1546 LayerTreeHostImpl::FrameData frame;
1548 EXPECT_FALSE(layer->will_draw_called());
1549 EXPECT_FALSE(layer->did_draw_called());
1551 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1552 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1553 host_impl_->DidDrawAllLayers(frame);
1555 EXPECT_FALSE(layer->will_draw_called());
1556 EXPECT_FALSE(layer->did_draw_called());
1558 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1560 // Ensure visible_content_rect for layer is not empty
1561 layer->SetPosition(gfx::PointF());
1563 EXPECT_FALSE(layer->will_draw_called());
1564 EXPECT_FALSE(layer->did_draw_called());
1566 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1567 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1568 host_impl_->DidDrawAllLayers(frame);
1570 EXPECT_TRUE(layer->will_draw_called());
1571 EXPECT_TRUE(layer->did_draw_called());
1573 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1576 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1577 gfx::Size big_size(1000, 1000);
1578 host_impl_->SetViewportSize(big_size);
1580 host_impl_->active_tree()->SetRootLayer(
1581 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1582 DidDrawCheckLayer* root =
1583 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1585 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1586 DidDrawCheckLayer* occluded_layer =
1587 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1589 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1590 DidDrawCheckLayer* top_layer =
1591 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1592 // This layer covers the occluded_layer above. Make this layer large so it can
1594 top_layer->SetBounds(big_size);
1595 top_layer->SetContentBounds(big_size);
1596 top_layer->SetContentsOpaque(true);
1598 LayerTreeHostImpl::FrameData frame;
1600 EXPECT_FALSE(occluded_layer->will_draw_called());
1601 EXPECT_FALSE(occluded_layer->did_draw_called());
1602 EXPECT_FALSE(top_layer->will_draw_called());
1603 EXPECT_FALSE(top_layer->did_draw_called());
1605 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1606 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1607 host_impl_->DidDrawAllLayers(frame);
1609 EXPECT_FALSE(occluded_layer->will_draw_called());
1610 EXPECT_FALSE(occluded_layer->did_draw_called());
1611 EXPECT_TRUE(top_layer->will_draw_called());
1612 EXPECT_TRUE(top_layer->did_draw_called());
1615 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1616 host_impl_->active_tree()->SetRootLayer(
1617 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1618 DidDrawCheckLayer* root =
1619 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1621 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1622 DidDrawCheckLayer* layer1 =
1623 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1625 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1626 DidDrawCheckLayer* layer2 =
1627 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1629 layer1->SetOpacity(0.3f);
1630 layer1->SetPreserves3d(false);
1632 EXPECT_FALSE(root->did_draw_called());
1633 EXPECT_FALSE(layer1->did_draw_called());
1634 EXPECT_FALSE(layer2->did_draw_called());
1636 LayerTreeHostImpl::FrameData frame;
1637 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1638 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1639 host_impl_->DidDrawAllLayers(frame);
1641 EXPECT_TRUE(root->did_draw_called());
1642 EXPECT_TRUE(layer1->did_draw_called());
1643 EXPECT_TRUE(layer2->did_draw_called());
1645 EXPECT_NE(root->render_surface(), layer1->render_surface());
1646 EXPECT_TRUE(!!layer1->render_surface());
1649 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1651 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1656 ResourceProvider* resource_provider) {
1657 return scoped_ptr<LayerImpl>(new MissingTextureAnimatingLayer(
1663 resource_provider));
1667 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1672 ResourceProvider* resource_provider)
1673 : DidDrawCheckLayer(tree_impl, id) {
1674 scoped_ptr<LayerTilingData> tiling_data =
1675 LayerTilingData::Create(gfx::Size(10, 10),
1676 LayerTilingData::NO_BORDER_TEXELS);
1677 tiling_data->SetBounds(bounds());
1678 SetTilingData(*tiling_data.get());
1679 set_skips_draw(skips_draw);
1680 if (!tile_missing) {
1681 ResourceProvider::ResourceId resource =
1682 resource_provider->CreateResource(gfx::Size(1, 1),
1684 ResourceProvider::TextureUsageAny,
1686 resource_provider->AllocateForTesting(resource);
1687 PushTileProperties(0, 0, resource, gfx::Rect(), false);
1690 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1694 TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
1695 // When the texture is not missing, we draw as usual.
1696 host_impl_->active_tree()->SetRootLayer(
1697 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1698 DidDrawCheckLayer* root =
1699 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1701 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1706 host_impl_->resource_provider()));
1708 LayerTreeHostImpl::FrameData frame;
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 not animating, we draw as usual with
1716 host_impl_->active_tree()->SetRootLayer(
1717 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1719 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1721 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1726 host_impl_->resource_provider()));
1728 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1729 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1730 host_impl_->DidDrawAllLayers(frame);
1732 // When a texture is missing and we're animating, we don't want to draw
1734 host_impl_->active_tree()->SetRootLayer(
1735 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
1737 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1739 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1744 host_impl_->resource_provider()));
1746 EXPECT_FALSE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1747 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1748 host_impl_->DidDrawAllLayers(frame);
1750 // When the layer skips draw and we're animating, we still draw the frame.
1751 host_impl_->active_tree()->SetRootLayer(
1752 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
1754 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1756 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1761 host_impl_->resource_provider()));
1763 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1764 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1765 host_impl_->DidDrawAllLayers(frame);
1768 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
1769 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1770 root->SetScrollable(false);
1771 host_impl_->active_tree()->SetRootLayer(root.Pass());
1772 InitializeRendererAndDrawFrame();
1774 // Scroll event is ignored because layer is not scrollable.
1775 EXPECT_EQ(InputHandler::ScrollIgnored,
1776 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1777 EXPECT_FALSE(did_request_redraw_);
1778 EXPECT_FALSE(did_request_commit_);
1781 TEST_F(LayerTreeHostImplTest, ScrollNonScrollableRootWithTopControls) {
1782 LayerTreeSettings settings;
1783 settings.calculate_top_controls_position = true;
1784 settings.top_controls_height = 50;
1786 host_impl_ = LayerTreeHostImpl::Create(
1787 settings, this, &proxy_, &stats_instrumentation_, NULL);
1788 host_impl_->InitializeRenderer(CreateOutputSurface());
1789 host_impl_->SetViewportSize(gfx::Size(10, 10));
1791 gfx::Size layer_size(5, 5);
1792 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1793 root->SetScrollable(true);
1794 root->SetMaxScrollOffset(gfx::Vector2d(layer_size.width(),
1795 layer_size.height()));
1796 root->SetBounds(layer_size);
1797 root->SetContentBounds(layer_size);
1798 root->SetPosition(gfx::PointF());
1799 root->SetAnchorPoint(gfx::PointF());
1800 root->SetDrawsContent(false);
1801 host_impl_->active_tree()->SetRootLayer(root.Pass());
1802 host_impl_->active_tree()->FindRootScrollLayer();
1803 InitializeRendererAndDrawFrame();
1805 EXPECT_EQ(InputHandler::ScrollIgnored,
1806 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
1808 host_impl_->top_controls_manager()->ScrollBegin();
1809 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
1810 host_impl_->top_controls_manager()->ScrollEnd();
1811 EXPECT_EQ(host_impl_->top_controls_manager()->content_top_offset(), 0.f);
1813 EXPECT_EQ(InputHandler::ScrollStarted,
1814 host_impl_->ScrollBegin(gfx::Point(),
1815 InputHandler::Gesture));
1818 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
1819 // Test the configuration where a non-composited root layer is embedded in a
1820 // scrollable outer layer.
1821 gfx::Size surface_size(10, 10);
1823 scoped_ptr<LayerImpl> content_layer =
1824 LayerImpl::Create(host_impl_->active_tree(), 1);
1825 content_layer->SetDrawsContent(true);
1826 content_layer->SetPosition(gfx::PointF());
1827 content_layer->SetAnchorPoint(gfx::PointF());
1828 content_layer->SetBounds(surface_size);
1829 content_layer->SetContentBounds(gfx::Size(surface_size.width() * 2,
1830 surface_size.height() * 2));
1831 content_layer->SetContentsScale(2.f, 2.f);
1833 scoped_ptr<LayerImpl> scroll_layer =
1834 LayerImpl::Create(host_impl_->active_tree(), 2);
1835 scroll_layer->SetScrollable(true);
1836 scroll_layer->SetMaxScrollOffset(gfx::Vector2d(surface_size.width(),
1837 surface_size.height()));
1838 scroll_layer->SetBounds(surface_size);
1839 scroll_layer->SetContentBounds(surface_size);
1840 scroll_layer->SetPosition(gfx::PointF());
1841 scroll_layer->SetAnchorPoint(gfx::PointF());
1842 scroll_layer->AddChild(content_layer.Pass());
1844 host_impl_->active_tree()->SetRootLayer(scroll_layer.Pass());
1845 host_impl_->SetViewportSize(surface_size);
1846 InitializeRendererAndDrawFrame();
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, ScrollChildCallsCommitAndRedraw) {
1858 gfx::Size surface_size(10, 10);
1859 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1860 root->SetBounds(surface_size);
1861 root->SetContentBounds(surface_size);
1862 root->AddChild(CreateScrollableLayer(2, surface_size));
1863 host_impl_->active_tree()->SetRootLayer(root.Pass());
1864 host_impl_->SetViewportSize(surface_size);
1865 InitializeRendererAndDrawFrame();
1867 EXPECT_EQ(InputHandler::ScrollStarted,
1868 host_impl_->ScrollBegin(gfx::Point(5, 5),
1869 InputHandler::Wheel));
1870 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1871 host_impl_->ScrollEnd();
1872 EXPECT_TRUE(did_request_redraw_);
1873 EXPECT_TRUE(did_request_commit_);
1876 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
1877 gfx::Size surface_size(10, 10);
1878 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1879 root->AddChild(CreateScrollableLayer(2, surface_size));
1880 host_impl_->active_tree()->SetRootLayer(root.Pass());
1881 host_impl_->SetViewportSize(surface_size);
1882 InitializeRendererAndDrawFrame();
1884 // Scroll event is ignored because the input coordinate is outside the layer
1886 EXPECT_EQ(InputHandler::ScrollIgnored,
1887 host_impl_->ScrollBegin(gfx::Point(15, 5),
1888 InputHandler::Wheel));
1889 EXPECT_FALSE(did_request_redraw_);
1890 EXPECT_FALSE(did_request_commit_);
1893 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
1894 gfx::Size surface_size(10, 10);
1895 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1896 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, surface_size);
1897 host_impl_->SetViewportSize(surface_size);
1899 gfx::Transform matrix;
1900 matrix.RotateAboutXAxis(180.0);
1901 child->SetTransform(matrix);
1902 child->SetDoubleSided(false);
1904 root->AddChild(child.Pass());
1905 host_impl_->active_tree()->SetRootLayer(root.Pass());
1906 InitializeRendererAndDrawFrame();
1908 // Scroll event is ignored because the scrollable layer is not facing the
1909 // viewer and there is nothing scrollable behind it.
1910 EXPECT_EQ(InputHandler::ScrollIgnored,
1911 host_impl_->ScrollBegin(gfx::Point(5, 5),
1912 InputHandler::Wheel));
1913 EXPECT_FALSE(did_request_redraw_);
1914 EXPECT_FALSE(did_request_commit_);
1917 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
1918 gfx::Size surface_size(10, 10);
1919 scoped_ptr<LayerImpl> content_layer = CreateScrollableLayer(1, surface_size);
1920 content_layer->SetShouldScrollOnMainThread(true);
1921 content_layer->SetScrollable(false);
1923 scoped_ptr<LayerImpl> scroll_layer = CreateScrollableLayer(2, surface_size);
1924 scroll_layer->AddChild(content_layer.Pass());
1926 host_impl_->active_tree()->SetRootLayer(scroll_layer.Pass());
1927 host_impl_->SetViewportSize(surface_size);
1928 InitializeRendererAndDrawFrame();
1930 // Scrolling fails because the content layer is asking to be scrolled on the
1932 EXPECT_EQ(InputHandler::ScrollOnMainThread,
1933 host_impl_->ScrollBegin(gfx::Point(5, 5),
1934 InputHandler::Wheel));
1937 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
1938 gfx::Size surface_size(10, 10);
1939 float page_scale = 2.f;
1940 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1941 scoped_ptr<LayerImpl> root_scrolling = CreateScrollableLayer(2, surface_size);
1942 root->AddChild(root_scrolling.Pass());
1943 host_impl_->active_tree()->SetRootLayer(root.Pass());
1944 host_impl_->active_tree()->DidBecomeActive();
1945 host_impl_->SetViewportSize(surface_size);
1946 InitializeRendererAndDrawFrame();
1948 LayerImpl* root_scroll = host_impl_->active_tree()->RootScrollLayer();
1950 gfx::Vector2d scroll_delta(0, 10);
1951 gfx::Vector2d expected_scroll_delta = scroll_delta;
1952 gfx::Vector2d expected_max_scroll = root_scroll->max_scroll_offset();
1953 EXPECT_EQ(InputHandler::ScrollStarted,
1954 host_impl_->ScrollBegin(gfx::Point(5, 5),
1955 InputHandler::Wheel));
1956 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
1957 host_impl_->ScrollEnd();
1959 // Set new page scale from main thread.
1960 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
1964 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
1965 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
1967 // The scroll range should also have been updated.
1968 EXPECT_EQ(expected_max_scroll, root_scroll->max_scroll_offset());
1970 // The page scale delta remains constant because the impl thread did not
1972 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
1975 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
1976 gfx::Size surface_size(10, 10);
1977 float page_scale = 2.f;
1978 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
1979 scoped_ptr<LayerImpl> root_scrolling = CreateScrollableLayer(2, surface_size);
1980 root->AddChild(root_scrolling.Pass());
1981 host_impl_->active_tree()->SetRootLayer(root.Pass());
1982 host_impl_->active_tree()->DidBecomeActive();
1983 host_impl_->SetViewportSize(surface_size);
1984 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
1985 InitializeRendererAndDrawFrame();
1987 LayerImpl* root_scroll = host_impl_->active_tree()->RootScrollLayer();
1989 gfx::Vector2d scroll_delta(0, 10);
1990 gfx::Vector2d expected_scroll_delta = scroll_delta;
1991 gfx::Vector2d expected_max_scroll = root_scroll->max_scroll_offset();
1992 EXPECT_EQ(InputHandler::ScrollStarted,
1993 host_impl_->ScrollBegin(gfx::Point(5, 5),
1994 InputHandler::Wheel));
1995 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
1996 host_impl_->ScrollEnd();
1998 // Set new page scale on impl thread by pinching.
1999 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2000 host_impl_->PinchGestureBegin();
2001 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
2002 host_impl_->PinchGestureEnd();
2003 host_impl_->ScrollEnd();
2006 // The scroll delta is not scaled because the main thread did not scale.
2007 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2008 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2010 // The scroll range should also have been updated.
2011 EXPECT_EQ(expected_max_scroll, root_scroll->max_scroll_offset());
2013 // The page scale delta should match the new scale on the impl side.
2014 EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
2017 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
2018 gfx::Size surface_size(10, 10);
2019 float default_page_scale = 1.f;
2020 gfx::Transform default_page_scale_matrix;
2021 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
2023 float new_page_scale = 2.f;
2024 gfx::Transform new_page_scale_matrix;
2025 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
2027 // Create a normal scrollable root layer and another scrollable child layer.
2028 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
2029 LayerImpl* root = host_impl_->active_tree()->root_layer();
2030 LayerImpl* child = scroll->children()[0];
2032 scoped_ptr<LayerImpl> scrollable_child =
2033 CreateScrollableLayer(4, surface_size);
2034 child->AddChild(scrollable_child.Pass());
2035 LayerImpl* grand_child = child->children()[0];
2037 // Set new page scale on impl thread by pinching.
2038 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2039 host_impl_->PinchGestureBegin();
2040 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
2041 host_impl_->PinchGestureEnd();
2042 host_impl_->ScrollEnd();
2045 EXPECT_EQ(1.f, root->contents_scale_x());
2046 EXPECT_EQ(1.f, root->contents_scale_y());
2047 EXPECT_EQ(1.f, scroll->contents_scale_x());
2048 EXPECT_EQ(1.f, scroll->contents_scale_y());
2049 EXPECT_EQ(1.f, child->contents_scale_x());
2050 EXPECT_EQ(1.f, child->contents_scale_y());
2051 EXPECT_EQ(1.f, grand_child->contents_scale_x());
2052 EXPECT_EQ(1.f, grand_child->contents_scale_y());
2054 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
2055 // the page scale delta on the root layer is applied hierarchically.
2056 LayerTreeHostImpl::FrameData frame;
2057 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2058 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2059 host_impl_->DidDrawAllLayers(frame);
2061 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
2062 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
2063 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
2064 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
2065 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
2066 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
2067 EXPECT_EQ(new_page_scale,
2068 grand_child->draw_transform().matrix().getDouble(0, 0));
2069 EXPECT_EQ(new_page_scale,
2070 grand_child->draw_transform().matrix().getDouble(1, 1));
2073 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
2074 gfx::Size surface_size(10, 10);
2075 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2076 scoped_ptr<LayerImpl> root_scrolling =
2077 LayerImpl::Create(host_impl_->active_tree(), 2);
2078 root_scrolling->SetBounds(surface_size);
2079 root_scrolling->SetContentBounds(surface_size);
2080 root_scrolling->SetScrollable(true);
2081 root->AddChild(root_scrolling.Pass());
2082 int child_scroll_layer_id = 3;
2083 scoped_ptr<LayerImpl> child_scrolling =
2084 CreateScrollableLayer(child_scroll_layer_id, surface_size);
2085 LayerImpl* child = child_scrolling.get();
2086 root->AddChild(child_scrolling.Pass());
2087 host_impl_->active_tree()->SetRootLayer(root.Pass());
2088 host_impl_->active_tree()->DidBecomeActive();
2089 host_impl_->SetViewportSize(surface_size);
2090 InitializeRendererAndDrawFrame();
2092 gfx::Vector2d scroll_delta(0, 10);
2093 gfx::Vector2d expected_scroll_delta(scroll_delta);
2094 gfx::Vector2d expected_max_scroll(child->max_scroll_offset());
2095 EXPECT_EQ(InputHandler::ScrollStarted,
2096 host_impl_->ScrollBegin(gfx::Point(5, 5),
2097 InputHandler::Wheel));
2098 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2099 host_impl_->ScrollEnd();
2101 float page_scale = 2.f;
2102 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2108 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2110 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
2112 // The scroll range should not have changed.
2113 EXPECT_EQ(child->max_scroll_offset(), expected_max_scroll);
2115 // The page scale delta remains constant because the impl thread did not
2117 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2120 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
2121 // Scroll a child layer beyond its maximum scroll range and make sure the
2122 // parent layer is scrolled on the axis on which the child was unable to
2124 gfx::Size surface_size(10, 10);
2125 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, surface_size);
2127 scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(3, surface_size);
2128 grand_child->SetScrollOffset(gfx::Vector2d(0, 5));
2130 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, surface_size);
2131 child->SetScrollOffset(gfx::Vector2d(3, 0));
2132 child->AddChild(grand_child.Pass());
2134 root->AddChild(child.Pass());
2135 host_impl_->active_tree()->SetRootLayer(root.Pass());
2136 host_impl_->active_tree()->DidBecomeActive();
2137 host_impl_->SetViewportSize(surface_size);
2138 InitializeRendererAndDrawFrame();
2140 gfx::Vector2d scroll_delta(-8, -7);
2141 EXPECT_EQ(InputHandler::ScrollStarted,
2142 host_impl_->ScrollBegin(gfx::Point(),
2143 InputHandler::Wheel));
2144 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2145 host_impl_->ScrollEnd();
2147 scoped_ptr<ScrollAndScaleSet> scroll_info =
2148 host_impl_->ProcessScrollDeltas();
2150 // The grand child should have scrolled up to its limit.
2151 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2152 LayerImpl* grand_child = child->children()[0];
2153 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
2155 // The child should have only scrolled on the other axis.
2156 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
2160 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
2161 // Scroll a child layer beyond its maximum scroll range and make sure the
2162 // the scroll doesn't bubble up to the parent layer.
2163 gfx::Size surface_size(10, 10);
2164 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2165 scoped_ptr<LayerImpl> root_scrolling = CreateScrollableLayer(2, surface_size);
2167 scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(4, surface_size);
2168 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
2170 scoped_ptr<LayerImpl> child = CreateScrollableLayer(3, surface_size);
2171 child->SetScrollOffset(gfx::Vector2d(0, 3));
2172 child->AddChild(grand_child.Pass());
2174 root_scrolling->AddChild(child.Pass());
2175 root->AddChild(root_scrolling.Pass());
2176 host_impl_->active_tree()->SetRootLayer(root.Pass());
2177 host_impl_->active_tree()->DidBecomeActive();
2178 host_impl_->SetViewportSize(surface_size);
2179 InitializeRendererAndDrawFrame();
2181 gfx::Vector2d scroll_delta(0, -10);
2182 EXPECT_EQ(InputHandler::ScrollStarted,
2183 host_impl_->ScrollBegin(gfx::Point(),
2184 InputHandler::NonBubblingGesture));
2185 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2186 host_impl_->ScrollEnd();
2188 scoped_ptr<ScrollAndScaleSet> scroll_info =
2189 host_impl_->ProcessScrollDeltas();
2191 // The grand child should have scrolled up to its limit.
2193 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
2194 LayerImpl* grand_child = child->children()[0];
2195 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2197 // The child should not have scrolled.
2198 ExpectNone(*scroll_info.get(), child->id());
2200 // The next time we scroll we should only scroll the parent.
2201 scroll_delta = gfx::Vector2d(0, -3);
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(), child);
2208 host_impl_->ScrollEnd();
2210 scroll_info = host_impl_->ProcessScrollDeltas();
2212 // The child should have scrolled up to its limit.
2213 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2215 // The grand child should not have scrolled.
2216 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2218 // After scrolling the parent, another scroll on the opposite direction
2219 // should still scroll the child.
2220 scroll_delta = gfx::Vector2d(0, 7);
2221 EXPECT_EQ(InputHandler::ScrollStarted,
2222 host_impl_->ScrollBegin(gfx::Point(5, 5),
2223 InputHandler::NonBubblingGesture));
2224 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2225 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2226 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2227 host_impl_->ScrollEnd();
2229 scroll_info = host_impl_->ProcessScrollDeltas();
2231 // The grand child should have scrolled.
2232 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
2234 // The child should not have scrolled.
2235 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2238 // Scrolling should be adjusted from viewport space.
2239 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
2240 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2242 scroll_delta = gfx::Vector2d(0, -2);
2243 EXPECT_EQ(InputHandler::ScrollStarted,
2244 host_impl_->ScrollBegin(gfx::Point(1, 1),
2245 InputHandler::NonBubblingGesture));
2246 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
2247 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2248 host_impl_->ScrollEnd();
2250 scroll_info = host_impl_->ProcessScrollDeltas();
2252 // Should have scrolled by half the amount in layer space (5 - 2/2)
2253 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
2257 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
2258 // When we try to scroll a non-scrollable child layer, the scroll delta
2259 // should be applied to one of its ancestors if possible.
2260 gfx::Size surface_size(10, 10);
2261 gfx::Size content_size(20, 20);
2262 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
2263 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
2265 child->SetScrollable(false);
2266 root->AddChild(child.Pass());
2268 host_impl_->SetViewportSize(surface_size);
2269 host_impl_->active_tree()->SetRootLayer(root.Pass());
2270 host_impl_->active_tree()->DidBecomeActive();
2271 InitializeRendererAndDrawFrame();
2273 gfx::Vector2d scroll_delta(0, 4);
2274 EXPECT_EQ(InputHandler::ScrollStarted,
2275 host_impl_->ScrollBegin(gfx::Point(5, 5),
2276 InputHandler::Wheel));
2277 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2278 host_impl_->ScrollEnd();
2280 scoped_ptr<ScrollAndScaleSet> scroll_info =
2281 host_impl_->ProcessScrollDeltas();
2283 // Only the root should have scrolled.
2284 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
2285 ExpectContains(*scroll_info.get(),
2286 host_impl_->active_tree()->root_layer()->id(),
2291 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
2292 gfx::Size surface_size(10, 10);
2293 host_impl_->active_tree()->SetRootLayer(
2294 CreateScrollableLayer(1, surface_size));
2295 host_impl_->active_tree()->DidBecomeActive();
2296 host_impl_->SetViewportSize(surface_size);
2298 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
2300 InitializeRendererAndDrawFrame();
2301 host_impl_->active_tree()->DetachLayerTree();
2302 host_impl_->active_tree()->SetRootLayer(
2303 CreateScrollableLayer(2, surface_size));
2304 host_impl_->active_tree()->DidBecomeActive();
2306 // Scrolling should still work even though we did not draw yet.
2307 EXPECT_EQ(InputHandler::ScrollStarted,
2308 host_impl_->ScrollBegin(gfx::Point(5, 5),
2309 InputHandler::Wheel));
2312 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
2313 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2315 // Rotate the root layer 90 degrees counter-clockwise about its center.
2316 gfx::Transform rotate_transform;
2317 rotate_transform.Rotate(-90.0);
2318 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
2320 gfx::Size surface_size(50, 50);
2321 host_impl_->SetViewportSize(surface_size);
2322 InitializeRendererAndDrawFrame();
2324 // Scroll to the right in screen coordinates with a gesture.
2325 gfx::Vector2d gesture_scroll_delta(10, 0);
2326 EXPECT_EQ(InputHandler::ScrollStarted,
2327 host_impl_->ScrollBegin(gfx::Point(),
2328 InputHandler::Gesture));
2329 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2330 host_impl_->ScrollEnd();
2332 // The layer should have scrolled down in its local coordinates.
2333 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2334 ExpectContains(*scroll_info.get(),
2336 gfx::Vector2d(0, gesture_scroll_delta.x()));
2338 // Reset and scroll down with the wheel.
2339 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2340 gfx::Vector2d wheel_scroll_delta(0, 10);
2341 EXPECT_EQ(InputHandler::ScrollStarted,
2342 host_impl_->ScrollBegin(gfx::Point(),
2343 InputHandler::Wheel));
2344 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2345 host_impl_->ScrollEnd();
2347 // The layer should have scrolled down in its local coordinates.
2348 scroll_info = host_impl_->ProcessScrollDeltas();
2349 ExpectContains(*scroll_info.get(),
2351 wheel_scroll_delta);
2354 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
2355 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2356 int child_layer_id = 4;
2357 float child_layer_angle = -20.f;
2359 // Create a child layer that is rotated to a non-axis-aligned angle.
2360 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
2362 scroll_layer->content_bounds());
2363 gfx::Transform rotate_transform;
2364 rotate_transform.Translate(-50.0, -50.0);
2365 rotate_transform.Rotate(child_layer_angle);
2366 rotate_transform.Translate(50.0, 50.0);
2367 child->SetTransform(rotate_transform);
2369 // Only allow vertical scrolling.
2370 child->SetMaxScrollOffset(gfx::Vector2d(0, child->content_bounds().height()));
2371 scroll_layer->AddChild(child.Pass());
2373 gfx::Size surface_size(50, 50);
2374 host_impl_->SetViewportSize(surface_size);
2375 InitializeRendererAndDrawFrame();
2377 // Scroll down in screen coordinates with a gesture.
2378 gfx::Vector2d gesture_scroll_delta(0, 10);
2379 EXPECT_EQ(InputHandler::ScrollStarted,
2380 host_impl_->ScrollBegin(gfx::Point(1, 1),
2381 InputHandler::Gesture));
2382 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2383 host_impl_->ScrollEnd();
2385 // The child layer should have scrolled down in its local coordinates an
2386 // amount proportional to the angle between it and the input scroll delta.
2387 gfx::Vector2d expected_scroll_delta(
2389 gesture_scroll_delta.y() *
2390 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
2391 scoped_ptr<ScrollAndScaleSet> scroll_info =
2392 host_impl_->ProcessScrollDeltas();
2393 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2395 // The root scroll layer should not have scrolled, because the input delta
2396 // was close to the layer's axis of movement.
2397 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
2400 // Now reset and scroll the same amount horizontally.
2401 scroll_layer->children()[1]->SetScrollDelta(
2403 gfx::Vector2d gesture_scroll_delta(10, 0);
2404 EXPECT_EQ(InputHandler::ScrollStarted,
2405 host_impl_->ScrollBegin(gfx::Point(1, 1),
2406 InputHandler::Gesture));
2407 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2408 host_impl_->ScrollEnd();
2410 // The child layer should have scrolled down in its local coordinates an
2411 // amount proportional to the angle between it and the input scroll delta.
2412 gfx::Vector2d expected_scroll_delta(
2414 -gesture_scroll_delta.x() *
2415 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
2416 scoped_ptr<ScrollAndScaleSet> scroll_info =
2417 host_impl_->ProcessScrollDeltas();
2418 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2420 // The root scroll layer should have scrolled more, since the input scroll
2421 // delta was mostly orthogonal to the child layer's vertical scroll axis.
2422 gfx::Vector2d expected_root_scroll_delta(
2423 gesture_scroll_delta.x() *
2424 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
2426 ExpectContains(*scroll_info.get(),
2428 expected_root_scroll_delta);
2432 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
2433 LayerImpl* scroll_layer =
2434 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2436 // Scale the layer to twice its normal size.
2438 gfx::Transform scale_transform;
2439 scale_transform.Scale(scale, scale);
2440 scroll_layer->SetTransform(scale_transform);
2442 gfx::Size surface_size(50, 50);
2443 host_impl_->SetViewportSize(surface_size);
2444 InitializeRendererAndDrawFrame();
2446 // Scroll down in screen coordinates with a gesture.
2447 gfx::Vector2d scroll_delta(0, 10);
2448 EXPECT_EQ(InputHandler::ScrollStarted,
2449 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2450 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2451 host_impl_->ScrollEnd();
2453 // The layer should have scrolled down in its local coordinates, but half the
2455 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2456 ExpectContains(*scroll_info.get(),
2458 gfx::Vector2d(0, scroll_delta.y() / scale));
2460 // Reset and scroll down with the wheel.
2461 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2462 gfx::Vector2d wheel_scroll_delta(0, 10);
2463 EXPECT_EQ(InputHandler::ScrollStarted,
2464 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2465 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2466 host_impl_->ScrollEnd();
2468 // The scale should not have been applied to the scroll delta.
2469 scroll_info = host_impl_->ProcessScrollDeltas();
2470 ExpectContains(*scroll_info.get(),
2472 wheel_scroll_delta);
2475 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
2477 TestScrollOffsetDelegate() : page_scale_factor_(0.f) {}
2479 virtual ~TestScrollOffsetDelegate() {}
2481 virtual void SetMaxScrollOffset(gfx::Vector2dF max_scroll_offset) OVERRIDE {
2482 max_scroll_offset_ = max_scroll_offset;
2485 virtual void SetTotalScrollOffset(gfx::Vector2dF new_value) OVERRIDE {
2486 last_set_scroll_offset_ = new_value;
2489 virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
2490 return getter_return_value_;
2493 virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
2495 virtual void SetTotalPageScaleFactor(float page_scale_factor) OVERRIDE {
2496 page_scale_factor_ = page_scale_factor;
2499 virtual void SetScrollableSize(gfx::SizeF scrollable_size) OVERRIDE {
2500 scrollable_size_ = scrollable_size;
2503 gfx::Vector2dF last_set_scroll_offset() {
2504 return last_set_scroll_offset_;
2507 void set_getter_return_value(gfx::Vector2dF value) {
2508 getter_return_value_ = value;
2511 gfx::Vector2dF max_scroll_offset() const {
2512 return max_scroll_offset_;
2515 gfx::SizeF scrollable_size() const {
2516 return scrollable_size_;
2519 float page_scale_factor() const {
2520 return page_scale_factor_;
2524 gfx::Vector2dF last_set_scroll_offset_;
2525 gfx::Vector2dF getter_return_value_;
2526 gfx::Vector2dF max_scroll_offset_;
2527 gfx::SizeF scrollable_size_;
2528 float page_scale_factor_;
2531 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
2532 TestScrollOffsetDelegate scroll_delegate;
2533 host_impl_->SetViewportSize(gfx::Size(10, 20));
2534 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2536 // Setting the delegate results in the current scroll offset being set.
2537 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
2538 scroll_layer->SetScrollOffset(gfx::Vector2d());
2539 scroll_layer->SetScrollDelta(initial_scroll_delta);
2540 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
2541 EXPECT_EQ(initial_scroll_delta.ToString(),
2542 scroll_delegate.last_set_scroll_offset().ToString());
2544 // Setting the delegate results in the scrollable_size, max_scroll_offset and
2545 // page_scale being set.
2546 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
2547 EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
2548 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
2550 // Updating page scale immediately updates the delegate.
2551 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
2552 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
2553 host_impl_->active_tree()->SetPageScaleDelta(1.5f);
2554 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
2555 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2556 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
2557 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
2559 // Scrolling should be relative to the offset as returned by the delegate.
2560 gfx::Vector2dF scroll_delta(0.f, 10.f);
2561 gfx::Vector2dF current_offset(7.f, 8.f);
2563 scroll_delegate.set_getter_return_value(current_offset);
2564 EXPECT_EQ(InputHandler::ScrollStarted,
2565 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2567 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2568 EXPECT_EQ(current_offset + scroll_delta,
2569 scroll_delegate.last_set_scroll_offset());
2571 current_offset = gfx::Vector2dF(42.f, 41.f);
2572 scroll_delegate.set_getter_return_value(current_offset);
2573 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2574 EXPECT_EQ(current_offset + scroll_delta,
2575 scroll_delegate.last_set_scroll_offset());
2576 host_impl_->ScrollEnd();
2578 // Forces a full tree synchronization and ensures that the scroll delegate
2579 // sees the correct size of the new tree.
2580 gfx::Size new_size(42, 24);
2581 host_impl_->CreatePendingTree();
2582 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
2583 host_impl_->ActivatePendingTree();
2584 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
2586 // Un-setting the delegate should propagate the delegate's current offset to
2587 // the root scrollable layer.
2588 current_offset = gfx::Vector2dF(13.f, 12.f);
2589 scroll_delegate.set_getter_return_value(current_offset);
2590 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
2592 EXPECT_EQ(current_offset.ToString(),
2593 scroll_layer->TotalScrollOffset().ToString());
2596 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
2597 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2598 host_impl_->SetViewportSize(gfx::Size(50, 50));
2599 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
2600 InitializeRendererAndDrawFrame();
2601 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2602 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2604 // In-bounds scrolling does not affect overscroll.
2605 EXPECT_EQ(InputHandler::ScrollStarted,
2606 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2607 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2608 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2609 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2611 // Overscroll events are reflected immediately.
2612 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
2613 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
2614 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2616 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
2617 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
2618 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
2619 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
2620 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
2621 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
2622 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
2623 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
2624 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
2625 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
2626 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
2627 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
2628 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
2630 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
2631 // as no scroll occurs.
2632 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
2633 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
2634 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
2635 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
2636 // Overscroll resets on valid scroll.
2637 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2638 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
2639 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
2640 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
2641 host_impl_->ScrollEnd();
2643 EXPECT_EQ(InputHandler::ScrollStarted,
2644 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2645 // Fling velocity is reflected immediately.
2646 host_impl_->NotifyCurrentFlingVelocity(gfx::Vector2dF(10, 0));
2647 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
2648 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
2649 EXPECT_EQ(gfx::Vector2dF(0, -20), host_impl_->accumulated_root_overscroll());
2650 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
2654 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
2655 // Scroll child layers beyond their maximum scroll range and make sure root
2656 // overscroll does not accumulate.
2657 gfx::Size surface_size(10, 10);
2658 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, surface_size);
2660 scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(3, surface_size);
2661 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
2663 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, surface_size);
2664 child->SetScrollOffset(gfx::Vector2d(0, 3));
2665 child->AddChild(grand_child.Pass());
2667 root->AddChild(child.Pass());
2668 host_impl_->active_tree()->SetRootLayer(root.Pass());
2669 host_impl_->active_tree()->DidBecomeActive();
2670 host_impl_->SetViewportSize(surface_size);
2671 InitializeRendererAndDrawFrame();
2673 gfx::Vector2d scroll_delta(0, -10);
2674 EXPECT_EQ(InputHandler::ScrollStarted,
2675 host_impl_->ScrollBegin(gfx::Point(),
2676 InputHandler::NonBubblingGesture));
2677 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2678 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2679 host_impl_->ScrollEnd();
2681 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2682 LayerImpl* grand_child = child->children()[0];
2684 // The next time we scroll we should only scroll the parent, but overscroll
2685 // should still not reach the root layer.
2686 scroll_delta = gfx::Vector2d(0, -30);
2687 EXPECT_EQ(InputHandler::ScrollStarted,
2688 host_impl_->ScrollBegin(gfx::Point(5, 5),
2689 InputHandler::NonBubblingGesture));
2690 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2691 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2692 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2693 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
2694 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2695 host_impl_->ScrollEnd();
2697 // After scrolling the parent, another scroll on the opposite direction
2698 // should scroll the child, resetting the fling velocity.
2699 scroll_delta = gfx::Vector2d(0, 70);
2700 host_impl_->NotifyCurrentFlingVelocity(gfx::Vector2dF(10, 0));
2701 EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
2702 EXPECT_EQ(InputHandler::ScrollStarted,
2703 host_impl_->ScrollBegin(gfx::Point(5, 5),
2704 InputHandler::NonBubblingGesture));
2705 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2706 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2707 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2708 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2709 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2710 host_impl_->ScrollEnd();
2714 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
2715 // When we try to scroll a non-scrollable child layer, the scroll delta
2716 // should be applied to one of its ancestors if possible. Overscroll should
2717 // be reflected only when it has bubbled up to the root scrolling layer.
2718 gfx::Size surface_size(10, 10);
2719 gfx::Size content_size(20, 20);
2720 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
2721 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
2723 child->SetScrollable(false);
2724 root->AddChild(child.Pass());
2726 host_impl_->SetViewportSize(surface_size);
2727 host_impl_->active_tree()->SetRootLayer(root.Pass());
2728 host_impl_->active_tree()->DidBecomeActive();
2729 InitializeRendererAndDrawFrame();
2731 gfx::Vector2d scroll_delta(0, 8);
2732 EXPECT_EQ(InputHandler::ScrollStarted,
2733 host_impl_->ScrollBegin(gfx::Point(5, 5),
2734 InputHandler::Wheel));
2735 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2736 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2737 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2738 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
2739 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2740 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
2741 host_impl_->ScrollEnd();
2745 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
2746 LayerTreeSettings settings;
2747 settings.always_overscroll = true;
2748 host_impl_ = LayerTreeHostImpl::Create(
2749 settings, this, &proxy_, &stats_instrumentation_, NULL);
2751 SetupScrollAndContentsLayers(gfx::Size(50, 50));
2752 host_impl_->SetViewportSize(gfx::Size(50, 50));
2753 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
2754 InitializeRendererAndDrawFrame();
2755 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
2756 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2758 // Even though the layer can't scroll the overscroll still happens.
2759 EXPECT_EQ(InputHandler::ScrollStarted,
2760 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2761 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2762 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
2763 EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
2766 class BlendStateTrackerContext: public TestWebGraphicsContext3D {
2768 BlendStateTrackerContext() : blend_(false) {}
2770 virtual void enable(WebKit::WGC3Denum cap) OVERRIDE {
2771 if (cap == GL_BLEND)
2775 virtual void disable(WebKit::WGC3Denum cap) OVERRIDE {
2776 if (cap == GL_BLEND)
2780 bool blend() const { return blend_; }
2786 class BlendStateCheckLayer : public LayerImpl {
2788 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
2790 ResourceProvider* resource_provider) {
2791 return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(tree_impl,
2793 resource_provider));
2796 virtual void AppendQuads(QuadSink* quad_sink,
2797 AppendQuadsData* append_quads_data) OVERRIDE {
2798 quads_appended_ = true;
2800 gfx::Rect opaque_rect;
2801 if (contents_opaque())
2802 opaque_rect = quad_rect_;
2804 opaque_rect = opaque_content_rect_;
2806 SharedQuadState* shared_quad_state =
2807 quad_sink->UseSharedQuadState(CreateSharedQuadState());
2808 scoped_ptr<TileDrawQuad> test_blending_draw_quad = TileDrawQuad::Create();
2809 test_blending_draw_quad->SetNew(shared_quad_state,
2813 gfx::RectF(0.f, 0.f, 1.f, 1.f),
2816 test_blending_draw_quad->visible_rect = quad_visible_rect_;
2817 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
2818 EXPECT_EQ(has_render_surface_, !!render_surface());
2819 quad_sink->Append(test_blending_draw_quad.PassAs<DrawQuad>(),
2823 void SetExpectation(bool blend, bool has_render_surface) {
2825 has_render_surface_ = has_render_surface;
2826 quads_appended_ = false;
2829 bool quads_appended() const { return quads_appended_; }
2831 void SetQuadRect(gfx::Rect rect) { quad_rect_ = rect; }
2832 void SetQuadVisibleRect(gfx::Rect rect) { quad_visible_rect_ = rect; }
2833 void SetOpaqueContentRect(gfx::Rect rect) { opaque_content_rect_ = rect; }
2836 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
2838 ResourceProvider* resource_provider)
2839 : LayerImpl(tree_impl, id),
2841 has_render_surface_(false),
2842 quads_appended_(false),
2843 quad_rect_(5, 5, 5, 5),
2844 quad_visible_rect_(5, 5, 5, 5),
2845 resource_id_(resource_provider->CreateResource(
2848 ResourceProvider::TextureUsageAny,
2850 resource_provider->AllocateForTesting(resource_id_);
2851 SetAnchorPoint(gfx::PointF());
2852 SetBounds(gfx::Size(10, 10));
2853 SetContentBounds(gfx::Size(10, 10));
2854 SetDrawsContent(true);
2858 bool has_render_surface_;
2859 bool quads_appended_;
2860 gfx::Rect quad_rect_;
2861 gfx::Rect opaque_content_rect_;
2862 gfx::Rect quad_visible_rect_;
2863 ResourceProvider::ResourceId resource_id_;
2866 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
2868 scoped_ptr<LayerImpl> root =
2869 LayerImpl::Create(host_impl_->active_tree(), 1);
2870 root->SetAnchorPoint(gfx::PointF());
2871 root->SetBounds(gfx::Size(10, 10));
2872 root->SetContentBounds(root->bounds());
2873 root->SetDrawsContent(false);
2874 host_impl_->active_tree()->SetRootLayer(root.Pass());
2876 LayerImpl* root = host_impl_->active_tree()->root_layer();
2879 BlendStateCheckLayer::Create(host_impl_->active_tree(),
2881 host_impl_->resource_provider()));
2882 BlendStateCheckLayer* layer1 =
2883 static_cast<BlendStateCheckLayer*>(root->children()[0]);
2884 layer1->SetPosition(gfx::PointF(2.f, 2.f));
2886 LayerTreeHostImpl::FrameData frame;
2888 // Opaque layer, drawn without blending.
2889 layer1->SetContentsOpaque(true);
2890 layer1->SetExpectation(false, false);
2891 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
2892 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2893 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2894 EXPECT_TRUE(layer1->quads_appended());
2895 host_impl_->DidDrawAllLayers(frame);
2897 // Layer with translucent content and painting, so drawn with blending.
2898 layer1->SetContentsOpaque(false);
2899 layer1->SetExpectation(true, false);
2900 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
2901 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2902 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2903 EXPECT_TRUE(layer1->quads_appended());
2904 host_impl_->DidDrawAllLayers(frame);
2906 // Layer with translucent opacity, drawn with blending.
2907 layer1->SetContentsOpaque(true);
2908 layer1->SetOpacity(0.5f);
2909 layer1->SetExpectation(true, false);
2910 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
2911 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2912 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2913 EXPECT_TRUE(layer1->quads_appended());
2914 host_impl_->DidDrawAllLayers(frame);
2916 // Layer with translucent opacity and painting, drawn with blending.
2917 layer1->SetContentsOpaque(true);
2918 layer1->SetOpacity(0.5f);
2919 layer1->SetExpectation(true, false);
2920 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
2921 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2922 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2923 EXPECT_TRUE(layer1->quads_appended());
2924 host_impl_->DidDrawAllLayers(frame);
2927 BlendStateCheckLayer::Create(host_impl_->active_tree(),
2929 host_impl_->resource_provider()));
2930 BlendStateCheckLayer* layer2 =
2931 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
2932 layer2->SetPosition(gfx::PointF(4.f, 4.f));
2934 // 2 opaque layers, drawn without blending.
2935 layer1->SetContentsOpaque(true);
2936 layer1->SetOpacity(1.f);
2937 layer1->SetExpectation(false, false);
2938 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
2939 layer2->SetContentsOpaque(true);
2940 layer2->SetOpacity(1.f);
2941 layer2->SetExpectation(false, false);
2942 layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
2943 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2944 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2945 EXPECT_TRUE(layer1->quads_appended());
2946 EXPECT_TRUE(layer2->quads_appended());
2947 host_impl_->DidDrawAllLayers(frame);
2949 // Parent layer with translucent content, drawn with blending.
2950 // Child layer with opaque content, drawn without blending.
2951 layer1->SetContentsOpaque(false);
2952 layer1->SetExpectation(true, false);
2953 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
2954 layer2->SetExpectation(false, false);
2955 layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
2956 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2957 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2958 EXPECT_TRUE(layer1->quads_appended());
2959 EXPECT_TRUE(layer2->quads_appended());
2960 host_impl_->DidDrawAllLayers(frame);
2962 // Parent layer with translucent content but opaque painting, drawn without
2964 // Child layer with opaque content, drawn without blending.
2965 layer1->SetContentsOpaque(true);
2966 layer1->SetExpectation(false, false);
2967 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
2968 layer2->SetExpectation(false, false);
2969 layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
2970 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2971 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2972 EXPECT_TRUE(layer1->quads_appended());
2973 EXPECT_TRUE(layer2->quads_appended());
2974 host_impl_->DidDrawAllLayers(frame);
2976 // Parent layer with translucent opacity and opaque content. Since it has a
2977 // drawing child, it's drawn to a render surface which carries the opacity,
2978 // so it's itself drawn without blending.
2979 // Child layer with opaque content, drawn without blending (parent surface
2980 // carries the inherited opacity).
2981 layer1->SetContentsOpaque(true);
2982 layer1->SetOpacity(0.5f);
2983 layer1->SetExpectation(false, true);
2984 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
2985 layer2->SetExpectation(false, false);
2986 layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
2987 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2988 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2989 EXPECT_TRUE(layer1->quads_appended());
2990 EXPECT_TRUE(layer2->quads_appended());
2991 host_impl_->DidDrawAllLayers(frame);
2993 // Draw again, but with child non-opaque, to make sure
2994 // layer1 not culled.
2995 layer1->SetContentsOpaque(true);
2996 layer1->SetOpacity(1.f);
2997 layer1->SetExpectation(false, false);
2998 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
2999 layer2->SetContentsOpaque(true);
3000 layer2->SetOpacity(0.5f);
3001 layer2->SetExpectation(true, false);
3002 layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
3003 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3004 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3005 EXPECT_TRUE(layer1->quads_appended());
3006 EXPECT_TRUE(layer2->quads_appended());
3007 host_impl_->DidDrawAllLayers(frame);
3009 // A second way of making the child non-opaque.
3010 layer1->SetContentsOpaque(true);
3011 layer1->SetOpacity(1.f);
3012 layer1->SetExpectation(false, false);
3013 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
3014 layer2->SetContentsOpaque(false);
3015 layer2->SetOpacity(1.f);
3016 layer2->SetExpectation(true, false);
3017 layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
3018 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3019 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3020 EXPECT_TRUE(layer1->quads_appended());
3021 EXPECT_TRUE(layer2->quads_appended());
3022 host_impl_->DidDrawAllLayers(frame);
3024 // And when the layer says its not opaque but is painted opaque, it is not
3026 layer1->SetContentsOpaque(true);
3027 layer1->SetOpacity(1.f);
3028 layer1->SetExpectation(false, false);
3029 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
3030 layer2->SetContentsOpaque(true);
3031 layer2->SetOpacity(1.f);
3032 layer2->SetExpectation(false, false);
3033 layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
3034 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3035 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3036 EXPECT_TRUE(layer1->quads_appended());
3037 EXPECT_TRUE(layer2->quads_appended());
3038 host_impl_->DidDrawAllLayers(frame);
3040 // Layer with partially opaque contents, drawn with blending.
3041 layer1->SetContentsOpaque(false);
3042 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3043 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
3044 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3045 layer1->SetExpectation(true, false);
3046 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
3047 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3048 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3049 EXPECT_TRUE(layer1->quads_appended());
3050 host_impl_->DidDrawAllLayers(frame);
3052 // Layer with partially opaque contents partially culled, drawn with blending.
3053 layer1->SetContentsOpaque(false);
3054 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3055 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
3056 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3057 layer1->SetExpectation(true, false);
3058 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
3059 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3060 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3061 EXPECT_TRUE(layer1->quads_appended());
3062 host_impl_->DidDrawAllLayers(frame);
3064 // Layer with partially opaque contents culled, drawn with blending.
3065 layer1->SetContentsOpaque(false);
3066 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3067 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
3068 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3069 layer1->SetExpectation(true, false);
3070 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
3071 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3072 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3073 EXPECT_TRUE(layer1->quads_appended());
3074 host_impl_->DidDrawAllLayers(frame);
3076 // Layer with partially opaque contents and translucent contents culled, drawn
3077 // without blending.
3078 layer1->SetContentsOpaque(false);
3079 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3080 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
3081 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3082 layer1->SetExpectation(false, false);
3083 layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
3084 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3085 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3086 EXPECT_TRUE(layer1->quads_appended());
3087 host_impl_->DidDrawAllLayers(frame);
3090 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
3092 LayerTreeHostImplViewportCoveredTest() :
3093 gutter_quad_material_(DrawQuad::SOLID_COLOR),
3095 did_activate_pending_tree_(false) {}
3097 void CreateLayerTreeHostImpl(bool always_draw) {
3098 LayerTreeSettings settings;
3099 settings.minimum_occlusion_tracking_size = gfx::Size();
3100 settings.impl_side_painting = true;
3101 host_impl_ = LayerTreeHostImpl::Create(
3102 settings, this, &proxy_, &stats_instrumentation_, NULL);
3104 scoped_ptr<FakeOutputSurface> output_surface;
3106 output_surface = FakeOutputSurface::CreateAlwaysDrawAndSwap3d().Pass();
3108 output_surface = FakeOutputSurface::Create3d().Pass();
3110 host_impl_->InitializeRenderer(output_surface.PassAs<OutputSurface>());
3111 viewport_size_ = gfx::Size(1000, 1000);
3114 void SetupActiveTreeLayers() {
3115 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
3116 host_impl_->active_tree()->SetRootLayer(
3117 LayerImpl::Create(host_impl_->active_tree(), 1));
3118 host_impl_->active_tree()->root_layer()->AddChild(
3119 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3121 host_impl_->resource_provider()));
3122 child_ = static_cast<BlendStateCheckLayer*>(
3123 host_impl_->active_tree()->root_layer()->children()[0]);
3124 child_->SetExpectation(false, false);
3125 child_->SetContentsOpaque(true);
3128 // Expect no gutter rects.
3129 void TestLayerCoversFullViewport() {
3130 gfx::Rect layer_rect(viewport_size_);
3131 child_->SetPosition(layer_rect.origin());
3132 child_->SetBounds(layer_rect.size());
3133 child_->SetContentBounds(layer_rect.size());
3134 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3135 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3137 LayerTreeHostImpl::FrameData frame;
3138 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3139 ASSERT_EQ(1u, frame.render_passes.size());
3141 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3142 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3143 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3145 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3146 host_impl_->DidDrawAllLayers(frame);
3149 // Expect fullscreen gutter rect.
3150 void TestEmptyLayer() {
3151 gfx::Rect layer_rect(0, 0, 0, 0);
3152 child_->SetPosition(layer_rect.origin());
3153 child_->SetBounds(layer_rect.size());
3154 child_->SetContentBounds(layer_rect.size());
3155 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3156 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3158 LayerTreeHostImpl::FrameData frame;
3159 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3160 ASSERT_EQ(1u, frame.render_passes.size());
3162 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
3163 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3164 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3166 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3167 host_impl_->DidDrawAllLayers(frame);
3170 // Expect four surrounding gutter rects.
3171 void TestLayerInMiddleOfViewport() {
3172 gfx::Rect layer_rect(500, 500, 200, 200);
3173 child_->SetPosition(layer_rect.origin());
3174 child_->SetBounds(layer_rect.size());
3175 child_->SetContentBounds(layer_rect.size());
3176 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3177 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3179 LayerTreeHostImpl::FrameData frame;
3180 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3181 ASSERT_EQ(1u, frame.render_passes.size());
3183 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
3184 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
3185 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3187 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3188 host_impl_->DidDrawAllLayers(frame);
3191 // Expect no gutter rects.
3192 void TestLayerIsLargerThanViewport() {
3193 gfx::Rect layer_rect(viewport_size_.width() + 10,
3194 viewport_size_.height() + 10);
3195 child_->SetPosition(layer_rect.origin());
3196 child_->SetBounds(layer_rect.size());
3197 child_->SetContentBounds(layer_rect.size());
3198 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3199 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3201 LayerTreeHostImpl::FrameData frame;
3202 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3203 ASSERT_EQ(1u, frame.render_passes.size());
3205 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3206 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3207 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3209 host_impl_->DidDrawAllLayers(frame);
3212 virtual void DidActivatePendingTree() OVERRIDE {
3213 did_activate_pending_tree_ = true;
3216 void set_gutter_quad_material(DrawQuad::Material material) {
3217 gutter_quad_material_ = material;
3219 void set_gutter_texture_size(gfx::Size gutter_texture_size) {
3220 gutter_texture_size_ = gutter_texture_size;
3224 size_t CountGutterQuads(const QuadList& quad_list) {
3225 size_t num_gutter_quads = 0;
3226 for (size_t i = 0; i < quad_list.size(); ++i) {
3227 num_gutter_quads += (quad_list[i]->material ==
3228 gutter_quad_material_) ? 1 : 0;
3230 return num_gutter_quads;
3233 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
3234 LayerTestCommon::VerifyQuadsExactlyCoverRect(
3235 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
3238 // Make sure that the texture coordinates match their expectations.
3239 void ValidateTextureDrawQuads(const QuadList& quad_list) {
3240 for (size_t i = 0; i < quad_list.size(); ++i) {
3241 if (quad_list[i]->material != DrawQuad::TEXTURE_CONTENT)
3243 const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(quad_list[i]);
3244 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
3245 gutter_texture_size_, host_impl_->device_scale_factor());
3246 EXPECT_EQ(quad->uv_top_left.x(),
3247 quad->rect.x() / gutter_texture_size_pixels.width());
3248 EXPECT_EQ(quad->uv_top_left.y(),
3249 quad->rect.y() / gutter_texture_size_pixels.height());
3250 EXPECT_EQ(quad->uv_bottom_right.x(),
3251 quad->rect.right() / gutter_texture_size_pixels.width());
3252 EXPECT_EQ(quad->uv_bottom_right.y(),
3253 quad->rect.bottom() / gutter_texture_size_pixels.height());
3257 gfx::Size DipSizeToPixelSize(gfx::Size size) {
3258 return gfx::ToRoundedSize(
3259 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
3262 DrawQuad::Material gutter_quad_material_;
3263 gfx::Size gutter_texture_size_;
3264 gfx::Size viewport_size_;
3265 BlendStateCheckLayer* child_;
3266 bool did_activate_pending_tree_;
3269 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
3270 bool always_draw = false;
3271 CreateLayerTreeHostImpl(always_draw);
3273 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3274 SetupActiveTreeLayers();
3275 TestLayerCoversFullViewport();
3277 TestLayerInMiddleOfViewport();
3278 TestLayerIsLargerThanViewport();
3281 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
3282 bool always_draw = false;
3283 CreateLayerTreeHostImpl(always_draw);
3285 host_impl_->SetDeviceScaleFactor(2.f);
3286 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3287 SetupActiveTreeLayers();
3288 TestLayerCoversFullViewport();
3290 TestLayerInMiddleOfViewport();
3291 TestLayerIsLargerThanViewport();
3294 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
3295 bool always_draw = false;
3296 CreateLayerTreeHostImpl(always_draw);
3298 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3299 SetupActiveTreeLayers();
3302 skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
3303 skbitmap.allocPixels();
3304 skbitmap.setImmutable();
3306 // Specify an overhang bitmap to use.
3307 UIResourceBitmap ui_resource_bitmap(skbitmap);
3308 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
3309 UIResourceId ui_resource_id = 12345;
3310 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
3311 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
3312 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
3313 set_gutter_texture_size(gfx::Size(32, 32));
3315 TestLayerCoversFullViewport();
3317 TestLayerInMiddleOfViewport();
3318 TestLayerIsLargerThanViewport();
3320 // Change the resource size.
3321 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
3322 set_gutter_texture_size(gfx::Size(128, 16));
3324 TestLayerCoversFullViewport();
3326 TestLayerInMiddleOfViewport();
3327 TestLayerIsLargerThanViewport();
3329 // Change the device scale factor
3330 host_impl_->SetDeviceScaleFactor(2.f);
3331 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3333 TestLayerCoversFullViewport();
3335 TestLayerInMiddleOfViewport();
3336 TestLayerIsLargerThanViewport();
3339 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
3340 bool always_draw = true;
3341 CreateLayerTreeHostImpl(always_draw);
3343 // Pending tree to force active_tree size invalid. Not used otherwise.
3344 host_impl_->CreatePendingTree();
3345 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3346 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3348 SetupActiveTreeLayers();
3350 TestLayerInMiddleOfViewport();
3351 TestLayerIsLargerThanViewport();
3354 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
3355 bool always_draw = true;
3356 CreateLayerTreeHostImpl(always_draw);
3358 // Set larger viewport and activate it to active tree.
3359 host_impl_->CreatePendingTree();
3360 gfx::Size larger_viewport(viewport_size_.width() + 100,
3361 viewport_size_.height() + 100);
3362 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
3363 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3364 host_impl_->ActivatePendingTree();
3365 EXPECT_TRUE(did_activate_pending_tree_);
3366 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
3368 // Shrink pending tree viewport without activating.
3369 host_impl_->CreatePendingTree();
3370 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3371 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3373 SetupActiveTreeLayers();
3375 TestLayerInMiddleOfViewport();
3376 TestLayerIsLargerThanViewport();
3379 class ReshapeTrackerContext: public TestWebGraphicsContext3D {
3381 ReshapeTrackerContext()
3382 : reshape_called_(false),
3383 last_reshape_width_(-1),
3384 last_reshape_height_(-1),
3385 last_reshape_scale_factor_(-1.f) {
3388 virtual void reshapeWithScaleFactor(
3389 int width, int height, float scale_factor) OVERRIDE {
3390 reshape_called_ = true;
3391 last_reshape_width_ = width;
3392 last_reshape_height_ = height;
3393 last_reshape_scale_factor_ = scale_factor;
3396 bool reshape_called() const { return reshape_called_; }
3397 void clear_reshape_called() { reshape_called_ = false; }
3398 int last_reshape_width() { return last_reshape_width_; }
3399 int last_reshape_height() { return last_reshape_height_; }
3400 int last_reshape_scale_factor() { return last_reshape_scale_factor_; }
3403 bool reshape_called_;
3404 int last_reshape_width_;
3405 int last_reshape_height_;
3406 float last_reshape_scale_factor_;
3409 class FakeDrawableLayerImpl: public LayerImpl {
3411 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
3412 return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(tree_impl, id));
3415 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
3416 : LayerImpl(tree_impl, id) {}
3419 // Only reshape when we know we are going to draw. Otherwise, the reshape
3420 // can leave the window at the wrong size if we never draw and the proper
3421 // viewport size is never set.
3422 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
3423 scoped_ptr<ReshapeTrackerContext> owned_reshape_tracker(
3424 new ReshapeTrackerContext);
3425 ReshapeTrackerContext* reshape_tracker = owned_reshape_tracker.get();
3426 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3427 owned_reshape_tracker.PassAs<TestWebGraphicsContext3D>()));
3428 host_impl_->InitializeRenderer(output_surface.Pass());
3430 scoped_ptr<LayerImpl> root =
3431 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
3432 root->SetAnchorPoint(gfx::PointF());
3433 root->SetBounds(gfx::Size(10, 10));
3434 root->SetContentBounds(gfx::Size(10, 10));
3435 root->SetDrawsContent(true);
3436 host_impl_->active_tree()->SetRootLayer(root.Pass());
3437 EXPECT_FALSE(reshape_tracker->reshape_called());
3438 reshape_tracker->clear_reshape_called();
3440 LayerTreeHostImpl::FrameData frame;
3441 host_impl_->SetViewportSize(gfx::Size(10, 10));
3442 host_impl_->SetDeviceScaleFactor(1.f);
3443 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3444 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3445 EXPECT_TRUE(reshape_tracker->reshape_called());
3446 EXPECT_EQ(reshape_tracker->last_reshape_width(), 10);
3447 EXPECT_EQ(reshape_tracker->last_reshape_height(), 10);
3448 EXPECT_EQ(reshape_tracker->last_reshape_scale_factor(), 1.f);
3449 host_impl_->DidDrawAllLayers(frame);
3450 reshape_tracker->clear_reshape_called();
3452 host_impl_->SetViewportSize(gfx::Size(20, 30));
3453 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3454 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3455 EXPECT_TRUE(reshape_tracker->reshape_called());
3456 EXPECT_EQ(reshape_tracker->last_reshape_width(), 20);
3457 EXPECT_EQ(reshape_tracker->last_reshape_height(), 30);
3458 EXPECT_EQ(reshape_tracker->last_reshape_scale_factor(), 1.f);
3459 host_impl_->DidDrawAllLayers(frame);
3460 reshape_tracker->clear_reshape_called();
3462 host_impl_->SetDeviceScaleFactor(2.f);
3463 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3464 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3465 EXPECT_TRUE(reshape_tracker->reshape_called());
3466 EXPECT_EQ(reshape_tracker->last_reshape_width(), 20);
3467 EXPECT_EQ(reshape_tracker->last_reshape_height(), 30);
3468 EXPECT_EQ(reshape_tracker->last_reshape_scale_factor(), 2.f);
3469 host_impl_->DidDrawAllLayers(frame);
3470 reshape_tracker->clear_reshape_called();
3473 class SwapTrackerContext : public TestWebGraphicsContext3D {
3475 SwapTrackerContext()
3476 : last_update_type_(NoUpdate) {
3477 test_capabilities_.post_sub_buffer = true;
3478 test_capabilities_.set_visibility = true;
3481 virtual void prepareTexture() OVERRIDE {
3482 update_rect_ = gfx::Rect(width_, height_);
3483 last_update_type_ = PrepareTexture;
3486 virtual void postSubBufferCHROMIUM(int x, int y, int width, int height)
3488 update_rect_ = gfx::Rect(x, y, width, height);
3489 last_update_type_ = PostSubBuffer;
3492 gfx::Rect update_rect() const { return update_rect_; }
3500 UpdateType last_update_type() {
3501 return last_update_type_;
3505 gfx::Rect update_rect_;
3506 UpdateType last_update_type_;
3509 // Make sure damage tracking propagates all the way to the graphics context,
3510 // where it should request to swap only the sub-buffer that is damaged.
3511 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
3512 scoped_ptr<SwapTrackerContext> context(new SwapTrackerContext);
3513 SwapTrackerContext* swap_tracker = context.get();
3515 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3516 context.PassAs<TestWebGraphicsContext3D>()));
3518 // This test creates its own LayerTreeHostImpl, so
3519 // that we can force partial swap enabled.
3520 LayerTreeSettings settings;
3521 settings.partial_swap_enabled = true;
3522 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
3523 LayerTreeHostImpl::Create(
3524 settings, this, &proxy_, &stats_instrumentation_, NULL);
3525 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
3526 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
3528 scoped_ptr<LayerImpl> root =
3529 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
3530 scoped_ptr<LayerImpl> child =
3531 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
3532 child->SetPosition(gfx::PointF(12.f, 13.f));
3533 child->SetAnchorPoint(gfx::PointF());
3534 child->SetBounds(gfx::Size(14, 15));
3535 child->SetContentBounds(gfx::Size(14, 15));
3536 child->SetDrawsContent(true);
3537 root->SetAnchorPoint(gfx::PointF());
3538 root->SetBounds(gfx::Size(500, 500));
3539 root->SetContentBounds(gfx::Size(500, 500));
3540 root->SetDrawsContent(true);
3541 root->AddChild(child.Pass());
3542 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
3544 LayerTreeHostImpl::FrameData frame;
3546 // First frame, the entire screen should get swapped.
3547 EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3548 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3549 layer_tree_host_impl->DidDrawAllLayers(frame);
3550 layer_tree_host_impl->SwapBuffers(frame);
3551 gfx::Rect actual_swap_rect = swap_tracker->update_rect();
3552 gfx::Rect expected_swap_rect = gfx::Rect(0, 0, 500, 500);
3553 EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
3554 EXPECT_EQ(expected_swap_rect.y(), actual_swap_rect.y());
3555 EXPECT_EQ(expected_swap_rect.width(), actual_swap_rect.width());
3556 EXPECT_EQ(expected_swap_rect.height(), actual_swap_rect.height());
3557 EXPECT_EQ(swap_tracker->last_update_type(),
3558 SwapTrackerContext::PrepareTexture);
3559 // Second frame, only the damaged area should get swapped. Damage should be
3560 // the union of old and new child rects.
3561 // expected damage rect: gfx::Rect(26, 28);
3562 // expected swap rect: vertically flipped, with origin at bottom left corner.
3563 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
3565 EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3566 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3567 host_impl_->DidDrawAllLayers(frame);
3568 layer_tree_host_impl->SwapBuffers(frame);
3569 actual_swap_rect = swap_tracker->update_rect();
3570 expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
3571 EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
3572 EXPECT_EQ(expected_swap_rect.y(), actual_swap_rect.y());
3573 EXPECT_EQ(expected_swap_rect.width(), actual_swap_rect.width());
3574 EXPECT_EQ(expected_swap_rect.height(), actual_swap_rect.height());
3575 EXPECT_EQ(swap_tracker->last_update_type(),
3576 SwapTrackerContext::PostSubBuffer);
3578 // Make sure that partial swap is constrained to the viewport dimensions
3579 // expected damage rect: gfx::Rect(500, 500);
3580 // expected swap rect: flipped damage rect, but also clamped to viewport
3581 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
3582 // This will damage everything.
3583 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
3585 EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3586 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3587 host_impl_->DidDrawAllLayers(frame);
3588 layer_tree_host_impl->SwapBuffers(frame);
3589 actual_swap_rect = swap_tracker->update_rect();
3590 expected_swap_rect = gfx::Rect(10, 10);
3591 EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
3592 EXPECT_EQ(expected_swap_rect.y(), actual_swap_rect.y());
3593 EXPECT_EQ(expected_swap_rect.width(), actual_swap_rect.width());
3594 EXPECT_EQ(expected_swap_rect.height(), actual_swap_rect.height());
3595 EXPECT_EQ(swap_tracker->last_update_type(),
3596 SwapTrackerContext::PrepareTexture);
3599 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
3600 scoped_ptr<LayerImpl> root =
3601 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
3602 scoped_ptr<LayerImpl> child =
3603 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
3604 child->SetAnchorPoint(gfx::PointF());
3605 child->SetBounds(gfx::Size(10, 10));
3606 child->SetContentBounds(gfx::Size(10, 10));
3607 child->SetDrawsContent(true);
3608 root->SetAnchorPoint(gfx::PointF());
3609 root->SetBounds(gfx::Size(10, 10));
3610 root->SetContentBounds(gfx::Size(10, 10));
3611 root->SetDrawsContent(true);
3612 root->SetForceRenderSurface(true);
3613 root->AddChild(child.Pass());
3615 host_impl_->active_tree()->SetRootLayer(root.Pass());
3617 LayerTreeHostImpl::FrameData frame;
3619 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3620 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
3621 EXPECT_EQ(1u, frame.render_passes.size());
3622 host_impl_->DidDrawAllLayers(frame);
3625 class FakeLayerWithQuads : public LayerImpl {
3627 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
3628 return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(tree_impl, id));
3631 virtual void AppendQuads(QuadSink* quad_sink,
3632 AppendQuadsData* append_quads_data) OVERRIDE {
3633 SharedQuadState* shared_quad_state =
3634 quad_sink->UseSharedQuadState(CreateSharedQuadState());
3636 SkColor gray = SkColorSetRGB(100, 100, 100);
3637 gfx::Rect quad_rect(content_bounds());
3638 scoped_ptr<SolidColorDrawQuad> my_quad = SolidColorDrawQuad::Create();
3639 my_quad->SetNew(shared_quad_state, quad_rect, gray, false);
3640 quad_sink->Append(my_quad.PassAs<DrawQuad>(), append_quads_data);
3644 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
3645 : LayerImpl(tree_impl, id) {}
3648 class MockContext : public TestWebGraphicsContext3D {
3650 MOCK_METHOD1(useProgram, void(WebKit::WebGLId program));
3651 MOCK_METHOD5(uniform4f, void(WebKit::WGC3Dint location,
3652 WebKit::WGC3Dfloat x,
3653 WebKit::WGC3Dfloat y,
3654 WebKit::WGC3Dfloat z,
3655 WebKit::WGC3Dfloat w));
3656 MOCK_METHOD4(uniformMatrix4fv, void(WebKit::WGC3Dint location,
3657 WebKit::WGC3Dsizei count,
3658 WebKit::WGC3Dboolean transpose,
3659 const WebKit::WGC3Dfloat* value));
3660 MOCK_METHOD4(drawElements, void(WebKit::WGC3Denum mode,
3661 WebKit::WGC3Dsizei count,
3662 WebKit::WGC3Denum type,
3663 WebKit::WGC3Dintptr offset));
3664 MOCK_METHOD0(getRequestableExtensionsCHROMIUM, WebKit::WebString());
3665 MOCK_METHOD1(enable, void(WebKit::WGC3Denum cap));
3666 MOCK_METHOD1(disable, void(WebKit::WGC3Denum cap));
3667 MOCK_METHOD4(scissor, void(WebKit::WGC3Dint x,
3669 WebKit::WGC3Dsizei width,
3670 WebKit::WGC3Dsizei height));
3673 class MockContextHarness {
3675 MockContext* context_;
3678 explicit MockContextHarness(MockContext* context)
3679 : context_(context) {
3680 context_->set_have_post_sub_buffer(true);
3682 // Catch "uninteresting" calls
3683 EXPECT_CALL(*context_, useProgram(_))
3686 EXPECT_CALL(*context_, drawElements(_, _, _, _))
3689 // These are not asserted
3690 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
3691 .WillRepeatedly(Return());
3693 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
3694 .WillRepeatedly(Return());
3696 // Any un-sanctioned calls to enable() are OK
3697 EXPECT_CALL(*context_, enable(_))
3698 .WillRepeatedly(Return());
3700 // Any un-sanctioned calls to disable() are OK
3701 EXPECT_CALL(*context_, disable(_))
3702 .WillRepeatedly(Return());
3705 void MustDrawSolidQuad() {
3706 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
3708 .RetiresOnSaturation();
3710 EXPECT_CALL(*context_, useProgram(_))
3712 .RetiresOnSaturation();
3715 void MustSetScissor(int x, int y, int width, int height) {
3716 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
3717 .WillRepeatedly(Return());
3719 EXPECT_CALL(*context_, scissor(x, y, width, height))
3721 .WillRepeatedly(Return());
3724 void MustSetNoScissor() {
3725 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
3726 .WillRepeatedly(Return());
3728 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
3731 EXPECT_CALL(*context_, scissor(_, _, _, _))
3736 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
3737 scoped_ptr<MockContext> mock_context_owned(new MockContext);
3738 MockContext* mock_context = mock_context_owned.get();
3740 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3741 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
3742 MockContextHarness harness(mock_context);
3745 CreateLayerTreeHost(false, output_surface.Pass());
3746 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
3748 // Without partial swap, and no clipping, no scissor is set.
3749 harness.MustDrawSolidQuad();
3750 harness.MustSetNoScissor();
3752 LayerTreeHostImpl::FrameData frame;
3753 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3754 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3755 host_impl_->DidDrawAllLayers(frame);
3757 Mock::VerifyAndClearExpectations(&mock_context);
3759 // Without partial swap, but a layer does clip its subtree, one scissor is
3761 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
3762 harness.MustDrawSolidQuad();
3763 harness.MustSetScissor(0, 0, 10, 10);
3765 LayerTreeHostImpl::FrameData frame;
3766 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3767 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3768 host_impl_->DidDrawAllLayers(frame);
3770 Mock::VerifyAndClearExpectations(&mock_context);
3773 TEST_F(LayerTreeHostImplTest, PartialSwap) {
3774 scoped_ptr<MockContext> context_owned(new MockContext);
3775 MockContext* mock_context = context_owned.get();
3776 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3777 context_owned.PassAs<TestWebGraphicsContext3D>()));
3778 MockContextHarness harness(mock_context);
3780 CreateLayerTreeHost(true, output_surface.Pass());
3781 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
3783 // The first frame is not a partially-swapped one.
3784 harness.MustSetScissor(0, 0, 10, 10);
3785 harness.MustDrawSolidQuad();
3787 LayerTreeHostImpl::FrameData frame;
3788 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3789 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3790 host_impl_->DidDrawAllLayers(frame);
3792 Mock::VerifyAndClearExpectations(&mock_context);
3794 // Damage a portion of the frame.
3795 host_impl_->active_tree()->root_layer()->set_update_rect(
3796 gfx::Rect(0, 0, 2, 3));
3798 // The second frame will be partially-swapped (the y coordinates are flipped).
3799 harness.MustSetScissor(0, 7, 2, 3);
3800 harness.MustDrawSolidQuad();
3802 LayerTreeHostImpl::FrameData frame;
3803 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
3804 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3805 host_impl_->DidDrawAllLayers(frame);
3807 Mock::VerifyAndClearExpectations(&mock_context);
3810 class PartialSwapContext : public TestWebGraphicsContext3D {
3812 PartialSwapContext() {
3813 test_capabilities_.post_sub_buffer = true;
3816 // Unlimited texture size.
3817 virtual void getIntegerv(WebKit::WGC3Denum pname, WebKit::WGC3Dint* value)
3819 if (pname == GL_MAX_TEXTURE_SIZE)
3821 else if (pname == GL_ACTIVE_TEXTURE)
3822 *value = GL_TEXTURE0;
3826 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
3828 LayerTreeHostImplClient* client,
3830 RenderingStatsInstrumentation* stats_instrumentation) {
3831 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3832 scoped_ptr<TestWebGraphicsContext3D>(new PartialSwapContext)));
3834 LayerTreeSettings settings;
3835 settings.partial_swap_enabled = partial_swap;
3836 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
3837 settings, client, proxy, stats_instrumentation, NULL);
3838 my_host_impl->InitializeRenderer(output_surface.Pass());
3839 my_host_impl->SetViewportSize(gfx::Size(100, 100));
3842 Layers are created as follows:
3844 +--------------------+
3848 | | +-------------------+
3850 | | +-------------------+
3855 +--------------------+
3857 Layers 1, 2 have render surfaces
3859 scoped_ptr<LayerImpl> root =
3860 LayerImpl::Create(my_host_impl->active_tree(), 1);
3861 scoped_ptr<LayerImpl> child =
3862 LayerImpl::Create(my_host_impl->active_tree(), 2);
3863 scoped_ptr<LayerImpl> grand_child =
3864 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
3866 gfx::Rect root_rect(0, 0, 100, 100);
3867 gfx::Rect child_rect(10, 10, 50, 50);
3868 gfx::Rect grand_child_rect(5, 5, 150, 150);
3870 root->CreateRenderSurface();
3871 root->SetAnchorPoint(gfx::PointF());
3872 root->SetPosition(root_rect.origin());
3873 root->SetBounds(root_rect.size());
3874 root->SetContentBounds(root->bounds());
3875 root->draw_properties().visible_content_rect = root_rect;
3876 root->SetDrawsContent(false);
3877 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
3879 child->SetAnchorPoint(gfx::PointF());
3880 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
3881 child->SetOpacity(0.5f);
3882 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
3883 child->SetContentBounds(child->bounds());
3884 child->draw_properties().visible_content_rect = child_rect;
3885 child->SetDrawsContent(false);
3886 child->SetForceRenderSurface(true);
3888 grand_child->SetAnchorPoint(gfx::PointF());
3889 grand_child->SetPosition(grand_child_rect.origin());
3890 grand_child->SetBounds(grand_child_rect.size());
3891 grand_child->SetContentBounds(grand_child->bounds());
3892 grand_child->draw_properties().visible_content_rect = grand_child_rect;
3893 grand_child->SetDrawsContent(true);
3895 child->AddChild(grand_child.Pass());
3896 root->AddChild(child.Pass());
3898 my_host_impl->active_tree()->SetRootLayer(root.Pass());
3899 return my_host_impl.Pass();
3902 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
3903 scoped_ptr<LayerTreeHostImpl> my_host_impl =
3904 SetupLayersForOpacity(true, this, &proxy_, &stats_instrumentation_);
3906 LayerTreeHostImpl::FrameData frame;
3907 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3909 // Verify all quads have been computed
3910 ASSERT_EQ(2U, frame.render_passes.size());
3911 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
3912 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
3913 EXPECT_EQ(DrawQuad::SOLID_COLOR,
3914 frame.render_passes[0]->quad_list[0]->material);
3915 EXPECT_EQ(DrawQuad::RENDER_PASS,
3916 frame.render_passes[1]->quad_list[0]->material);
3918 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3919 my_host_impl->DidDrawAllLayers(frame);
3923 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
3924 scoped_ptr<LayerTreeHostImpl> my_host_impl =
3925 SetupLayersForOpacity(false, this, &proxy_, &stats_instrumentation_);
3927 LayerTreeHostImpl::FrameData frame;
3928 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3930 // Verify all quads have been computed
3931 ASSERT_EQ(2U, frame.render_passes.size());
3932 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
3933 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
3934 EXPECT_EQ(DrawQuad::SOLID_COLOR,
3935 frame.render_passes[0]->quad_list[0]->material);
3936 EXPECT_EQ(DrawQuad::RENDER_PASS,
3937 frame.render_passes[1]->quad_list[0]->material);
3939 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
3940 my_host_impl->DidDrawAllLayers(frame);
3944 // Fake WebKit::WebGraphicsContext3D that tracks the number of textures in use.
3945 class TrackingWebGraphicsContext3D : public TestWebGraphicsContext3D {
3947 TrackingWebGraphicsContext3D()
3948 : TestWebGraphicsContext3D(),
3950 test_capabilities_.iosurface = true;
3951 test_capabilities_.texture_rectangle = true;
3954 virtual WebKit::WebGLId createTexture() OVERRIDE {
3955 WebKit::WebGLId id = TestWebGraphicsContext3D::createTexture();
3957 textures_[id] = true;
3962 virtual void deleteTexture(WebKit::WebGLId id) OVERRIDE {
3963 if (textures_.find(id) == textures_.end())
3966 textures_[id] = false;
3970 unsigned num_textures() const { return num_textures_; }
3973 base::hash_map<WebKit::WebGLId, bool> textures_;
3974 unsigned num_textures_;
3977 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
3978 scoped_ptr<TestWebGraphicsContext3D> context =
3979 TestWebGraphicsContext3D::Create();
3980 TestWebGraphicsContext3D* context3d = context.get();
3981 scoped_ptr<OutputSurface> output_surface(
3982 FakeOutputSurface::Create3d(context.Pass()));
3983 host_impl_->InitializeRenderer(output_surface.Pass());
3985 scoped_ptr<LayerImpl> root_layer =
3986 LayerImpl::Create(host_impl_->active_tree(), 1);
3987 root_layer->SetBounds(gfx::Size(10, 10));
3988 root_layer->SetAnchorPoint(gfx::PointF());
3990 scoped_refptr<VideoFrame> softwareFrame =
3991 media::VideoFrame::CreateColorFrame(
3992 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
3993 FakeVideoFrameProvider provider;
3994 provider.set_frame(softwareFrame);
3995 scoped_ptr<VideoLayerImpl> video_layer =
3996 VideoLayerImpl::Create(host_impl_->active_tree(), 4, &provider);
3997 video_layer->SetBounds(gfx::Size(10, 10));
3998 video_layer->SetAnchorPoint(gfx::PointF());
3999 video_layer->SetContentBounds(gfx::Size(10, 10));
4000 video_layer->SetDrawsContent(true);
4001 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
4003 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
4004 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
4005 io_surface_layer->SetBounds(gfx::Size(10, 10));
4006 io_surface_layer->SetAnchorPoint(gfx::PointF());
4007 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
4008 io_surface_layer->SetDrawsContent(true);
4009 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
4010 root_layer->AddChild(io_surface_layer.PassAs<LayerImpl>());
4012 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
4014 EXPECT_EQ(0u, context3d->NumTextures());
4016 LayerTreeHostImpl::FrameData frame;
4017 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4018 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4019 host_impl_->DidDrawAllLayers(frame);
4020 host_impl_->SwapBuffers(frame);
4022 EXPECT_GT(context3d->NumTextures(), 0u);
4024 // Kill the layer tree.
4025 host_impl_->active_tree()->SetRootLayer(
4026 LayerImpl::Create(host_impl_->active_tree(), 100));
4027 // There should be no textures left in use after.
4028 EXPECT_EQ(0u, context3d->NumTextures());
4031 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
4033 MOCK_METHOD1(useProgram, void(WebKit::WebGLId program));
4034 MOCK_METHOD4(drawElements, void(WebKit::WGC3Denum mode,
4035 WebKit::WGC3Dsizei count,
4036 WebKit::WGC3Denum type,
4037 WebKit::WGC3Dintptr offset));
4040 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
4041 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
4042 new MockDrawQuadsToFillScreenContext);
4043 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
4045 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4046 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4049 CreateLayerTreeHost(false, output_surface.Pass());
4050 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
4051 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
4053 // Verify one quad is drawn when transparent background set is not set.
4054 host_impl_->active_tree()->set_has_transparent_background(false);
4055 EXPECT_CALL(*mock_context, useProgram(_))
4057 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
4059 LayerTreeHostImpl::FrameData frame;
4060 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4061 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4062 host_impl_->DidDrawAllLayers(frame);
4063 Mock::VerifyAndClearExpectations(&mock_context);
4065 // Verify no quads are drawn when transparent background is set.
4066 host_impl_->active_tree()->set_has_transparent_background(true);
4067 host_impl_->SetFullRootLayerDamage();
4068 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4069 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4070 host_impl_->DidDrawAllLayers(frame);
4071 Mock::VerifyAndClearExpectations(&mock_context);
4074 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
4075 set_reduce_memory_result(false);
4077 // If changing the memory limit wouldn't result in changing what was
4078 // committed, then no commit should be requested.
4079 set_reduce_memory_result(false);
4080 host_impl_->set_max_memory_needed_bytes(
4081 host_impl_->memory_allocation_limit_bytes() - 1);
4082 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4083 host_impl_->memory_allocation_limit_bytes() - 1));
4084 EXPECT_FALSE(did_request_commit_);
4085 did_request_commit_ = false;
4087 // If changing the memory limit would result in changing what was
4088 // committed, then a commit should be requested, even though nothing was
4090 set_reduce_memory_result(false);
4091 host_impl_->set_max_memory_needed_bytes(
4092 host_impl_->memory_allocation_limit_bytes());
4093 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4094 host_impl_->memory_allocation_limit_bytes() - 1));
4095 EXPECT_TRUE(did_request_commit_);
4096 did_request_commit_ = false;
4098 // Especially if changing the memory limit caused evictions, we need
4100 set_reduce_memory_result(true);
4101 host_impl_->set_max_memory_needed_bytes(1);
4102 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4103 host_impl_->memory_allocation_limit_bytes() - 1));
4104 EXPECT_TRUE(did_request_commit_);
4105 did_request_commit_ = false;
4107 // But if we set it to the same value that it was before, we shouldn't
4109 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4110 host_impl_->memory_allocation_limit_bytes()));
4111 EXPECT_FALSE(did_request_commit_);
4114 class LayerTreeHostImplTestWithDelegatingRenderer
4115 : public LayerTreeHostImplTest {
4117 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
4118 return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
4121 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
4122 bool expect_to_draw = !expected_damage.IsEmpty();
4124 LayerTreeHostImpl::FrameData frame;
4125 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4127 if (!expect_to_draw) {
4128 // With no damage, we don't draw, and no quads are created.
4129 ASSERT_EQ(0u, frame.render_passes.size());
4131 ASSERT_EQ(1u, frame.render_passes.size());
4133 // Verify the damage rect for the root render pass.
4134 const RenderPass* root_render_pass = frame.render_passes.back();
4135 EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
4137 // Verify the root and child layers' quads are generated and not being
4139 ASSERT_EQ(2u, root_render_pass->quad_list.size());
4141 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
4142 gfx::RectF expected_child_visible_rect(child->content_bounds());
4143 EXPECT_RECT_EQ(expected_child_visible_rect,
4144 root_render_pass->quad_list[0]->visible_rect);
4146 LayerImpl* root = host_impl_->active_tree()->root_layer();
4147 gfx::RectF expected_root_visible_rect(root->content_bounds());
4148 EXPECT_RECT_EQ(expected_root_visible_rect,
4149 root_render_pass->quad_list[1]->visible_rect);
4152 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4153 host_impl_->DidDrawAllLayers(frame);
4154 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
4158 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
4159 scoped_ptr<SolidColorLayerImpl> root =
4160 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4161 root->SetAnchorPoint(gfx::PointF());
4162 root->SetPosition(gfx::PointF());
4163 root->SetBounds(gfx::Size(10, 10));
4164 root->SetContentBounds(gfx::Size(10, 10));
4165 root->SetDrawsContent(true);
4167 // Child layer is in the bottom right corner.
4168 scoped_ptr<SolidColorLayerImpl> child =
4169 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
4170 child->SetAnchorPoint(gfx::PointF(0.f, 0.f));
4171 child->SetPosition(gfx::PointF(9.f, 9.f));
4172 child->SetBounds(gfx::Size(1, 1));
4173 child->SetContentBounds(gfx::Size(1, 1));
4174 child->SetDrawsContent(true);
4175 root->AddChild(child.PassAs<LayerImpl>());
4177 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
4179 // Draw a frame. In the first frame, the entire viewport should be damaged.
4180 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
4181 DrawFrameAndTestDamage(full_frame_damage);
4183 // The second frame has damage that doesn't touch the child layer. Its quads
4184 // should still be generated.
4185 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
4186 host_impl_->active_tree()->root_layer()->set_update_rect(small_damage);
4187 DrawFrameAndTestDamage(small_damage);
4189 // The third frame should have no damage, so no quads should be generated.
4190 gfx::Rect no_damage;
4191 DrawFrameAndTestDamage(no_damage);
4194 class FakeMaskLayerImpl : public LayerImpl {
4196 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
4198 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
4201 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
4206 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
4207 : LayerImpl(tree_impl, id) {}
4210 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
4211 LayerTreeSettings settings;
4212 settings.layer_transforms_should_scale_layer_contents = true;
4213 host_impl_ = LayerTreeHostImpl::Create(
4214 settings, this, &proxy_, &stats_instrumentation_, NULL);
4215 host_impl_->InitializeRenderer(CreateOutputSurface());
4216 host_impl_->SetViewportSize(gfx::Size(10, 10));
4220 // +-- Scaling Layer (adds a 2x scale)
4222 // +-- Content Layer
4224 scoped_ptr<LayerImpl> scoped_root =
4225 LayerImpl::Create(host_impl_->active_tree(), 1);
4226 LayerImpl* root = scoped_root.get();
4227 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4229 scoped_ptr<LayerImpl> scoped_scaling_layer =
4230 LayerImpl::Create(host_impl_->active_tree(), 2);
4231 LayerImpl* scaling_layer = scoped_scaling_layer.get();
4232 root->AddChild(scoped_scaling_layer.Pass());
4234 scoped_ptr<LayerImpl> scoped_content_layer =
4235 LayerImpl::Create(host_impl_->active_tree(), 3);
4236 LayerImpl* content_layer = scoped_content_layer.get();
4237 scaling_layer->AddChild(scoped_content_layer.Pass());
4239 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4240 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4241 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4242 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4244 gfx::Size root_size(100, 100);
4245 root->SetBounds(root_size);
4246 root->SetContentBounds(root_size);
4247 root->SetPosition(gfx::PointF());
4248 root->SetAnchorPoint(gfx::PointF());
4250 gfx::Size scaling_layer_size(50, 50);
4251 scaling_layer->SetBounds(scaling_layer_size);
4252 scaling_layer->SetContentBounds(scaling_layer_size);
4253 scaling_layer->SetPosition(gfx::PointF());
4254 scaling_layer->SetAnchorPoint(gfx::PointF());
4255 gfx::Transform scale;
4256 scale.Scale(2.f, 2.f);
4257 scaling_layer->SetTransform(scale);
4259 content_layer->SetBounds(scaling_layer_size);
4260 content_layer->SetContentBounds(scaling_layer_size);
4261 content_layer->SetPosition(gfx::PointF());
4262 content_layer->SetAnchorPoint(gfx::PointF());
4263 content_layer->SetDrawsContent(true);
4265 mask_layer->SetBounds(scaling_layer_size);
4266 mask_layer->SetContentBounds(scaling_layer_size);
4267 mask_layer->SetPosition(gfx::PointF());
4268 mask_layer->SetAnchorPoint(gfx::PointF());
4269 mask_layer->SetDrawsContent(true);
4272 // Check that the tree scaling is correctly taken into account for the mask,
4273 // that should fully map onto the quad.
4274 float device_scale_factor = 1.f;
4275 host_impl_->SetViewportSize(root_size);
4276 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4278 LayerTreeHostImpl::FrameData frame;
4279 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4281 ASSERT_EQ(1u, frame.render_passes.size());
4282 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4283 ASSERT_EQ(DrawQuad::RENDER_PASS,
4284 frame.render_passes[0]->quad_list[0]->material);
4285 const RenderPassDrawQuad* render_pass_quad =
4286 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4287 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4288 render_pass_quad->rect.ToString());
4289 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4290 render_pass_quad->mask_uv_rect.ToString());
4292 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4293 host_impl_->DidDrawAllLayers(frame);
4297 // Applying a DSF should change the render surface size, but won't affect
4298 // which part of the mask is used.
4299 device_scale_factor = 2.f;
4300 gfx::Size device_viewport =
4301 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4302 host_impl_->SetViewportSize(device_viewport);
4303 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4304 host_impl_->active_tree()->set_needs_update_draw_properties();
4306 LayerTreeHostImpl::FrameData frame;
4307 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4309 ASSERT_EQ(1u, frame.render_passes.size());
4310 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4311 ASSERT_EQ(DrawQuad::RENDER_PASS,
4312 frame.render_passes[0]->quad_list[0]->material);
4313 const RenderPassDrawQuad* render_pass_quad =
4314 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4315 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4316 render_pass_quad->rect.ToString());
4317 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4318 render_pass_quad->mask_uv_rect.ToString());
4320 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4321 host_impl_->DidDrawAllLayers(frame);
4325 // Applying an equivalent content scale on the content layer and the mask
4326 // should still result in the same part of the mask being used.
4327 gfx::Size content_bounds =
4328 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
4329 device_scale_factor));
4330 content_layer->SetContentBounds(content_bounds);
4331 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4332 mask_layer->SetContentBounds(content_bounds);
4333 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4334 host_impl_->active_tree()->set_needs_update_draw_properties();
4336 LayerTreeHostImpl::FrameData frame;
4337 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4339 ASSERT_EQ(1u, frame.render_passes.size());
4340 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4341 ASSERT_EQ(DrawQuad::RENDER_PASS,
4342 frame.render_passes[0]->quad_list[0]->material);
4343 const RenderPassDrawQuad* render_pass_quad =
4344 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4345 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4346 render_pass_quad->rect.ToString());
4347 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4348 render_pass_quad->mask_uv_rect.ToString());
4350 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4351 host_impl_->DidDrawAllLayers(frame);
4355 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
4356 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4359 scoped_ptr<LayerImpl> scoped_root =
4360 LayerImpl::Create(host_impl_->active_tree(), 1);
4361 LayerImpl* root = scoped_root.get();
4362 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4364 scoped_ptr<LayerImpl> scoped_content_layer =
4365 LayerImpl::Create(host_impl_->active_tree(), 3);
4366 LayerImpl* content_layer = scoped_content_layer.get();
4367 root->AddChild(scoped_content_layer.Pass());
4369 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4370 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4371 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4372 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4374 gfx::Size root_size(100, 100);
4375 root->SetBounds(root_size);
4376 root->SetContentBounds(root_size);
4377 root->SetPosition(gfx::PointF());
4378 root->SetAnchorPoint(gfx::PointF());
4380 gfx::Size layer_size(50, 50);
4381 content_layer->SetBounds(layer_size);
4382 content_layer->SetContentBounds(layer_size);
4383 content_layer->SetPosition(gfx::PointF());
4384 content_layer->SetAnchorPoint(gfx::PointF());
4385 content_layer->SetDrawsContent(true);
4387 gfx::Size mask_size(100, 100);
4388 mask_layer->SetBounds(mask_size);
4389 mask_layer->SetContentBounds(mask_size);
4390 mask_layer->SetPosition(gfx::PointF());
4391 mask_layer->SetAnchorPoint(gfx::PointF());
4392 mask_layer->SetDrawsContent(true);
4394 // Check that the mask fills the surface.
4395 float device_scale_factor = 1.f;
4396 host_impl_->SetViewportSize(root_size);
4397 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4399 LayerTreeHostImpl::FrameData frame;
4400 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4402 ASSERT_EQ(1u, frame.render_passes.size());
4403 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4404 ASSERT_EQ(DrawQuad::RENDER_PASS,
4405 frame.render_passes[0]->quad_list[0]->material);
4406 const RenderPassDrawQuad* render_pass_quad =
4407 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4408 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4409 render_pass_quad->rect.ToString());
4410 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4411 render_pass_quad->mask_uv_rect.ToString());
4413 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4414 host_impl_->DidDrawAllLayers(frame);
4417 // Applying a DSF should change the render surface size, but won't affect
4418 // which part of the mask is used.
4419 device_scale_factor = 2.f;
4420 gfx::Size device_viewport =
4421 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4422 host_impl_->SetViewportSize(device_viewport);
4423 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4424 host_impl_->active_tree()->set_needs_update_draw_properties();
4426 LayerTreeHostImpl::FrameData frame;
4427 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4429 ASSERT_EQ(1u, frame.render_passes.size());
4430 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4431 ASSERT_EQ(DrawQuad::RENDER_PASS,
4432 frame.render_passes[0]->quad_list[0]->material);
4433 const RenderPassDrawQuad* render_pass_quad =
4434 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4435 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4436 render_pass_quad->rect.ToString());
4437 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4438 render_pass_quad->mask_uv_rect.ToString());
4440 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4441 host_impl_->DidDrawAllLayers(frame);
4444 // Applying an equivalent content scale on the content layer and the mask
4445 // should still result in the same part of the mask being used.
4446 gfx::Size layer_size_large =
4447 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
4448 content_layer->SetContentBounds(layer_size_large);
4449 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4450 gfx::Size mask_size_large =
4451 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
4452 mask_layer->SetContentBounds(mask_size_large);
4453 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4454 host_impl_->active_tree()->set_needs_update_draw_properties();
4456 LayerTreeHostImpl::FrameData frame;
4457 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4459 ASSERT_EQ(1u, frame.render_passes.size());
4460 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4461 ASSERT_EQ(DrawQuad::RENDER_PASS,
4462 frame.render_passes[0]->quad_list[0]->material);
4463 const RenderPassDrawQuad* render_pass_quad =
4464 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4465 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4466 render_pass_quad->rect.ToString());
4467 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4468 render_pass_quad->mask_uv_rect.ToString());
4470 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4471 host_impl_->DidDrawAllLayers(frame);
4474 // Applying a different contents scale to the mask layer means it will have
4475 // a larger texture, but it should use the same tex coords to cover the
4477 mask_layer->SetContentBounds(mask_size);
4478 mask_layer->SetContentsScale(1.f, 1.f);
4479 host_impl_->active_tree()->set_needs_update_draw_properties();
4481 LayerTreeHostImpl::FrameData frame;
4482 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4484 ASSERT_EQ(1u, frame.render_passes.size());
4485 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4486 ASSERT_EQ(DrawQuad::RENDER_PASS,
4487 frame.render_passes[0]->quad_list[0]->material);
4488 const RenderPassDrawQuad* render_pass_quad =
4489 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4490 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4491 render_pass_quad->rect.ToString());
4492 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4493 render_pass_quad->mask_uv_rect.ToString());
4495 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4496 host_impl_->DidDrawAllLayers(frame);
4500 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
4501 // The replica's mask layer has bounds 100x100 but the replica is of a
4502 // layer with bounds 50x50.
4504 scoped_ptr<LayerImpl> scoped_root =
4505 LayerImpl::Create(host_impl_->active_tree(), 1);
4506 LayerImpl* root = scoped_root.get();
4507 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4509 scoped_ptr<LayerImpl> scoped_content_layer =
4510 LayerImpl::Create(host_impl_->active_tree(), 3);
4511 LayerImpl* content_layer = scoped_content_layer.get();
4512 root->AddChild(scoped_content_layer.Pass());
4514 scoped_ptr<LayerImpl> scoped_replica_layer =
4515 LayerImpl::Create(host_impl_->active_tree(), 2);
4516 LayerImpl* replica_layer = scoped_replica_layer.get();
4517 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
4519 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4520 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4521 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4522 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4524 gfx::Size root_size(100, 100);
4525 root->SetBounds(root_size);
4526 root->SetContentBounds(root_size);
4527 root->SetPosition(gfx::PointF());
4528 root->SetAnchorPoint(gfx::PointF());
4530 gfx::Size layer_size(50, 50);
4531 content_layer->SetBounds(layer_size);
4532 content_layer->SetContentBounds(layer_size);
4533 content_layer->SetPosition(gfx::PointF());
4534 content_layer->SetAnchorPoint(gfx::PointF());
4535 content_layer->SetDrawsContent(true);
4537 gfx::Size mask_size(100, 100);
4538 mask_layer->SetBounds(mask_size);
4539 mask_layer->SetContentBounds(mask_size);
4540 mask_layer->SetPosition(gfx::PointF());
4541 mask_layer->SetAnchorPoint(gfx::PointF());
4542 mask_layer->SetDrawsContent(true);
4544 // Check that the mask fills the surface.
4545 float device_scale_factor = 1.f;
4546 host_impl_->SetViewportSize(root_size);
4547 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4549 LayerTreeHostImpl::FrameData frame;
4550 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4552 ASSERT_EQ(1u, frame.render_passes.size());
4553 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4554 ASSERT_EQ(DrawQuad::RENDER_PASS,
4555 frame.render_passes[0]->quad_list[1]->material);
4556 const RenderPassDrawQuad* replica_quad =
4557 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4558 EXPECT_TRUE(replica_quad->is_replica);
4559 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4560 replica_quad->rect.ToString());
4561 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4562 replica_quad->mask_uv_rect.ToString());
4564 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4565 host_impl_->DidDrawAllLayers(frame);
4568 // Applying a DSF should change the render surface size, but won't affect
4569 // which part of the mask is used.
4570 device_scale_factor = 2.f;
4571 gfx::Size device_viewport =
4572 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4573 host_impl_->SetViewportSize(device_viewport);
4574 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4575 host_impl_->active_tree()->set_needs_update_draw_properties();
4577 LayerTreeHostImpl::FrameData frame;
4578 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4580 ASSERT_EQ(1u, frame.render_passes.size());
4581 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4582 ASSERT_EQ(DrawQuad::RENDER_PASS,
4583 frame.render_passes[0]->quad_list[1]->material);
4584 const RenderPassDrawQuad* replica_quad =
4585 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4586 EXPECT_TRUE(replica_quad->is_replica);
4587 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4588 replica_quad->rect.ToString());
4589 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4590 replica_quad->mask_uv_rect.ToString());
4592 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4593 host_impl_->DidDrawAllLayers(frame);
4596 // Applying an equivalent content scale on the content layer and the mask
4597 // should still result in the same part of the mask being used.
4598 gfx::Size layer_size_large =
4599 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
4600 content_layer->SetContentBounds(layer_size_large);
4601 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4602 gfx::Size mask_size_large =
4603 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
4604 mask_layer->SetContentBounds(mask_size_large);
4605 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4606 host_impl_->active_tree()->set_needs_update_draw_properties();
4608 LayerTreeHostImpl::FrameData frame;
4609 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4611 ASSERT_EQ(1u, frame.render_passes.size());
4612 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4613 ASSERT_EQ(DrawQuad::RENDER_PASS,
4614 frame.render_passes[0]->quad_list[1]->material);
4615 const RenderPassDrawQuad* replica_quad =
4616 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4617 EXPECT_TRUE(replica_quad->is_replica);
4618 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4619 replica_quad->rect.ToString());
4620 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4621 replica_quad->mask_uv_rect.ToString());
4623 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4624 host_impl_->DidDrawAllLayers(frame);
4627 // Applying a different contents scale to the mask layer means it will have
4628 // a larger texture, but it should use the same tex coords to cover the
4630 mask_layer->SetContentBounds(mask_size);
4631 mask_layer->SetContentsScale(1.f, 1.f);
4632 host_impl_->active_tree()->set_needs_update_draw_properties();
4634 LayerTreeHostImpl::FrameData frame;
4635 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4637 ASSERT_EQ(1u, frame.render_passes.size());
4638 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4639 ASSERT_EQ(DrawQuad::RENDER_PASS,
4640 frame.render_passes[0]->quad_list[1]->material);
4641 const RenderPassDrawQuad* replica_quad =
4642 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4643 EXPECT_TRUE(replica_quad->is_replica);
4644 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4645 replica_quad->rect.ToString());
4646 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4647 replica_quad->mask_uv_rect.ToString());
4649 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4650 host_impl_->DidDrawAllLayers(frame);
4654 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
4655 // The replica is of a layer with bounds 50x50, but it has a child that causes
4656 // the surface bounds to be larger.
4658 scoped_ptr<LayerImpl> scoped_root =
4659 LayerImpl::Create(host_impl_->active_tree(), 1);
4660 LayerImpl* root = scoped_root.get();
4661 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4663 scoped_ptr<LayerImpl> scoped_content_layer =
4664 LayerImpl::Create(host_impl_->active_tree(), 2);
4665 LayerImpl* content_layer = scoped_content_layer.get();
4666 root->AddChild(scoped_content_layer.Pass());
4668 scoped_ptr<LayerImpl> scoped_content_child_layer =
4669 LayerImpl::Create(host_impl_->active_tree(), 3);
4670 LayerImpl* content_child_layer = scoped_content_child_layer.get();
4671 content_layer->AddChild(scoped_content_child_layer.Pass());
4673 scoped_ptr<LayerImpl> scoped_replica_layer =
4674 LayerImpl::Create(host_impl_->active_tree(), 4);
4675 LayerImpl* replica_layer = scoped_replica_layer.get();
4676 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
4678 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4679 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
4680 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4681 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4683 gfx::Size root_size(100, 100);
4684 root->SetBounds(root_size);
4685 root->SetContentBounds(root_size);
4686 root->SetPosition(gfx::PointF());
4687 root->SetAnchorPoint(gfx::PointF());
4689 gfx::Size layer_size(50, 50);
4690 content_layer->SetBounds(layer_size);
4691 content_layer->SetContentBounds(layer_size);
4692 content_layer->SetPosition(gfx::PointF());
4693 content_layer->SetAnchorPoint(gfx::PointF());
4694 content_layer->SetDrawsContent(true);
4696 gfx::Size child_size(50, 50);
4697 content_child_layer->SetBounds(child_size);
4698 content_child_layer->SetContentBounds(child_size);
4699 content_child_layer->SetPosition(gfx::Point(50, 0));
4700 content_child_layer->SetAnchorPoint(gfx::PointF());
4701 content_child_layer->SetDrawsContent(true);
4703 gfx::Size mask_size(50, 50);
4704 mask_layer->SetBounds(mask_size);
4705 mask_layer->SetContentBounds(mask_size);
4706 mask_layer->SetPosition(gfx::PointF());
4707 mask_layer->SetAnchorPoint(gfx::PointF());
4708 mask_layer->SetDrawsContent(true);
4710 float device_scale_factor = 1.f;
4711 host_impl_->SetViewportSize(root_size);
4712 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4714 LayerTreeHostImpl::FrameData frame;
4715 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4717 ASSERT_EQ(1u, frame.render_passes.size());
4718 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4720 // The surface is 100x50.
4721 ASSERT_EQ(DrawQuad::RENDER_PASS,
4722 frame.render_passes[0]->quad_list[0]->material);
4723 const RenderPassDrawQuad* render_pass_quad =
4724 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4725 EXPECT_FALSE(render_pass_quad->is_replica);
4726 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
4727 render_pass_quad->rect.ToString());
4729 // The mask covers the owning layer only.
4730 ASSERT_EQ(DrawQuad::RENDER_PASS,
4731 frame.render_passes[0]->quad_list[1]->material);
4732 const RenderPassDrawQuad* replica_quad =
4733 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4734 EXPECT_TRUE(replica_quad->is_replica);
4735 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
4736 replica_quad->rect.ToString());
4737 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
4738 replica_quad->mask_uv_rect.ToString());
4740 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4741 host_impl_->DidDrawAllLayers(frame);
4744 // Move the child to (-50, 0) instead. Now the mask should be moved to still
4745 // cover the layer being replicated.
4746 content_child_layer->SetPosition(gfx::Point(-50, 0));
4748 LayerTreeHostImpl::FrameData frame;
4749 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4751 ASSERT_EQ(1u, frame.render_passes.size());
4752 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
4754 // The surface is 100x50 with its origin at (-50, 0).
4755 ASSERT_EQ(DrawQuad::RENDER_PASS,
4756 frame.render_passes[0]->quad_list[0]->material);
4757 const RenderPassDrawQuad* render_pass_quad =
4758 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4759 EXPECT_FALSE(render_pass_quad->is_replica);
4760 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
4761 render_pass_quad->rect.ToString());
4763 // The mask covers the owning layer only.
4764 ASSERT_EQ(DrawQuad::RENDER_PASS,
4765 frame.render_passes[0]->quad_list[1]->material);
4766 const RenderPassDrawQuad* replica_quad =
4767 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
4768 EXPECT_TRUE(replica_quad->is_replica);
4769 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
4770 replica_quad->rect.ToString());
4771 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
4772 replica_quad->mask_uv_rect.ToString());
4774 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4775 host_impl_->DidDrawAllLayers(frame);
4779 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
4780 // The masked layer has bounds 50x50, but it has a child that causes
4781 // the surface bounds to be larger. It also has a parent that clips the
4782 // masked layer and its surface.
4784 scoped_ptr<LayerImpl> scoped_root =
4785 LayerImpl::Create(host_impl_->active_tree(), 1);
4786 LayerImpl* root = scoped_root.get();
4787 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4789 scoped_ptr<LayerImpl> scoped_clipping_layer =
4790 LayerImpl::Create(host_impl_->active_tree(), 2);
4791 LayerImpl* clipping_layer = scoped_clipping_layer.get();
4792 root->AddChild(scoped_clipping_layer.Pass());
4794 scoped_ptr<LayerImpl> scoped_content_layer =
4795 LayerImpl::Create(host_impl_->active_tree(), 3);
4796 LayerImpl* content_layer = scoped_content_layer.get();
4797 clipping_layer->AddChild(scoped_content_layer.Pass());
4799 scoped_ptr<LayerImpl> scoped_content_child_layer =
4800 LayerImpl::Create(host_impl_->active_tree(), 4);
4801 LayerImpl* content_child_layer = scoped_content_child_layer.get();
4802 content_layer->AddChild(scoped_content_child_layer.Pass());
4804 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4805 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
4806 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4807 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4809 gfx::Size root_size(100, 100);
4810 root->SetBounds(root_size);
4811 root->SetContentBounds(root_size);
4812 root->SetPosition(gfx::PointF());
4813 root->SetAnchorPoint(gfx::PointF());
4815 gfx::Rect clipping_rect(20, 10, 10, 20);
4816 clipping_layer->SetBounds(clipping_rect.size());
4817 clipping_layer->SetContentBounds(clipping_rect.size());
4818 clipping_layer->SetPosition(clipping_rect.origin());
4819 clipping_layer->SetAnchorPoint(gfx::PointF());
4820 clipping_layer->SetMasksToBounds(true);
4822 gfx::Size layer_size(50, 50);
4823 content_layer->SetBounds(layer_size);
4824 content_layer->SetContentBounds(layer_size);
4825 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
4826 content_layer->SetAnchorPoint(gfx::PointF());
4827 content_layer->SetDrawsContent(true);
4829 gfx::Size child_size(50, 50);
4830 content_child_layer->SetBounds(child_size);
4831 content_child_layer->SetContentBounds(child_size);
4832 content_child_layer->SetPosition(gfx::Point(50, 0));
4833 content_child_layer->SetAnchorPoint(gfx::PointF());
4834 content_child_layer->SetDrawsContent(true);
4836 gfx::Size mask_size(100, 100);
4837 mask_layer->SetBounds(mask_size);
4838 mask_layer->SetContentBounds(mask_size);
4839 mask_layer->SetPosition(gfx::PointF());
4840 mask_layer->SetAnchorPoint(gfx::PointF());
4841 mask_layer->SetDrawsContent(true);
4843 float device_scale_factor = 1.f;
4844 host_impl_->SetViewportSize(root_size);
4845 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4847 LayerTreeHostImpl::FrameData frame;
4848 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4850 ASSERT_EQ(1u, frame.render_passes.size());
4851 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4853 // The surface is clipped to 10x20.
4854 ASSERT_EQ(DrawQuad::RENDER_PASS,
4855 frame.render_passes[0]->quad_list[0]->material);
4856 const RenderPassDrawQuad* render_pass_quad =
4857 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4858 EXPECT_FALSE(render_pass_quad->is_replica);
4859 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
4860 render_pass_quad->rect.ToString());
4862 // The masked layer is 50x50, but the surface size is 10x20. So the texture
4863 // coords in the mask are scaled by 10/50 and 20/50.
4864 // The surface is clipped to (20,10) so the mask texture coords are offset
4865 // by 20/50 and 10/50
4866 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f),
4867 1.f / 50.f).ToString(),
4868 render_pass_quad->mask_uv_rect.ToString());
4870 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4871 host_impl_->DidDrawAllLayers(frame);
4875 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
4877 using GLRenderer::SetupQuadForAntialiasing;
4880 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
4881 // Due to precision issues (especially on Android), sometimes far
4882 // away quads can end up thinking they need AA.
4883 float device_scale_factor = 4.f / 3.f;
4884 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4885 gfx::Size root_size(2000, 1000);
4886 gfx::Size device_viewport_size =
4887 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
4888 host_impl_->SetViewportSize(device_viewport_size);
4890 host_impl_->CreatePendingTree();
4891 host_impl_->pending_tree()
4892 ->SetPageScaleFactorAndLimits(1.f, 1.f / 16.f, 16.f);
4894 scoped_ptr<LayerImpl> scoped_root =
4895 LayerImpl::Create(host_impl_->pending_tree(), 1);
4896 LayerImpl* root = scoped_root.get();
4898 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
4900 scoped_ptr<LayerImpl> scoped_scrolling_layer =
4901 LayerImpl::Create(host_impl_->pending_tree(), 2);
4902 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
4903 root->AddChild(scoped_scrolling_layer.Pass());
4905 gfx::Size content_layer_bounds(100000, 100);
4906 gfx::Size pile_tile_size(3000, 3000);
4907 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
4908 pile_tile_size, content_layer_bounds));
4910 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
4911 FakePictureLayerImpl::CreateWithPile(host_impl_->pending_tree(), 3, pile);
4912 LayerImpl* content_layer = scoped_content_layer.get();
4913 scrolling_layer->AddChild(scoped_content_layer.PassAs<LayerImpl>());
4914 content_layer->SetBounds(content_layer_bounds);
4915 content_layer->SetDrawsContent(true);
4917 root->SetBounds(root_size);
4919 gfx::Vector2d scroll_offset(100000, 0);
4920 scrolling_layer->SetScrollable(true);
4921 scrolling_layer->SetMaxScrollOffset(scroll_offset);
4922 scrolling_layer->SetScrollOffset(scroll_offset);
4924 host_impl_->ActivatePendingTree();
4926 host_impl_->active_tree()->UpdateDrawProperties();
4927 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
4929 LayerTreeHostImpl::FrameData frame;
4930 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4932 ASSERT_EQ(1u, frame.render_passes.size());
4933 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
4934 const DrawQuad* quad = frame.render_passes[0]->quad_list[0];
4937 gfx::QuadF device_layer_quad;
4939 GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
4940 quad->quadTransform(), quad, &device_layer_quad, edge);
4941 EXPECT_FALSE(antialiased);
4943 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4944 host_impl_->DidDrawAllLayers(frame);
4948 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
4950 CompositorFrameMetadataTest()
4951 : swap_buffers_complete_(0) {}
4953 virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {
4954 swap_buffers_complete_++;
4957 int swap_buffers_complete_;
4960 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
4961 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4963 LayerTreeHostImpl::FrameData frame;
4964 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
4965 host_impl_->DrawLayers(&frame, base::TimeTicks());
4966 host_impl_->DidDrawAllLayers(frame);
4968 CompositorFrameAck ack;
4969 host_impl_->ReclaimResources(&ack);
4970 host_impl_->OnSwapBuffersComplete();
4971 EXPECT_EQ(swap_buffers_complete_, 1);
4974 class CountingSoftwareDevice : public SoftwareOutputDevice {
4976 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
4978 virtual SkCanvas* BeginPaint(gfx::Rect damage_rect) OVERRIDE {
4980 return SoftwareOutputDevice::BeginPaint(damage_rect);
4982 virtual void EndPaint(SoftwareFrameData* frame_data) OVERRIDE {
4984 SoftwareOutputDevice::EndPaint(frame_data);
4987 int frames_began_, frames_ended_;
4990 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
4991 // No main thread evictions in resourceless software mode.
4992 set_reduce_memory_result(false);
4993 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4994 host_impl_->SetViewportSize(gfx::Size(50, 50));
4995 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
4996 FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
4997 scoped_ptr<SoftwareOutputDevice>(software_device)).release();
4998 EXPECT_TRUE(host_impl_->InitializeRenderer(
4999 scoped_ptr<OutputSurface>(output_surface)));
5001 output_surface->set_forced_draw_to_software_device(true);
5002 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5004 EXPECT_EQ(0, software_device->frames_began_);
5005 EXPECT_EQ(0, software_device->frames_ended_);
5009 EXPECT_EQ(1, software_device->frames_began_);
5010 EXPECT_EQ(1, software_device->frames_ended_);
5012 // Call other API methods that are likely to hit NULL pointer in this mode.
5013 EXPECT_TRUE(host_impl_->AsValue());
5014 EXPECT_TRUE(host_impl_->ActivationStateAsValue());
5017 TEST_F(LayerTreeHostImplTest,
5018 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
5019 set_reduce_memory_result(false);
5020 FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
5021 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())).release();
5022 host_impl_->InitializeRenderer(
5023 scoped_ptr<OutputSurface>(output_surface));
5025 output_surface->set_forced_draw_to_software_device(true);
5026 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5028 // SolidColorLayerImpl will be drawn.
5029 scoped_ptr<SolidColorLayerImpl> root_layer =
5030 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5032 // VideoLayerImpl will not be drawn.
5033 FakeVideoFrameProvider provider;
5034 scoped_ptr<VideoLayerImpl> video_layer =
5035 VideoLayerImpl::Create(host_impl_->active_tree(), 2, &provider);
5036 video_layer->SetBounds(gfx::Size(10, 10));
5037 video_layer->SetContentBounds(gfx::Size(10, 10));
5038 video_layer->SetDrawsContent(true);
5039 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
5040 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5042 LayerTreeHostImpl::FrameData frame;
5043 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5044 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5045 host_impl_->DidDrawAllLayers(frame);
5047 EXPECT_EQ(1u, frame.will_draw_layers.size());
5048 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
5051 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
5053 virtual void SetUp() OVERRIDE {
5054 LayerTreeHostImplTest::SetUp();
5056 set_reduce_memory_result(false);
5058 scoped_ptr<FakeOutputSurface> output_surface(
5059 FakeOutputSurface::CreateDeferredGL(
5060 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())));
5061 output_surface_ = output_surface.get();
5063 EXPECT_TRUE(host_impl_->InitializeRenderer(
5064 output_surface.PassAs<OutputSurface>()));
5066 scoped_ptr<SolidColorLayerImpl> root_layer =
5067 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5068 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5070 onscreen_context_provider_ = TestContextProvider::Create();
5071 offscreen_context_provider_ = TestContextProvider::Create();
5074 FakeOutputSurface* output_surface_;
5075 scoped_refptr<TestContextProvider> onscreen_context_provider_;
5076 scoped_refptr<TestContextProvider> offscreen_context_provider_;
5080 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
5084 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5085 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5087 // DeferredInitialize and hardware draw.
5088 EXPECT_TRUE(output_surface_->InitializeAndSetContext3d(
5089 onscreen_context_provider_, offscreen_context_provider_));
5090 EXPECT_EQ(onscreen_context_provider_,
5091 host_impl_->output_surface()->context_provider());
5092 EXPECT_EQ(offscreen_context_provider_,
5093 host_impl_->offscreen_context_provider());
5095 // Defer intialized GL draw.
5098 // Revert back to software.
5099 output_surface_->ReleaseGL();
5100 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5101 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5103 // Software draw again.
5107 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_0) {
5111 // Fail initialization of the onscreen context before the OutputSurface binds
5112 // it to the thread.
5113 onscreen_context_provider_->UnboundTestContext3d()
5114 ->set_times_make_current_succeeds(0);
5116 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5117 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5118 EXPECT_FALSE(did_lose_output_surface_);
5120 // DeferredInitialize fails.
5121 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5122 onscreen_context_provider_, offscreen_context_provider_));
5123 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5124 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5126 // Software draw again.
5130 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_1) {
5134 // Fail initialization of the onscreen context after the OutputSurface binds
5135 // it to the thread.
5136 onscreen_context_provider_->UnboundTestContext3d()
5137 ->set_times_make_current_succeeds(2);
5139 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5140 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5141 EXPECT_FALSE(did_lose_output_surface_);
5143 // DeferredInitialize fails.
5144 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5145 onscreen_context_provider_, offscreen_context_provider_));
5146 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5147 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5149 // We lose the output surface.
5150 EXPECT_TRUE(did_lose_output_surface_);
5153 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OnscreenContext_2) {
5157 // Fail initialization of the onscreen context after the OutputSurface binds
5158 // it to the thread and during renderer initialization.
5159 onscreen_context_provider_->UnboundTestContext3d()
5160 ->set_times_make_current_succeeds(1);
5162 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5163 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5164 EXPECT_FALSE(did_lose_output_surface_);
5166 // DeferredInitialize fails.
5167 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5168 onscreen_context_provider_, offscreen_context_provider_));
5169 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5170 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5172 // We lose the output surface.
5173 EXPECT_TRUE(did_lose_output_surface_);
5176 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails_OffscreenContext) {
5180 // Fail initialization of the offscreen context.
5181 offscreen_context_provider_->UnboundTestContext3d()
5182 ->set_times_make_current_succeeds(0);
5184 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5185 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5186 EXPECT_FALSE(did_lose_output_surface_);
5188 // DeferredInitialize fails.
5189 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
5190 onscreen_context_provider_, offscreen_context_provider_));
5191 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5192 EXPECT_FALSE(host_impl_->offscreen_context_provider());
5194 // We lose the output surface.
5195 EXPECT_TRUE(did_lose_output_surface_);
5198 // Checks that we have a non-0 default allocation if we pass a context that
5199 // doesn't support memory management extensions.
5200 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5201 LayerTreeSettings settings;
5202 host_impl_ = LayerTreeHostImpl::Create(
5203 settings, this, &proxy_, &stats_instrumentation_, NULL);
5205 scoped_ptr<OutputSurface> output_surface(
5206 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5207 host_impl_->InitializeRenderer(output_surface.Pass());
5208 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5211 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5212 ManagedMemoryPolicy policy1(
5213 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5214 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5215 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5216 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5217 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5219 host_impl_->SetVisible(true);
5220 host_impl_->SetMemoryPolicy(policy1);
5221 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5222 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5224 host_impl_->SetVisible(false);
5225 EXPECT_EQ(0u, current_limit_bytes_);
5226 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5228 host_impl_->SetVisible(true);
5229 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5230 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5233 class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
5235 virtual void SetUp() OVERRIDE {
5236 LayerTreeSettings settings;
5237 settings.impl_side_painting = true;
5239 fake_host_impl_ = new FakeLayerTreeHostImpl(settings, &proxy_);
5240 host_impl_.reset(fake_host_impl_);
5241 host_impl_->InitializeRenderer(CreateOutputSurface());
5242 host_impl_->SetViewportSize(gfx::Size(10, 10));
5245 FakeLayerTreeHostImpl* fake_host_impl_;
5248 TEST_F(LayerTreeHostImplTestManageTiles, ManageTilesWhenInvisible) {
5249 fake_host_impl_->DidModifyTilePriorities();
5250 EXPECT_TRUE(fake_host_impl_->manage_tiles_needed());
5251 fake_host_impl_->SetVisible(false);
5252 EXPECT_FALSE(fake_host_impl_->manage_tiles_needed());
5255 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
5256 scoped_ptr<TestWebGraphicsContext3D> context =
5257 TestWebGraphicsContext3D::Create();
5258 TestWebGraphicsContext3D* context3d = context.get();
5259 scoped_ptr<OutputSurface> output_surface = CreateFakeOutputSurface();
5260 host_impl_->InitializeRenderer(output_surface.Pass());
5262 EXPECT_EQ(0u, context3d->NumTextures());
5265 skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
5266 skbitmap.allocPixels();
5267 skbitmap.setImmutable();
5269 UIResourceId ui_resource_id = 1;
5270 UIResourceBitmap bitmap(skbitmap);
5271 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5272 EXPECT_EQ(1u, context3d->NumTextures());
5273 ResourceProvider::ResourceId id1 =
5274 host_impl_->ResourceIdForUIResource(ui_resource_id);
5277 // Multiple requests with the same id is allowed. The previous texture is
5279 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5280 EXPECT_EQ(1u, context3d->NumTextures());
5281 ResourceProvider::ResourceId id2 =
5282 host_impl_->ResourceIdForUIResource(ui_resource_id);
5284 EXPECT_NE(id1, id2);
5286 // Deleting invalid UIResourceId is allowed and does not change state.
5287 host_impl_->DeleteUIResource(-1);
5288 EXPECT_EQ(1u, context3d->NumTextures());
5290 // Should return zero for invalid UIResourceId. Number of textures should
5292 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
5293 EXPECT_EQ(1u, context3d->NumTextures());
5295 host_impl_->DeleteUIResource(ui_resource_id);
5296 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
5297 EXPECT_EQ(0u, context3d->NumTextures());
5299 // Should not change state for multiple deletion on one UIResourceId
5300 host_impl_->DeleteUIResource(ui_resource_id);
5301 EXPECT_EQ(0u, context3d->NumTextures());
5304 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
5307 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
5308 scoped_refptr<TestContextProvider> context_provider =
5309 TestContextProvider::Create();
5311 host_impl_ = LayerTreeHostImpl::Create(
5312 LayerTreeSettings(), this, &proxy_, &stats_instrumentation_, NULL);
5313 host_impl_->InitializeRenderer(FakeOutputSurface::Create3d(context_provider)
5314 .PassAs<OutputSurface>());
5315 host_impl_->SetViewportSize(gfx::Size(10, 10));
5317 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5319 ScopedPtrVector<CopyOutputRequest> requests;
5320 requests.push_back(CopyOutputRequest::CreateRequest(
5321 base::Bind(&ShutdownReleasesContext_Callback)));
5323 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
5325 LayerTreeHostImpl::FrameData frame;
5326 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5327 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5328 host_impl_->DidDrawAllLayers(frame);
5330 // The CopyOutputResult's callback has a ref on the ContextProvider and a
5331 // texture in a texture mailbox.
5332 EXPECT_FALSE(context_provider->HasOneRef());
5333 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
5337 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
5338 // released, and the texture deleted.
5339 EXPECT_TRUE(context_provider->HasOneRef());
5340 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
5343 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
5344 // When flinging via touch, only the child should scroll (we should not
5346 gfx::Size surface_size(10, 10);
5347 gfx::Size content_size(20, 20);
5348 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
5349 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
5351 root->AddChild(child.Pass());
5353 host_impl_->SetViewportSize(surface_size);
5354 host_impl_->active_tree()->SetRootLayer(root.Pass());
5355 host_impl_->active_tree()->DidBecomeActive();
5356 InitializeRendererAndDrawFrame();
5358 EXPECT_EQ(InputHandler::ScrollStarted,
5359 host_impl_->ScrollBegin(gfx::Point(),
5360 InputHandler::Gesture));
5362 EXPECT_EQ(InputHandler::ScrollStarted,
5363 host_impl_->FlingScrollBegin());
5365 gfx::Vector2d scroll_delta(0, 100);
5366 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5367 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5369 host_impl_->ScrollEnd();
5371 scoped_ptr<ScrollAndScaleSet> scroll_info =
5372 host_impl_->ProcessScrollDeltas();
5374 // Only the child should have scrolled.
5375 ASSERT_EQ(1u, scroll_info->scrolls.size());
5376 ExpectNone(*scroll_info.get(),
5377 host_impl_->active_tree()->root_layer()->id());
5381 TEST_F(LayerTreeHostImplTest, TouchFlingShouldBubbleIfPrecedingScrollBubbled) {
5382 // When flinging via touch, bubble scrolls if the touch scroll
5383 // immediately preceding the fling bubbled.
5384 gfx::Size surface_size(10, 10);
5385 gfx::Size root_content_size(10, 20);
5386 gfx::Size child_content_size(40, 40);
5387 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, root_content_size);
5388 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, child_content_size);
5390 root->AddChild(child.Pass());
5392 host_impl_->SetViewportSize(surface_size);
5393 host_impl_->active_tree()->SetRootLayer(root.Pass());
5394 host_impl_->active_tree()->DidBecomeActive();
5395 InitializeRendererAndDrawFrame();
5397 EXPECT_EQ(InputHandler::ScrollStarted,
5398 host_impl_->ScrollBegin(gfx::Point(),
5399 InputHandler::Gesture));
5401 // Touch scroll before starting the fling. The second scroll should bubble.
5402 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 100)));
5403 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 5)));
5405 scoped_ptr<ScrollAndScaleSet> scroll_info =
5406 host_impl_->ProcessScrollDeltas();
5408 // The root should have (partially) scrolled.
5409 EXPECT_EQ(2u, scroll_info->scrolls.size());
5410 ExpectContains(*scroll_info.get(),
5411 host_impl_->active_tree()->root_layer()->id(),
5412 gfx::Vector2d(0, 5));
5414 EXPECT_EQ(InputHandler::ScrollStarted,
5415 host_impl_->FlingScrollBegin());
5417 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 5)));
5418 host_impl_->ScrollEnd();
5420 // The root should have (fully) scrolled from the fling.
5421 scroll_info = host_impl_->ProcessScrollDeltas();
5422 EXPECT_EQ(2u, scroll_info->scrolls.size());
5423 ExpectContains(*scroll_info.get(),
5424 host_impl_->active_tree()->root_layer()->id(),
5425 gfx::Vector2d(0, 10));
5429 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
5430 // When flinging via wheel, the root should eventually scroll (we should
5432 gfx::Size surface_size(10, 10);
5433 gfx::Size content_size(20, 20);
5434 scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
5435 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
5437 root->AddChild(child.Pass());
5439 host_impl_->SetViewportSize(surface_size);
5440 host_impl_->active_tree()->SetRootLayer(root.Pass());
5441 host_impl_->active_tree()->DidBecomeActive();
5442 InitializeRendererAndDrawFrame();
5444 EXPECT_EQ(InputHandler::ScrollStarted,
5445 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
5447 EXPECT_EQ(InputHandler::ScrollStarted,
5448 host_impl_->FlingScrollBegin());
5450 gfx::Vector2d scroll_delta(0, 100);
5451 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5452 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5454 host_impl_->ScrollEnd();
5456 scoped_ptr<ScrollAndScaleSet> scroll_info =
5457 host_impl_->ProcessScrollDeltas();
5459 // The root should have scrolled.
5460 ASSERT_EQ(2u, scroll_info->scrolls.size());
5461 ExpectContains(*scroll_info.get(),
5462 host_impl_->active_tree()->root_layer()->id(),
5463 gfx::Vector2d(0, 10));