GoogleURLTrackerInfoBarDelegate: Initialize uninitialized member in constructor.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blob919382fde14f4d59713f0eb7803b8591c8a9581c
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host_impl.h"
7 #include <cmath>
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/containers/hash_tables.h"
12 #include "base/containers/scoped_ptr_hash_map.h"
13 #include "cc/animation/scrollbar_animation_controller_thinning.h"
14 #include "cc/base/latency_info_swap_promise.h"
15 #include "cc/base/math_util.h"
16 #include "cc/input/top_controls_manager.h"
17 #include "cc/layers/append_quads_data.h"
18 #include "cc/layers/delegated_renderer_layer_impl.h"
19 #include "cc/layers/heads_up_display_layer_impl.h"
20 #include "cc/layers/io_surface_layer_impl.h"
21 #include "cc/layers/layer_impl.h"
22 #include "cc/layers/painted_scrollbar_layer_impl.h"
23 #include "cc/layers/quad_sink.h"
24 #include "cc/layers/render_surface_impl.h"
25 #include "cc/layers/solid_color_layer_impl.h"
26 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
27 #include "cc/layers/texture_layer_impl.h"
28 #include "cc/layers/tiled_layer_impl.h"
29 #include "cc/layers/video_layer_impl.h"
30 #include "cc/output/begin_frame_args.h"
31 #include "cc/output/compositor_frame_ack.h"
32 #include "cc/output/compositor_frame_metadata.h"
33 #include "cc/output/copy_output_request.h"
34 #include "cc/output/copy_output_result.h"
35 #include "cc/output/gl_renderer.h"
36 #include "cc/quads/render_pass_draw_quad.h"
37 #include "cc/quads/solid_color_draw_quad.h"
38 #include "cc/quads/texture_draw_quad.h"
39 #include "cc/quads/tile_draw_quad.h"
40 #include "cc/resources/layer_tiling_data.h"
41 #include "cc/test/animation_test_common.h"
42 #include "cc/test/fake_layer_tree_host_impl.h"
43 #include "cc/test/fake_output_surface.h"
44 #include "cc/test/fake_output_surface_client.h"
45 #include "cc/test/fake_picture_layer_impl.h"
46 #include "cc/test/fake_picture_pile_impl.h"
47 #include "cc/test/fake_proxy.h"
48 #include "cc/test/fake_rendering_stats_instrumentation.h"
49 #include "cc/test/fake_video_frame_provider.h"
50 #include "cc/test/geometry_test_utils.h"
51 #include "cc/test/layer_test_common.h"
52 #include "cc/test/render_pass_test_common.h"
53 #include "cc/test/test_shared_bitmap_manager.h"
54 #include "cc/test/test_web_graphics_context_3d.h"
55 #include "cc/trees/layer_tree_impl.h"
56 #include "cc/trees/single_thread_proxy.h"
57 #include "media/base/media.h"
58 #include "testing/gmock/include/gmock/gmock.h"
59 #include "testing/gtest/include/gtest/gtest.h"
60 #include "third_party/skia/include/core/SkMallocPixelRef.h"
61 #include "ui/gfx/frame_time.h"
62 #include "ui/gfx/rect_conversions.h"
63 #include "ui/gfx/size_conversions.h"
64 #include "ui/gfx/vector2d_conversions.h"
66 using ::testing::Mock;
67 using ::testing::Return;
68 using ::testing::AnyNumber;
69 using ::testing::AtLeast;
70 using ::testing::_;
71 using media::VideoFrame;
73 namespace cc {
74 namespace {
76 class LayerTreeHostImplTest : public testing::Test,
77 public LayerTreeHostImplClient {
78 public:
79 LayerTreeHostImplTest()
80 : proxy_(base::MessageLoopProxy::current()),
81 always_impl_thread_(&proxy_),
82 always_main_thread_blocked_(&proxy_),
83 shared_bitmap_manager_(new TestSharedBitmapManager()),
84 on_can_draw_state_changed_called_(false),
85 did_notify_ready_to_activate_(false),
86 did_request_commit_(false),
87 did_request_redraw_(false),
88 did_request_animate_(false),
89 did_request_manage_tiles_(false),
90 did_upload_visible_tile_(false),
91 reduce_memory_result_(true),
92 current_limit_bytes_(0),
93 current_priority_cutoff_value_(0) {
94 media::InitializeMediaLibraryForTesting();
97 LayerTreeSettings DefaultSettings() {
98 LayerTreeSettings settings;
99 settings.minimum_occlusion_tracking_size = gfx::Size();
100 settings.impl_side_painting = true;
101 settings.texture_id_allocation_chunk_size = 1;
102 settings.report_overscroll_only_for_scrollable_axes = true;
103 return settings;
106 virtual void SetUp() OVERRIDE {
107 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
110 virtual void TearDown() OVERRIDE {}
112 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {}
113 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
114 virtual void CommitVSyncParameters(base::TimeTicks timebase,
115 base::TimeDelta interval) OVERRIDE {}
116 virtual void SetEstimatedParentDrawTime(base::TimeDelta draw_time) OVERRIDE {}
117 virtual void SetMaxSwapsPendingOnImplThread(int max) OVERRIDE {}
118 virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
119 virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {}
120 virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {}
121 virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
122 on_can_draw_state_changed_called_ = true;
124 virtual void NotifyReadyToActivate() OVERRIDE {
125 did_notify_ready_to_activate_ = true;
126 host_impl_->ActivatePendingTree();
128 virtual void SetNeedsRedrawOnImplThread() OVERRIDE {
129 did_request_redraw_ = true;
131 virtual void SetNeedsRedrawRectOnImplThread(
132 const gfx::Rect& damage_rect) OVERRIDE {
133 did_request_redraw_ = true;
135 virtual void SetNeedsAnimateOnImplThread() OVERRIDE {
136 did_request_animate_ = true;
138 virtual void SetNeedsManageTilesOnImplThread() OVERRIDE {
139 did_request_manage_tiles_ = true;
141 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {
142 did_upload_visible_tile_ = true;
144 virtual void SetNeedsCommitOnImplThread() OVERRIDE {
145 did_request_commit_ = true;
147 virtual void PostAnimationEventsToMainThreadOnImplThread(
148 scoped_ptr<AnimationEventsVector> events) OVERRIDE {}
149 virtual bool ReduceContentsTextureMemoryOnImplThread(
150 size_t limit_bytes, int priority_cutoff) OVERRIDE {
151 current_limit_bytes_ = limit_bytes;
152 current_priority_cutoff_value_ = priority_cutoff;
153 return reduce_memory_result_;
155 virtual void SendManagedMemoryStats() OVERRIDE {}
156 virtual bool IsInsideDraw() OVERRIDE { return false; }
157 virtual void RenewTreePriority() OVERRIDE {}
158 virtual void PostDelayedScrollbarFadeOnImplThread(
159 const base::Closure& start_fade,
160 base::TimeDelta delay) OVERRIDE {
161 scrollbar_fade_start_ = start_fade;
162 requested_scrollbar_animation_delay_ = delay;
164 virtual void DidActivatePendingTree() OVERRIDE {}
165 virtual void DidManageTiles() OVERRIDE {}
167 void set_reduce_memory_result(bool reduce_memory_result) {
168 reduce_memory_result_ = reduce_memory_result;
171 bool CreateHostImpl(const LayerTreeSettings& settings,
172 scoped_ptr<OutputSurface> output_surface) {
173 host_impl_ = LayerTreeHostImpl::Create(settings,
174 this,
175 &proxy_,
176 &stats_instrumentation_,
177 shared_bitmap_manager_.get(),
179 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
180 host_impl_->SetViewportSize(gfx::Size(10, 10));
181 return init;
184 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
185 root->SetAnchorPoint(gfx::PointF());
186 root->SetPosition(gfx::PointF());
187 root->SetBounds(gfx::Size(10, 10));
188 root->SetContentBounds(gfx::Size(10, 10));
189 root->SetDrawsContent(true);
190 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
191 host_impl_->active_tree()->SetRootLayer(root.Pass());
194 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
195 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
196 for (size_t i = 0; i < layer->children().size(); ++i)
197 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
200 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
201 int id,
202 const gfx::Vector2d& scroll_delta) {
203 int times_encountered = 0;
205 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
206 if (scroll_info.scrolls[i].layer_id != id)
207 continue;
208 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
209 times_encountered++;
212 ASSERT_EQ(1, times_encountered);
215 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
216 int times_encountered = 0;
218 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
219 if (scroll_info.scrolls[i].layer_id != id)
220 continue;
221 times_encountered++;
224 ASSERT_EQ(0, times_encountered);
227 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
228 const gfx::Size& content_size) {
229 const int kInnerViewportScrollLayerId = 2;
230 const int kInnerViewportClipLayerId = 4;
231 const int kPageScaleLayerId = 5;
232 scoped_ptr<LayerImpl> root =
233 LayerImpl::Create(layer_tree_impl, 1);
234 root->SetBounds(content_size);
235 root->SetContentBounds(content_size);
236 root->SetPosition(gfx::PointF());
237 root->SetAnchorPoint(gfx::PointF());
239 scoped_ptr<LayerImpl> scroll =
240 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
241 LayerImpl* scroll_layer = scroll.get();
242 scroll->SetIsContainerForFixedPositionLayers(true);
243 scroll->SetScrollOffset(gfx::Vector2d());
245 scoped_ptr<LayerImpl> clip =
246 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
247 clip->SetBounds(
248 gfx::Size(content_size.width() / 2, content_size.height() / 2));
250 scoped_ptr<LayerImpl> page_scale =
251 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
253 scroll->SetScrollClipLayer(clip->id());
254 scroll->SetBounds(content_size);
255 scroll->SetContentBounds(content_size);
256 scroll->SetPosition(gfx::PointF());
257 scroll->SetAnchorPoint(gfx::PointF());
258 scroll->SetIsContainerForFixedPositionLayers(true);
260 scoped_ptr<LayerImpl> contents =
261 LayerImpl::Create(layer_tree_impl, 3);
262 contents->SetDrawsContent(true);
263 contents->SetBounds(content_size);
264 contents->SetContentBounds(content_size);
265 contents->SetPosition(gfx::PointF());
266 contents->SetAnchorPoint(gfx::PointF());
268 scroll->AddChild(contents.Pass());
269 page_scale->AddChild(scroll.Pass());
270 clip->AddChild(page_scale.Pass());
271 root->AddChild(clip.Pass());
273 layer_tree_impl->SetRootLayer(root.Pass());
274 layer_tree_impl->SetViewportLayersFromIds(
275 kPageScaleLayerId, kInnerViewportScrollLayerId, Layer::INVALID_ID);
277 return scroll_layer;
280 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
281 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
282 host_impl_->active_tree(), content_size);
283 host_impl_->active_tree()->DidBecomeActive();
284 return scroll_layer;
287 // TODO(wjmaclean) Add clip-layer pointer to parameters.
288 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
289 const gfx::Size& size,
290 LayerImpl* clip_layer) {
291 DCHECK(clip_layer);
292 DCHECK(id != clip_layer->id());
293 scoped_ptr<LayerImpl> layer =
294 LayerImpl::Create(host_impl_->active_tree(), id);
295 layer->SetScrollClipLayer(clip_layer->id());
296 layer->SetDrawsContent(true);
297 layer->SetBounds(size);
298 layer->SetContentBounds(size);
299 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
300 return layer.Pass();
303 void DrawFrame() {
304 LayerTreeHostImpl::FrameData frame;
305 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
306 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
307 host_impl_->DidDrawAllLayers(frame);
310 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
311 void pinch_zoom_pan_viewport_test(float device_scale_factor);
312 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
313 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
314 float device_scale_factor);
316 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
317 // Note: It is not possible to disable the renderer once it has been set,
318 // so we do not need to test that disabling the renderer notifies us
319 // that can_draw changed.
320 EXPECT_FALSE(host_impl_->CanDraw());
321 on_can_draw_state_changed_called_ = false;
323 // Set up the root layer, which allows us to draw.
324 SetupScrollAndContentsLayers(gfx::Size(100, 100));
325 EXPECT_TRUE(host_impl_->CanDraw());
326 EXPECT_TRUE(on_can_draw_state_changed_called_);
327 on_can_draw_state_changed_called_ = false;
329 // Toggle the root layer to make sure it toggles can_draw
330 host_impl_->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
331 EXPECT_FALSE(host_impl_->CanDraw());
332 EXPECT_TRUE(on_can_draw_state_changed_called_);
333 on_can_draw_state_changed_called_ = false;
335 SetupScrollAndContentsLayers(gfx::Size(100, 100));
336 EXPECT_TRUE(host_impl_->CanDraw());
337 EXPECT_TRUE(on_can_draw_state_changed_called_);
338 on_can_draw_state_changed_called_ = false;
340 // Toggle the device viewport size to make sure it toggles can_draw.
341 host_impl_->SetViewportSize(gfx::Size());
342 if (always_draw) {
343 EXPECT_TRUE(host_impl_->CanDraw());
344 } else {
345 EXPECT_FALSE(host_impl_->CanDraw());
347 EXPECT_TRUE(on_can_draw_state_changed_called_);
348 on_can_draw_state_changed_called_ = false;
350 host_impl_->SetViewportSize(gfx::Size(100, 100));
351 EXPECT_TRUE(host_impl_->CanDraw());
352 EXPECT_TRUE(on_can_draw_state_changed_called_);
353 on_can_draw_state_changed_called_ = false;
355 // Toggle contents textures purged without causing any evictions,
356 // and make sure that it does not change can_draw.
357 set_reduce_memory_result(false);
358 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
359 host_impl_->memory_allocation_limit_bytes() - 1));
360 EXPECT_TRUE(host_impl_->CanDraw());
361 EXPECT_FALSE(on_can_draw_state_changed_called_);
362 on_can_draw_state_changed_called_ = false;
364 // Toggle contents textures purged to make sure it toggles can_draw.
365 set_reduce_memory_result(true);
366 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
367 host_impl_->memory_allocation_limit_bytes() - 1));
368 if (always_draw) {
369 EXPECT_TRUE(host_impl_->CanDraw());
370 } else {
371 EXPECT_FALSE(host_impl_->CanDraw());
373 EXPECT_TRUE(on_can_draw_state_changed_called_);
374 on_can_draw_state_changed_called_ = false;
376 host_impl_->active_tree()->ResetContentsTexturesPurged();
377 EXPECT_TRUE(host_impl_->CanDraw());
378 EXPECT_TRUE(on_can_draw_state_changed_called_);
379 on_can_draw_state_changed_called_ = false;
382 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
384 protected:
385 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
386 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
389 void DrawOneFrame() {
390 LayerTreeHostImpl::FrameData frame_data;
391 host_impl_->PrepareToDraw(&frame_data);
392 host_impl_->DidDrawAllLayers(frame_data);
395 FakeProxy proxy_;
396 DebugScopedSetImplThread always_impl_thread_;
397 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
399 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
400 scoped_ptr<LayerTreeHostImpl> host_impl_;
401 FakeRenderingStatsInstrumentation stats_instrumentation_;
402 bool on_can_draw_state_changed_called_;
403 bool did_notify_ready_to_activate_;
404 bool did_request_commit_;
405 bool did_request_redraw_;
406 bool did_request_animate_;
407 bool did_request_manage_tiles_;
408 bool did_upload_visible_tile_;
409 bool reduce_memory_result_;
410 base::Closure scrollbar_fade_start_;
411 base::TimeDelta requested_scrollbar_animation_delay_;
412 size_t current_limit_bytes_;
413 int current_priority_cutoff_value_;
416 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
417 bool always_draw = false;
418 CheckNotifyCalledIfCanDrawChanged(always_draw);
421 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
422 scoped_ptr<FakeOutputSurface> output_surface(
423 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
424 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
426 bool always_draw = true;
427 CheckNotifyCalledIfCanDrawChanged(always_draw);
430 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
431 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
433 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
434 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
437 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
439 scoped_ptr<LayerImpl> root =
440 LayerImpl::Create(host_impl_->active_tree(), 1);
441 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
442 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
443 root->children()[1]->AddChild(
444 LayerImpl::Create(host_impl_->active_tree(), 4));
445 root->children()[1]->AddChild(
446 LayerImpl::Create(host_impl_->active_tree(), 5));
447 root->children()[1]->children()[0]->AddChild(
448 LayerImpl::Create(host_impl_->active_tree(), 6));
449 host_impl_->active_tree()->SetRootLayer(root.Pass());
451 LayerImpl* root = host_impl_->active_tree()->root_layer();
453 ExpectClearedScrollDeltasRecursive(root);
455 scoped_ptr<ScrollAndScaleSet> scroll_info;
457 scroll_info = host_impl_->ProcessScrollDeltas();
458 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
459 ExpectClearedScrollDeltasRecursive(root);
461 scroll_info = host_impl_->ProcessScrollDeltas();
462 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
463 ExpectClearedScrollDeltasRecursive(root);
466 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
467 gfx::Vector2d scroll_offset(20, 30);
468 gfx::Vector2d scroll_delta(11, -15);
470 scoped_ptr<LayerImpl> root_clip =
471 LayerImpl::Create(host_impl_->active_tree(), 2);
472 scoped_ptr<LayerImpl> root =
473 LayerImpl::Create(host_impl_->active_tree(), 1);
474 root_clip->SetBounds(gfx::Size(10, 10));
475 LayerImpl* root_layer = root.get();
476 root_clip->AddChild(root.Pass());
477 root_layer->SetBounds(gfx::Size(110, 110));
478 root_layer->SetScrollClipLayer(root_clip->id());
479 root_layer->SetScrollOffset(scroll_offset);
480 root_layer->ScrollBy(scroll_delta);
481 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
483 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
485 scoped_ptr<ScrollAndScaleSet> scroll_info;
487 scroll_info = host_impl_->ProcessScrollDeltas();
488 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
489 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta);
490 ExpectContains(*scroll_info, root->id(), scroll_delta);
492 gfx::Vector2d scroll_delta2(-5, 27);
493 root->ScrollBy(scroll_delta2);
494 scroll_info = host_impl_->ProcessScrollDeltas();
495 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
496 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
497 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
499 root->ScrollBy(gfx::Vector2d());
500 scroll_info = host_impl_->ProcessScrollDeltas();
501 EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
504 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
505 SetupScrollAndContentsLayers(gfx::Size(100, 100));
506 host_impl_->SetViewportSize(gfx::Size(50, 50));
507 DrawFrame();
509 EXPECT_EQ(InputHandler::ScrollStarted,
510 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
511 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
512 InputHandler::Wheel));
513 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
514 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
515 InputHandler::Wheel));
516 host_impl_->ScrollEnd();
517 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
518 InputHandler::Wheel));
519 EXPECT_TRUE(did_request_redraw_);
520 EXPECT_TRUE(did_request_commit_);
523 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
524 // We should not crash when trying to scroll an empty layer tree.
525 EXPECT_EQ(InputHandler::ScrollIgnored,
526 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
529 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
530 scoped_ptr<TestWebGraphicsContext3D> context_owned =
531 TestWebGraphicsContext3D::Create();
532 context_owned->set_context_lost(true);
534 scoped_ptr<FakeOutputSurface> output_surface(FakeOutputSurface::Create3d(
535 context_owned.Pass()));
537 // Initialization will fail.
538 EXPECT_FALSE(CreateHostImpl(DefaultSettings(),
539 output_surface.PassAs<OutputSurface>()));
541 SetupScrollAndContentsLayers(gfx::Size(100, 100));
543 // We should not crash when trying to scroll after the renderer initialization
544 // fails.
545 EXPECT_EQ(InputHandler::ScrollIgnored,
546 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
549 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
550 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
551 host_impl_->SetViewportSize(gfx::Size(50, 50));
552 DrawFrame();
554 // We should not crash if the tree is replaced while we are scrolling.
555 EXPECT_EQ(InputHandler::ScrollStarted,
556 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
557 host_impl_->active_tree()->DetachLayerTree();
559 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
561 // We should still be scrolling, because the scrolled layer also exists in the
562 // new tree.
563 gfx::Vector2d scroll_delta(0, 10);
564 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
565 host_impl_->ScrollEnd();
566 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
567 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
570 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
571 SetupScrollAndContentsLayers(gfx::Size(100, 100));
572 host_impl_->SetViewportSize(gfx::Size(50, 50));
573 DrawFrame();
575 // We should be able to scroll even if the root layer loses its render surface
576 // after the most recent render.
577 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
578 host_impl_->active_tree()->set_needs_update_draw_properties();
580 EXPECT_EQ(InputHandler::ScrollStarted,
581 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
584 TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
585 SetupScrollAndContentsLayers(gfx::Size(100, 100));
586 host_impl_->SetViewportSize(gfx::Size(50, 50));
587 DrawFrame();
588 LayerImpl* root = host_impl_->active_tree()->root_layer();
590 root->SetHaveWheelEventHandlers(true);
592 // With registered event handlers, wheel scrolls have to go to the main
593 // thread.
594 EXPECT_EQ(InputHandler::ScrollOnMainThread,
595 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
597 // But gesture scrolls can still be handled.
598 EXPECT_EQ(InputHandler::ScrollStarted,
599 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
602 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
603 SetupScrollAndContentsLayers(gfx::Size(100, 100));
604 host_impl_->SetViewportSize(gfx::Size(50, 50));
605 DrawFrame();
607 // Ignore the fling since no layer is being scrolled
608 EXPECT_EQ(InputHandler::ScrollIgnored,
609 host_impl_->FlingScrollBegin());
611 // Start scrolling a layer
612 EXPECT_EQ(InputHandler::ScrollStarted,
613 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
615 // Now the fling should go ahead since we've started scrolling a layer
616 EXPECT_EQ(InputHandler::ScrollStarted,
617 host_impl_->FlingScrollBegin());
620 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
621 SetupScrollAndContentsLayers(gfx::Size(100, 100));
622 host_impl_->SetViewportSize(gfx::Size(50, 50));
623 DrawFrame();
625 // Ignore the fling since no layer is being scrolled
626 EXPECT_EQ(InputHandler::ScrollIgnored,
627 host_impl_->FlingScrollBegin());
629 // Start scrolling a layer
630 EXPECT_EQ(InputHandler::ScrollStarted,
631 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
633 // Now the fling should go ahead since we've started scrolling a layer
634 EXPECT_EQ(InputHandler::ScrollStarted,
635 host_impl_->FlingScrollBegin());
638 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
639 SetupScrollAndContentsLayers(gfx::Size(100, 100));
640 host_impl_->SetViewportSize(gfx::Size(50, 50));
641 DrawFrame();
642 LayerImpl* root = host_impl_->active_tree()->root_layer();
644 root->SetShouldScrollOnMainThread(true);
646 // Start scrolling a layer
647 EXPECT_EQ(InputHandler::ScrollOnMainThread,
648 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
650 // The fling should be ignored since there's no layer being scrolled impl-side
651 EXPECT_EQ(InputHandler::ScrollIgnored,
652 host_impl_->FlingScrollBegin());
655 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
656 SetupScrollAndContentsLayers(gfx::Size(100, 100));
657 host_impl_->SetViewportSize(gfx::Size(50, 50));
658 DrawFrame();
659 LayerImpl* root = host_impl_->active_tree()->root_layer();
661 root->SetShouldScrollOnMainThread(true);
663 EXPECT_EQ(InputHandler::ScrollOnMainThread,
664 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
665 EXPECT_EQ(InputHandler::ScrollOnMainThread,
666 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
669 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
670 SetupScrollAndContentsLayers(gfx::Size(200, 200));
671 host_impl_->SetViewportSize(gfx::Size(100, 100));
673 LayerImpl* root = host_impl_->active_tree()->root_layer();
674 root->SetContentsScale(2.f, 2.f);
675 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
677 DrawFrame();
679 // All scroll types inside the non-fast scrollable region should fail.
680 EXPECT_EQ(InputHandler::ScrollOnMainThread,
681 host_impl_->ScrollBegin(gfx::Point(25, 25),
682 InputHandler::Wheel));
683 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
684 InputHandler::Wheel));
685 EXPECT_EQ(InputHandler::ScrollOnMainThread,
686 host_impl_->ScrollBegin(gfx::Point(25, 25),
687 InputHandler::Gesture));
688 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
689 InputHandler::Gesture));
691 // All scroll types outside this region should succeed.
692 EXPECT_EQ(InputHandler::ScrollStarted,
693 host_impl_->ScrollBegin(gfx::Point(75, 75),
694 InputHandler::Wheel));
695 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
696 InputHandler::Gesture));
697 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
698 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
699 InputHandler::Gesture));
700 host_impl_->ScrollEnd();
701 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
702 InputHandler::Gesture));
703 EXPECT_EQ(InputHandler::ScrollStarted,
704 host_impl_->ScrollBegin(gfx::Point(75, 75),
705 InputHandler::Gesture));
706 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
707 InputHandler::Gesture));
708 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
709 host_impl_->ScrollEnd();
710 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
711 InputHandler::Gesture));
714 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
715 SetupScrollAndContentsLayers(gfx::Size(200, 200));
716 host_impl_->SetViewportSize(gfx::Size(100, 100));
718 LayerImpl* root = host_impl_->active_tree()->root_layer();
719 root->SetContentsScale(2.f, 2.f);
720 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
721 root->SetPosition(gfx::PointF(-25.f, 0.f));
723 DrawFrame();
725 // This point would fall into the non-fast scrollable region except that we've
726 // moved the layer down by 25 pixels.
727 EXPECT_EQ(InputHandler::ScrollStarted,
728 host_impl_->ScrollBegin(gfx::Point(40, 10),
729 InputHandler::Wheel));
730 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
731 InputHandler::Wheel));
732 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
733 host_impl_->ScrollEnd();
735 // This point is still inside the non-fast region.
736 EXPECT_EQ(InputHandler::ScrollOnMainThread,
737 host_impl_->ScrollBegin(gfx::Point(10, 10),
738 InputHandler::Wheel));
741 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
742 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
743 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
744 host_impl_->SetViewportSize(gfx::Size(50, 50));
745 DrawFrame();
747 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
748 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
749 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
750 host_impl_->ScrollEnd();
751 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
754 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
755 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
756 scroll_layer->SetHaveScrollEventHandlers(true);
757 host_impl_->SetViewportSize(gfx::Size(50, 50));
758 DrawFrame();
760 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
761 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
762 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
763 host_impl_->ScrollEnd();
764 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
767 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
768 SetupScrollAndContentsLayers(gfx::Size(200, 200));
769 host_impl_->SetViewportSize(gfx::Size(100, 100));
771 DrawFrame();
773 EXPECT_EQ(InputHandler::ScrollStarted,
774 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
776 // Trying to scroll to the left/top will not succeed.
777 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
778 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
779 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
781 // Scrolling to the right/bottom will succeed.
782 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
783 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
784 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
786 // Scrolling to left/top will now succeed.
787 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
788 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
789 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
791 // Scrolling diagonally against an edge will succeed.
792 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
793 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
794 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
796 // Trying to scroll more than the available space will also succeed.
797 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
800 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
801 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
802 host_impl_->SetViewportSize(gfx::Size(100, 1000));
804 DrawFrame();
806 EXPECT_EQ(InputHandler::ScrollStarted,
807 host_impl_->ScrollBegin(gfx::Point(),
808 InputHandler::Wheel));
810 // Trying to scroll without a vertical scrollbar will fail.
811 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
812 gfx::Point(), SCROLL_FORWARD));
813 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
814 gfx::Point(), SCROLL_BACKWARD));
816 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
817 PaintedScrollbarLayerImpl::Create(
818 host_impl_->active_tree(),
820 VERTICAL));
821 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
822 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
823 vertical_scrollbar.get());
825 // Trying to scroll with a vertical scrollbar will succeed.
826 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
827 gfx::Point(), SCROLL_FORWARD));
828 EXPECT_FLOAT_EQ(875.f,
829 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
830 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
831 gfx::Point(), SCROLL_BACKWARD));
834 // The user-scrollability breaks for zoomed-in pages. So disable this.
835 // http://crbug.com/322223
836 TEST_F(LayerTreeHostImplTest, DISABLED_ScrollWithUserUnscrollableLayers) {
837 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
838 host_impl_->SetViewportSize(gfx::Size(100, 100));
840 gfx::Size overflow_size(400, 400);
841 ASSERT_EQ(1u, scroll_layer->children().size());
842 LayerImpl* overflow = scroll_layer->children()[0];
843 overflow->SetBounds(overflow_size);
844 overflow->SetContentBounds(overflow_size);
845 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
846 overflow->SetScrollOffset(gfx::Vector2d());
847 overflow->SetPosition(gfx::PointF());
848 overflow->SetAnchorPoint(gfx::PointF());
850 DrawFrame();
851 gfx::Point scroll_position(10, 10);
853 EXPECT_EQ(InputHandler::ScrollStarted,
854 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
855 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
856 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->TotalScrollOffset());
858 gfx::Vector2dF scroll_delta(10, 10);
859 host_impl_->ScrollBy(scroll_position, scroll_delta);
860 host_impl_->ScrollEnd();
861 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
862 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
864 overflow->set_user_scrollable_horizontal(false);
866 EXPECT_EQ(InputHandler::ScrollStarted,
867 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
868 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->TotalScrollOffset());
869 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->TotalScrollOffset());
871 host_impl_->ScrollBy(scroll_position, scroll_delta);
872 host_impl_->ScrollEnd();
873 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
874 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
876 overflow->set_user_scrollable_vertical(false);
878 EXPECT_EQ(InputHandler::ScrollStarted,
879 host_impl_->ScrollBegin(scroll_position, InputHandler::Wheel));
880 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->TotalScrollOffset());
881 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
883 host_impl_->ScrollBy(scroll_position, scroll_delta);
884 host_impl_->ScrollEnd();
885 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->TotalScrollOffset());
886 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->TotalScrollOffset());
889 TEST_F(LayerTreeHostImplTest,
890 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
891 SetupScrollAndContentsLayers(gfx::Size(100, 100));
892 host_impl_->SetViewportSize(gfx::Size(50, 50));
893 DrawFrame();
895 // We should be able to hit test for touch event handlers even if the root
896 // layer loses its render surface after the most recent render.
897 host_impl_->active_tree()->root_layer()->ClearRenderSurface();
898 host_impl_->active_tree()->set_needs_update_draw_properties();
900 EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
903 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
904 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
905 host_impl_->SetViewportSize(gfx::Size(50, 50));
906 DrawFrame();
908 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
909 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
910 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
912 float min_page_scale = 1.f, max_page_scale = 4.f;
913 float page_scale_factor = 1.f;
915 // The impl-based pinch zoom should adjust the max scroll position.
917 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
918 page_scale_factor, min_page_scale, max_page_scale);
919 host_impl_->active_tree()->SetPageScaleDelta(1.f);
920 scroll_layer->SetScrollDelta(gfx::Vector2d());
922 float page_scale_delta = 2.f;
923 gfx::Vector2dF expected_container_size_delta(
924 container_layer->bounds().width(), container_layer->bounds().height());
925 expected_container_size_delta.Scale((1.f - page_scale_delta) /
926 (page_scale_factor * page_scale_delta));
928 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
929 host_impl_->PinchGestureBegin();
930 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
931 // While the gesture is still active, the scroll layer should have a
932 // container size delta = container->bounds() * ((1.f -
933 // page_scale_delta)/())
934 EXPECT_EQ(expected_container_size_delta,
935 scroll_layer->FixedContainerSizeDelta());
936 host_impl_->PinchGestureEnd();
937 host_impl_->ScrollEnd();
938 EXPECT_FALSE(did_request_animate_);
939 EXPECT_TRUE(did_request_redraw_);
940 EXPECT_TRUE(did_request_commit_);
941 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
943 scoped_ptr<ScrollAndScaleSet> scroll_info =
944 host_impl_->ProcessScrollDeltas();
945 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
947 EXPECT_EQ(gfx::Vector2d(75, 75).ToString(),
948 scroll_layer->MaxScrollOffset().ToString());
951 // Scrolling after a pinch gesture should always be in local space. The
952 // scroll deltas do not have the page scale factor applied.
954 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
955 page_scale_factor, min_page_scale, max_page_scale);
956 host_impl_->active_tree()->SetPageScaleDelta(1.f);
957 scroll_layer->SetScrollDelta(gfx::Vector2d());
959 float page_scale_delta = 2.f;
960 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
961 host_impl_->PinchGestureBegin();
962 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
963 host_impl_->PinchGestureEnd();
964 host_impl_->ScrollEnd();
966 gfx::Vector2d scroll_delta(0, 10);
967 EXPECT_EQ(InputHandler::ScrollStarted,
968 host_impl_->ScrollBegin(gfx::Point(5, 5),
969 InputHandler::Wheel));
970 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
971 host_impl_->ScrollEnd();
973 scoped_ptr<ScrollAndScaleSet> scroll_info =
974 host_impl_->ProcessScrollDeltas();
975 ExpectContains(*scroll_info.get(),
976 scroll_layer->id(),
977 scroll_delta);
981 TEST_F(LayerTreeHostImplTest, MasksToBoundsDoesntClobberInnerContainerSize) {
982 SetupScrollAndContentsLayers(gfx::Size(100, 100));
983 host_impl_->SetViewportSize(gfx::Size(50, 50));
984 DrawFrame();
986 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
987 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
988 DCHECK(scroll_layer);
990 float min_page_scale = 1.f;
991 float max_page_scale = 4.f;
992 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
993 min_page_scale,
994 max_page_scale);
996 // If the container's masks_to_bounds is false, the viewport size should
997 // overwrite the inner viewport container layer's size.
999 EXPECT_EQ(gfx::Size(50, 50),
1000 container_layer->bounds());
1001 container_layer->SetMasksToBounds(false);
1003 container_layer->SetBounds(gfx::Size(30, 25));
1004 EXPECT_EQ(gfx::Size(30, 25),
1005 container_layer->bounds());
1007 // This should cause a reset of the inner viewport container layer's bounds.
1008 host_impl_->DidChangeTopControlsPosition();
1010 EXPECT_EQ(gfx::Size(50, 50),
1011 container_layer->bounds());
1014 host_impl_->SetViewportSize(gfx::Size(50, 50));
1015 container_layer->SetBounds(gfx::Size(50, 50));
1017 // If the container's masks_to_bounds is true, the viewport size should
1018 // *NOT* overwrite the inner viewport container layer's size.
1020 EXPECT_EQ(gfx::Size(50, 50),
1021 container_layer->bounds());
1022 container_layer->SetMasksToBounds(true);
1024 container_layer->SetBounds(gfx::Size(30, 25));
1025 EXPECT_EQ(gfx::Size(30, 25),
1026 container_layer->bounds());
1028 // This should cause a reset of the inner viewport container layer's bounds.
1029 host_impl_->DidChangeTopControlsPosition();
1031 EXPECT_EQ(gfx::Size(30, 25),
1032 container_layer->bounds());
1036 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1037 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1038 host_impl_->SetViewportSize(gfx::Size(50, 50));
1039 DrawFrame();
1041 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1042 DCHECK(scroll_layer);
1044 float min_page_scale = 1.f;
1045 float max_page_scale = 4.f;
1047 // Basic pinch zoom in gesture
1049 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1050 min_page_scale,
1051 max_page_scale);
1052 scroll_layer->SetScrollDelta(gfx::Vector2d());
1054 float page_scale_delta = 2.f;
1055 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1056 host_impl_->PinchGestureBegin();
1057 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1058 host_impl_->PinchGestureEnd();
1059 host_impl_->ScrollEnd();
1060 EXPECT_FALSE(did_request_animate_);
1061 EXPECT_TRUE(did_request_redraw_);
1062 EXPECT_TRUE(did_request_commit_);
1064 scoped_ptr<ScrollAndScaleSet> scroll_info =
1065 host_impl_->ProcessScrollDeltas();
1066 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1069 // Zoom-in clamping
1071 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1072 min_page_scale,
1073 max_page_scale);
1074 scroll_layer->SetScrollDelta(gfx::Vector2d());
1075 float page_scale_delta = 10.f;
1077 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
1078 host_impl_->PinchGestureBegin();
1079 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1080 host_impl_->PinchGestureEnd();
1081 host_impl_->ScrollEnd();
1083 scoped_ptr<ScrollAndScaleSet> scroll_info =
1084 host_impl_->ProcessScrollDeltas();
1085 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1088 // Zoom-out clamping
1090 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1091 min_page_scale,
1092 max_page_scale);
1093 scroll_layer->SetScrollDelta(gfx::Vector2d());
1094 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1096 float page_scale_delta = 0.1f;
1097 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1098 host_impl_->PinchGestureBegin();
1099 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1100 host_impl_->PinchGestureEnd();
1101 host_impl_->ScrollEnd();
1103 scoped_ptr<ScrollAndScaleSet> scroll_info =
1104 host_impl_->ProcessScrollDeltas();
1105 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1107 EXPECT_TRUE(scroll_info->scrolls.empty());
1110 // Two-finger panning should not happen based on pinch events only
1112 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1113 min_page_scale,
1114 max_page_scale);
1115 scroll_layer->SetScrollDelta(gfx::Vector2d());
1116 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1118 float page_scale_delta = 1.f;
1119 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1120 host_impl_->PinchGestureBegin();
1121 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1122 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1123 host_impl_->PinchGestureEnd();
1124 host_impl_->ScrollEnd();
1126 scoped_ptr<ScrollAndScaleSet> scroll_info =
1127 host_impl_->ProcessScrollDeltas();
1128 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1129 EXPECT_TRUE(scroll_info->scrolls.empty());
1132 // Two-finger panning should work with interleaved scroll events
1134 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1135 min_page_scale,
1136 max_page_scale);
1137 scroll_layer->SetScrollDelta(gfx::Vector2d());
1138 scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
1140 float page_scale_delta = 1.f;
1141 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
1142 host_impl_->PinchGestureBegin();
1143 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1144 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1145 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1146 host_impl_->PinchGestureEnd();
1147 host_impl_->ScrollEnd();
1149 scoped_ptr<ScrollAndScaleSet> scroll_info =
1150 host_impl_->ProcessScrollDeltas();
1151 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1152 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1155 // Two-finger panning should work when starting fully zoomed out.
1157 host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
1158 0.5f,
1159 4.f);
1160 scroll_layer->SetScrollDelta(gfx::Vector2d());
1161 scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
1163 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
1164 host_impl_->PinchGestureBegin();
1165 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1166 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1167 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1168 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1169 host_impl_->PinchGestureEnd();
1170 host_impl_->ScrollEnd();
1172 scoped_ptr<ScrollAndScaleSet> scroll_info =
1173 host_impl_->ProcessScrollDeltas();
1174 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1175 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1179 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1180 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1181 host_impl_->SetViewportSize(gfx::Size(50, 50));
1182 DrawFrame();
1184 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1185 DCHECK(scroll_layer);
1187 float min_page_scale = 0.5f;
1188 float max_page_scale = 4.f;
1189 base::TimeTicks start_time = base::TimeTicks() +
1190 base::TimeDelta::FromSeconds(1);
1191 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1192 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1193 base::TimeTicks end_time = start_time + duration;
1195 // Non-anchor zoom-in
1197 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1198 min_page_scale,
1199 max_page_scale);
1200 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1202 did_request_redraw_ = false;
1203 did_request_animate_ = false;
1204 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), false, 2.f, duration);
1205 EXPECT_FALSE(did_request_redraw_);
1206 EXPECT_TRUE(did_request_animate_);
1208 did_request_redraw_ = false;
1209 did_request_animate_ = false;
1210 host_impl_->Animate(start_time);
1211 EXPECT_TRUE(did_request_redraw_);
1212 EXPECT_TRUE(did_request_animate_);
1214 did_request_redraw_ = false;
1215 did_request_animate_ = false;
1216 host_impl_->Animate(halfway_through_animation);
1217 EXPECT_TRUE(did_request_redraw_);
1218 EXPECT_TRUE(did_request_animate_);
1220 did_request_redraw_ = false;
1221 did_request_animate_ = false;
1222 did_request_commit_ = false;
1223 host_impl_->Animate(end_time);
1224 EXPECT_TRUE(did_request_commit_);
1225 EXPECT_FALSE(did_request_animate_);
1227 scoped_ptr<ScrollAndScaleSet> scroll_info =
1228 host_impl_->ProcessScrollDeltas();
1229 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1230 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1233 // Anchor zoom-out
1235 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1236 min_page_scale,
1237 max_page_scale);
1238 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1240 did_request_redraw_ = false;
1241 did_request_animate_ = false;
1242 host_impl_->StartPageScaleAnimation(
1243 gfx::Vector2d(25, 25), true, min_page_scale, duration);
1244 EXPECT_FALSE(did_request_redraw_);
1245 EXPECT_TRUE(did_request_animate_);
1247 did_request_redraw_ = false;
1248 did_request_animate_ = false;
1249 host_impl_->Animate(start_time);
1250 EXPECT_TRUE(did_request_redraw_);
1251 EXPECT_TRUE(did_request_animate_);
1253 did_request_redraw_ = false;
1254 did_request_commit_ = false;
1255 did_request_animate_ = false;
1256 host_impl_->Animate(end_time);
1257 EXPECT_TRUE(did_request_redraw_);
1258 EXPECT_FALSE(did_request_animate_);
1259 EXPECT_TRUE(did_request_commit_);
1261 scoped_ptr<ScrollAndScaleSet> scroll_info =
1262 host_impl_->ProcessScrollDeltas();
1263 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1264 // Pushed to (0,0) via clamping against contents layer size.
1265 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1269 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1270 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1271 host_impl_->SetViewportSize(gfx::Size(50, 50));
1272 DrawFrame();
1274 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1275 DCHECK(scroll_layer);
1277 float min_page_scale = 0.5f;
1278 float max_page_scale = 4.f;
1279 base::TimeTicks start_time = base::TimeTicks() +
1280 base::TimeDelta::FromSeconds(1);
1281 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1282 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1283 base::TimeTicks end_time = start_time + duration;
1285 // Anchor zoom with unchanged page scale should not change scroll or scale.
1287 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
1288 min_page_scale,
1289 max_page_scale);
1290 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
1292 host_impl_->StartPageScaleAnimation(gfx::Vector2d(), true, 1.f, duration);
1293 host_impl_->Animate(start_time);
1294 host_impl_->Animate(halfway_through_animation);
1295 EXPECT_TRUE(did_request_redraw_);
1296 host_impl_->Animate(end_time);
1297 EXPECT_TRUE(did_request_commit_);
1299 scoped_ptr<ScrollAndScaleSet> scroll_info =
1300 host_impl_->ProcessScrollDeltas();
1301 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1302 ExpectNone(*scroll_info, scroll_layer->id());
1306 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1307 public:
1308 LayerTreeHostImplOverridePhysicalTime(
1309 const LayerTreeSettings& settings,
1310 LayerTreeHostImplClient* client,
1311 Proxy* proxy,
1312 SharedBitmapManager* manager,
1313 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1314 : LayerTreeHostImpl(settings,
1315 client,
1316 proxy,
1317 rendering_stats_instrumentation,
1318 manager,
1319 0) {}
1321 virtual base::TimeTicks CurrentFrameTimeTicks() OVERRIDE {
1322 return fake_current_physical_time_;
1325 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1326 fake_current_physical_time_ = fake_now;
1329 private:
1330 base::TimeTicks fake_current_physical_time_;
1333 #define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST() \
1334 gfx::Size viewport_size(10, 10); \
1335 gfx::Size content_size(100, 100); \
1337 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = \
1338 new LayerTreeHostImplOverridePhysicalTime(settings, \
1339 this, \
1340 &proxy_, \
1341 shared_bitmap_manager_.get(), \
1342 &stats_instrumentation_); \
1343 host_impl_ = make_scoped_ptr(host_impl_override_time); \
1344 host_impl_->InitializeRenderer(CreateOutputSurface()); \
1345 host_impl_->SetViewportSize(viewport_size); \
1347 scoped_ptr<LayerImpl> root = \
1348 LayerImpl::Create(host_impl_->active_tree(), 1); \
1349 root->SetBounds(viewport_size); \
1351 scoped_ptr<LayerImpl> scroll = \
1352 LayerImpl::Create(host_impl_->active_tree(), 2); \
1353 scroll->SetScrollClipLayer(root->id()); \
1354 scroll->SetScrollOffset(gfx::Vector2d()); \
1355 root->SetBounds(viewport_size); \
1356 scroll->SetBounds(content_size); \
1357 scroll->SetContentBounds(content_size); \
1358 scroll->SetIsContainerForFixedPositionLayers(true); \
1360 scoped_ptr<LayerImpl> contents = \
1361 LayerImpl::Create(host_impl_->active_tree(), 3); \
1362 contents->SetDrawsContent(true); \
1363 contents->SetBounds(content_size); \
1364 contents->SetContentBounds(content_size); \
1366 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = \
1367 SolidColorScrollbarLayerImpl::Create( \
1368 host_impl_->active_tree(), 4, VERTICAL, 10, 0, false, true); \
1369 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); \
1370 scrollbar->SetScrollLayerById(2); \
1371 scrollbar->SetClipLayerById(1); \
1373 scroll->AddChild(contents.Pass()); \
1374 root->AddChild(scroll.Pass()); \
1375 root->AddChild(scrollbar.PassAs<LayerImpl>()); \
1377 host_impl_->active_tree()->SetRootLayer(root.Pass()); \
1378 host_impl_->active_tree()->SetViewportLayersFromIds( \
1379 1, 2, Layer::INVALID_ID); \
1380 host_impl_->active_tree()->DidBecomeActive(); \
1381 DrawFrame();
1383 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
1384 LayerTreeSettings settings;
1385 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1386 settings.scrollbar_fade_delay_ms = 20;
1387 settings.scrollbar_fade_duration_ms = 20;
1389 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1391 base::TimeTicks fake_now = gfx::FrameTime::Now();
1393 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1394 EXPECT_FALSE(did_request_redraw_);
1396 // If no scroll happened during a scroll gesture, it should have no effect.
1397 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1398 host_impl_->ScrollEnd();
1399 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1400 EXPECT_FALSE(did_request_redraw_);
1401 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1403 // After a scroll, a fade animation should be scheduled about 20ms from now.
1404 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1405 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1406 host_impl_->ScrollEnd();
1407 did_request_redraw_ = false;
1408 did_request_animate_ = false;
1409 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1410 requested_scrollbar_animation_delay_);
1411 EXPECT_FALSE(did_request_redraw_);
1412 EXPECT_FALSE(did_request_animate_);
1413 requested_scrollbar_animation_delay_ = base::TimeDelta();
1414 scrollbar_fade_start_.Run();
1415 host_impl_->Animate(fake_now);
1417 // After the fade begins, we should start getting redraws instead of a
1418 // scheduled animation.
1419 fake_now += base::TimeDelta::FromMilliseconds(25);
1420 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1421 EXPECT_TRUE(did_request_animate_);
1422 did_request_animate_ = false;
1424 // Setting the scroll offset outside a scroll should also cause the scrollbar
1425 // to appear and to schedule a fade.
1426 host_impl_->InnerViewportScrollLayer()->SetScrollOffset(gfx::Vector2d(5, 5));
1427 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1428 requested_scrollbar_animation_delay_);
1429 EXPECT_FALSE(did_request_redraw_);
1430 EXPECT_FALSE(did_request_animate_);
1431 requested_scrollbar_animation_delay_ = base::TimeDelta();
1434 TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) {
1435 LayerTreeSettings settings;
1436 settings.scrollbar_animator = LayerTreeSettings::LinearFade;
1437 settings.scrollbar_fade_delay_ms = 20;
1438 settings.scrollbar_fade_duration_ms = 20;
1439 settings.use_pinch_zoom_scrollbars = true;
1441 SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST();
1443 base::TimeTicks fake_now = gfx::FrameTime::Now();
1445 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
1447 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1448 EXPECT_FALSE(did_request_animate_);
1450 // If no scroll happened during a scroll gesture, it should have no effect.
1451 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1452 host_impl_->ScrollEnd();
1453 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1454 EXPECT_FALSE(did_request_animate_);
1455 EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure()));
1457 // After a scroll, no fade animation should be scheduled.
1458 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1459 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1460 host_impl_->ScrollEnd();
1461 did_request_redraw_ = false;
1462 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1463 EXPECT_FALSE(did_request_animate_);
1464 requested_scrollbar_animation_delay_ = base::TimeDelta();
1466 // We should not see any draw requests.
1467 fake_now += base::TimeDelta::FromMilliseconds(25);
1468 EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
1469 EXPECT_FALSE(did_request_animate_);
1471 // Make page scale > min so that subsequent scrolls will trigger fades.
1472 host_impl_->active_tree()->SetPageScaleDelta(1.1f);
1474 // After a scroll, a fade animation should be scheduled about 20ms from now.
1475 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
1476 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1477 host_impl_->ScrollEnd();
1478 did_request_redraw_ = false;
1479 EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
1480 requested_scrollbar_animation_delay_);
1481 EXPECT_FALSE(did_request_animate_);
1482 requested_scrollbar_animation_delay_ = base::TimeDelta();
1483 scrollbar_fade_start_.Run();
1485 // After the fade begins, we should start getting redraws instead of a
1486 // scheduled animation.
1487 fake_now += base::TimeDelta::FromMilliseconds(25);
1488 host_impl_->Animate(fake_now);
1489 EXPECT_TRUE(did_request_animate_);
1492 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1493 float device_scale_factor) {
1494 LayerTreeSettings settings;
1495 settings.scrollbar_fade_delay_ms = 500;
1496 settings.scrollbar_fade_duration_ms = 300;
1497 settings.scrollbar_animator = LayerTreeSettings::Thinning;
1499 gfx::Size viewport_size(300, 200);
1500 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1501 gfx::ScaleSize(viewport_size, device_scale_factor));
1502 gfx::Size content_size(1000, 1000);
1504 CreateHostImpl(settings, CreateOutputSurface());
1505 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1506 host_impl_->SetViewportSize(device_viewport_size);
1508 scoped_ptr<LayerImpl> root =
1509 LayerImpl::Create(host_impl_->active_tree(), 1);
1510 root->SetBounds(viewport_size);
1512 scoped_ptr<LayerImpl> scroll =
1513 LayerImpl::Create(host_impl_->active_tree(), 2);
1514 scroll->SetScrollClipLayer(root->id());
1515 scroll->SetScrollOffset(gfx::Vector2d());
1516 scroll->SetBounds(content_size);
1517 scroll->SetContentBounds(content_size);
1518 scroll->SetIsContainerForFixedPositionLayers(true);
1520 scoped_ptr<LayerImpl> contents =
1521 LayerImpl::Create(host_impl_->active_tree(), 3);
1522 contents->SetDrawsContent(true);
1523 contents->SetBounds(content_size);
1524 contents->SetContentBounds(content_size);
1526 // The scrollbar is on the right side.
1527 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1528 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1529 scrollbar->SetDrawsContent(true);
1530 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1531 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1532 scrollbar->SetPosition(gfx::Point(285, 0));
1533 scrollbar->SetClipLayerById(1);
1534 scrollbar->SetScrollLayerById(2);
1536 scroll->AddChild(contents.Pass());
1537 root->AddChild(scroll.Pass());
1538 root->AddChild(scrollbar.PassAs<LayerImpl>());
1540 host_impl_->active_tree()->SetRootLayer(root.Pass());
1541 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
1542 host_impl_->active_tree()->DidBecomeActive();
1543 DrawFrame();
1545 LayerImpl* root_scroll =
1546 host_impl_->active_tree()->InnerViewportScrollLayer();
1547 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1548 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1549 static_cast<ScrollbarAnimationControllerThinning*>(
1550 root_scroll->scrollbar_animation_controller());
1551 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1553 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1554 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1556 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1557 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1559 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1560 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1562 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1563 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1564 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1566 did_request_redraw_ = false;
1567 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1568 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1569 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1570 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1571 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1572 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1573 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1576 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1577 SetupMouseMoveAtWithDeviceScale(1.f);
1580 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1581 SetupMouseMoveAtWithDeviceScale(2.f);
1584 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1585 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1586 host_impl_->SetViewportSize(gfx::Size(50, 50));
1587 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
1588 DrawFrame();
1590 CompositorFrameMetadata metadata =
1591 host_impl_->MakeCompositorFrameMetadata();
1592 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1593 EXPECT_EQ(1.f, metadata.page_scale_factor);
1594 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.viewport_size);
1595 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1596 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1597 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1600 // Scrolling should update metadata immediately.
1601 EXPECT_EQ(InputHandler::ScrollStarted,
1602 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
1603 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1605 CompositorFrameMetadata metadata =
1606 host_impl_->MakeCompositorFrameMetadata();
1607 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1609 host_impl_->ScrollEnd();
1611 CompositorFrameMetadata metadata =
1612 host_impl_->MakeCompositorFrameMetadata();
1613 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1616 // Page scale should update metadata correctly (shrinking only the viewport).
1617 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
1618 host_impl_->PinchGestureBegin();
1619 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1620 host_impl_->PinchGestureEnd();
1621 host_impl_->ScrollEnd();
1623 CompositorFrameMetadata metadata =
1624 host_impl_->MakeCompositorFrameMetadata();
1625 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1626 EXPECT_EQ(2.f, metadata.page_scale_factor);
1627 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.viewport_size);
1628 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1629 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1630 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1633 // Likewise if set from the main thread.
1634 host_impl_->ProcessScrollDeltas();
1635 host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
1636 host_impl_->active_tree()->SetPageScaleDelta(1.f);
1638 CompositorFrameMetadata metadata =
1639 host_impl_->MakeCompositorFrameMetadata();
1640 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1641 EXPECT_EQ(4.f, metadata.page_scale_factor);
1642 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.viewport_size);
1643 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1644 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1645 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1649 // TODO(enne): Convert this to PictureLayerImpl
1650 class DidDrawCheckLayer : public TiledLayerImpl {
1651 public:
1652 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1653 return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(tree_impl, id));
1656 virtual bool WillDraw(DrawMode draw_mode, ResourceProvider* provider)
1657 OVERRIDE {
1658 will_draw_called_ = true;
1659 if (will_draw_returns_false_)
1660 return false;
1661 return TiledLayerImpl::WillDraw(draw_mode, provider);
1664 virtual void AppendQuads(QuadSink* quad_sink,
1665 AppendQuadsData* append_quads_data) OVERRIDE {
1666 append_quads_called_ = true;
1667 TiledLayerImpl::AppendQuads(quad_sink, append_quads_data);
1670 virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
1671 did_draw_called_ = true;
1672 TiledLayerImpl::DidDraw(provider);
1675 bool will_draw_called() const { return will_draw_called_; }
1676 bool append_quads_called() const { return append_quads_called_; }
1677 bool did_draw_called() const { return did_draw_called_; }
1679 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1681 void ClearDidDrawCheck() {
1682 will_draw_called_ = false;
1683 append_quads_called_ = false;
1684 did_draw_called_ = false;
1687 protected:
1688 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1689 : TiledLayerImpl(tree_impl, id),
1690 will_draw_returns_false_(false),
1691 will_draw_called_(false),
1692 append_quads_called_(false),
1693 did_draw_called_(false) {
1694 SetAnchorPoint(gfx::PointF());
1695 SetBounds(gfx::Size(10, 10));
1696 SetContentBounds(gfx::Size(10, 10));
1697 SetDrawsContent(true);
1698 set_skips_draw(false);
1699 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1701 scoped_ptr<LayerTilingData> tiler =
1702 LayerTilingData::Create(gfx::Size(100, 100),
1703 LayerTilingData::HAS_BORDER_TEXELS);
1704 tiler->SetTilingRect(gfx::Rect(content_bounds()));
1705 SetTilingData(*tiler.get());
1708 private:
1709 bool will_draw_returns_false_;
1710 bool will_draw_called_;
1711 bool append_quads_called_;
1712 bool did_draw_called_;
1715 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1716 // The root layer is always drawn, so run this test on a child layer that
1717 // will be masked out by the root layer's bounds.
1718 host_impl_->active_tree()->SetRootLayer(
1719 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1720 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1721 host_impl_->active_tree()->root_layer());
1723 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1724 DidDrawCheckLayer* layer =
1725 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1728 LayerTreeHostImpl::FrameData frame;
1729 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1730 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1731 host_impl_->DidDrawAllLayers(frame);
1733 EXPECT_TRUE(layer->will_draw_called());
1734 EXPECT_TRUE(layer->append_quads_called());
1735 EXPECT_TRUE(layer->did_draw_called());
1738 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
1741 LayerTreeHostImpl::FrameData frame;
1743 layer->set_will_draw_returns_false();
1744 layer->ClearDidDrawCheck();
1746 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1747 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1748 host_impl_->DidDrawAllLayers(frame);
1750 EXPECT_TRUE(layer->will_draw_called());
1751 EXPECT_FALSE(layer->append_quads_called());
1752 EXPECT_FALSE(layer->did_draw_called());
1756 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
1757 // The root layer is always drawn, so run this test on a child layer that
1758 // will be masked out by the root layer's bounds.
1759 host_impl_->active_tree()->SetRootLayer(
1760 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1761 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1762 host_impl_->active_tree()->root_layer());
1763 root->SetMasksToBounds(true);
1765 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1766 DidDrawCheckLayer* layer =
1767 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1768 // Ensure visible_content_rect for layer is empty.
1769 layer->SetPosition(gfx::PointF(100.f, 100.f));
1770 layer->SetBounds(gfx::Size(10, 10));
1771 layer->SetContentBounds(gfx::Size(10, 10));
1773 LayerTreeHostImpl::FrameData frame;
1775 EXPECT_FALSE(layer->will_draw_called());
1776 EXPECT_FALSE(layer->did_draw_called());
1778 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1779 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1780 host_impl_->DidDrawAllLayers(frame);
1782 EXPECT_FALSE(layer->will_draw_called());
1783 EXPECT_FALSE(layer->did_draw_called());
1785 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1787 // Ensure visible_content_rect for layer is not empty
1788 layer->SetPosition(gfx::PointF());
1790 EXPECT_FALSE(layer->will_draw_called());
1791 EXPECT_FALSE(layer->did_draw_called());
1793 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1794 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1795 host_impl_->DidDrawAllLayers(frame);
1797 EXPECT_TRUE(layer->will_draw_called());
1798 EXPECT_TRUE(layer->did_draw_called());
1800 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1803 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1804 gfx::Size big_size(1000, 1000);
1805 host_impl_->SetViewportSize(big_size);
1807 host_impl_->active_tree()->SetRootLayer(
1808 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1809 DidDrawCheckLayer* root =
1810 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1812 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1813 DidDrawCheckLayer* occluded_layer =
1814 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1816 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1817 DidDrawCheckLayer* top_layer =
1818 static_cast<DidDrawCheckLayer*>(root->children()[1]);
1819 // This layer covers the occluded_layer above. Make this layer large so it can
1820 // occlude.
1821 top_layer->SetBounds(big_size);
1822 top_layer->SetContentBounds(big_size);
1823 top_layer->SetContentsOpaque(true);
1825 LayerTreeHostImpl::FrameData frame;
1827 EXPECT_FALSE(occluded_layer->will_draw_called());
1828 EXPECT_FALSE(occluded_layer->did_draw_called());
1829 EXPECT_FALSE(top_layer->will_draw_called());
1830 EXPECT_FALSE(top_layer->did_draw_called());
1832 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1833 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1834 host_impl_->DidDrawAllLayers(frame);
1836 EXPECT_FALSE(occluded_layer->will_draw_called());
1837 EXPECT_FALSE(occluded_layer->did_draw_called());
1838 EXPECT_TRUE(top_layer->will_draw_called());
1839 EXPECT_TRUE(top_layer->did_draw_called());
1842 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
1843 host_impl_->active_tree()->SetRootLayer(
1844 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1845 DidDrawCheckLayer* root =
1846 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1848 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1849 DidDrawCheckLayer* layer1 =
1850 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1852 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1853 DidDrawCheckLayer* layer2 =
1854 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1856 layer1->SetOpacity(0.3f);
1857 layer1->SetShouldFlattenTransform(true);
1859 EXPECT_FALSE(root->did_draw_called());
1860 EXPECT_FALSE(layer1->did_draw_called());
1861 EXPECT_FALSE(layer2->did_draw_called());
1863 LayerTreeHostImpl::FrameData frame;
1864 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1865 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1866 host_impl_->DidDrawAllLayers(frame);
1868 EXPECT_TRUE(root->did_draw_called());
1869 EXPECT_TRUE(layer1->did_draw_called());
1870 EXPECT_TRUE(layer2->did_draw_called());
1872 EXPECT_NE(root->render_surface(), layer1->render_surface());
1873 EXPECT_TRUE(!!layer1->render_surface());
1876 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1877 public:
1878 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
1879 int id,
1880 bool tile_missing,
1881 bool skips_draw,
1882 bool animating,
1883 ResourceProvider* resource_provider) {
1884 return scoped_ptr<LayerImpl>(new MissingTextureAnimatingLayer(
1885 tree_impl,
1887 tile_missing,
1888 skips_draw,
1889 animating,
1890 resource_provider));
1893 virtual void AppendQuads(QuadSink* quad_sink,
1894 AppendQuadsData* append_quads_data) OVERRIDE {
1895 TiledLayerImpl::AppendQuads(quad_sink, append_quads_data);
1896 if (tile_missing_)
1897 append_quads_data->had_incomplete_tile = true;
1900 private:
1901 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
1902 int id,
1903 bool tile_missing,
1904 bool skips_draw,
1905 bool animating,
1906 ResourceProvider* resource_provider)
1907 : DidDrawCheckLayer(tree_impl, id), tile_missing_(tile_missing) {
1908 scoped_ptr<LayerTilingData> tiling_data =
1909 LayerTilingData::Create(gfx::Size(10, 10),
1910 LayerTilingData::NO_BORDER_TEXELS);
1911 tiling_data->SetTilingRect(gfx::Rect(bounds()));
1912 SetTilingData(*tiling_data.get());
1913 set_skips_draw(skips_draw);
1914 if (!tile_missing) {
1915 ResourceProvider::ResourceId resource =
1916 resource_provider->CreateResource(gfx::Size(1, 1),
1917 GL_CLAMP_TO_EDGE,
1918 ResourceProvider::TextureUsageAny,
1919 RGBA_8888);
1920 resource_provider->AllocateForTesting(resource);
1921 PushTileProperties(0, 0, resource, gfx::Rect(), false);
1923 if (animating)
1924 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1927 bool tile_missing_;
1930 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenNoTexturesMissing) {
1931 host_impl_->active_tree()->SetRootLayer(
1932 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1933 DidDrawCheckLayer* root =
1934 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1936 bool tile_missing = false;
1937 bool skips_draw = false;
1938 bool is_animating = false;
1939 root->AddChild(
1940 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1942 tile_missing,
1943 skips_draw,
1944 is_animating,
1945 host_impl_->resource_provider()));
1947 LayerTreeHostImpl::FrameData frame;
1949 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1950 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1951 host_impl_->DidDrawAllLayers(frame);
1954 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) {
1955 host_impl_->active_tree()->SetRootLayer(
1956 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1957 DidDrawCheckLayer* root =
1958 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1959 bool tile_missing = false;
1960 bool skips_draw = false;
1961 bool is_animating = true;
1962 root->AddChild(
1963 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1965 tile_missing,
1966 skips_draw,
1967 is_animating,
1968 host_impl_->resource_provider()));
1970 LayerTreeHostImpl::FrameData frame;
1972 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1973 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1974 host_impl_->DidDrawAllLayers(frame);
1977 TEST_F(LayerTreeHostImplTest,
1978 PrepareToDrawSucceedsWithNonAnimatedMissingTexture) {
1979 // When a texture is missing and we're not animating, we draw as usual with
1980 // checkerboarding.
1981 host_impl_->active_tree()->SetRootLayer(
1982 DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1983 DidDrawCheckLayer* root =
1984 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
1986 bool tile_missing = true;
1987 bool skips_draw = false;
1988 bool is_animating = false;
1989 root->AddChild(
1990 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
1992 tile_missing,
1993 skips_draw,
1994 is_animating,
1995 host_impl_->resource_provider()));
1996 LayerTreeHostImpl::FrameData frame;
1997 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
1998 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
1999 host_impl_->DidDrawAllLayers(frame);
2002 TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
2003 // When a texture is missing and we're animating, we don't want to draw
2004 // anything.
2005 host_impl_->active_tree()->SetRootLayer(
2006 DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
2007 DidDrawCheckLayer* root =
2008 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2009 bool tile_missing = true;
2010 bool skips_draw = false;
2011 bool is_animating = true;
2012 root->AddChild(
2013 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2015 tile_missing,
2016 skips_draw,
2017 is_animating,
2018 host_impl_->resource_provider()));
2019 LayerTreeHostImpl::FrameData frame;
2020 EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS,
2021 host_impl_->PrepareToDraw(&frame));
2022 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2023 host_impl_->DidDrawAllLayers(frame);
2026 TEST_F(LayerTreeHostImplTest,
2027 PrepareToDrawSucceedsWithMissingSkippedAnimatedLayer) {
2028 // When the layer skips draw and we're animating, we still draw the frame.
2029 host_impl_->active_tree()->SetRootLayer(
2030 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2031 DidDrawCheckLayer* root =
2032 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2033 bool tile_missing = false;
2034 bool skips_draw = true;
2035 bool is_animating = true;
2036 root->AddChild(
2037 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2039 tile_missing,
2040 skips_draw,
2041 is_animating,
2042 host_impl_->resource_provider()));
2043 LayerTreeHostImpl::FrameData frame;
2044 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2045 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2046 host_impl_->DidDrawAllLayers(frame);
2049 TEST_F(LayerTreeHostImplTest,
2050 PrepareToDrawSucceedsWhenHighResRequiredButNoMissingTextures) {
2051 // When the layer skips draw and we're animating, we still draw the frame.
2052 host_impl_->active_tree()->SetRootLayer(
2053 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2054 DidDrawCheckLayer* root =
2055 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2056 bool tile_missing = false;
2057 bool skips_draw = false;
2058 bool is_animating = false;
2059 root->AddChild(
2060 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2062 tile_missing,
2063 skips_draw,
2064 is_animating,
2065 host_impl_->resource_provider()));
2066 host_impl_->active_tree()->SetRequiresHighResToDraw();
2067 LayerTreeHostImpl::FrameData frame;
2068 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2069 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2070 host_impl_->DidDrawAllLayers(frame);
2073 TEST_F(LayerTreeHostImplTest,
2074 PrepareToDrawFailsWhenHighResRequiredAndMissingTextures) {
2075 // When the layer skips draw and we're animating, we still draw the frame.
2076 host_impl_->active_tree()->SetRootLayer(
2077 DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
2078 DidDrawCheckLayer* root =
2079 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2080 bool tile_missing = true;
2081 bool skips_draw = false;
2082 bool is_animating = false;
2083 root->AddChild(
2084 MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
2086 tile_missing,
2087 skips_draw,
2088 is_animating,
2089 host_impl_->resource_provider()));
2090 host_impl_->active_tree()->SetRequiresHighResToDraw();
2091 LayerTreeHostImpl::FrameData frame;
2092 EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT,
2093 host_impl_->PrepareToDraw(&frame));
2094 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2095 host_impl_->DidDrawAllLayers(frame);
2098 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2099 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2100 root->SetScrollClipLayer(Layer::INVALID_ID);
2101 host_impl_->active_tree()->SetRootLayer(root.Pass());
2102 DrawFrame();
2104 // Scroll event is ignored because layer is not scrollable.
2105 EXPECT_EQ(InputHandler::ScrollIgnored,
2106 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
2107 EXPECT_FALSE(did_request_redraw_);
2108 EXPECT_FALSE(did_request_commit_);
2111 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2112 public:
2113 LayerTreeHostImplTopControlsTest()
2114 // Make the clip size the same as the layer (content) size so the layer is
2115 // non-scrollable.
2116 : layer_size_(10, 10),
2117 clip_size_(layer_size_) {
2118 settings_.calculate_top_controls_position = true;
2119 settings_.top_controls_height = 50;
2121 viewport_size_ =
2122 gfx::Size(clip_size_.width(),
2123 clip_size_.height() + settings_.top_controls_height);
2126 void SetupTopControlsAndScrollLayer() {
2127 CreateHostImpl(settings_, CreateOutputSurface());
2129 scoped_ptr<LayerImpl> root =
2130 LayerImpl::Create(host_impl_->active_tree(), 1);
2131 scoped_ptr<LayerImpl> root_clip =
2132 LayerImpl::Create(host_impl_->active_tree(), 2);
2133 root_clip->SetBounds(clip_size_);
2134 root->SetScrollClipLayer(root_clip->id());
2135 root->SetBounds(layer_size_);
2136 root->SetContentBounds(layer_size_);
2137 root->SetPosition(gfx::PointF());
2138 root->SetAnchorPoint(gfx::PointF());
2139 root->SetDrawsContent(false);
2140 root->SetIsContainerForFixedPositionLayers(true);
2141 int inner_viewport_scroll_layer_id = root->id();
2142 int page_scale_layer_id = root_clip->id();
2143 root_clip->AddChild(root.Pass());
2144 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2145 host_impl_->active_tree()->SetViewportLayersFromIds(
2146 page_scale_layer_id, inner_viewport_scroll_layer_id, Layer::INVALID_ID);
2147 // Set a viewport size that is large enough to contain both the top controls
2148 // and some content.
2149 host_impl_->SetViewportSize(viewport_size_);
2150 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2151 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2154 protected:
2155 gfx::Size layer_size_;
2156 gfx::Size clip_size_;
2157 gfx::Size viewport_size_;
2159 LayerTreeSettings settings_;
2160 }; // class LayerTreeHostImplTopControlsTest
2162 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2163 SetupTopControlsAndScrollLayer();
2164 DrawFrame();
2166 EXPECT_EQ(InputHandler::ScrollStarted,
2167 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2169 // Make the test scroll delta a fractional amount, to verify that the
2170 // fixed container size delta is (1) non-zero, and (2) fractional, and
2171 // (3) matches the movement of the top controls.
2172 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2173 host_impl_->top_controls_manager()->ScrollBegin();
2174 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2175 host_impl_->top_controls_manager()->ScrollEnd();
2177 LayerImpl* inner_viewport_scroll_layer =
2178 host_impl_->active_tree()->InnerViewportScrollLayer();
2179 DCHECK(inner_viewport_scroll_layer);
2180 host_impl_->ScrollEnd();
2181 EXPECT_EQ(top_controls_scroll_delta,
2182 inner_viewport_scroll_layer->FixedContainerSizeDelta());
2185 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsWithPageScale) {
2186 SetupTopControlsAndScrollLayer();
2187 DrawFrame();
2189 EXPECT_EQ(InputHandler::ScrollStarted,
2190 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2192 float page_scale = 1.5f;
2193 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale, 1.f, 2.f);
2195 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.f);
2196 gfx::Vector2dF expected_container_size_delta =
2197 ScaleVector2d(top_controls_scroll_delta, 1.f / page_scale);
2198 host_impl_->top_controls_manager()->ScrollBegin();
2199 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2200 host_impl_->top_controls_manager()->ScrollEnd();
2202 LayerImpl* inner_viewport_scroll_layer =
2203 host_impl_->active_tree()->InnerViewportScrollLayer();
2204 DCHECK(inner_viewport_scroll_layer);
2205 host_impl_->ScrollEnd();
2207 // Use a tolerance that requires the container size delta to be within 0.01
2208 // pixels.
2209 double tolerance = 0.0001;
2210 EXPECT_LT(
2211 (expected_container_size_delta -
2212 inner_viewport_scroll_layer->FixedContainerSizeDelta()).LengthSquared(),
2213 tolerance);
2216 TEST_F(LayerTreeHostImplTopControlsTest,
2217 ScrollNonScrollableRootWithTopControls) {
2218 SetupTopControlsAndScrollLayer();
2219 DrawFrame();
2221 EXPECT_EQ(InputHandler::ScrollStarted,
2222 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2224 host_impl_->top_controls_manager()->ScrollBegin();
2225 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
2226 host_impl_->top_controls_manager()->ScrollEnd();
2227 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->content_top_offset());
2228 // Now that top controls have moved, expect the clip to resize.
2229 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2230 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2232 host_impl_->ScrollEnd();
2234 EXPECT_EQ(InputHandler::ScrollStarted,
2235 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2237 float scroll_increment_y = -25.f;
2238 host_impl_->top_controls_manager()->ScrollBegin();
2239 host_impl_->top_controls_manager()->ScrollBy(
2240 gfx::Vector2dF(0.f, scroll_increment_y));
2241 EXPECT_EQ(-scroll_increment_y,
2242 host_impl_->top_controls_manager()->content_top_offset());
2243 // Now that top controls have moved, expect the clip to resize.
2244 EXPECT_EQ(gfx::Size(viewport_size_.width(),
2245 viewport_size_.height() + scroll_increment_y),
2246 root_clip_ptr->bounds());
2248 host_impl_->top_controls_manager()->ScrollBy(
2249 gfx::Vector2dF(0.f, scroll_increment_y));
2250 host_impl_->top_controls_manager()->ScrollEnd();
2251 EXPECT_EQ(-2 * scroll_increment_y,
2252 host_impl_->top_controls_manager()->content_top_offset());
2253 // Now that top controls have moved, expect the clip to resize.
2254 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
2256 host_impl_->ScrollEnd();
2258 // Verify the layer is once-again non-scrollable.
2259 EXPECT_EQ(
2260 gfx::Vector2d(),
2261 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
2263 EXPECT_EQ(InputHandler::ScrollStarted,
2264 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2267 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
2268 // Test the configuration where a non-composited root layer is embedded in a
2269 // scrollable outer layer.
2270 gfx::Size surface_size(10, 10);
2271 gfx::Size contents_size(20, 20);
2273 scoped_ptr<LayerImpl> content_layer =
2274 LayerImpl::Create(host_impl_->active_tree(), 1);
2275 content_layer->SetDrawsContent(true);
2276 content_layer->SetPosition(gfx::PointF());
2277 content_layer->SetAnchorPoint(gfx::PointF());
2278 content_layer->SetBounds(contents_size);
2279 content_layer->SetContentBounds(contents_size);
2280 content_layer->SetContentsScale(2.f, 2.f);
2282 scoped_ptr<LayerImpl> scroll_clip_layer =
2283 LayerImpl::Create(host_impl_->active_tree(), 3);
2284 scroll_clip_layer->SetBounds(surface_size);
2286 scoped_ptr<LayerImpl> scroll_layer =
2287 LayerImpl::Create(host_impl_->active_tree(), 2);
2288 scroll_layer->SetScrollClipLayer(3);
2289 scroll_layer->SetBounds(contents_size);
2290 scroll_layer->SetContentBounds(contents_size);
2291 scroll_layer->SetPosition(gfx::PointF());
2292 scroll_layer->SetAnchorPoint(gfx::PointF());
2293 scroll_layer->AddChild(content_layer.Pass());
2294 scroll_clip_layer->AddChild(scroll_layer.Pass());
2296 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
2297 host_impl_->SetViewportSize(surface_size);
2298 DrawFrame();
2300 EXPECT_EQ(InputHandler::ScrollStarted,
2301 host_impl_->ScrollBegin(gfx::Point(5, 5),
2302 InputHandler::Wheel));
2303 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2304 host_impl_->ScrollEnd();
2305 EXPECT_TRUE(did_request_redraw_);
2306 EXPECT_TRUE(did_request_commit_);
2309 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
2310 gfx::Size surface_size(10, 10);
2311 gfx::Size contents_size(20, 20);
2312 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2313 root->SetBounds(surface_size);
2314 root->SetContentBounds(contents_size);
2315 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
2316 host_impl_->active_tree()->SetRootLayer(root.Pass());
2317 host_impl_->SetViewportSize(surface_size);
2318 DrawFrame();
2320 EXPECT_EQ(InputHandler::ScrollStarted,
2321 host_impl_->ScrollBegin(gfx::Point(5, 5),
2322 InputHandler::Wheel));
2323 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2324 host_impl_->ScrollEnd();
2325 EXPECT_TRUE(did_request_redraw_);
2326 EXPECT_TRUE(did_request_commit_);
2329 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
2330 gfx::Size surface_size(10, 10);
2331 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2332 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
2333 host_impl_->active_tree()->SetRootLayer(root.Pass());
2334 host_impl_->SetViewportSize(surface_size);
2335 DrawFrame();
2337 // Scroll event is ignored because the input coordinate is outside the layer
2338 // boundaries.
2339 EXPECT_EQ(InputHandler::ScrollIgnored,
2340 host_impl_->ScrollBegin(gfx::Point(15, 5),
2341 InputHandler::Wheel));
2342 EXPECT_FALSE(did_request_redraw_);
2343 EXPECT_FALSE(did_request_commit_);
2346 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
2347 gfx::Size surface_size(10, 10);
2348 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2349 scoped_ptr<LayerImpl> child =
2350 CreateScrollableLayer(2, surface_size, root.get());
2351 host_impl_->SetViewportSize(surface_size);
2353 gfx::Transform matrix;
2354 matrix.RotateAboutXAxis(180.0);
2355 child->SetTransform(matrix);
2356 child->SetDoubleSided(false);
2358 root->AddChild(child.Pass());
2359 host_impl_->active_tree()->SetRootLayer(root.Pass());
2360 DrawFrame();
2362 // Scroll event is ignored because the scrollable layer is not facing the
2363 // viewer and there is nothing scrollable behind it.
2364 EXPECT_EQ(InputHandler::ScrollIgnored,
2365 host_impl_->ScrollBegin(gfx::Point(5, 5),
2366 InputHandler::Wheel));
2367 EXPECT_FALSE(did_request_redraw_);
2368 EXPECT_FALSE(did_request_commit_);
2371 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
2372 gfx::Size surface_size(10, 10);
2373 scoped_ptr<LayerImpl> clip_layer =
2374 LayerImpl::Create(host_impl_->active_tree(), 3);
2375 scoped_ptr<LayerImpl> content_layer =
2376 CreateScrollableLayer(1, surface_size, clip_layer.get());
2377 content_layer->SetShouldScrollOnMainThread(true);
2378 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
2380 // Note: we can use the same clip layer for both since both calls to
2381 // CreateScrollableLayer() use the same surface size.
2382 scoped_ptr<LayerImpl> scroll_layer =
2383 CreateScrollableLayer(2, surface_size, clip_layer.get());
2384 scroll_layer->AddChild(content_layer.Pass());
2385 clip_layer->AddChild(scroll_layer.Pass());
2387 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
2388 host_impl_->SetViewportSize(surface_size);
2389 DrawFrame();
2391 // Scrolling fails because the content layer is asking to be scrolled on the
2392 // main thread.
2393 EXPECT_EQ(InputHandler::ScrollOnMainThread,
2394 host_impl_->ScrollBegin(gfx::Point(5, 5),
2395 InputHandler::Wheel));
2398 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
2399 gfx::Size surface_size(20, 20);
2400 gfx::Size viewport_size(10, 10);
2401 float page_scale = 2.f;
2402 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2403 scoped_ptr<LayerImpl> root_clip =
2404 LayerImpl::Create(host_impl_->active_tree(), 2);
2405 scoped_ptr<LayerImpl> root_scrolling =
2406 CreateScrollableLayer(3, surface_size, root_clip.get());
2407 EXPECT_EQ(viewport_size, root_clip->bounds());
2408 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2409 root_clip->AddChild(root_scrolling.Pass());
2410 root->AddChild(root_clip.Pass());
2411 host_impl_->active_tree()->SetRootLayer(root.Pass());
2412 // The behaviour in this test assumes the page scale is applied at a layer
2413 // above the clip layer.
2414 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2415 host_impl_->active_tree()->DidBecomeActive();
2416 host_impl_->SetViewportSize(viewport_size);
2417 DrawFrame();
2419 LayerImpl* root_scroll =
2420 host_impl_->active_tree()->InnerViewportScrollLayer();
2421 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2423 gfx::Vector2d scroll_delta(0, 10);
2424 gfx::Vector2d expected_scroll_delta = scroll_delta;
2425 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2426 EXPECT_EQ(InputHandler::ScrollStarted,
2427 host_impl_->ScrollBegin(gfx::Point(5, 5),
2428 InputHandler::Wheel));
2429 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2430 host_impl_->ScrollEnd();
2432 // Set new page scale from main thread.
2433 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2434 page_scale,
2435 page_scale);
2437 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2438 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2440 // The scroll range should also have been updated.
2441 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2443 // The page scale delta remains constant because the impl thread did not
2444 // scale.
2445 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2448 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
2449 gfx::Size surface_size(20, 20);
2450 gfx::Size viewport_size(10, 10);
2451 float page_scale = 2.f;
2452 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2453 scoped_ptr<LayerImpl> root_clip =
2454 LayerImpl::Create(host_impl_->active_tree(), 2);
2455 scoped_ptr<LayerImpl> root_scrolling =
2456 CreateScrollableLayer(3, surface_size, root_clip.get());
2457 EXPECT_EQ(viewport_size, root_clip->bounds());
2458 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2459 root_clip->AddChild(root_scrolling.Pass());
2460 root->AddChild(root_clip.Pass());
2461 host_impl_->active_tree()->SetRootLayer(root.Pass());
2462 // The behaviour in this test assumes the page scale is applied at a layer
2463 // above the clip layer.
2464 host_impl_->active_tree()->SetViewportLayersFromIds(1, 3, Layer::INVALID_ID);
2465 host_impl_->active_tree()->DidBecomeActive();
2466 host_impl_->SetViewportSize(viewport_size);
2467 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
2468 DrawFrame();
2470 LayerImpl* root_scroll =
2471 host_impl_->active_tree()->InnerViewportScrollLayer();
2472 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
2474 gfx::Vector2d scroll_delta(0, 10);
2475 gfx::Vector2d expected_scroll_delta = scroll_delta;
2476 gfx::Vector2d expected_max_scroll = root_scroll->MaxScrollOffset();
2477 EXPECT_EQ(InputHandler::ScrollStarted,
2478 host_impl_->ScrollBegin(gfx::Point(5, 5),
2479 InputHandler::Wheel));
2480 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2481 host_impl_->ScrollEnd();
2483 // Set new page scale on impl thread by pinching.
2484 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2485 host_impl_->PinchGestureBegin();
2486 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
2487 host_impl_->PinchGestureEnd();
2488 host_impl_->ScrollEnd();
2489 DrawOneFrame();
2491 // The scroll delta is not scaled because the main thread did not scale.
2492 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2493 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
2495 // The scroll range should also have been updated.
2496 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
2498 // The page scale delta should match the new scale on the impl side.
2499 EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
2502 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
2503 gfx::Size surface_size(10, 10);
2504 float default_page_scale = 1.f;
2505 gfx::Transform default_page_scale_matrix;
2506 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
2508 float new_page_scale = 2.f;
2509 gfx::Transform new_page_scale_matrix;
2510 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
2512 // Create a normal scrollable root layer and another scrollable child layer.
2513 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
2514 LayerImpl* root = host_impl_->active_tree()->root_layer();
2515 LayerImpl* child = scroll->children()[0];
2517 scoped_ptr<LayerImpl> scrollable_child_clip =
2518 LayerImpl::Create(host_impl_->active_tree(), 6);
2519 scoped_ptr<LayerImpl> scrollable_child =
2520 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
2521 scrollable_child_clip->AddChild(scrollable_child.Pass());
2522 child->AddChild(scrollable_child_clip.Pass());
2523 LayerImpl* grand_child = child->children()[0];
2525 // Set new page scale on impl thread by pinching.
2526 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
2527 host_impl_->PinchGestureBegin();
2528 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
2529 host_impl_->PinchGestureEnd();
2530 host_impl_->ScrollEnd();
2531 DrawOneFrame();
2533 EXPECT_EQ(1.f, root->contents_scale_x());
2534 EXPECT_EQ(1.f, root->contents_scale_y());
2535 EXPECT_EQ(1.f, scroll->contents_scale_x());
2536 EXPECT_EQ(1.f, scroll->contents_scale_y());
2537 EXPECT_EQ(1.f, child->contents_scale_x());
2538 EXPECT_EQ(1.f, child->contents_scale_y());
2539 EXPECT_EQ(1.f, grand_child->contents_scale_x());
2540 EXPECT_EQ(1.f, grand_child->contents_scale_y());
2542 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
2543 // the page scale delta on the root layer is applied hierarchically.
2544 LayerTreeHostImpl::FrameData frame;
2545 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2546 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2547 host_impl_->DidDrawAllLayers(frame);
2549 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
2550 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
2551 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
2552 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
2553 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
2554 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
2555 EXPECT_EQ(new_page_scale,
2556 grand_child->draw_transform().matrix().getDouble(0, 0));
2557 EXPECT_EQ(new_page_scale,
2558 grand_child->draw_transform().matrix().getDouble(1, 1));
2561 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
2562 gfx::Size surface_size(30, 30);
2563 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2564 root->SetBounds(gfx::Size(5, 5));
2565 scoped_ptr<LayerImpl> root_scrolling =
2566 LayerImpl::Create(host_impl_->active_tree(), 2);
2567 root_scrolling->SetBounds(surface_size);
2568 root_scrolling->SetContentBounds(surface_size);
2569 root_scrolling->SetScrollClipLayer(root->id());
2570 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2571 LayerImpl* root_scrolling_ptr = root_scrolling.get();
2572 root->AddChild(root_scrolling.Pass());
2573 int child_scroll_layer_id = 3;
2574 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
2575 child_scroll_layer_id, surface_size, root_scrolling_ptr);
2576 LayerImpl* child = child_scrolling.get();
2577 root_scrolling_ptr->AddChild(child_scrolling.Pass());
2578 host_impl_->active_tree()->SetRootLayer(root.Pass());
2579 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2580 host_impl_->active_tree()->DidBecomeActive();
2581 host_impl_->SetViewportSize(surface_size);
2582 DrawFrame();
2584 gfx::Vector2d scroll_delta(0, 10);
2585 gfx::Vector2d expected_scroll_delta(scroll_delta);
2586 gfx::Vector2d expected_max_scroll(child->MaxScrollOffset());
2587 EXPECT_EQ(InputHandler::ScrollStarted,
2588 host_impl_->ScrollBegin(gfx::Point(5, 5),
2589 InputHandler::Wheel));
2590 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2591 host_impl_->ScrollEnd();
2593 float page_scale = 2.f;
2594 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
2595 1.f,
2596 page_scale);
2598 DrawOneFrame();
2600 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2601 ExpectContains(
2602 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
2604 // The scroll range should not have changed.
2605 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
2607 // The page scale delta remains constant because the impl thread did not
2608 // scale.
2609 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
2612 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
2613 // Scroll a child layer beyond its maximum scroll range and make sure the
2614 // parent layer is scrolled on the axis on which the child was unable to
2615 // scroll.
2616 gfx::Size surface_size(10, 10);
2617 gfx::Size content_size(20, 20);
2618 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2619 root->SetBounds(surface_size);
2621 scoped_ptr<LayerImpl> grand_child =
2622 CreateScrollableLayer(3, content_size, root.get());
2624 scoped_ptr<LayerImpl> child =
2625 CreateScrollableLayer(2, content_size, root.get());
2626 LayerImpl* grand_child_layer = grand_child.get();
2627 child->AddChild(grand_child.Pass());
2629 LayerImpl* child_layer = child.get();
2630 root->AddChild(child.Pass());
2631 host_impl_->active_tree()->SetRootLayer(root.Pass());
2632 host_impl_->active_tree()->DidBecomeActive();
2633 host_impl_->SetViewportSize(surface_size);
2634 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 5));
2635 child_layer->SetScrollOffset(gfx::Vector2d(3, 0));
2637 DrawFrame();
2639 gfx::Vector2d scroll_delta(-8, -7);
2640 EXPECT_EQ(InputHandler::ScrollStarted,
2641 host_impl_->ScrollBegin(gfx::Point(),
2642 InputHandler::Wheel));
2643 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2644 host_impl_->ScrollEnd();
2646 scoped_ptr<ScrollAndScaleSet> scroll_info =
2647 host_impl_->ProcessScrollDeltas();
2649 // The grand child should have scrolled up to its limit.
2650 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
2651 LayerImpl* grand_child = child->children()[0];
2652 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
2654 // The child should have only scrolled on the other axis.
2655 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
2659 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
2660 // Scroll a child layer beyond its maximum scroll range and make sure the
2661 // the scroll doesn't bubble up to the parent layer.
2662 gfx::Size surface_size(20, 20);
2663 gfx::Size viewport_size(10, 10);
2664 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2665 scoped_ptr<LayerImpl> root_scrolling =
2666 CreateScrollableLayer(2, surface_size, root.get());
2667 root_scrolling->SetIsContainerForFixedPositionLayers(true);
2669 scoped_ptr<LayerImpl> grand_child =
2670 CreateScrollableLayer(4, surface_size, root.get());
2672 scoped_ptr<LayerImpl> child =
2673 CreateScrollableLayer(3, surface_size, root.get());
2674 LayerImpl* grand_child_layer = grand_child.get();
2675 child->AddChild(grand_child.Pass());
2677 LayerImpl* child_layer = child.get();
2678 root_scrolling->AddChild(child.Pass());
2679 root->AddChild(root_scrolling.Pass());
2680 EXPECT_EQ(viewport_size, root->bounds());
2681 host_impl_->active_tree()->SetRootLayer(root.Pass());
2682 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2683 host_impl_->active_tree()->DidBecomeActive();
2684 host_impl_->SetViewportSize(viewport_size);
2686 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
2687 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
2689 DrawFrame();
2691 gfx::Vector2d scroll_delta(0, -10);
2692 EXPECT_EQ(InputHandler::ScrollStarted,
2693 host_impl_->ScrollBegin(gfx::Point(),
2694 InputHandler::NonBubblingGesture));
2695 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2696 host_impl_->ScrollEnd();
2698 scoped_ptr<ScrollAndScaleSet> scroll_info =
2699 host_impl_->ProcessScrollDeltas();
2701 // The grand child should have scrolled up to its limit.
2702 LayerImpl* child =
2703 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
2704 LayerImpl* grand_child = child->children()[0];
2705 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2707 // The child should not have scrolled.
2708 ExpectNone(*scroll_info.get(), child->id());
2710 // The next time we scroll we should only scroll the parent.
2711 scroll_delta = gfx::Vector2d(0, -3);
2712 EXPECT_EQ(InputHandler::ScrollStarted,
2713 host_impl_->ScrollBegin(gfx::Point(5, 5),
2714 InputHandler::NonBubblingGesture));
2715 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2716 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2717 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
2718 host_impl_->ScrollEnd();
2720 scroll_info = host_impl_->ProcessScrollDeltas();
2722 // The child should have scrolled up to its limit.
2723 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2725 // The grand child should not have scrolled.
2726 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
2728 // After scrolling the parent, another scroll on the opposite direction
2729 // should still scroll the child.
2730 scroll_delta = gfx::Vector2d(0, 7);
2731 EXPECT_EQ(InputHandler::ScrollStarted,
2732 host_impl_->ScrollBegin(gfx::Point(5, 5),
2733 InputHandler::NonBubblingGesture));
2734 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2735 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2736 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
2737 host_impl_->ScrollEnd();
2739 scroll_info = host_impl_->ProcessScrollDeltas();
2741 // The grand child should have scrolled.
2742 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
2744 // The child should not have scrolled.
2745 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
2748 // Scrolling should be adjusted from viewport space.
2749 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
2750 host_impl_->active_tree()->SetPageScaleDelta(1.f);
2752 scroll_delta = gfx::Vector2d(0, -2);
2753 EXPECT_EQ(InputHandler::ScrollStarted,
2754 host_impl_->ScrollBegin(gfx::Point(1, 1),
2755 InputHandler::NonBubblingGesture));
2756 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
2757 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2758 host_impl_->ScrollEnd();
2760 scroll_info = host_impl_->ProcessScrollDeltas();
2762 // Should have scrolled by half the amount in layer space (5 - 2/2)
2763 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
2766 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
2767 // When we try to scroll a non-scrollable child layer, the scroll delta
2768 // should be applied to one of its ancestors if possible.
2769 gfx::Size surface_size(10, 10);
2770 gfx::Size content_size(20, 20);
2771 scoped_ptr<LayerImpl> root_clip =
2772 LayerImpl::Create(host_impl_->active_tree(), 3);
2773 scoped_ptr<LayerImpl> root =
2774 CreateScrollableLayer(1, content_size, root_clip.get());
2775 // Make 'root' the clip layer for child: since they have the same sizes the
2776 // child will have zero max_scroll_offset and scrolls will bubble.
2777 scoped_ptr<LayerImpl> child =
2778 CreateScrollableLayer(2, content_size, root.get());
2779 child->SetIsContainerForFixedPositionLayers(true);
2780 root->SetBounds(content_size);
2782 int root_scroll_id = root->id();
2783 root->AddChild(child.Pass());
2784 root_clip->AddChild(root.Pass());
2786 host_impl_->SetViewportSize(surface_size);
2787 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2788 host_impl_->active_tree()->SetViewportLayersFromIds(3, 2, Layer::INVALID_ID);
2789 host_impl_->active_tree()->DidBecomeActive();
2790 DrawFrame();
2792 gfx::Vector2d scroll_delta(0, 4);
2793 EXPECT_EQ(InputHandler::ScrollStarted,
2794 host_impl_->ScrollBegin(gfx::Point(5, 5),
2795 InputHandler::Wheel));
2796 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2797 host_impl_->ScrollEnd();
2799 scoped_ptr<ScrollAndScaleSet> scroll_info =
2800 host_impl_->ProcessScrollDeltas();
2802 // Only the root scroll should have scrolled.
2803 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
2804 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
2808 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
2809 gfx::Size surface_size(10, 10);
2810 scoped_ptr<LayerImpl> root_clip =
2811 LayerImpl::Create(host_impl_->active_tree(), 1);
2812 scoped_ptr<LayerImpl> root_scroll =
2813 CreateScrollableLayer(2, surface_size, root_clip.get());
2814 root_scroll->SetIsContainerForFixedPositionLayers(true);
2815 root_clip->AddChild(root_scroll.Pass());
2816 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2817 host_impl_->active_tree()->SetViewportLayersFromIds(1, 2, Layer::INVALID_ID);
2818 host_impl_->active_tree()->DidBecomeActive();
2819 host_impl_->SetViewportSize(surface_size);
2821 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
2822 // synchronization.
2823 DrawFrame();
2824 host_impl_->active_tree()->DetachLayerTree();
2825 scoped_ptr<LayerImpl> root_clip2 =
2826 LayerImpl::Create(host_impl_->active_tree(), 3);
2827 scoped_ptr<LayerImpl> root_scroll2 =
2828 CreateScrollableLayer(4, surface_size, root_clip2.get());
2829 root_scroll2->SetIsContainerForFixedPositionLayers(true);
2830 root_clip2->AddChild(root_scroll2.Pass());
2831 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
2832 host_impl_->active_tree()->SetViewportLayersFromIds(3, 4, Layer::INVALID_ID);
2833 host_impl_->active_tree()->DidBecomeActive();
2835 // Scrolling should still work even though we did not draw yet.
2836 EXPECT_EQ(InputHandler::ScrollStarted,
2837 host_impl_->ScrollBegin(gfx::Point(5, 5),
2838 InputHandler::Wheel));
2841 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
2842 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2844 // Rotate the root layer 90 degrees counter-clockwise about its center.
2845 gfx::Transform rotate_transform;
2846 rotate_transform.Rotate(-90.0);
2847 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
2849 gfx::Size surface_size(50, 50);
2850 host_impl_->SetViewportSize(surface_size);
2851 DrawFrame();
2853 // Scroll to the right in screen coordinates with a gesture.
2854 gfx::Vector2d gesture_scroll_delta(10, 0);
2855 EXPECT_EQ(InputHandler::ScrollStarted,
2856 host_impl_->ScrollBegin(gfx::Point(),
2857 InputHandler::Gesture));
2858 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2859 host_impl_->ScrollEnd();
2861 // The layer should have scrolled down in its local coordinates.
2862 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2863 ExpectContains(*scroll_info.get(),
2864 scroll_layer->id(),
2865 gfx::Vector2d(0, gesture_scroll_delta.x()));
2867 // Reset and scroll down with the wheel.
2868 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2869 gfx::Vector2d wheel_scroll_delta(0, 10);
2870 EXPECT_EQ(InputHandler::ScrollStarted,
2871 host_impl_->ScrollBegin(gfx::Point(),
2872 InputHandler::Wheel));
2873 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
2874 host_impl_->ScrollEnd();
2876 // The layer should have scrolled down in its local coordinates.
2877 scroll_info = host_impl_->ProcessScrollDeltas();
2878 ExpectContains(*scroll_info.get(),
2879 scroll_layer->id(),
2880 wheel_scroll_delta);
2883 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
2884 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
2885 int child_clip_layer_id = 6;
2886 int child_layer_id = 7;
2887 float child_layer_angle = -20.f;
2889 // Create a child layer that is rotated to a non-axis-aligned angle.
2890 scoped_ptr<LayerImpl> clip_layer =
2891 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
2892 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
2893 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
2894 gfx::Transform rotate_transform;
2895 rotate_transform.Translate(-50.0, -50.0);
2896 rotate_transform.Rotate(child_layer_angle);
2897 rotate_transform.Translate(50.0, 50.0);
2898 clip_layer->SetTransform(rotate_transform);
2900 // Only allow vertical scrolling.
2901 clip_layer->SetBounds(
2902 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
2903 // The rotation depends on the layer's anchor point, and the child layer is a
2904 // different size than the clip, so make sure the clip layer's anchor lines
2905 // up over the child.
2906 clip_layer->SetAnchorPoint(gfx::PointF(0.5, 1.0));
2907 LayerImpl* child_ptr = child.get();
2908 clip_layer->AddChild(child.Pass());
2909 scroll_layer->AddChild(clip_layer.Pass());
2911 gfx::Size surface_size(50, 50);
2912 host_impl_->SetViewportSize(surface_size);
2913 DrawFrame();
2915 // Scroll down in screen coordinates with a gesture.
2916 gfx::Vector2d gesture_scroll_delta(0, 10);
2917 EXPECT_EQ(InputHandler::ScrollStarted,
2918 host_impl_->ScrollBegin(gfx::Point(1, 1),
2919 InputHandler::Gesture));
2920 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2921 host_impl_->ScrollEnd();
2923 // The child layer should have scrolled down in its local coordinates an
2924 // amount proportional to the angle between it and the input scroll delta.
2925 gfx::Vector2d expected_scroll_delta(
2927 gesture_scroll_delta.y() *
2928 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
2929 scoped_ptr<ScrollAndScaleSet> scroll_info =
2930 host_impl_->ProcessScrollDeltas();
2931 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2933 // The root scroll layer should not have scrolled, because the input delta
2934 // was close to the layer's axis of movement.
2935 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
2938 // Now reset and scroll the same amount horizontally.
2939 child_ptr->SetScrollDelta(gfx::Vector2dF());
2940 gfx::Vector2d gesture_scroll_delta(10, 0);
2941 EXPECT_EQ(InputHandler::ScrollStarted,
2942 host_impl_->ScrollBegin(gfx::Point(1, 1),
2943 InputHandler::Gesture));
2944 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
2945 host_impl_->ScrollEnd();
2947 // The child layer should have scrolled down in its local coordinates an
2948 // amount proportional to the angle between it and the input scroll delta.
2949 gfx::Vector2d expected_scroll_delta(
2951 -gesture_scroll_delta.x() *
2952 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
2953 scoped_ptr<ScrollAndScaleSet> scroll_info =
2954 host_impl_->ProcessScrollDeltas();
2955 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
2957 // The root scroll layer should have scrolled more, since the input scroll
2958 // delta was mostly orthogonal to the child layer's vertical scroll axis.
2959 gfx::Vector2d expected_root_scroll_delta(
2960 gesture_scroll_delta.x() *
2961 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
2963 ExpectContains(*scroll_info.get(),
2964 scroll_layer->id(),
2965 expected_root_scroll_delta);
2969 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
2970 LayerImpl* scroll_layer =
2971 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2973 // Scale the layer to twice its normal size.
2974 int scale = 2;
2975 gfx::Transform scale_transform;
2976 scale_transform.Scale(scale, scale);
2977 scroll_layer->SetTransform(scale_transform);
2979 gfx::Size surface_size(50, 50);
2980 host_impl_->SetViewportSize(surface_size);
2981 DrawFrame();
2983 // Scroll down in screen coordinates with a gesture.
2984 gfx::Vector2d scroll_delta(0, 10);
2985 EXPECT_EQ(InputHandler::ScrollStarted,
2986 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2987 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2988 host_impl_->ScrollEnd();
2990 // The layer should have scrolled down in its local coordinates, but half the
2991 // amount.
2992 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
2993 ExpectContains(*scroll_info.get(),
2994 scroll_layer->id(),
2995 gfx::Vector2d(0, scroll_delta.y() / scale));
2997 // Reset and scroll down with the wheel.
2998 scroll_layer->SetScrollDelta(gfx::Vector2dF());
2999 gfx::Vector2d wheel_scroll_delta(0, 10);
3000 EXPECT_EQ(InputHandler::ScrollStarted,
3001 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3002 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3003 host_impl_->ScrollEnd();
3005 // The scale should not have been applied to the scroll delta.
3006 scroll_info = host_impl_->ProcessScrollDeltas();
3007 ExpectContains(*scroll_info.get(),
3008 scroll_layer->id(),
3009 wheel_scroll_delta);
3012 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
3013 public:
3014 TestScrollOffsetDelegate()
3015 : page_scale_factor_(0.f),
3016 min_page_scale_factor_(-1.f),
3017 max_page_scale_factor_(-1.f) {}
3019 virtual ~TestScrollOffsetDelegate() {}
3021 virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
3022 return getter_return_value_;
3025 virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
3027 virtual void UpdateRootLayerState(const gfx::Vector2dF& total_scroll_offset,
3028 const gfx::Vector2dF& max_scroll_offset,
3029 const gfx::SizeF& scrollable_size,
3030 float page_scale_factor,
3031 float min_page_scale_factor,
3032 float max_page_scale_factor) OVERRIDE {
3033 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
3034 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
3035 last_set_scroll_offset_ = total_scroll_offset;
3036 max_scroll_offset_ = max_scroll_offset;
3037 scrollable_size_ = scrollable_size;
3038 page_scale_factor_ = page_scale_factor;
3039 min_page_scale_factor_ = min_page_scale_factor;
3040 max_page_scale_factor_ = max_page_scale_factor;
3043 gfx::Vector2dF last_set_scroll_offset() {
3044 return last_set_scroll_offset_;
3047 void set_getter_return_value(const gfx::Vector2dF& value) {
3048 getter_return_value_ = value;
3051 gfx::Vector2dF max_scroll_offset() const {
3052 return max_scroll_offset_;
3055 gfx::SizeF scrollable_size() const {
3056 return scrollable_size_;
3059 float page_scale_factor() const {
3060 return page_scale_factor_;
3063 float min_page_scale_factor() const {
3064 return min_page_scale_factor_;
3067 float max_page_scale_factor() const {
3068 return max_page_scale_factor_;
3071 private:
3072 gfx::Vector2dF last_set_scroll_offset_;
3073 gfx::Vector2dF getter_return_value_;
3074 gfx::Vector2dF max_scroll_offset_;
3075 gfx::SizeF scrollable_size_;
3076 float page_scale_factor_;
3077 float min_page_scale_factor_;
3078 float max_page_scale_factor_;
3081 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
3082 TestScrollOffsetDelegate scroll_delegate;
3083 host_impl_->SetViewportSize(gfx::Size(10, 20));
3084 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3085 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3086 clip_layer->SetBounds(gfx::Size(10, 20));
3088 // Setting the delegate results in the current scroll offset being set.
3089 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
3090 scroll_layer->SetScrollOffset(gfx::Vector2d());
3091 scroll_layer->SetScrollDelta(initial_scroll_delta);
3092 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3093 EXPECT_EQ(initial_scroll_delta.ToString(),
3094 scroll_delegate.last_set_scroll_offset().ToString());
3096 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3097 // page_scale_factor and {min|max}_page_scale_factor being set.
3098 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
3099 EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
3100 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3101 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
3102 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
3104 // Updating page scale immediately updates the delegate.
3105 host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
3106 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
3107 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3108 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3109 host_impl_->active_tree()->SetPageScaleDelta(1.5f);
3110 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
3111 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3112 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3113 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3114 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3115 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3116 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3117 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3119 // The pinch gesture doesn't put the delegate into a state where the scroll
3120 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3121 // delegate).
3122 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
3123 host_impl_->PinchGestureBegin();
3124 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
3125 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
3126 host_impl_->PinchGestureEnd();
3127 host_impl_->ScrollEnd();
3129 // Scrolling should be relative to the offset as returned by the delegate.
3130 gfx::Vector2dF scroll_delta(0.f, 10.f);
3131 gfx::Vector2dF current_offset(7.f, 8.f);
3133 scroll_delegate.set_getter_return_value(current_offset);
3134 EXPECT_EQ(InputHandler::ScrollStarted,
3135 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
3137 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3138 EXPECT_EQ(current_offset + scroll_delta,
3139 scroll_delegate.last_set_scroll_offset());
3141 current_offset = gfx::Vector2dF(42.f, 41.f);
3142 scroll_delegate.set_getter_return_value(current_offset);
3143 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3144 EXPECT_EQ(current_offset + scroll_delta,
3145 scroll_delegate.last_set_scroll_offset());
3146 host_impl_->ScrollEnd();
3147 scroll_delegate.set_getter_return_value(gfx::Vector2dF());
3149 // Forces a full tree synchronization and ensures that the scroll delegate
3150 // sees the correct size of the new tree.
3151 gfx::Size new_size(42, 24);
3152 host_impl_->CreatePendingTree();
3153 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
3154 host_impl_->ActivatePendingTree();
3155 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
3157 // Un-setting the delegate should propagate the delegate's current offset to
3158 // the root scrollable layer.
3159 current_offset = gfx::Vector2dF(13.f, 12.f);
3160 scroll_delegate.set_getter_return_value(current_offset);
3161 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
3163 EXPECT_EQ(current_offset.ToString(),
3164 scroll_layer->TotalScrollOffset().ToString());
3167 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
3168 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3169 host_impl_->SetViewportSize(gfx::Size(50, 50));
3170 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3171 DrawFrame();
3172 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3174 // In-bounds scrolling does not affect overscroll.
3175 EXPECT_EQ(InputHandler::ScrollStarted,
3176 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3177 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3178 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3180 // Overscroll events are reflected immediately.
3181 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
3182 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3184 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
3185 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
3186 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3187 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
3188 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3189 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
3190 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3191 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
3192 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
3193 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
3194 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
3195 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
3196 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3198 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
3199 // as no scroll occurs.
3200 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3201 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
3202 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3203 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
3204 // Overscroll resets on valid scroll.
3205 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3206 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
3207 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
3208 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
3209 host_impl_->ScrollEnd();
3213 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
3214 // Scroll child layers beyond their maximum scroll range and make sure root
3215 // overscroll does not accumulate.
3216 gfx::Size surface_size(10, 10);
3217 scoped_ptr<LayerImpl> root_clip =
3218 LayerImpl::Create(host_impl_->active_tree(), 4);
3219 scoped_ptr<LayerImpl> root =
3220 CreateScrollableLayer(1, surface_size, root_clip.get());
3222 scoped_ptr<LayerImpl> grand_child =
3223 CreateScrollableLayer(3, surface_size, root_clip.get());
3225 scoped_ptr<LayerImpl> child =
3226 CreateScrollableLayer(2, surface_size, root_clip.get());
3227 LayerImpl* grand_child_layer = grand_child.get();
3228 child->AddChild(grand_child.Pass());
3230 LayerImpl* child_layer = child.get();
3231 root->AddChild(child.Pass());
3232 root_clip->AddChild(root.Pass());
3233 child_layer->SetScrollOffset(gfx::Vector2d(0, 3));
3234 grand_child_layer->SetScrollOffset(gfx::Vector2d(0, 2));
3235 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3236 host_impl_->active_tree()->DidBecomeActive();
3237 host_impl_->SetViewportSize(surface_size);
3238 DrawFrame();
3240 gfx::Vector2d scroll_delta(0, -10);
3241 EXPECT_EQ(InputHandler::ScrollStarted,
3242 host_impl_->ScrollBegin(gfx::Point(),
3243 InputHandler::NonBubblingGesture));
3244 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3245 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3246 host_impl_->ScrollEnd();
3248 // The next time we scroll we should only scroll the parent, but overscroll
3249 // should still not reach the root layer.
3250 scroll_delta = gfx::Vector2d(0, -30);
3251 EXPECT_EQ(InputHandler::ScrollStarted,
3252 host_impl_->ScrollBegin(gfx::Point(5, 5),
3253 InputHandler::NonBubblingGesture));
3254 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3255 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3256 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3257 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
3258 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3259 host_impl_->ScrollEnd();
3261 // After scrolling the parent, another scroll on the opposite direction
3262 // should scroll the child.
3263 scroll_delta = gfx::Vector2d(0, 70);
3264 EXPECT_EQ(InputHandler::ScrollStarted,
3265 host_impl_->ScrollBegin(gfx::Point(5, 5),
3266 InputHandler::NonBubblingGesture));
3267 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3268 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3269 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
3270 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3271 host_impl_->ScrollEnd();
3275 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
3276 // When we try to scroll a non-scrollable child layer, the scroll delta
3277 // should be applied to one of its ancestors if possible. Overscroll should
3278 // be reflected only when it has bubbled up to the root scrolling layer.
3279 gfx::Size surface_size(10, 10);
3280 gfx::Size content_size(20, 20);
3281 scoped_ptr<LayerImpl> root_clip =
3282 LayerImpl::Create(host_impl_->active_tree(), 3);
3283 scoped_ptr<LayerImpl> root =
3284 CreateScrollableLayer(1, content_size, root_clip.get());
3285 root->SetIsContainerForFixedPositionLayers(true);
3286 scoped_ptr<LayerImpl> child =
3287 CreateScrollableLayer(2, content_size, root_clip.get());
3289 child->SetScrollClipLayer(Layer::INVALID_ID);
3290 root->AddChild(child.Pass());
3291 root_clip->AddChild(root.Pass());
3293 host_impl_->SetViewportSize(surface_size);
3294 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3295 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3296 host_impl_->active_tree()->DidBecomeActive();
3297 DrawFrame();
3299 gfx::Vector2d scroll_delta(0, 8);
3300 EXPECT_EQ(InputHandler::ScrollStarted,
3301 host_impl_->ScrollBegin(gfx::Point(5, 5),
3302 InputHandler::Wheel));
3303 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3304 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3305 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3306 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
3307 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3308 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
3309 host_impl_->ScrollEnd();
3313 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
3314 LayerTreeSettings settings;
3315 CreateHostImpl(settings, CreateOutputSurface());
3317 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
3318 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3319 clip_layer->SetBounds(gfx::Size(50, 50));
3320 host_impl_->SetViewportSize(gfx::Size(50, 50));
3321 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
3322 DrawFrame();
3323 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
3325 // Even though the layer can't scroll the overscroll still happens.
3326 EXPECT_EQ(InputHandler::ScrollStarted,
3327 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
3328 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3329 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
3332 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
3333 gfx::Size surface_size(980, 1439);
3334 gfx::Size content_size(980, 1438);
3335 float device_scale_factor = 1.5f;
3336 scoped_ptr<LayerImpl> root_clip =
3337 LayerImpl::Create(host_impl_->active_tree(), 3);
3338 scoped_ptr<LayerImpl> root =
3339 CreateScrollableLayer(1, content_size, root_clip.get());
3340 root->SetIsContainerForFixedPositionLayers(true);
3341 scoped_ptr<LayerImpl> child =
3342 CreateScrollableLayer(2, content_size, root_clip.get());
3343 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
3344 host_impl_->active_tree()->SetPageScaleFactorAndLimits(
3345 0.326531f, 0.326531f, 5.f);
3346 host_impl_->active_tree()->SetPageScaleDelta(1.f);
3347 child->SetScrollClipLayer(Layer::INVALID_ID);
3348 root->AddChild(child.Pass());
3349 root_clip->AddChild(root.Pass());
3351 host_impl_->SetViewportSize(surface_size);
3352 host_impl_->SetDeviceScaleFactor(device_scale_factor);
3353 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3354 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3355 host_impl_->active_tree()->DidBecomeActive();
3356 DrawFrame();
3358 // Horizontal & Vertical GlowEffect should not be applied when
3359 // content size is less then view port size. For Example Horizontal &
3360 // vertical GlowEffect should not be applied in about:blank page.
3361 EXPECT_EQ(InputHandler::ScrollStarted,
3362 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3363 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
3364 EXPECT_EQ(gfx::Vector2dF().ToString(),
3365 host_impl_->accumulated_root_overscroll().ToString());
3367 host_impl_->ScrollEnd();
3371 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
3372 gfx::Size surface_size(100, 100);
3373 gfx::Size content_size(200, 200);
3374 scoped_ptr<LayerImpl> root_clip =
3375 LayerImpl::Create(host_impl_->active_tree(), 3);
3376 scoped_ptr<LayerImpl> root =
3377 CreateScrollableLayer(1, content_size, root_clip.get());
3378 root->SetIsContainerForFixedPositionLayers(true);
3379 scoped_ptr<LayerImpl> child =
3380 CreateScrollableLayer(2, content_size, root_clip.get());
3382 child->SetScrollClipLayer(Layer::INVALID_ID);
3383 root->AddChild(child.Pass());
3384 root_clip->AddChild(root.Pass());
3386 host_impl_->SetViewportSize(surface_size);
3387 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3388 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
3389 host_impl_->active_tree()->DidBecomeActive();
3390 DrawFrame();
3392 // Edge glow effect should be applicable only upon reaching Edges
3393 // of the content. unnecessary glow effect calls shouldn't be
3394 // called while scrolling up without reaching the edge of the content.
3395 EXPECT_EQ(InputHandler::ScrollStarted,
3396 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3397 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
3398 EXPECT_EQ(gfx::Vector2dF().ToString(),
3399 host_impl_->accumulated_root_overscroll().ToString());
3400 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
3401 EXPECT_EQ(gfx::Vector2dF().ToString(),
3402 host_impl_->accumulated_root_overscroll().ToString());
3403 host_impl_->ScrollEnd();
3404 // unusedrootDelta should be subtracted from applied delta so that
3405 // unwanted glow effect calls are not called.
3406 EXPECT_EQ(InputHandler::ScrollStarted,
3407 host_impl_->ScrollBegin(gfx::Point(0, 0),
3408 InputHandler::NonBubblingGesture));
3409 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
3410 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
3411 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3412 host_impl_->accumulated_root_overscroll().ToString());
3414 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
3415 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
3416 host_impl_->accumulated_root_overscroll().ToString());
3417 host_impl_->ScrollEnd();
3418 // TestCase to check kEpsilon, which prevents minute values to trigger
3419 // gloweffect without reaching edge.
3420 EXPECT_EQ(InputHandler::ScrollStarted,
3421 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
3422 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
3423 EXPECT_EQ(gfx::Vector2dF().ToString(),
3424 host_impl_->accumulated_root_overscroll().ToString());
3425 host_impl_->ScrollEnd();
3429 class BlendStateCheckLayer : public LayerImpl {
3430 public:
3431 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
3432 int id,
3433 ResourceProvider* resource_provider) {
3434 return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(tree_impl,
3436 resource_provider));
3439 virtual void AppendQuads(QuadSink* quad_sink,
3440 AppendQuadsData* append_quads_data) OVERRIDE {
3441 quads_appended_ = true;
3443 gfx::Rect opaque_rect;
3444 if (contents_opaque())
3445 opaque_rect = quad_rect_;
3446 else
3447 opaque_rect = opaque_content_rect_;
3448 gfx::Rect visible_quad_rect = quad_rect_;
3450 SharedQuadState* shared_quad_state = quad_sink->CreateSharedQuadState();
3451 PopulateSharedQuadState(shared_quad_state);
3453 scoped_ptr<TileDrawQuad> test_blending_draw_quad = TileDrawQuad::Create();
3454 test_blending_draw_quad->SetNew(shared_quad_state,
3455 quad_rect_,
3456 opaque_rect,
3457 visible_quad_rect,
3458 resource_id_,
3459 gfx::RectF(0.f, 0.f, 1.f, 1.f),
3460 gfx::Size(1, 1),
3461 false);
3462 test_blending_draw_quad->visible_rect = quad_visible_rect_;
3463 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
3464 EXPECT_EQ(has_render_surface_, !!render_surface());
3465 quad_sink->Append(test_blending_draw_quad.PassAs<DrawQuad>());
3468 void SetExpectation(bool blend, bool has_render_surface) {
3469 blend_ = blend;
3470 has_render_surface_ = has_render_surface;
3471 quads_appended_ = false;
3474 bool quads_appended() const { return quads_appended_; }
3476 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
3477 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
3478 void SetOpaqueContentRect(const gfx::Rect& rect) {
3479 opaque_content_rect_ = rect;
3482 private:
3483 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
3484 int id,
3485 ResourceProvider* resource_provider)
3486 : LayerImpl(tree_impl, id),
3487 blend_(false),
3488 has_render_surface_(false),
3489 quads_appended_(false),
3490 quad_rect_(5, 5, 5, 5),
3491 quad_visible_rect_(5, 5, 5, 5),
3492 resource_id_(resource_provider->CreateResource(
3493 gfx::Size(1, 1),
3494 GL_CLAMP_TO_EDGE,
3495 ResourceProvider::TextureUsageAny,
3496 RGBA_8888)) {
3497 resource_provider->AllocateForTesting(resource_id_);
3498 SetAnchorPoint(gfx::PointF());
3499 SetBounds(gfx::Size(10, 10));
3500 SetContentBounds(gfx::Size(10, 10));
3501 SetDrawsContent(true);
3504 bool blend_;
3505 bool has_render_surface_;
3506 bool quads_appended_;
3507 gfx::Rect quad_rect_;
3508 gfx::Rect opaque_content_rect_;
3509 gfx::Rect quad_visible_rect_;
3510 ResourceProvider::ResourceId resource_id_;
3513 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
3515 scoped_ptr<LayerImpl> root =
3516 LayerImpl::Create(host_impl_->active_tree(), 1);
3517 root->SetAnchorPoint(gfx::PointF());
3518 root->SetBounds(gfx::Size(10, 10));
3519 root->SetContentBounds(root->bounds());
3520 root->SetDrawsContent(false);
3521 host_impl_->active_tree()->SetRootLayer(root.Pass());
3523 LayerImpl* root = host_impl_->active_tree()->root_layer();
3525 root->AddChild(
3526 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3528 host_impl_->resource_provider()));
3529 BlendStateCheckLayer* layer1 =
3530 static_cast<BlendStateCheckLayer*>(root->children()[0]);
3531 layer1->SetPosition(gfx::PointF(2.f, 2.f));
3533 LayerTreeHostImpl::FrameData frame;
3535 // Opaque layer, drawn without blending.
3536 layer1->SetContentsOpaque(true);
3537 layer1->SetExpectation(false, false);
3538 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3539 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3540 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3541 EXPECT_TRUE(layer1->quads_appended());
3542 host_impl_->DidDrawAllLayers(frame);
3544 // Layer with translucent content and painting, so drawn with blending.
3545 layer1->SetContentsOpaque(false);
3546 layer1->SetExpectation(true, false);
3547 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3548 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3549 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3550 EXPECT_TRUE(layer1->quads_appended());
3551 host_impl_->DidDrawAllLayers(frame);
3553 // Layer with translucent opacity, drawn with blending.
3554 layer1->SetContentsOpaque(true);
3555 layer1->SetOpacity(0.5f);
3556 layer1->SetExpectation(true, false);
3557 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3558 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3559 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3560 EXPECT_TRUE(layer1->quads_appended());
3561 host_impl_->DidDrawAllLayers(frame);
3563 // Layer with translucent opacity and painting, drawn with blending.
3564 layer1->SetContentsOpaque(true);
3565 layer1->SetOpacity(0.5f);
3566 layer1->SetExpectation(true, false);
3567 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3568 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3569 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3570 EXPECT_TRUE(layer1->quads_appended());
3571 host_impl_->DidDrawAllLayers(frame);
3573 layer1->AddChild(
3574 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3576 host_impl_->resource_provider()));
3577 BlendStateCheckLayer* layer2 =
3578 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
3579 layer2->SetPosition(gfx::PointF(4.f, 4.f));
3581 // 2 opaque layers, drawn without blending.
3582 layer1->SetContentsOpaque(true);
3583 layer1->SetOpacity(1.f);
3584 layer1->SetExpectation(false, false);
3585 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3586 layer2->SetContentsOpaque(true);
3587 layer2->SetOpacity(1.f);
3588 layer2->SetExpectation(false, false);
3589 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3590 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3591 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3592 EXPECT_TRUE(layer1->quads_appended());
3593 EXPECT_TRUE(layer2->quads_appended());
3594 host_impl_->DidDrawAllLayers(frame);
3596 // Parent layer with translucent content, drawn with blending.
3597 // Child layer with opaque content, drawn without blending.
3598 layer1->SetContentsOpaque(false);
3599 layer1->SetExpectation(true, false);
3600 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3601 layer2->SetExpectation(false, false);
3602 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3603 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3604 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3605 EXPECT_TRUE(layer1->quads_appended());
3606 EXPECT_TRUE(layer2->quads_appended());
3607 host_impl_->DidDrawAllLayers(frame);
3609 // Parent layer with translucent content but opaque painting, drawn without
3610 // blending.
3611 // Child layer with opaque content, drawn without blending.
3612 layer1->SetContentsOpaque(true);
3613 layer1->SetExpectation(false, false);
3614 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3615 layer2->SetExpectation(false, false);
3616 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3617 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3618 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3619 EXPECT_TRUE(layer1->quads_appended());
3620 EXPECT_TRUE(layer2->quads_appended());
3621 host_impl_->DidDrawAllLayers(frame);
3623 // Parent layer with translucent opacity and opaque content. Since it has a
3624 // drawing child, it's drawn to a render surface which carries the opacity,
3625 // so it's itself drawn without blending.
3626 // Child layer with opaque content, drawn without blending (parent surface
3627 // carries the inherited opacity).
3628 layer1->SetContentsOpaque(true);
3629 layer1->SetOpacity(0.5f);
3630 layer1->SetExpectation(false, true);
3631 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3632 layer2->SetExpectation(false, false);
3633 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3634 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3635 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3636 EXPECT_TRUE(layer1->quads_appended());
3637 EXPECT_TRUE(layer2->quads_appended());
3638 host_impl_->DidDrawAllLayers(frame);
3640 // Draw again, but with child non-opaque, to make sure
3641 // layer1 not culled.
3642 layer1->SetContentsOpaque(true);
3643 layer1->SetOpacity(1.f);
3644 layer1->SetExpectation(false, false);
3645 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3646 layer2->SetContentsOpaque(true);
3647 layer2->SetOpacity(0.5f);
3648 layer2->SetExpectation(true, false);
3649 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3650 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3651 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3652 EXPECT_TRUE(layer1->quads_appended());
3653 EXPECT_TRUE(layer2->quads_appended());
3654 host_impl_->DidDrawAllLayers(frame);
3656 // A second way of making the child non-opaque.
3657 layer1->SetContentsOpaque(true);
3658 layer1->SetOpacity(1.f);
3659 layer1->SetExpectation(false, false);
3660 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3661 layer2->SetContentsOpaque(false);
3662 layer2->SetOpacity(1.f);
3663 layer2->SetExpectation(true, false);
3664 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3665 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3666 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3667 EXPECT_TRUE(layer1->quads_appended());
3668 EXPECT_TRUE(layer2->quads_appended());
3669 host_impl_->DidDrawAllLayers(frame);
3671 // And when the layer says its not opaque but is painted opaque, it is not
3672 // blended.
3673 layer1->SetContentsOpaque(true);
3674 layer1->SetOpacity(1.f);
3675 layer1->SetExpectation(false, false);
3676 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3677 layer2->SetContentsOpaque(true);
3678 layer2->SetOpacity(1.f);
3679 layer2->SetExpectation(false, false);
3680 layer2->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3681 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3682 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3683 EXPECT_TRUE(layer1->quads_appended());
3684 EXPECT_TRUE(layer2->quads_appended());
3685 host_impl_->DidDrawAllLayers(frame);
3687 // Layer with partially opaque contents, drawn with blending.
3688 layer1->SetContentsOpaque(false);
3689 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3690 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
3691 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3692 layer1->SetExpectation(true, false);
3693 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3694 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3695 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3696 EXPECT_TRUE(layer1->quads_appended());
3697 host_impl_->DidDrawAllLayers(frame);
3699 // Layer with partially opaque contents partially culled, drawn with blending.
3700 layer1->SetContentsOpaque(false);
3701 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3702 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
3703 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3704 layer1->SetExpectation(true, false);
3705 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3706 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3707 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3708 EXPECT_TRUE(layer1->quads_appended());
3709 host_impl_->DidDrawAllLayers(frame);
3711 // Layer with partially opaque contents culled, drawn with blending.
3712 layer1->SetContentsOpaque(false);
3713 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3714 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
3715 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3716 layer1->SetExpectation(true, false);
3717 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3718 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3719 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3720 EXPECT_TRUE(layer1->quads_appended());
3721 host_impl_->DidDrawAllLayers(frame);
3723 // Layer with partially opaque contents and translucent contents culled, drawn
3724 // without blending.
3725 layer1->SetContentsOpaque(false);
3726 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
3727 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
3728 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
3729 layer1->SetExpectation(false, false);
3730 layer1->SetUpdateRect(gfx::RectF(layer1->content_bounds()));
3731 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3732 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3733 EXPECT_TRUE(layer1->quads_appended());
3734 host_impl_->DidDrawAllLayers(frame);
3737 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
3738 protected:
3739 LayerTreeHostImplViewportCoveredTest() :
3740 gutter_quad_material_(DrawQuad::SOLID_COLOR),
3741 child_(NULL),
3742 did_activate_pending_tree_(false) {}
3744 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
3745 if (always_draw) {
3746 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
3747 .PassAs<OutputSurface>();
3749 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
3752 void SetupActiveTreeLayers() {
3753 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
3754 host_impl_->active_tree()->SetRootLayer(
3755 LayerImpl::Create(host_impl_->active_tree(), 1));
3756 host_impl_->active_tree()->root_layer()->AddChild(
3757 BlendStateCheckLayer::Create(host_impl_->active_tree(),
3759 host_impl_->resource_provider()));
3760 child_ = static_cast<BlendStateCheckLayer*>(
3761 host_impl_->active_tree()->root_layer()->children()[0]);
3762 child_->SetExpectation(false, false);
3763 child_->SetContentsOpaque(true);
3766 // Expect no gutter rects.
3767 void TestLayerCoversFullViewport() {
3768 gfx::Rect layer_rect(viewport_size_);
3769 child_->SetPosition(layer_rect.origin());
3770 child_->SetBounds(layer_rect.size());
3771 child_->SetContentBounds(layer_rect.size());
3772 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3773 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3775 LayerTreeHostImpl::FrameData frame;
3776 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3777 ASSERT_EQ(1u, frame.render_passes.size());
3779 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3780 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3781 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3783 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3784 host_impl_->DidDrawAllLayers(frame);
3787 // Expect fullscreen gutter rect.
3788 void TestEmptyLayer() {
3789 gfx::Rect layer_rect(0, 0, 0, 0);
3790 child_->SetPosition(layer_rect.origin());
3791 child_->SetBounds(layer_rect.size());
3792 child_->SetContentBounds(layer_rect.size());
3793 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3794 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3796 LayerTreeHostImpl::FrameData frame;
3797 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3798 ASSERT_EQ(1u, frame.render_passes.size());
3800 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
3801 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3802 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3804 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3805 host_impl_->DidDrawAllLayers(frame);
3808 // Expect four surrounding gutter rects.
3809 void TestLayerInMiddleOfViewport() {
3810 gfx::Rect layer_rect(500, 500, 200, 200);
3811 child_->SetPosition(layer_rect.origin());
3812 child_->SetBounds(layer_rect.size());
3813 child_->SetContentBounds(layer_rect.size());
3814 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3815 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3817 LayerTreeHostImpl::FrameData frame;
3818 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3819 ASSERT_EQ(1u, frame.render_passes.size());
3821 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
3822 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
3823 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3825 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
3826 host_impl_->DidDrawAllLayers(frame);
3829 // Expect no gutter rects.
3830 void TestLayerIsLargerThanViewport() {
3831 gfx::Rect layer_rect(viewport_size_.width() + 10,
3832 viewport_size_.height() + 10);
3833 child_->SetPosition(layer_rect.origin());
3834 child_->SetBounds(layer_rect.size());
3835 child_->SetContentBounds(layer_rect.size());
3836 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
3837 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
3839 LayerTreeHostImpl::FrameData frame;
3840 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3841 ASSERT_EQ(1u, frame.render_passes.size());
3843 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
3844 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
3845 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
3847 host_impl_->DidDrawAllLayers(frame);
3850 virtual void DidActivatePendingTree() OVERRIDE {
3851 did_activate_pending_tree_ = true;
3854 void set_gutter_quad_material(DrawQuad::Material material) {
3855 gutter_quad_material_ = material;
3857 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
3858 gutter_texture_size_ = gutter_texture_size;
3861 protected:
3862 size_t CountGutterQuads(const QuadList& quad_list) {
3863 size_t num_gutter_quads = 0;
3864 for (size_t i = 0; i < quad_list.size(); ++i) {
3865 num_gutter_quads += (quad_list[i]->material ==
3866 gutter_quad_material_) ? 1 : 0;
3868 return num_gutter_quads;
3871 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
3872 LayerTestCommon::VerifyQuadsExactlyCoverRect(
3873 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
3876 // Make sure that the texture coordinates match their expectations.
3877 void ValidateTextureDrawQuads(const QuadList& quad_list) {
3878 for (size_t i = 0; i < quad_list.size(); ++i) {
3879 if (quad_list[i]->material != DrawQuad::TEXTURE_CONTENT)
3880 continue;
3881 const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(quad_list[i]);
3882 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
3883 gutter_texture_size_, host_impl_->device_scale_factor());
3884 EXPECT_EQ(quad->uv_top_left.x(),
3885 quad->rect.x() / gutter_texture_size_pixels.width());
3886 EXPECT_EQ(quad->uv_top_left.y(),
3887 quad->rect.y() / gutter_texture_size_pixels.height());
3888 EXPECT_EQ(quad->uv_bottom_right.x(),
3889 quad->rect.right() / gutter_texture_size_pixels.width());
3890 EXPECT_EQ(quad->uv_bottom_right.y(),
3891 quad->rect.bottom() / gutter_texture_size_pixels.height());
3895 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
3896 return gfx::ToRoundedSize(
3897 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
3900 DrawQuad::Material gutter_quad_material_;
3901 gfx::Size gutter_texture_size_;
3902 gfx::Size viewport_size_;
3903 BlendStateCheckLayer* child_;
3904 bool did_activate_pending_tree_;
3907 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
3908 viewport_size_ = gfx::Size(1000, 1000);
3910 bool always_draw = false;
3911 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3913 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3914 SetupActiveTreeLayers();
3915 TestLayerCoversFullViewport();
3916 TestEmptyLayer();
3917 TestLayerInMiddleOfViewport();
3918 TestLayerIsLargerThanViewport();
3921 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
3922 viewport_size_ = gfx::Size(1000, 1000);
3924 bool always_draw = false;
3925 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3927 host_impl_->SetDeviceScaleFactor(2.f);
3928 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3929 SetupActiveTreeLayers();
3930 TestLayerCoversFullViewport();
3931 TestEmptyLayer();
3932 TestLayerInMiddleOfViewport();
3933 TestLayerIsLargerThanViewport();
3936 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) {
3937 viewport_size_ = gfx::Size(1000, 1000);
3939 bool always_draw = false;
3940 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3942 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3943 SetupActiveTreeLayers();
3945 // Specify an overhang bitmap to use.
3946 bool is_opaque = false;
3947 UIResourceBitmap ui_resource_bitmap(gfx::Size(2, 2), is_opaque);
3948 ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
3949 UIResourceId ui_resource_id = 12345;
3950 host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
3951 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32));
3952 set_gutter_quad_material(DrawQuad::TEXTURE_CONTENT);
3953 set_gutter_texture_size(gfx::Size(32, 32));
3955 TestLayerCoversFullViewport();
3956 TestEmptyLayer();
3957 TestLayerInMiddleOfViewport();
3958 TestLayerIsLargerThanViewport();
3960 // Change the resource size.
3961 host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(128, 16));
3962 set_gutter_texture_size(gfx::Size(128, 16));
3964 TestLayerCoversFullViewport();
3965 TestEmptyLayer();
3966 TestLayerInMiddleOfViewport();
3967 TestLayerIsLargerThanViewport();
3969 // Change the device scale factor
3970 host_impl_->SetDeviceScaleFactor(2.f);
3971 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3973 TestLayerCoversFullViewport();
3974 TestEmptyLayer();
3975 TestLayerInMiddleOfViewport();
3976 TestLayerIsLargerThanViewport();
3979 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
3980 viewport_size_ = gfx::Size(1000, 1000);
3982 bool always_draw = true;
3983 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
3985 // Pending tree to force active_tree size invalid. Not used otherwise.
3986 host_impl_->CreatePendingTree();
3987 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
3988 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
3990 SetupActiveTreeLayers();
3991 TestEmptyLayer();
3992 TestLayerInMiddleOfViewport();
3993 TestLayerIsLargerThanViewport();
3996 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
3997 viewport_size_ = gfx::Size(1000, 1000);
3999 bool always_draw = true;
4000 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4002 // Set larger viewport and activate it to active tree.
4003 host_impl_->CreatePendingTree();
4004 gfx::Size larger_viewport(viewport_size_.width() + 100,
4005 viewport_size_.height() + 100);
4006 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
4007 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4008 host_impl_->ActivatePendingTree();
4009 EXPECT_TRUE(did_activate_pending_tree_);
4010 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
4012 // Shrink pending tree viewport without activating.
4013 host_impl_->CreatePendingTree();
4014 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4015 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4017 SetupActiveTreeLayers();
4018 TestEmptyLayer();
4019 TestLayerInMiddleOfViewport();
4020 TestLayerIsLargerThanViewport();
4023 class FakeDrawableLayerImpl: public LayerImpl {
4024 public:
4025 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4026 return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(tree_impl, id));
4028 protected:
4029 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
4030 : LayerImpl(tree_impl, id) {}
4033 // Only reshape when we know we are going to draw. Otherwise, the reshape
4034 // can leave the window at the wrong size if we never draw and the proper
4035 // viewport size is never set.
4036 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
4037 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4038 scoped_ptr<OutputSurface> output_surface(
4039 FakeOutputSurface::Create3d(provider));
4040 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4042 scoped_ptr<LayerImpl> root =
4043 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4044 root->SetAnchorPoint(gfx::PointF());
4045 root->SetBounds(gfx::Size(10, 10));
4046 root->SetContentBounds(gfx::Size(10, 10));
4047 root->SetDrawsContent(true);
4048 host_impl_->active_tree()->SetRootLayer(root.Pass());
4049 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
4050 provider->TestContext3d()->clear_reshape_called();
4052 LayerTreeHostImpl::FrameData frame;
4053 host_impl_->SetViewportSize(gfx::Size(10, 10));
4054 host_impl_->SetDeviceScaleFactor(1.f);
4055 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4056 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4057 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4058 EXPECT_EQ(provider->TestContext3d()->width(), 10);
4059 EXPECT_EQ(provider->TestContext3d()->height(), 10);
4060 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4061 host_impl_->DidDrawAllLayers(frame);
4062 provider->TestContext3d()->clear_reshape_called();
4064 host_impl_->SetViewportSize(gfx::Size(20, 30));
4065 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4066 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4067 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4068 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4069 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4070 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
4071 host_impl_->DidDrawAllLayers(frame);
4072 provider->TestContext3d()->clear_reshape_called();
4074 host_impl_->SetDeviceScaleFactor(2.f);
4075 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4076 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4077 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
4078 EXPECT_EQ(provider->TestContext3d()->width(), 20);
4079 EXPECT_EQ(provider->TestContext3d()->height(), 30);
4080 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
4081 host_impl_->DidDrawAllLayers(frame);
4082 provider->TestContext3d()->clear_reshape_called();
4085 // Make sure damage tracking propagates all the way to the graphics context,
4086 // where it should request to swap only the sub-buffer that is damaged.
4087 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
4088 scoped_refptr<TestContextProvider> context_provider(
4089 TestContextProvider::Create());
4090 context_provider->BindToCurrentThread();
4091 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
4093 scoped_ptr<OutputSurface> output_surface(
4094 FakeOutputSurface::Create3d(context_provider));
4096 // This test creates its own LayerTreeHostImpl, so
4097 // that we can force partial swap enabled.
4098 LayerTreeSettings settings;
4099 settings.partial_swap_enabled = true;
4100 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4101 new TestSharedBitmapManager());
4102 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
4103 LayerTreeHostImpl::Create(settings,
4104 this,
4105 &proxy_,
4106 &stats_instrumentation_,
4107 shared_bitmap_manager.get(),
4109 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
4110 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
4112 scoped_ptr<LayerImpl> root =
4113 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
4114 scoped_ptr<LayerImpl> child =
4115 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
4116 child->SetPosition(gfx::PointF(12.f, 13.f));
4117 child->SetAnchorPoint(gfx::PointF());
4118 child->SetBounds(gfx::Size(14, 15));
4119 child->SetContentBounds(gfx::Size(14, 15));
4120 child->SetDrawsContent(true);
4121 root->SetAnchorPoint(gfx::PointF());
4122 root->SetBounds(gfx::Size(500, 500));
4123 root->SetContentBounds(gfx::Size(500, 500));
4124 root->SetDrawsContent(true);
4125 root->AddChild(child.Pass());
4126 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
4128 LayerTreeHostImpl::FrameData frame;
4130 // First frame, the entire screen should get swapped.
4131 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4132 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4133 layer_tree_host_impl->DidDrawAllLayers(frame);
4134 layer_tree_host_impl->SwapBuffers(frame);
4135 EXPECT_EQ(TestContextSupport::SWAP,
4136 context_provider->support()->last_swap_type());
4138 // Second frame, only the damaged area should get swapped. Damage should be
4139 // the union of old and new child rects.
4140 // expected damage rect: gfx::Rect(26, 28);
4141 // expected swap rect: vertically flipped, with origin at bottom left corner.
4142 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
4143 gfx::PointF());
4144 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4145 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4146 host_impl_->DidDrawAllLayers(frame);
4147 layer_tree_host_impl->SwapBuffers(frame);
4149 // Make sure that partial swap is constrained to the viewport dimensions
4150 // expected damage rect: gfx::Rect(500, 500);
4151 // expected swap rect: flipped damage rect, but also clamped to viewport
4152 EXPECT_EQ(TestContextSupport::PARTIAL_SWAP,
4153 context_provider->support()->last_swap_type());
4154 gfx::Rect expected_swap_rect(0, 500-28, 26, 28);
4155 EXPECT_EQ(expected_swap_rect.ToString(),
4156 context_provider->support()->
4157 last_partial_swap_rect().ToString());
4159 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
4160 // This will damage everything.
4161 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
4162 SK_ColorBLACK);
4163 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
4164 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4165 host_impl_->DidDrawAllLayers(frame);
4166 layer_tree_host_impl->SwapBuffers(frame);
4168 EXPECT_EQ(TestContextSupport::SWAP,
4169 context_provider->support()->last_swap_type());
4172 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
4173 scoped_ptr<LayerImpl> root =
4174 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4175 scoped_ptr<LayerImpl> child =
4176 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
4177 child->SetAnchorPoint(gfx::PointF());
4178 child->SetBounds(gfx::Size(10, 10));
4179 child->SetContentBounds(gfx::Size(10, 10));
4180 child->SetDrawsContent(true);
4181 root->SetAnchorPoint(gfx::PointF());
4182 root->SetBounds(gfx::Size(10, 10));
4183 root->SetContentBounds(gfx::Size(10, 10));
4184 root->SetDrawsContent(true);
4185 root->SetForceRenderSurface(true);
4186 root->AddChild(child.Pass());
4188 host_impl_->active_tree()->SetRootLayer(root.Pass());
4190 LayerTreeHostImpl::FrameData frame;
4192 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4193 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
4194 EXPECT_EQ(1u, frame.render_passes.size());
4195 host_impl_->DidDrawAllLayers(frame);
4198 class FakeLayerWithQuads : public LayerImpl {
4199 public:
4200 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4201 return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(tree_impl, id));
4204 virtual void AppendQuads(QuadSink* quad_sink,
4205 AppendQuadsData* append_quads_data) OVERRIDE {
4206 SharedQuadState* shared_quad_state = quad_sink->CreateSharedQuadState();
4207 PopulateSharedQuadState(shared_quad_state);
4209 SkColor gray = SkColorSetRGB(100, 100, 100);
4210 gfx::Rect quad_rect(content_bounds());
4211 gfx::Rect visible_quad_rect(quad_rect);
4212 scoped_ptr<SolidColorDrawQuad> my_quad = SolidColorDrawQuad::Create();
4213 my_quad->SetNew(
4214 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
4215 quad_sink->Append(my_quad.PassAs<DrawQuad>());
4218 private:
4219 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
4220 : LayerImpl(tree_impl, id) {}
4223 class MockContext : public TestWebGraphicsContext3D {
4224 public:
4225 MOCK_METHOD1(useProgram, void(GLuint program));
4226 MOCK_METHOD5(uniform4f, void(GLint location,
4227 GLfloat x,
4228 GLfloat y,
4229 GLfloat z,
4230 GLfloat w));
4231 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
4232 GLsizei count,
4233 GLboolean transpose,
4234 const GLfloat* value));
4235 MOCK_METHOD4(drawElements, void(GLenum mode,
4236 GLsizei count,
4237 GLenum type,
4238 GLintptr offset));
4239 MOCK_METHOD1(enable, void(GLenum cap));
4240 MOCK_METHOD1(disable, void(GLenum cap));
4241 MOCK_METHOD4(scissor, void(GLint x,
4242 GLint y,
4243 GLsizei width,
4244 GLsizei height));
4247 class MockContextHarness {
4248 private:
4249 MockContext* context_;
4251 public:
4252 explicit MockContextHarness(MockContext* context)
4253 : context_(context) {
4254 context_->set_have_post_sub_buffer(true);
4256 // Catch "uninteresting" calls
4257 EXPECT_CALL(*context_, useProgram(_))
4258 .Times(0);
4260 EXPECT_CALL(*context_, drawElements(_, _, _, _))
4261 .Times(0);
4263 // These are not asserted
4264 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
4265 .WillRepeatedly(Return());
4267 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
4268 .WillRepeatedly(Return());
4270 // Any un-sanctioned calls to enable() are OK
4271 EXPECT_CALL(*context_, enable(_))
4272 .WillRepeatedly(Return());
4274 // Any un-sanctioned calls to disable() are OK
4275 EXPECT_CALL(*context_, disable(_))
4276 .WillRepeatedly(Return());
4279 void MustDrawSolidQuad() {
4280 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
4281 .WillOnce(Return())
4282 .RetiresOnSaturation();
4284 EXPECT_CALL(*context_, useProgram(_))
4285 .WillOnce(Return())
4286 .RetiresOnSaturation();
4289 void MustSetScissor(int x, int y, int width, int height) {
4290 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4291 .WillRepeatedly(Return());
4293 EXPECT_CALL(*context_, scissor(x, y, width, height))
4294 .Times(AtLeast(1))
4295 .WillRepeatedly(Return());
4298 void MustSetNoScissor() {
4299 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
4300 .WillRepeatedly(Return());
4302 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
4303 .Times(0);
4305 EXPECT_CALL(*context_, scissor(_, _, _, _))
4306 .Times(0);
4310 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
4311 scoped_ptr<MockContext> mock_context_owned(new MockContext);
4312 MockContext* mock_context = mock_context_owned.get();
4314 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4315 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4316 MockContextHarness harness(mock_context);
4318 // Run test case
4319 LayerTreeSettings settings = DefaultSettings();
4320 settings.partial_swap_enabled = false;
4321 CreateHostImpl(settings, output_surface.Pass());
4322 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4324 // Without partial swap, and no clipping, no scissor is set.
4325 harness.MustDrawSolidQuad();
4326 harness.MustSetNoScissor();
4328 LayerTreeHostImpl::FrameData frame;
4329 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4330 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4331 host_impl_->DidDrawAllLayers(frame);
4333 Mock::VerifyAndClearExpectations(&mock_context);
4335 // Without partial swap, but a layer does clip its subtree, one scissor is
4336 // set.
4337 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
4338 harness.MustDrawSolidQuad();
4339 harness.MustSetScissor(0, 0, 10, 10);
4341 LayerTreeHostImpl::FrameData frame;
4342 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4343 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4344 host_impl_->DidDrawAllLayers(frame);
4346 Mock::VerifyAndClearExpectations(&mock_context);
4349 TEST_F(LayerTreeHostImplTest, PartialSwap) {
4350 scoped_ptr<MockContext> context_owned(new MockContext);
4351 MockContext* mock_context = context_owned.get();
4352 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4353 context_owned.PassAs<TestWebGraphicsContext3D>()));
4354 MockContextHarness harness(mock_context);
4356 LayerTreeSettings settings = DefaultSettings();
4357 settings.partial_swap_enabled = true;
4358 CreateHostImpl(settings, output_surface.Pass());
4359 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
4361 // The first frame is not a partially-swapped one.
4362 harness.MustSetScissor(0, 0, 10, 10);
4363 harness.MustDrawSolidQuad();
4365 LayerTreeHostImpl::FrameData frame;
4366 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4367 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4368 host_impl_->DidDrawAllLayers(frame);
4370 Mock::VerifyAndClearExpectations(&mock_context);
4372 // Damage a portion of the frame.
4373 host_impl_->active_tree()->root_layer()->SetUpdateRect(
4374 gfx::Rect(0, 0, 2, 3));
4376 // The second frame will be partially-swapped (the y coordinates are flipped).
4377 harness.MustSetScissor(0, 7, 2, 3);
4378 harness.MustDrawSolidQuad();
4380 LayerTreeHostImpl::FrameData frame;
4381 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4382 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4383 host_impl_->DidDrawAllLayers(frame);
4385 Mock::VerifyAndClearExpectations(&mock_context);
4388 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
4389 bool partial_swap,
4390 LayerTreeHostImplClient* client,
4391 Proxy* proxy,
4392 SharedBitmapManager* manager,
4393 RenderingStatsInstrumentation* stats_instrumentation) {
4394 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4395 scoped_ptr<OutputSurface> output_surface(
4396 FakeOutputSurface::Create3d(provider));
4397 provider->BindToCurrentThread();
4398 provider->TestContext3d()->set_have_post_sub_buffer(true);
4400 LayerTreeSettings settings;
4401 settings.partial_swap_enabled = partial_swap;
4402 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
4403 settings, client, proxy, stats_instrumentation, manager, 0);
4404 my_host_impl->InitializeRenderer(output_surface.Pass());
4405 my_host_impl->SetViewportSize(gfx::Size(100, 100));
4408 Layers are created as follows:
4410 +--------------------+
4411 | 1 |
4412 | +-----------+ |
4413 | | 2 | |
4414 | | +-------------------+
4415 | | | 3 |
4416 | | +-------------------+
4417 | | | |
4418 | +-----------+ |
4421 +--------------------+
4423 Layers 1, 2 have render surfaces
4425 scoped_ptr<LayerImpl> root =
4426 LayerImpl::Create(my_host_impl->active_tree(), 1);
4427 scoped_ptr<LayerImpl> child =
4428 LayerImpl::Create(my_host_impl->active_tree(), 2);
4429 scoped_ptr<LayerImpl> grand_child =
4430 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
4432 gfx::Rect root_rect(0, 0, 100, 100);
4433 gfx::Rect child_rect(10, 10, 50, 50);
4434 gfx::Rect grand_child_rect(5, 5, 150, 150);
4436 root->CreateRenderSurface();
4437 root->SetAnchorPoint(gfx::PointF());
4438 root->SetPosition(root_rect.origin());
4439 root->SetBounds(root_rect.size());
4440 root->SetContentBounds(root->bounds());
4441 root->draw_properties().visible_content_rect = root_rect;
4442 root->SetDrawsContent(false);
4443 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
4445 child->SetAnchorPoint(gfx::PointF());
4446 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
4447 child->SetOpacity(0.5f);
4448 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
4449 child->SetContentBounds(child->bounds());
4450 child->draw_properties().visible_content_rect = child_rect;
4451 child->SetDrawsContent(false);
4452 child->SetForceRenderSurface(true);
4454 grand_child->SetAnchorPoint(gfx::PointF());
4455 grand_child->SetPosition(grand_child_rect.origin());
4456 grand_child->SetBounds(grand_child_rect.size());
4457 grand_child->SetContentBounds(grand_child->bounds());
4458 grand_child->draw_properties().visible_content_rect = grand_child_rect;
4459 grand_child->SetDrawsContent(true);
4461 child->AddChild(grand_child.Pass());
4462 root->AddChild(child.Pass());
4464 my_host_impl->active_tree()->SetRootLayer(root.Pass());
4465 return my_host_impl.Pass();
4468 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
4469 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4470 new TestSharedBitmapManager());
4471 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4472 SetupLayersForOpacity(true,
4473 this,
4474 &proxy_,
4475 shared_bitmap_manager.get(),
4476 &stats_instrumentation_);
4478 LayerTreeHostImpl::FrameData frame;
4479 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4481 // Verify all quads have been computed
4482 ASSERT_EQ(2U, frame.render_passes.size());
4483 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4484 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4485 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4486 frame.render_passes[0]->quad_list[0]->material);
4487 EXPECT_EQ(DrawQuad::RENDER_PASS,
4488 frame.render_passes[1]->quad_list[0]->material);
4490 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4491 my_host_impl->DidDrawAllLayers(frame);
4495 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
4496 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
4497 new TestSharedBitmapManager());
4498 scoped_ptr<LayerTreeHostImpl> my_host_impl =
4499 SetupLayersForOpacity(false,
4500 this,
4501 &proxy_,
4502 shared_bitmap_manager.get(),
4503 &stats_instrumentation_);
4505 LayerTreeHostImpl::FrameData frame;
4506 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
4508 // Verify all quads have been computed
4509 ASSERT_EQ(2U, frame.render_passes.size());
4510 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
4511 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
4512 EXPECT_EQ(DrawQuad::SOLID_COLOR,
4513 frame.render_passes[0]->quad_list[0]->material);
4514 EXPECT_EQ(DrawQuad::RENDER_PASS,
4515 frame.render_passes[1]->quad_list[0]->material);
4517 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
4518 my_host_impl->DidDrawAllLayers(frame);
4522 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
4523 scoped_ptr<TestWebGraphicsContext3D> context =
4524 TestWebGraphicsContext3D::Create();
4525 TestWebGraphicsContext3D* context3d = context.get();
4526 scoped_ptr<OutputSurface> output_surface(
4527 FakeOutputSurface::Create3d(context.Pass()));
4528 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4530 scoped_ptr<LayerImpl> root_layer =
4531 LayerImpl::Create(host_impl_->active_tree(), 1);
4532 root_layer->SetBounds(gfx::Size(10, 10));
4533 root_layer->SetAnchorPoint(gfx::PointF());
4535 scoped_refptr<VideoFrame> softwareFrame =
4536 media::VideoFrame::CreateColorFrame(
4537 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
4538 FakeVideoFrameProvider provider;
4539 provider.set_frame(softwareFrame);
4540 scoped_ptr<VideoLayerImpl> video_layer =
4541 VideoLayerImpl::Create(host_impl_->active_tree(), 4, &provider);
4542 video_layer->SetBounds(gfx::Size(10, 10));
4543 video_layer->SetAnchorPoint(gfx::PointF());
4544 video_layer->SetContentBounds(gfx::Size(10, 10));
4545 video_layer->SetDrawsContent(true);
4546 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
4548 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
4549 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
4550 io_surface_layer->SetBounds(gfx::Size(10, 10));
4551 io_surface_layer->SetAnchorPoint(gfx::PointF());
4552 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
4553 io_surface_layer->SetDrawsContent(true);
4554 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
4555 root_layer->AddChild(io_surface_layer.PassAs<LayerImpl>());
4557 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
4559 EXPECT_EQ(0u, context3d->NumTextures());
4561 LayerTreeHostImpl::FrameData frame;
4562 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4563 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4564 host_impl_->DidDrawAllLayers(frame);
4565 host_impl_->SwapBuffers(frame);
4567 EXPECT_GT(context3d->NumTextures(), 0u);
4569 // Kill the layer tree.
4570 host_impl_->active_tree()->SetRootLayer(
4571 LayerImpl::Create(host_impl_->active_tree(), 100));
4572 // There should be no textures left in use after.
4573 EXPECT_EQ(0u, context3d->NumTextures());
4576 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
4577 public:
4578 MOCK_METHOD1(useProgram, void(GLuint program));
4579 MOCK_METHOD4(drawElements, void(GLenum mode,
4580 GLsizei count,
4581 GLenum type,
4582 GLintptr offset));
4585 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
4586 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
4587 new MockDrawQuadsToFillScreenContext);
4588 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
4590 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
4591 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
4593 // Run test case
4594 LayerTreeSettings settings = DefaultSettings();
4595 settings.partial_swap_enabled = false;
4596 CreateHostImpl(settings, output_surface.Pass());
4597 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
4598 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
4600 // Verify one quad is drawn when transparent background set is not set.
4601 host_impl_->active_tree()->set_has_transparent_background(false);
4602 EXPECT_CALL(*mock_context, useProgram(_))
4603 .Times(1);
4604 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
4605 .Times(1);
4606 LayerTreeHostImpl::FrameData frame;
4607 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4608 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4609 host_impl_->DidDrawAllLayers(frame);
4610 Mock::VerifyAndClearExpectations(&mock_context);
4612 // Verify no quads are drawn when transparent background is set.
4613 host_impl_->active_tree()->set_has_transparent_background(true);
4614 host_impl_->SetFullRootLayerDamage();
4615 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4616 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4617 host_impl_->DidDrawAllLayers(frame);
4618 Mock::VerifyAndClearExpectations(&mock_context);
4621 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
4622 set_reduce_memory_result(false);
4624 // If changing the memory limit wouldn't result in changing what was
4625 // committed, then no commit should be requested.
4626 set_reduce_memory_result(false);
4627 host_impl_->set_max_memory_needed_bytes(
4628 host_impl_->memory_allocation_limit_bytes() - 1);
4629 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4630 host_impl_->memory_allocation_limit_bytes() - 1));
4631 EXPECT_FALSE(did_request_commit_);
4632 did_request_commit_ = false;
4634 // If changing the memory limit would result in changing what was
4635 // committed, then a commit should be requested, even though nothing was
4636 // evicted.
4637 set_reduce_memory_result(false);
4638 host_impl_->set_max_memory_needed_bytes(
4639 host_impl_->memory_allocation_limit_bytes());
4640 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4641 host_impl_->memory_allocation_limit_bytes() - 1));
4642 EXPECT_TRUE(did_request_commit_);
4643 did_request_commit_ = false;
4645 // Especially if changing the memory limit caused evictions, we need
4646 // to re-commit.
4647 set_reduce_memory_result(true);
4648 host_impl_->set_max_memory_needed_bytes(1);
4649 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4650 host_impl_->memory_allocation_limit_bytes() - 1));
4651 EXPECT_TRUE(did_request_commit_);
4652 did_request_commit_ = false;
4654 // But if we set it to the same value that it was before, we shouldn't
4655 // re-commit.
4656 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
4657 host_impl_->memory_allocation_limit_bytes()));
4658 EXPECT_FALSE(did_request_commit_);
4661 class LayerTreeHostImplTestWithDelegatingRenderer
4662 : public LayerTreeHostImplTest {
4663 protected:
4664 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
4665 return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
4668 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
4669 bool expect_to_draw = !expected_damage.IsEmpty();
4671 LayerTreeHostImpl::FrameData frame;
4672 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4674 if (!expect_to_draw) {
4675 // With no damage, we don't draw, and no quads are created.
4676 ASSERT_EQ(0u, frame.render_passes.size());
4677 } else {
4678 ASSERT_EQ(1u, frame.render_passes.size());
4680 // Verify the damage rect for the root render pass.
4681 const RenderPass* root_render_pass = frame.render_passes.back();
4682 EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
4684 // Verify the root and child layers' quads are generated and not being
4685 // culled.
4686 ASSERT_EQ(2u, root_render_pass->quad_list.size());
4688 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
4689 gfx::RectF expected_child_visible_rect(child->content_bounds());
4690 EXPECT_RECT_EQ(expected_child_visible_rect,
4691 root_render_pass->quad_list[0]->visible_rect);
4693 LayerImpl* root = host_impl_->active_tree()->root_layer();
4694 gfx::RectF expected_root_visible_rect(root->content_bounds());
4695 EXPECT_RECT_EQ(expected_root_visible_rect,
4696 root_render_pass->quad_list[1]->visible_rect);
4699 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4700 host_impl_->DidDrawAllLayers(frame);
4701 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
4705 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
4706 scoped_ptr<SolidColorLayerImpl> root =
4707 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
4708 root->SetAnchorPoint(gfx::PointF());
4709 root->SetPosition(gfx::PointF());
4710 root->SetBounds(gfx::Size(10, 10));
4711 root->SetContentBounds(gfx::Size(10, 10));
4712 root->SetDrawsContent(true);
4714 // Child layer is in the bottom right corner.
4715 scoped_ptr<SolidColorLayerImpl> child =
4716 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
4717 child->SetAnchorPoint(gfx::PointF(0.f, 0.f));
4718 child->SetPosition(gfx::PointF(9.f, 9.f));
4719 child->SetBounds(gfx::Size(1, 1));
4720 child->SetContentBounds(gfx::Size(1, 1));
4721 child->SetDrawsContent(true);
4722 root->AddChild(child.PassAs<LayerImpl>());
4724 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
4726 // Draw a frame. In the first frame, the entire viewport should be damaged.
4727 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
4728 DrawFrameAndTestDamage(full_frame_damage);
4730 // The second frame has damage that doesn't touch the child layer. Its quads
4731 // should still be generated.
4732 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
4733 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
4734 DrawFrameAndTestDamage(small_damage);
4736 // The third frame should have no damage, so no quads should be generated.
4737 gfx::Rect no_damage;
4738 DrawFrameAndTestDamage(no_damage);
4741 // TODO(reveman): Remove this test and the ability to prevent on demand raster
4742 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
4743 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
4744 LayerTreeSettings settings;
4745 CreateHostImpl(settings, CreateOutputSurface());
4746 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
4749 class FakeMaskLayerImpl : public LayerImpl {
4750 public:
4751 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
4752 int id) {
4753 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
4756 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
4757 return 0;
4760 private:
4761 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
4762 : LayerImpl(tree_impl, id) {}
4765 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
4766 LayerTreeSettings settings;
4767 settings.layer_transforms_should_scale_layer_contents = true;
4768 CreateHostImpl(settings, CreateOutputSurface());
4770 // Root
4771 // |
4772 // +-- Scaling Layer (adds a 2x scale)
4773 // |
4774 // +-- Content Layer
4775 // +--Mask
4776 scoped_ptr<LayerImpl> scoped_root =
4777 LayerImpl::Create(host_impl_->active_tree(), 1);
4778 LayerImpl* root = scoped_root.get();
4779 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4781 scoped_ptr<LayerImpl> scoped_scaling_layer =
4782 LayerImpl::Create(host_impl_->active_tree(), 2);
4783 LayerImpl* scaling_layer = scoped_scaling_layer.get();
4784 root->AddChild(scoped_scaling_layer.Pass());
4786 scoped_ptr<LayerImpl> scoped_content_layer =
4787 LayerImpl::Create(host_impl_->active_tree(), 3);
4788 LayerImpl* content_layer = scoped_content_layer.get();
4789 scaling_layer->AddChild(scoped_content_layer.Pass());
4791 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4792 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4793 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4794 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4796 gfx::Size root_size(100, 100);
4797 root->SetBounds(root_size);
4798 root->SetContentBounds(root_size);
4799 root->SetPosition(gfx::PointF());
4800 root->SetAnchorPoint(gfx::PointF());
4802 gfx::Size scaling_layer_size(50, 50);
4803 scaling_layer->SetBounds(scaling_layer_size);
4804 scaling_layer->SetContentBounds(scaling_layer_size);
4805 scaling_layer->SetPosition(gfx::PointF());
4806 scaling_layer->SetAnchorPoint(gfx::PointF());
4807 gfx::Transform scale;
4808 scale.Scale(2.f, 2.f);
4809 scaling_layer->SetTransform(scale);
4811 content_layer->SetBounds(scaling_layer_size);
4812 content_layer->SetContentBounds(scaling_layer_size);
4813 content_layer->SetPosition(gfx::PointF());
4814 content_layer->SetAnchorPoint(gfx::PointF());
4815 content_layer->SetDrawsContent(true);
4817 mask_layer->SetBounds(scaling_layer_size);
4818 mask_layer->SetContentBounds(scaling_layer_size);
4819 mask_layer->SetPosition(gfx::PointF());
4820 mask_layer->SetAnchorPoint(gfx::PointF());
4821 mask_layer->SetDrawsContent(true);
4824 // Check that the tree scaling is correctly taken into account for the mask,
4825 // that should fully map onto the quad.
4826 float device_scale_factor = 1.f;
4827 host_impl_->SetViewportSize(root_size);
4828 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4830 LayerTreeHostImpl::FrameData frame;
4831 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4833 ASSERT_EQ(1u, frame.render_passes.size());
4834 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4835 ASSERT_EQ(DrawQuad::RENDER_PASS,
4836 frame.render_passes[0]->quad_list[0]->material);
4837 const RenderPassDrawQuad* render_pass_quad =
4838 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4839 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4840 render_pass_quad->rect.ToString());
4841 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4842 render_pass_quad->mask_uv_rect.ToString());
4844 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4845 host_impl_->DidDrawAllLayers(frame);
4849 // Applying a DSF should change the render surface size, but won't affect
4850 // which part of the mask is used.
4851 device_scale_factor = 2.f;
4852 gfx::Size device_viewport =
4853 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4854 host_impl_->SetViewportSize(device_viewport);
4855 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4856 host_impl_->active_tree()->set_needs_update_draw_properties();
4858 LayerTreeHostImpl::FrameData frame;
4859 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4861 ASSERT_EQ(1u, frame.render_passes.size());
4862 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4863 ASSERT_EQ(DrawQuad::RENDER_PASS,
4864 frame.render_passes[0]->quad_list[0]->material);
4865 const RenderPassDrawQuad* render_pass_quad =
4866 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4867 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4868 render_pass_quad->rect.ToString());
4869 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4870 render_pass_quad->mask_uv_rect.ToString());
4872 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4873 host_impl_->DidDrawAllLayers(frame);
4877 // Applying an equivalent content scale on the content layer and the mask
4878 // should still result in the same part of the mask being used.
4879 gfx::Size content_bounds =
4880 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
4881 device_scale_factor));
4882 content_layer->SetContentBounds(content_bounds);
4883 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4884 mask_layer->SetContentBounds(content_bounds);
4885 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
4886 host_impl_->active_tree()->set_needs_update_draw_properties();
4888 LayerTreeHostImpl::FrameData frame;
4889 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4891 ASSERT_EQ(1u, frame.render_passes.size());
4892 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4893 ASSERT_EQ(DrawQuad::RENDER_PASS,
4894 frame.render_passes[0]->quad_list[0]->material);
4895 const RenderPassDrawQuad* render_pass_quad =
4896 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4897 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4898 render_pass_quad->rect.ToString());
4899 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4900 render_pass_quad->mask_uv_rect.ToString());
4902 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4903 host_impl_->DidDrawAllLayers(frame);
4907 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
4908 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4909 // 50x50.
4911 scoped_ptr<LayerImpl> scoped_root =
4912 LayerImpl::Create(host_impl_->active_tree(), 1);
4913 LayerImpl* root = scoped_root.get();
4914 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
4916 scoped_ptr<LayerImpl> scoped_content_layer =
4917 LayerImpl::Create(host_impl_->active_tree(), 3);
4918 LayerImpl* content_layer = scoped_content_layer.get();
4919 root->AddChild(scoped_content_layer.Pass());
4921 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
4922 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
4923 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
4924 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
4926 gfx::Size root_size(100, 100);
4927 root->SetBounds(root_size);
4928 root->SetContentBounds(root_size);
4929 root->SetPosition(gfx::PointF());
4930 root->SetAnchorPoint(gfx::PointF());
4932 gfx::Size layer_size(50, 50);
4933 content_layer->SetBounds(layer_size);
4934 content_layer->SetContentBounds(layer_size);
4935 content_layer->SetPosition(gfx::PointF());
4936 content_layer->SetAnchorPoint(gfx::PointF());
4937 content_layer->SetDrawsContent(true);
4939 gfx::Size mask_size(100, 100);
4940 mask_layer->SetBounds(mask_size);
4941 mask_layer->SetContentBounds(mask_size);
4942 mask_layer->SetPosition(gfx::PointF());
4943 mask_layer->SetAnchorPoint(gfx::PointF());
4944 mask_layer->SetDrawsContent(true);
4946 // Check that the mask fills the surface.
4947 float device_scale_factor = 1.f;
4948 host_impl_->SetViewportSize(root_size);
4949 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4951 LayerTreeHostImpl::FrameData frame;
4952 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4954 ASSERT_EQ(1u, frame.render_passes.size());
4955 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4956 ASSERT_EQ(DrawQuad::RENDER_PASS,
4957 frame.render_passes[0]->quad_list[0]->material);
4958 const RenderPassDrawQuad* render_pass_quad =
4959 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4960 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4961 render_pass_quad->rect.ToString());
4962 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4963 render_pass_quad->mask_uv_rect.ToString());
4965 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4966 host_impl_->DidDrawAllLayers(frame);
4969 // Applying a DSF should change the render surface size, but won't affect
4970 // which part of the mask is used.
4971 device_scale_factor = 2.f;
4972 gfx::Size device_viewport =
4973 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
4974 host_impl_->SetViewportSize(device_viewport);
4975 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4976 host_impl_->active_tree()->set_needs_update_draw_properties();
4978 LayerTreeHostImpl::FrameData frame;
4979 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4981 ASSERT_EQ(1u, frame.render_passes.size());
4982 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4983 ASSERT_EQ(DrawQuad::RENDER_PASS,
4984 frame.render_passes[0]->quad_list[0]->material);
4985 const RenderPassDrawQuad* render_pass_quad =
4986 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
4987 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4988 render_pass_quad->rect.ToString());
4989 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
4990 render_pass_quad->mask_uv_rect.ToString());
4992 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4993 host_impl_->DidDrawAllLayers(frame);
4996 // Applying an equivalent content scale on the content layer and the mask
4997 // should still result in the same part of the mask being used.
4998 gfx::Size layer_size_large =
4999 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5000 content_layer->SetContentBounds(layer_size_large);
5001 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5002 gfx::Size mask_size_large =
5003 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5004 mask_layer->SetContentBounds(mask_size_large);
5005 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5006 host_impl_->active_tree()->set_needs_update_draw_properties();
5008 LayerTreeHostImpl::FrameData frame;
5009 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5011 ASSERT_EQ(1u, frame.render_passes.size());
5012 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5013 ASSERT_EQ(DrawQuad::RENDER_PASS,
5014 frame.render_passes[0]->quad_list[0]->material);
5015 const RenderPassDrawQuad* render_pass_quad =
5016 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5017 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5018 render_pass_quad->rect.ToString());
5019 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5020 render_pass_quad->mask_uv_rect.ToString());
5022 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5023 host_impl_->DidDrawAllLayers(frame);
5026 // Applying a different contents scale to the mask layer means it will have
5027 // a larger texture, but it should use the same tex coords to cover the
5028 // layer it masks.
5029 mask_layer->SetContentBounds(mask_size);
5030 mask_layer->SetContentsScale(1.f, 1.f);
5031 host_impl_->active_tree()->set_needs_update_draw_properties();
5033 LayerTreeHostImpl::FrameData frame;
5034 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5036 ASSERT_EQ(1u, frame.render_passes.size());
5037 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5038 ASSERT_EQ(DrawQuad::RENDER_PASS,
5039 frame.render_passes[0]->quad_list[0]->material);
5040 const RenderPassDrawQuad* render_pass_quad =
5041 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5042 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5043 render_pass_quad->rect.ToString());
5044 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5045 render_pass_quad->mask_uv_rect.ToString());
5047 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5048 host_impl_->DidDrawAllLayers(frame);
5052 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
5053 // The replica's mask layer has bounds 100x100 but the replica is of a
5054 // layer with bounds 50x50.
5056 scoped_ptr<LayerImpl> scoped_root =
5057 LayerImpl::Create(host_impl_->active_tree(), 1);
5058 LayerImpl* root = scoped_root.get();
5059 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5061 scoped_ptr<LayerImpl> scoped_content_layer =
5062 LayerImpl::Create(host_impl_->active_tree(), 3);
5063 LayerImpl* content_layer = scoped_content_layer.get();
5064 root->AddChild(scoped_content_layer.Pass());
5066 scoped_ptr<LayerImpl> scoped_replica_layer =
5067 LayerImpl::Create(host_impl_->active_tree(), 2);
5068 LayerImpl* replica_layer = scoped_replica_layer.get();
5069 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5071 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5072 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
5073 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5074 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5076 gfx::Size root_size(100, 100);
5077 root->SetBounds(root_size);
5078 root->SetContentBounds(root_size);
5079 root->SetPosition(gfx::PointF());
5080 root->SetAnchorPoint(gfx::PointF());
5082 gfx::Size layer_size(50, 50);
5083 content_layer->SetBounds(layer_size);
5084 content_layer->SetContentBounds(layer_size);
5085 content_layer->SetPosition(gfx::PointF());
5086 content_layer->SetAnchorPoint(gfx::PointF());
5087 content_layer->SetDrawsContent(true);
5089 gfx::Size mask_size(100, 100);
5090 mask_layer->SetBounds(mask_size);
5091 mask_layer->SetContentBounds(mask_size);
5092 mask_layer->SetPosition(gfx::PointF());
5093 mask_layer->SetAnchorPoint(gfx::PointF());
5094 mask_layer->SetDrawsContent(true);
5096 // Check that the mask fills the surface.
5097 float device_scale_factor = 1.f;
5098 host_impl_->SetViewportSize(root_size);
5099 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5101 LayerTreeHostImpl::FrameData frame;
5102 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5104 ASSERT_EQ(1u, frame.render_passes.size());
5105 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5106 ASSERT_EQ(DrawQuad::RENDER_PASS,
5107 frame.render_passes[0]->quad_list[1]->material);
5108 const RenderPassDrawQuad* replica_quad =
5109 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5110 EXPECT_TRUE(replica_quad->is_replica);
5111 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5112 replica_quad->rect.ToString());
5113 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5114 replica_quad->mask_uv_rect.ToString());
5116 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5117 host_impl_->DidDrawAllLayers(frame);
5120 // Applying a DSF should change the render surface size, but won't affect
5121 // which part of the mask is used.
5122 device_scale_factor = 2.f;
5123 gfx::Size device_viewport =
5124 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
5125 host_impl_->SetViewportSize(device_viewport);
5126 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5127 host_impl_->active_tree()->set_needs_update_draw_properties();
5129 LayerTreeHostImpl::FrameData frame;
5130 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5132 ASSERT_EQ(1u, frame.render_passes.size());
5133 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5134 ASSERT_EQ(DrawQuad::RENDER_PASS,
5135 frame.render_passes[0]->quad_list[1]->material);
5136 const RenderPassDrawQuad* replica_quad =
5137 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5138 EXPECT_TRUE(replica_quad->is_replica);
5139 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5140 replica_quad->rect.ToString());
5141 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5142 replica_quad->mask_uv_rect.ToString());
5144 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5145 host_impl_->DidDrawAllLayers(frame);
5148 // Applying an equivalent content scale on the content layer and the mask
5149 // should still result in the same part of the mask being used.
5150 gfx::Size layer_size_large =
5151 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
5152 content_layer->SetContentBounds(layer_size_large);
5153 content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5154 gfx::Size mask_size_large =
5155 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
5156 mask_layer->SetContentBounds(mask_size_large);
5157 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
5158 host_impl_->active_tree()->set_needs_update_draw_properties();
5160 LayerTreeHostImpl::FrameData frame;
5161 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5163 ASSERT_EQ(1u, frame.render_passes.size());
5164 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5165 ASSERT_EQ(DrawQuad::RENDER_PASS,
5166 frame.render_passes[0]->quad_list[1]->material);
5167 const RenderPassDrawQuad* replica_quad =
5168 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5169 EXPECT_TRUE(replica_quad->is_replica);
5170 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5171 replica_quad->rect.ToString());
5172 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5173 replica_quad->mask_uv_rect.ToString());
5175 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5176 host_impl_->DidDrawAllLayers(frame);
5179 // Applying a different contents scale to the mask layer means it will have
5180 // a larger texture, but it should use the same tex coords to cover the
5181 // layer it masks.
5182 mask_layer->SetContentBounds(mask_size);
5183 mask_layer->SetContentsScale(1.f, 1.f);
5184 host_impl_->active_tree()->set_needs_update_draw_properties();
5186 LayerTreeHostImpl::FrameData frame;
5187 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5189 ASSERT_EQ(1u, frame.render_passes.size());
5190 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5191 ASSERT_EQ(DrawQuad::RENDER_PASS,
5192 frame.render_passes[0]->quad_list[1]->material);
5193 const RenderPassDrawQuad* replica_quad =
5194 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5195 EXPECT_TRUE(replica_quad->is_replica);
5196 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5197 replica_quad->rect.ToString());
5198 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
5199 replica_quad->mask_uv_rect.ToString());
5201 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5202 host_impl_->DidDrawAllLayers(frame);
5206 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
5207 // The replica is of a layer with bounds 50x50, but it has a child that causes
5208 // the surface bounds to be larger.
5210 scoped_ptr<LayerImpl> scoped_root =
5211 LayerImpl::Create(host_impl_->active_tree(), 1);
5212 LayerImpl* root = scoped_root.get();
5213 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5215 scoped_ptr<LayerImpl> scoped_content_layer =
5216 LayerImpl::Create(host_impl_->active_tree(), 2);
5217 LayerImpl* content_layer = scoped_content_layer.get();
5218 root->AddChild(scoped_content_layer.Pass());
5220 scoped_ptr<LayerImpl> scoped_content_child_layer =
5221 LayerImpl::Create(host_impl_->active_tree(), 3);
5222 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5223 content_layer->AddChild(scoped_content_child_layer.Pass());
5225 scoped_ptr<LayerImpl> scoped_replica_layer =
5226 LayerImpl::Create(host_impl_->active_tree(), 4);
5227 LayerImpl* replica_layer = scoped_replica_layer.get();
5228 content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
5230 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5231 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
5232 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5233 replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5235 gfx::Size root_size(100, 100);
5236 root->SetBounds(root_size);
5237 root->SetContentBounds(root_size);
5238 root->SetPosition(gfx::PointF());
5239 root->SetAnchorPoint(gfx::PointF());
5241 gfx::Size layer_size(50, 50);
5242 content_layer->SetBounds(layer_size);
5243 content_layer->SetContentBounds(layer_size);
5244 content_layer->SetPosition(gfx::PointF());
5245 content_layer->SetAnchorPoint(gfx::PointF());
5246 content_layer->SetDrawsContent(true);
5248 gfx::Size child_size(50, 50);
5249 content_child_layer->SetBounds(child_size);
5250 content_child_layer->SetContentBounds(child_size);
5251 content_child_layer->SetPosition(gfx::Point(50, 0));
5252 content_child_layer->SetAnchorPoint(gfx::PointF());
5253 content_child_layer->SetDrawsContent(true);
5255 gfx::Size mask_size(50, 50);
5256 mask_layer->SetBounds(mask_size);
5257 mask_layer->SetContentBounds(mask_size);
5258 mask_layer->SetPosition(gfx::PointF());
5259 mask_layer->SetAnchorPoint(gfx::PointF());
5260 mask_layer->SetDrawsContent(true);
5262 float device_scale_factor = 1.f;
5263 host_impl_->SetViewportSize(root_size);
5264 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5266 LayerTreeHostImpl::FrameData frame;
5267 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5269 ASSERT_EQ(1u, frame.render_passes.size());
5270 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5272 // The surface is 100x50.
5273 ASSERT_EQ(DrawQuad::RENDER_PASS,
5274 frame.render_passes[0]->quad_list[0]->material);
5275 const RenderPassDrawQuad* render_pass_quad =
5276 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5277 EXPECT_FALSE(render_pass_quad->is_replica);
5278 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5279 render_pass_quad->rect.ToString());
5281 // The mask covers the owning layer only.
5282 ASSERT_EQ(DrawQuad::RENDER_PASS,
5283 frame.render_passes[0]->quad_list[1]->material);
5284 const RenderPassDrawQuad* replica_quad =
5285 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5286 EXPECT_TRUE(replica_quad->is_replica);
5287 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5288 replica_quad->rect.ToString());
5289 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
5290 replica_quad->mask_uv_rect.ToString());
5292 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5293 host_impl_->DidDrawAllLayers(frame);
5296 // Move the child to (-50, 0) instead. Now the mask should be moved to still
5297 // cover the layer being replicated.
5298 content_child_layer->SetPosition(gfx::Point(-50, 0));
5300 LayerTreeHostImpl::FrameData frame;
5301 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5303 ASSERT_EQ(1u, frame.render_passes.size());
5304 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
5306 // The surface is 100x50 with its origin at (-50, 0).
5307 ASSERT_EQ(DrawQuad::RENDER_PASS,
5308 frame.render_passes[0]->quad_list[0]->material);
5309 const RenderPassDrawQuad* render_pass_quad =
5310 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5311 EXPECT_FALSE(render_pass_quad->is_replica);
5312 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5313 render_pass_quad->rect.ToString());
5315 // The mask covers the owning layer only.
5316 ASSERT_EQ(DrawQuad::RENDER_PASS,
5317 frame.render_passes[0]->quad_list[1]->material);
5318 const RenderPassDrawQuad* replica_quad =
5319 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
5320 EXPECT_TRUE(replica_quad->is_replica);
5321 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5322 replica_quad->rect.ToString());
5323 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
5324 replica_quad->mask_uv_rect.ToString());
5326 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5327 host_impl_->DidDrawAllLayers(frame);
5331 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
5332 // The masked layer has bounds 50x50, but it has a child that causes
5333 // the surface bounds to be larger. It also has a parent that clips the
5334 // masked layer and its surface.
5336 scoped_ptr<LayerImpl> scoped_root =
5337 LayerImpl::Create(host_impl_->active_tree(), 1);
5338 LayerImpl* root = scoped_root.get();
5339 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
5341 scoped_ptr<LayerImpl> scoped_clipping_layer =
5342 LayerImpl::Create(host_impl_->active_tree(), 2);
5343 LayerImpl* clipping_layer = scoped_clipping_layer.get();
5344 root->AddChild(scoped_clipping_layer.Pass());
5346 scoped_ptr<LayerImpl> scoped_content_layer =
5347 LayerImpl::Create(host_impl_->active_tree(), 3);
5348 LayerImpl* content_layer = scoped_content_layer.get();
5349 clipping_layer->AddChild(scoped_content_layer.Pass());
5351 scoped_ptr<LayerImpl> scoped_content_child_layer =
5352 LayerImpl::Create(host_impl_->active_tree(), 4);
5353 LayerImpl* content_child_layer = scoped_content_child_layer.get();
5354 content_layer->AddChild(scoped_content_child_layer.Pass());
5356 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
5357 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
5358 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
5359 content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
5361 gfx::Size root_size(100, 100);
5362 root->SetBounds(root_size);
5363 root->SetContentBounds(root_size);
5364 root->SetPosition(gfx::PointF());
5365 root->SetAnchorPoint(gfx::PointF());
5367 gfx::Rect clipping_rect(20, 10, 10, 20);
5368 clipping_layer->SetBounds(clipping_rect.size());
5369 clipping_layer->SetContentBounds(clipping_rect.size());
5370 clipping_layer->SetPosition(clipping_rect.origin());
5371 clipping_layer->SetAnchorPoint(gfx::PointF());
5372 clipping_layer->SetMasksToBounds(true);
5374 gfx::Size layer_size(50, 50);
5375 content_layer->SetBounds(layer_size);
5376 content_layer->SetContentBounds(layer_size);
5377 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
5378 content_layer->SetAnchorPoint(gfx::PointF());
5379 content_layer->SetDrawsContent(true);
5381 gfx::Size child_size(50, 50);
5382 content_child_layer->SetBounds(child_size);
5383 content_child_layer->SetContentBounds(child_size);
5384 content_child_layer->SetPosition(gfx::Point(50, 0));
5385 content_child_layer->SetAnchorPoint(gfx::PointF());
5386 content_child_layer->SetDrawsContent(true);
5388 gfx::Size mask_size(100, 100);
5389 mask_layer->SetBounds(mask_size);
5390 mask_layer->SetContentBounds(mask_size);
5391 mask_layer->SetPosition(gfx::PointF());
5392 mask_layer->SetAnchorPoint(gfx::PointF());
5393 mask_layer->SetDrawsContent(true);
5395 float device_scale_factor = 1.f;
5396 host_impl_->SetViewportSize(root_size);
5397 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5399 LayerTreeHostImpl::FrameData frame;
5400 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5402 ASSERT_EQ(1u, frame.render_passes.size());
5403 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
5405 // The surface is clipped to 10x20.
5406 ASSERT_EQ(DrawQuad::RENDER_PASS,
5407 frame.render_passes[0]->quad_list[0]->material);
5408 const RenderPassDrawQuad* render_pass_quad =
5409 RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
5410 EXPECT_FALSE(render_pass_quad->is_replica);
5411 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
5412 render_pass_quad->rect.ToString());
5414 // The masked layer is 50x50, but the surface size is 10x20. So the texture
5415 // coords in the mask are scaled by 10/50 and 20/50.
5416 // The surface is clipped to (20,10) so the mask texture coords are offset
5417 // by 20/50 and 10/50
5418 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f),
5419 1.f / 50.f).ToString(),
5420 render_pass_quad->mask_uv_rect.ToString());
5422 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5423 host_impl_->DidDrawAllLayers(frame);
5427 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
5428 public:
5429 using GLRenderer::SetupQuadForAntialiasing;
5432 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
5433 // Due to precision issues (especially on Android), sometimes far
5434 // away quads can end up thinking they need AA.
5435 float device_scale_factor = 4.f / 3.f;
5436 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5437 gfx::Size root_size(2000, 1000);
5438 gfx::Size device_viewport_size =
5439 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
5440 host_impl_->SetViewportSize(device_viewport_size);
5442 host_impl_->CreatePendingTree();
5443 host_impl_->pending_tree()
5444 ->SetPageScaleFactorAndLimits(1.f, 1.f / 16.f, 16.f);
5446 scoped_ptr<LayerImpl> scoped_root =
5447 LayerImpl::Create(host_impl_->pending_tree(), 1);
5448 LayerImpl* root = scoped_root.get();
5450 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
5452 scoped_ptr<LayerImpl> scoped_scrolling_layer =
5453 LayerImpl::Create(host_impl_->pending_tree(), 2);
5454 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
5455 root->AddChild(scoped_scrolling_layer.Pass());
5457 gfx::Size content_layer_bounds(100000, 100);
5458 gfx::Size pile_tile_size(3000, 3000);
5459 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
5460 pile_tile_size, content_layer_bounds));
5462 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
5463 FakePictureLayerImpl::CreateWithPile(host_impl_->pending_tree(), 3, pile);
5464 LayerImpl* content_layer = scoped_content_layer.get();
5465 scrolling_layer->AddChild(scoped_content_layer.PassAs<LayerImpl>());
5466 content_layer->SetBounds(content_layer_bounds);
5467 content_layer->SetDrawsContent(true);
5469 root->SetBounds(root_size);
5471 gfx::Vector2d scroll_offset(100000, 0);
5472 scrolling_layer->SetScrollClipLayer(root->id());
5473 scrolling_layer->SetScrollOffset(scroll_offset);
5475 host_impl_->ActivatePendingTree();
5477 host_impl_->active_tree()->UpdateDrawProperties();
5478 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
5480 LayerTreeHostImpl::FrameData frame;
5481 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5483 ASSERT_EQ(1u, frame.render_passes.size());
5484 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
5485 const DrawQuad* quad = frame.render_passes[0]->quad_list[0];
5487 float edge[24];
5488 gfx::QuadF device_layer_quad;
5489 bool antialiased =
5490 GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
5491 quad->quadTransform(), quad, &device_layer_quad, edge);
5492 EXPECT_FALSE(antialiased);
5494 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5495 host_impl_->DidDrawAllLayers(frame);
5499 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
5500 public:
5501 CompositorFrameMetadataTest()
5502 : swap_buffers_complete_(0) {}
5504 virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {
5505 swap_buffers_complete_++;
5508 int swap_buffers_complete_;
5511 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
5512 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5514 LayerTreeHostImpl::FrameData frame;
5515 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5516 host_impl_->DrawLayers(&frame, base::TimeTicks());
5517 host_impl_->DidDrawAllLayers(frame);
5519 CompositorFrameAck ack;
5520 host_impl_->ReclaimResources(&ack);
5521 host_impl_->DidSwapBuffersComplete();
5522 EXPECT_EQ(swap_buffers_complete_, 1);
5525 class CountingSoftwareDevice : public SoftwareOutputDevice {
5526 public:
5527 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5529 virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
5530 ++frames_began_;
5531 return SoftwareOutputDevice::BeginPaint(damage_rect);
5533 virtual void EndPaint(SoftwareFrameData* frame_data) OVERRIDE {
5534 ++frames_ended_;
5535 SoftwareOutputDevice::EndPaint(frame_data);
5538 int frames_began_, frames_ended_;
5541 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
5542 // No main thread evictions in resourceless software mode.
5543 set_reduce_memory_result(false);
5544 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
5545 bool delegated_rendering = false;
5546 FakeOutputSurface* output_surface =
5547 FakeOutputSurface::CreateDeferredGL(
5548 scoped_ptr<SoftwareOutputDevice>(software_device),
5549 delegated_rendering).release();
5550 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5551 scoped_ptr<OutputSurface>(output_surface)));
5552 host_impl_->SetViewportSize(gfx::Size(50, 50));
5554 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5556 output_surface->set_forced_draw_to_software_device(true);
5557 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5559 EXPECT_EQ(0, software_device->frames_began_);
5560 EXPECT_EQ(0, software_device->frames_ended_);
5562 DrawFrame();
5564 EXPECT_EQ(1, software_device->frames_began_);
5565 EXPECT_EQ(1, software_device->frames_ended_);
5567 // Call other API methods that are likely to hit NULL pointer in this mode.
5568 EXPECT_TRUE(host_impl_->AsValue());
5569 EXPECT_TRUE(host_impl_->ActivationStateAsValue());
5572 TEST_F(LayerTreeHostImplTest,
5573 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
5574 set_reduce_memory_result(false);
5575 bool delegated_rendering = false;
5576 FakeOutputSurface* output_surface =
5577 FakeOutputSurface::CreateDeferredGL(
5578 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5579 delegated_rendering).release();
5580 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5581 scoped_ptr<OutputSurface>(output_surface)));
5583 output_surface->set_forced_draw_to_software_device(true);
5584 EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
5586 // SolidColorLayerImpl will be drawn.
5587 scoped_ptr<SolidColorLayerImpl> root_layer =
5588 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5590 // VideoLayerImpl will not be drawn.
5591 FakeVideoFrameProvider provider;
5592 scoped_ptr<VideoLayerImpl> video_layer =
5593 VideoLayerImpl::Create(host_impl_->active_tree(), 2, &provider);
5594 video_layer->SetBounds(gfx::Size(10, 10));
5595 video_layer->SetContentBounds(gfx::Size(10, 10));
5596 video_layer->SetDrawsContent(true);
5597 root_layer->AddChild(video_layer.PassAs<LayerImpl>());
5598 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5600 LayerTreeHostImpl::FrameData frame;
5601 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5602 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5603 host_impl_->DidDrawAllLayers(frame);
5605 EXPECT_EQ(1u, frame.will_draw_layers.size());
5606 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
5609 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest {
5610 protected:
5611 virtual void SetUp() OVERRIDE {
5612 LayerTreeHostImplTest::SetUp();
5614 set_reduce_memory_result(false);
5616 bool delegated_rendering = false;
5617 scoped_ptr<FakeOutputSurface> output_surface(
5618 FakeOutputSurface::CreateDeferredGL(
5619 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()),
5620 delegated_rendering));
5621 output_surface_ = output_surface.get();
5623 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5624 output_surface.PassAs<OutputSurface>()));
5626 scoped_ptr<SolidColorLayerImpl> root_layer =
5627 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5628 SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
5630 onscreen_context_provider_ = TestContextProvider::Create();
5633 virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {
5634 did_update_renderer_capabilities_ = true;
5637 FakeOutputSurface* output_surface_;
5638 scoped_refptr<TestContextProvider> onscreen_context_provider_;
5639 bool did_update_renderer_capabilities_;
5643 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) {
5644 // Software draw.
5645 DrawFrame();
5647 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5649 // DeferredInitialize and hardware draw.
5650 did_update_renderer_capabilities_ = false;
5651 EXPECT_TRUE(
5652 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5653 EXPECT_EQ(onscreen_context_provider_,
5654 host_impl_->output_surface()->context_provider());
5655 EXPECT_TRUE(did_update_renderer_capabilities_);
5657 // Defer intialized GL draw.
5658 DrawFrame();
5660 // Revert back to software.
5661 did_update_renderer_capabilities_ = false;
5662 output_surface_->ReleaseGL();
5663 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5664 EXPECT_TRUE(did_update_renderer_capabilities_);
5666 // Software draw again.
5667 DrawFrame();
5670 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails) {
5671 // Software draw.
5672 DrawFrame();
5674 // Fail initialization of the onscreen context before the OutputSurface binds
5675 // it to the thread.
5676 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true);
5678 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5680 // DeferredInitialize fails.
5681 did_update_renderer_capabilities_ = false;
5682 EXPECT_FALSE(
5683 output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
5684 EXPECT_FALSE(host_impl_->output_surface()->context_provider());
5685 EXPECT_FALSE(did_update_renderer_capabilities_);
5687 // Software draw again.
5688 DrawFrame();
5691 // Checks that we have a non-0 default allocation if we pass a context that
5692 // doesn't support memory management extensions.
5693 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5694 LayerTreeSettings settings;
5695 host_impl_ = LayerTreeHostImpl::Create(settings,
5696 this,
5697 &proxy_,
5698 &stats_instrumentation_,
5699 shared_bitmap_manager_.get(),
5702 scoped_ptr<OutputSurface> output_surface(
5703 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5704 host_impl_->InitializeRenderer(output_surface.Pass());
5705 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5708 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5709 ManagedMemoryPolicy policy1(
5710 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5711 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5712 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5713 int allow_nice_to_have_cutoff_value =
5714 ManagedMemoryPolicy::PriorityCutoffToValue(
5715 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
5716 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5717 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5719 // GPU rasterization should be disabled by default on the tree(s)
5720 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
5721 EXPECT_TRUE(host_impl_->pending_tree() == NULL);
5723 host_impl_->SetVisible(true);
5724 host_impl_->SetMemoryPolicy(policy1);
5725 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5726 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5728 host_impl_->SetVisible(false);
5729 EXPECT_EQ(0u, current_limit_bytes_);
5730 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5732 host_impl_->SetVisible(true);
5733 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5734 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5736 // Now enable GPU rasterization and test if we get nice to have cutoff,
5737 // when visible.
5738 LayerTreeSettings settings;
5739 settings.gpu_rasterization_enabled = true;
5740 host_impl_ = LayerTreeHostImpl::Create(
5741 settings, this, &proxy_, &stats_instrumentation_, NULL, 0);
5742 host_impl_->SetUseGpuRasterization(true);
5743 host_impl_->SetVisible(true);
5744 host_impl_->SetMemoryPolicy(policy1);
5745 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5746 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
5748 host_impl_->SetVisible(false);
5749 EXPECT_EQ(0u, current_limit_bytes_);
5750 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5753 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
5754 ASSERT_TRUE(host_impl_->active_tree());
5756 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5757 host_impl_->SetVisible(false);
5758 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5759 host_impl_->SetVisible(true);
5760 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5761 host_impl_->SetVisible(false);
5762 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5764 host_impl_->CreatePendingTree();
5765 host_impl_->ActivatePendingTree();
5767 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5768 host_impl_->SetVisible(true);
5769 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5772 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
5773 ASSERT_TRUE(host_impl_->active_tree());
5774 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
5776 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5777 host_impl_->SetUseGpuRasterization(false);
5778 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5779 host_impl_->SetUseGpuRasterization(true);
5780 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5781 host_impl_->SetUseGpuRasterization(false);
5782 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5784 host_impl_->CreatePendingTree();
5785 host_impl_->ActivatePendingTree();
5787 EXPECT_FALSE(host_impl_->active_tree()->RequiresHighResToDraw());
5788 host_impl_->SetUseGpuRasterization(true);
5789 EXPECT_TRUE(host_impl_->active_tree()->RequiresHighResToDraw());
5792 class LayerTreeHostImplTestManageTiles : public LayerTreeHostImplTest {
5793 public:
5794 virtual void SetUp() OVERRIDE {
5795 LayerTreeSettings settings;
5796 settings.impl_side_painting = true;
5798 fake_host_impl_ = new FakeLayerTreeHostImpl(
5799 settings, &proxy_, shared_bitmap_manager_.get());
5800 host_impl_.reset(fake_host_impl_);
5801 host_impl_->InitializeRenderer(CreateOutputSurface());
5802 host_impl_->SetViewportSize(gfx::Size(10, 10));
5805 FakeLayerTreeHostImpl* fake_host_impl_;
5808 TEST_F(LayerTreeHostImplTestManageTiles, ManageTilesWhenInvisible) {
5809 fake_host_impl_->DidModifyTilePriorities();
5810 EXPECT_TRUE(fake_host_impl_->manage_tiles_needed());
5811 fake_host_impl_->SetVisible(false);
5812 EXPECT_FALSE(fake_host_impl_->manage_tiles_needed());
5815 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
5816 scoped_ptr<TestWebGraphicsContext3D> context =
5817 TestWebGraphicsContext3D::Create();
5818 TestWebGraphicsContext3D* context3d = context.get();
5819 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5820 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5822 EXPECT_EQ(0u, context3d->NumTextures());
5824 UIResourceId ui_resource_id = 1;
5825 bool is_opaque = false;
5826 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
5827 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5828 EXPECT_EQ(1u, context3d->NumTextures());
5829 ResourceProvider::ResourceId id1 =
5830 host_impl_->ResourceIdForUIResource(ui_resource_id);
5831 EXPECT_NE(0u, id1);
5833 // Multiple requests with the same id is allowed. The previous texture is
5834 // deleted.
5835 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5836 EXPECT_EQ(1u, context3d->NumTextures());
5837 ResourceProvider::ResourceId id2 =
5838 host_impl_->ResourceIdForUIResource(ui_resource_id);
5839 EXPECT_NE(0u, id2);
5840 EXPECT_NE(id1, id2);
5842 // Deleting invalid UIResourceId is allowed and does not change state.
5843 host_impl_->DeleteUIResource(-1);
5844 EXPECT_EQ(1u, context3d->NumTextures());
5846 // Should return zero for invalid UIResourceId. Number of textures should
5847 // not change.
5848 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
5849 EXPECT_EQ(1u, context3d->NumTextures());
5851 host_impl_->DeleteUIResource(ui_resource_id);
5852 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
5853 EXPECT_EQ(0u, context3d->NumTextures());
5855 // Should not change state for multiple deletion on one UIResourceId
5856 host_impl_->DeleteUIResource(ui_resource_id);
5857 EXPECT_EQ(0u, context3d->NumTextures());
5860 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
5861 scoped_ptr<TestWebGraphicsContext3D> context =
5862 TestWebGraphicsContext3D::Create();
5863 TestWebGraphicsContext3D* context3d = context.get();
5864 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
5865 CreateHostImpl(DefaultSettings(), output_surface.PassAs<OutputSurface>());
5867 EXPECT_EQ(0u, context3d->NumTextures());
5869 gfx::Size size(4, 4);
5870 // SkImageInfo has no support for ETC1. The |info| below contains the right
5871 // total pixel size for the bitmap but not the right height and width. The
5872 // correct width/height are passed directly to UIResourceBitmap.
5873 SkImageInfo info =
5874 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
5875 skia::RefPtr<SkPixelRef> pixel_ref =
5876 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
5877 pixel_ref->setImmutable();
5878 UIResourceBitmap bitmap(pixel_ref, size);
5879 UIResourceId ui_resource_id = 1;
5880 host_impl_->CreateUIResource(ui_resource_id, bitmap);
5881 EXPECT_EQ(1u, context3d->NumTextures());
5882 ResourceProvider::ResourceId id1 =
5883 host_impl_->ResourceIdForUIResource(ui_resource_id);
5884 EXPECT_NE(0u, id1);
5887 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
5890 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
5891 scoped_refptr<TestContextProvider> context_provider =
5892 TestContextProvider::Create();
5894 CreateHostImpl(
5895 DefaultSettings(),
5896 FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>());
5898 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5900 ScopedPtrVector<CopyOutputRequest> requests;
5901 requests.push_back(CopyOutputRequest::CreateRequest(
5902 base::Bind(&ShutdownReleasesContext_Callback)));
5904 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
5906 LayerTreeHostImpl::FrameData frame;
5907 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5908 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5909 host_impl_->DidDrawAllLayers(frame);
5911 // The CopyOutputResult's callback has a ref on the ContextProvider and a
5912 // texture in a texture mailbox.
5913 EXPECT_FALSE(context_provider->HasOneRef());
5914 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
5916 host_impl_.reset();
5918 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
5919 // released, and the texture deleted.
5920 EXPECT_TRUE(context_provider->HasOneRef());
5921 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
5924 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
5925 // When flinging via touch, only the child should scroll (we should not
5926 // bubble).
5927 gfx::Size surface_size(10, 10);
5928 gfx::Size content_size(20, 20);
5929 scoped_ptr<LayerImpl> root_clip =
5930 LayerImpl::Create(host_impl_->active_tree(), 3);
5931 scoped_ptr<LayerImpl> root =
5932 CreateScrollableLayer(1, content_size, root_clip.get());
5933 root->SetIsContainerForFixedPositionLayers(true);
5934 scoped_ptr<LayerImpl> child =
5935 CreateScrollableLayer(2, content_size, root_clip.get());
5937 root->AddChild(child.Pass());
5938 int root_id = root->id();
5939 root_clip->AddChild(root.Pass());
5941 host_impl_->SetViewportSize(surface_size);
5942 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
5943 host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
5944 host_impl_->active_tree()->DidBecomeActive();
5945 DrawFrame();
5947 EXPECT_EQ(InputHandler::ScrollStarted,
5948 host_impl_->ScrollBegin(gfx::Point(),
5949 InputHandler::Gesture));
5951 EXPECT_EQ(InputHandler::ScrollStarted,
5952 host_impl_->FlingScrollBegin());
5954 gfx::Vector2d scroll_delta(0, 100);
5955 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5956 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
5958 host_impl_->ScrollEnd();
5960 scoped_ptr<ScrollAndScaleSet> scroll_info =
5961 host_impl_->ProcessScrollDeltas();
5963 // Only the child should have scrolled.
5964 ASSERT_EQ(1u, scroll_info->scrolls.size());
5965 ExpectNone(*scroll_info.get(), root_id);
5969 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
5970 // Scroll a child layer beyond its maximum scroll range and make sure the
5971 // the scroll doesn't bubble up to the parent layer.
5972 gfx::Size surface_size(10, 10);
5973 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
5974 scoped_ptr<LayerImpl> root_scrolling =
5975 CreateScrollableLayer(2, surface_size, root.get());
5977 scoped_ptr<LayerImpl> grand_child =
5978 CreateScrollableLayer(4, surface_size, root.get());
5979 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
5981 scoped_ptr<LayerImpl> child =
5982 CreateScrollableLayer(3, surface_size, root.get());
5983 child->SetScrollOffset(gfx::Vector2d(0, 4));
5984 child->AddChild(grand_child.Pass());
5986 root_scrolling->AddChild(child.Pass());
5987 root->AddChild(root_scrolling.Pass());
5988 host_impl_->active_tree()->SetRootLayer(root.Pass());
5989 host_impl_->active_tree()->DidBecomeActive();
5990 host_impl_->SetViewportSize(surface_size);
5991 DrawFrame();
5993 scoped_ptr<ScrollAndScaleSet> scroll_info;
5994 LayerImpl* child =
5995 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
5996 LayerImpl* grand_child = child->children()[0];
5998 gfx::Vector2d scroll_delta(0, -2);
5999 EXPECT_EQ(InputHandler::ScrollStarted,
6000 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6001 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6003 // The grand child should have scrolled up to its limit.
6004 scroll_info = host_impl_->ProcessScrollDeltas();
6005 ASSERT_EQ(1u, scroll_info->scrolls.size());
6006 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6007 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6009 // The child should have received the bubbled delta, but the locked
6010 // scrolling layer should remain set as the grand child.
6011 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6012 scroll_info = host_impl_->ProcessScrollDeltas();
6013 ASSERT_EQ(2u, scroll_info->scrolls.size());
6014 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6015 ExpectContains(*scroll_info, child->id(), scroll_delta);
6016 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6018 // The first |ScrollBy| after the fling should re-lock the scrolling
6019 // layer to the first layer that scrolled, which is the child.
6020 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6021 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6022 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6024 // The child should have scrolled up to its limit.
6025 scroll_info = host_impl_->ProcessScrollDeltas();
6026 ASSERT_EQ(2u, scroll_info->scrolls.size());
6027 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6028 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
6030 // As the locked layer is at it's limit, no further scrolling can occur.
6031 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
6032 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6033 host_impl_->ScrollEnd();
6037 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6038 // When flinging via wheel, the root should eventually scroll (we should
6039 // bubble).
6040 gfx::Size surface_size(10, 10);
6041 gfx::Size content_size(20, 20);
6042 scoped_ptr<LayerImpl> root_clip =
6043 LayerImpl::Create(host_impl_->active_tree(), 3);
6044 scoped_ptr<LayerImpl> root_scroll =
6045 CreateScrollableLayer(1, content_size, root_clip.get());
6046 int root_scroll_id = root_scroll->id();
6047 scoped_ptr<LayerImpl> child =
6048 CreateScrollableLayer(2, content_size, root_clip.get());
6050 root_scroll->AddChild(child.Pass());
6051 root_clip->AddChild(root_scroll.Pass());
6053 host_impl_->SetViewportSize(surface_size);
6054 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6055 host_impl_->active_tree()->DidBecomeActive();
6056 DrawFrame();
6058 EXPECT_EQ(InputHandler::ScrollStarted,
6059 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6061 EXPECT_EQ(InputHandler::ScrollStarted,
6062 host_impl_->FlingScrollBegin());
6064 gfx::Vector2d scroll_delta(0, 100);
6065 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6066 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6068 host_impl_->ScrollEnd();
6070 scoped_ptr<ScrollAndScaleSet> scroll_info =
6071 host_impl_->ProcessScrollDeltas();
6073 // The root should have scrolled.
6074 ASSERT_EQ(2u, scroll_info->scrolls.size());
6075 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
6079 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6080 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6081 // we should return ScrollUnknown.
6082 gfx::Size content_size(100, 100);
6083 SetupScrollAndContentsLayers(content_size);
6085 int scroll_layer_id = 2;
6086 LayerImpl* scroll_layer =
6087 host_impl_->active_tree()->LayerById(scroll_layer_id);
6088 scroll_layer->SetDrawsContent(true);
6090 int page_scale_layer_id = 5;
6091 LayerImpl* page_scale_layer =
6092 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6094 int occluder_layer_id = 6;
6095 scoped_ptr<LayerImpl> occluder_layer =
6096 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6097 occluder_layer->SetDrawsContent(true);
6098 occluder_layer->SetBounds(content_size);
6099 occluder_layer->SetContentBounds(content_size);
6100 occluder_layer->SetPosition(gfx::PointF());
6101 occluder_layer->SetAnchorPoint(gfx::PointF());
6103 // The parent of the occluder is *above* the scroller.
6104 page_scale_layer->AddChild(occluder_layer.Pass());
6106 DrawFrame();
6108 EXPECT_EQ(InputHandler::ScrollUnknown,
6109 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6112 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6113 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6114 // is not the first scroller we encounter when walking up from the layer, we
6115 // should also return ScrollUnknown.
6116 gfx::Size content_size(100, 100);
6117 SetupScrollAndContentsLayers(content_size);
6119 int scroll_layer_id = 2;
6120 LayerImpl* scroll_layer =
6121 host_impl_->active_tree()->LayerById(scroll_layer_id);
6122 scroll_layer->SetDrawsContent(true);
6124 int occluder_layer_id = 6;
6125 scoped_ptr<LayerImpl> occluder_layer =
6126 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6127 occluder_layer->SetDrawsContent(true);
6128 occluder_layer->SetBounds(content_size);
6129 occluder_layer->SetContentBounds(content_size);
6130 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6131 occluder_layer->SetAnchorPoint(gfx::PointF());
6133 int child_scroll_clip_layer_id = 7;
6134 scoped_ptr<LayerImpl> child_scroll_clip =
6135 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6137 int child_scroll_layer_id = 8;
6138 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6139 child_scroll_layer_id, content_size, child_scroll_clip.get());
6141 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6143 child_scroll->AddChild(occluder_layer.Pass());
6144 scroll_layer->AddChild(child_scroll.Pass());
6146 DrawFrame();
6148 EXPECT_EQ(InputHandler::ScrollUnknown,
6149 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6152 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) {
6153 gfx::Size content_size(100, 100);
6154 SetupScrollAndContentsLayers(content_size);
6156 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6158 int scroll_layer_id = 2;
6159 LayerImpl* scroll_layer =
6160 host_impl_->active_tree()->LayerById(scroll_layer_id);
6162 int child_scroll_layer_id = 7;
6163 scoped_ptr<LayerImpl> child_scroll =
6164 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6165 child_scroll->SetDrawsContent(false);
6167 scroll_layer->AddChild(child_scroll.Pass());
6169 DrawFrame();
6171 // We should not have scrolled |child_scroll| even though we technically "hit"
6172 // it. The reason for this is that if the scrolling the scroll would not move
6173 // any layer that is a drawn RSLL member, then we can ignore the hit.
6175 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6176 // overscrolling the inner viewport.
6177 EXPECT_EQ(InputHandler::ScrollStarted,
6178 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6180 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6183 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6184 // This test case is very similar to the one above with one key difference:
6185 // the invisible scroller has a scroll child that is indeed draw contents.
6186 // If we attempt to initiate a gesture scroll off of the visible scroll child
6187 // we should still start the scroll child.
6188 gfx::Size content_size(100, 100);
6189 SetupScrollAndContentsLayers(content_size);
6191 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6193 int scroll_layer_id = 2;
6194 LayerImpl* scroll_layer =
6195 host_impl_->active_tree()->LayerById(scroll_layer_id);
6197 int scroll_child_id = 6;
6198 scoped_ptr<LayerImpl> scroll_child =
6199 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6200 scroll_child->SetDrawsContent(true);
6201 scroll_child->SetBounds(content_size);
6202 scroll_child->SetContentBounds(content_size);
6203 // Move the scroll child so it's not hit by our test point.
6204 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6205 scroll_child->SetAnchorPoint(gfx::PointF());
6207 int invisible_scroll_layer_id = 7;
6208 scoped_ptr<LayerImpl> invisible_scroll =
6209 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6210 invisible_scroll->SetDrawsContent(false);
6212 int container_id = 8;
6213 scoped_ptr<LayerImpl> container =
6214 LayerImpl::Create(host_impl_->active_tree(), container_id);
6216 scoped_ptr<std::set<LayerImpl*> > scroll_children(new std::set<LayerImpl*>());
6217 scroll_children->insert(scroll_child.get());
6218 invisible_scroll->SetScrollChildren(scroll_children.release());
6220 scroll_child->SetScrollParent(invisible_scroll.get());
6222 container->AddChild(invisible_scroll.Pass());
6223 container->AddChild(scroll_child.Pass());
6225 scroll_layer->AddChild(container.Pass());
6227 DrawFrame();
6229 // We should not have scrolled |child_scroll| even though we technically "hit"
6230 // it. The reason for this is that if the scrolling the scroll would not move
6231 // any layer that is a drawn RSLL member, then we can ignore the hit.
6233 // Why ScrollStarted? In this case, it's because we've bubbled out and started
6234 // overscrolling the inner viewport.
6235 EXPECT_EQ(InputHandler::ScrollStarted,
6236 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
6238 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6241 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6242 // to CompositorFrameMetadata after SwapBuffers();
6243 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6244 scoped_ptr<SolidColorLayerImpl> root =
6245 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6246 root->SetAnchorPoint(gfx::PointF());
6247 root->SetPosition(gfx::PointF());
6248 root->SetBounds(gfx::Size(10, 10));
6249 root->SetContentBounds(gfx::Size(10, 10));
6250 root->SetDrawsContent(true);
6252 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
6254 FakeOutputSurface* fake_output_surface =
6255 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6257 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6258 fake_output_surface->last_sent_frame().metadata.latency_info;
6259 EXPECT_TRUE(metadata_latency_before.empty());
6261 ui::LatencyInfo latency_info;
6262 latency_info.AddLatencyNumber(
6263 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6264 scoped_ptr<SwapPromise> swap_promise(
6265 new LatencyInfoSwapPromise(latency_info));
6266 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
6267 host_impl_->SetNeedsRedraw();
6269 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6270 LayerTreeHostImpl::FrameData frame;
6271 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6272 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6273 host_impl_->DidDrawAllLayers(frame);
6274 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6276 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6277 fake_output_surface->last_sent_frame().metadata.latency_info;
6278 EXPECT_EQ(1u, metadata_latency_after.size());
6279 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6280 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6283 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
6284 public:
6285 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
6286 LayerTreeHostImpl* layer_tree_host_impl,
6287 int* set_needs_commit_count,
6288 int* set_needs_redraw_count)
6289 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
6290 set_needs_commit_count_(set_needs_commit_count),
6291 set_needs_redraw_count_(set_needs_redraw_count) {}
6293 virtual ~SimpleSwapPromiseMonitor() {}
6295 virtual void OnSetNeedsCommitOnMain() OVERRIDE {
6296 (*set_needs_commit_count_)++;
6299 virtual void OnSetNeedsRedrawOnImpl() OVERRIDE {
6300 (*set_needs_redraw_count_)++;
6303 private:
6304 int* set_needs_commit_count_;
6305 int* set_needs_redraw_count_;
6308 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
6309 int set_needs_commit_count = 0;
6310 int set_needs_redraw_count = 0;
6313 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6314 new SimpleSwapPromiseMonitor(NULL,
6315 host_impl_.get(),
6316 &set_needs_commit_count,
6317 &set_needs_redraw_count));
6318 host_impl_->SetNeedsRedraw();
6319 EXPECT_EQ(0, set_needs_commit_count);
6320 EXPECT_EQ(1, set_needs_redraw_count);
6323 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6324 // monitored.
6325 host_impl_->SetNeedsRedraw();
6326 EXPECT_EQ(0, set_needs_commit_count);
6327 EXPECT_EQ(1, set_needs_redraw_count);
6330 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6331 new SimpleSwapPromiseMonitor(NULL,
6332 host_impl_.get(),
6333 &set_needs_commit_count,
6334 &set_needs_redraw_count));
6335 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
6336 EXPECT_EQ(0, set_needs_commit_count);
6337 EXPECT_EQ(2, set_needs_redraw_count);
6341 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6342 new SimpleSwapPromiseMonitor(NULL,
6343 host_impl_.get(),
6344 &set_needs_commit_count,
6345 &set_needs_redraw_count));
6346 // Empty damage rect won't signal the monitor.
6347 host_impl_->SetNeedsRedrawRect(gfx::Rect());
6348 EXPECT_EQ(0, set_needs_commit_count);
6349 EXPECT_EQ(2, set_needs_redraw_count);
6353 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
6354 public:
6355 virtual void SetUp() OVERRIDE {
6356 LayerTreeSettings settings = DefaultSettings();
6357 settings.calculate_top_controls_position = true;
6358 settings.top_controls_height = top_controls_height_;
6359 CreateHostImpl(settings, CreateOutputSurface());
6362 protected:
6363 static const int top_controls_height_;
6366 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
6368 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
6369 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6370 ->SetScrollOffset(gfx::Vector2d(0, 10));
6371 host_impl_->Animate(base::TimeTicks());
6372 EXPECT_FALSE(did_request_redraw_);
6375 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
6376 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6377 ->SetScrollOffset(gfx::Vector2d(0, 10));
6378 host_impl_->DidChangeTopControlsPosition();
6379 EXPECT_TRUE(did_request_animate_);
6380 EXPECT_TRUE(did_request_redraw_);
6383 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
6384 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6385 host_impl_->SetViewportSize(gfx::Size(100, 100));
6386 DrawFrame();
6388 EXPECT_EQ(InputHandler::ScrollStarted,
6389 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6390 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6391 EXPECT_EQ(gfx::Vector2dF().ToString(),
6392 scroll_layer->TotalScrollOffset().ToString());
6394 // Scroll just the top controls and verify that the scroll succeeds.
6395 const float residue = 10;
6396 float offset = top_controls_height_ - residue;
6397 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6398 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->controls_top_offset());
6399 EXPECT_EQ(gfx::Vector2dF().ToString(),
6400 scroll_layer->TotalScrollOffset().ToString());
6402 // Scroll across the boundary
6403 const float content_scroll = 20;
6404 offset = residue + content_scroll;
6405 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6406 EXPECT_EQ(-top_controls_height_,
6407 host_impl_->top_controls_manager()->controls_top_offset());
6408 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
6409 scroll_layer->TotalScrollOffset().ToString());
6411 // Now scroll back to the top of the content
6412 offset = -content_scroll;
6413 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6414 EXPECT_EQ(-top_controls_height_,
6415 host_impl_->top_controls_manager()->controls_top_offset());
6416 EXPECT_EQ(gfx::Vector2dF().ToString(),
6417 scroll_layer->TotalScrollOffset().ToString());
6419 // And scroll the top controls completely into view
6420 offset = -top_controls_height_;
6421 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6422 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6423 EXPECT_EQ(gfx::Vector2dF().ToString(),
6424 scroll_layer->TotalScrollOffset().ToString());
6426 // And attempt to scroll past the end
6427 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
6428 EXPECT_EQ(0, host_impl_->top_controls_manager()->controls_top_offset());
6429 EXPECT_EQ(gfx::Vector2dF().ToString(),
6430 scroll_layer->TotalScrollOffset().ToString());
6432 host_impl_->ScrollEnd();
6435 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
6436 public:
6437 void SetupVirtualViewportLayers(const gfx::Size& content_size,
6438 const gfx::Size& outer_viewport,
6439 const gfx::Size& inner_viewport) {
6440 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
6441 const int kOuterViewportClipLayerId = 6;
6442 const int kOuterViewportScrollLayerId = 7;
6443 const int kInnerViewportScrollLayerId = 2;
6444 const int kInnerViewportClipLayerId = 4;
6445 const int kPageScaleLayerId = 5;
6447 scoped_ptr<LayerImpl> inner_scroll =
6448 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
6449 inner_scroll->SetIsContainerForFixedPositionLayers(true);
6450 inner_scroll->SetScrollOffset(gfx::Vector2d());
6452 scoped_ptr<LayerImpl> inner_clip =
6453 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
6454 inner_clip->SetBounds(inner_viewport);
6456 scoped_ptr<LayerImpl> page_scale =
6457 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
6459 inner_scroll->SetScrollClipLayer(inner_clip->id());
6460 inner_scroll->SetBounds(outer_viewport);
6461 inner_scroll->SetContentBounds(outer_viewport);
6462 inner_scroll->SetPosition(gfx::PointF());
6463 inner_scroll->SetAnchorPoint(gfx::PointF());
6465 scoped_ptr<LayerImpl> outer_clip =
6466 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
6467 outer_clip->SetBounds(outer_viewport);
6468 outer_clip->SetIsContainerForFixedPositionLayers(true);
6470 scoped_ptr<LayerImpl> outer_scroll =
6471 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
6472 outer_scroll->SetScrollClipLayer(outer_clip->id());
6473 outer_scroll->SetScrollOffset(gfx::Vector2d());
6474 outer_scroll->SetBounds(content_size);
6475 outer_scroll->SetContentBounds(content_size);
6476 outer_scroll->SetPosition(gfx::PointF());
6477 outer_scroll->SetAnchorPoint(gfx::PointF());
6479 scoped_ptr<LayerImpl> contents =
6480 LayerImpl::Create(layer_tree_impl, 8);
6481 contents->SetDrawsContent(true);
6482 contents->SetBounds(content_size);
6483 contents->SetContentBounds(content_size);
6484 contents->SetPosition(gfx::PointF());
6485 contents->SetAnchorPoint(gfx::PointF());
6487 outer_scroll->AddChild(contents.Pass());
6488 outer_clip->AddChild(outer_scroll.Pass());
6489 inner_scroll->AddChild(outer_clip.Pass());
6490 page_scale->AddChild(inner_scroll.Pass());
6491 inner_clip->AddChild(page_scale.Pass());
6493 layer_tree_impl->SetRootLayer(inner_clip.Pass());
6494 layer_tree_impl->SetViewportLayersFromIds(kPageScaleLayerId,
6495 kInnerViewportScrollLayerId, kOuterViewportScrollLayerId);
6497 host_impl_->active_tree()->DidBecomeActive();
6501 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
6502 gfx::Size content_size = gfx::Size(100, 160);
6503 gfx::Size outer_viewport = gfx::Size(50, 80);
6504 gfx::Size inner_viewport = gfx::Size(25, 40);
6506 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
6508 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
6509 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
6510 DrawFrame();
6512 gfx::Vector2dF inner_expected;
6513 gfx::Vector2dF outer_expected;
6514 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6515 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6517 // Make sure the fling goes to the outer viewport first
6518 EXPECT_EQ(InputHandler::ScrollStarted,
6519 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6520 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6522 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
6523 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6524 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6526 host_impl_->ScrollEnd();
6528 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6529 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6531 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
6532 EXPECT_EQ(InputHandler::ScrollStarted,
6533 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
6534 EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
6536 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6537 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6539 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6540 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
6542 host_impl_->ScrollEnd();
6544 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->TotalScrollOffset());
6545 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->TotalScrollOffset());
6549 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
6550 public:
6551 virtual void SetUp() OVERRIDE {
6552 LayerTreeSettings settings = DefaultSettings();
6553 settings.max_memory_for_prepaint_percentage = 50;
6554 CreateHostImpl(settings, CreateOutputSurface());
6558 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
6559 // Set up a memory policy and percentages which could cause
6560 // 32-bit integer overflows.
6561 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
6563 // Verify implicit limits are calculated correctly with no overflows
6564 host_impl_->SetMemoryPolicy(mem_policy);
6565 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
6566 300u * 1024u * 1024u);
6567 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
6568 150u * 1024u * 1024u);
6571 TEST_F(LayerTreeHostImplTest, UpdateTilesForMasksWithNoVisibleContent) {
6572 gfx::Size bounds(100000, 100);
6574 host_impl_->CreatePendingTree();
6576 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->pending_tree(), 1);
6578 scoped_ptr<FakePictureLayerImpl> layer_with_mask =
6579 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 2);
6581 layer_with_mask->SetBounds(bounds);
6583 scoped_ptr<FakePictureLayerImpl> mask =
6584 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 3);
6586 mask->SetIsMask(true);
6587 mask->SetBounds(bounds);
6589 FakePictureLayerImpl* pending_mask_content = mask.get();
6590 layer_with_mask->SetMaskLayer(mask.PassAs<LayerImpl>());
6592 scoped_ptr<FakePictureLayerImpl> child_of_layer_with_mask =
6593 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 4);
6595 child_of_layer_with_mask->SetBounds(bounds);
6596 child_of_layer_with_mask->SetDrawsContent(true);
6598 layer_with_mask->AddChild(child_of_layer_with_mask.PassAs<LayerImpl>());
6600 root->AddChild(layer_with_mask.PassAs<LayerImpl>());
6602 host_impl_->pending_tree()->SetRootLayer(root.Pass());
6604 gfx::Rect r1 = pending_mask_content->visible_rect_for_tile_priority();
6605 ASSERT_EQ(0, r1.x());
6606 ASSERT_EQ(0, r1.y());
6607 ASSERT_EQ(0, r1.width());
6608 ASSERT_EQ(0, r1.height());
6610 host_impl_->ActivatePendingTree();
6612 host_impl_->active_tree()->UpdateDrawProperties();
6614 ASSERT_EQ(2u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
6616 FakePictureLayerImpl* active_mask_content =
6617 static_cast<FakePictureLayerImpl*>(
6618 host_impl_->active_tree()->root_layer()->children()[0]->mask_layer());
6619 gfx::Rect r2 = active_mask_content->visible_rect_for_tile_priority();
6621 ASSERT_TRUE(!r2.IsEmpty());
6624 } // namespace
6625 } // namespace cc