OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "cc/trees/layer_tree_host_impl.h" | |
6 | |
7 #include <algorithm> | |
8 #include <cmath> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/command_line.h" | |
12 #include "base/containers/hash_tables.h" | |
13 #include "base/containers/scoped_ptr_hash_map.h" | |
14 #include "cc/animation/scrollbar_animation_controller_thinning.h" | |
15 #include "cc/base/math_util.h" | |
16 #include "cc/input/page_scale_animation.h" | |
17 #include "cc/input/top_controls_manager.h" | |
18 #include "cc/layers/append_quads_data.h" | |
19 #include "cc/layers/delegated_renderer_layer_impl.h" | |
20 #include "cc/layers/heads_up_display_layer_impl.h" | |
21 #include "cc/layers/io_surface_layer_impl.h" | |
22 #include "cc/layers/layer_impl.h" | |
23 #include "cc/layers/painted_scrollbar_layer_impl.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/output/begin_frame_args.h" | |
30 #include "cc/output/compositor_frame_ack.h" | |
31 #include "cc/output/compositor_frame_metadata.h" | |
32 #include "cc/output/copy_output_request.h" | |
33 #include "cc/output/copy_output_result.h" | |
34 #include "cc/output/gl_renderer.h" | |
35 #include "cc/output/latency_info_swap_promise.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/begin_frame_args_test.h" | |
43 #include "cc/test/fake_layer_tree_host_impl.h" | |
44 #include "cc/test/fake_output_surface.h" | |
45 #include "cc/test/fake_output_surface_client.h" | |
46 #include "cc/test/fake_picture_layer_impl.h" | |
47 #include "cc/test/fake_picture_pile_impl.h" | |
48 #include "cc/test/fake_proxy.h" | |
49 #include "cc/test/geometry_test_utils.h" | |
50 #include "cc/test/layer_test_common.h" | |
51 #include "cc/test/layer_tree_test.h" | |
52 #include "cc/test/render_pass_test_common.h" | |
53 #include "cc/test/test_gpu_memory_buffer_manager.h" | |
54 #include "cc/test/test_shared_bitmap_manager.h" | |
55 #include "cc/test/test_task_graph_runner.h" | |
56 #include "cc/test/test_web_graphics_context_3d.h" | |
57 #include "cc/trees/layer_tree_impl.h" | |
58 #include "cc/trees/single_thread_proxy.h" | |
59 #include "testing/gmock/include/gmock/gmock.h" | |
60 #include "testing/gtest/include/gtest/gtest.h" | |
61 #include "third_party/skia/include/core/SkMallocPixelRef.h" | |
62 #include "ui/gfx/frame_time.h" | |
63 #include "ui/gfx/geometry/rect_conversions.h" | |
64 #include "ui/gfx/geometry/size_conversions.h" | |
65 #include "ui/gfx/geometry/vector2d_conversions.h" | |
66 | |
67 using ::testing::Mock; | |
68 using ::testing::Return; | |
69 using ::testing::AnyNumber; | |
70 using ::testing::AtLeast; | |
71 using ::testing::_; | |
72 | |
73 namespace cc { | |
74 namespace { | |
75 | |
76 class LayerTreeHostImplTest : public testing::Test, | |
77 public LayerTreeHostImplClient { | |
78 public: | |
79 LayerTreeHostImplTest() | |
80 : proxy_(base::MessageLoopProxy::current(), | |
81 base::MessageLoopProxy::current()), | |
82 always_impl_thread_(&proxy_), | |
83 always_main_thread_blocked_(&proxy_), | |
84 shared_bitmap_manager_(new TestSharedBitmapManager), | |
85 gpu_memory_buffer_manager_(new TestGpuMemoryBufferManager), | |
86 task_graph_runner_(new TestTaskGraphRunner), | |
87 on_can_draw_state_changed_called_(false), | |
88 did_notify_ready_to_activate_(false), | |
89 did_request_commit_(false), | |
90 did_request_redraw_(false), | |
91 did_request_animate_(false), | |
92 did_request_prepare_tiles_(false), | |
93 did_complete_page_scale_animation_(false), | |
94 reduce_memory_result_(true), | |
95 current_limit_bytes_(0), | |
96 current_priority_cutoff_value_(0) { | |
97 } | |
98 | |
99 LayerTreeSettings DefaultSettings() { | |
100 LayerTreeSettings settings; | |
101 settings.minimum_occlusion_tracking_size = gfx::Size(); | |
102 settings.impl_side_painting = true; | |
103 settings.renderer_settings.texture_id_allocation_chunk_size = 1; | |
104 settings.report_overscroll_only_for_scrollable_axes = true; | |
105 settings.use_pinch_virtual_viewport = true; | |
106 return settings; | |
107 } | |
108 | |
109 void SetUp() override { | |
110 CreateHostImpl(DefaultSettings(), CreateOutputSurface()); | |
111 } | |
112 | |
113 void TearDown() override {} | |
114 | |
115 void UpdateRendererCapabilitiesOnImplThread() override {} | |
116 void DidLoseOutputSurfaceOnImplThread() override {} | |
117 void CommitVSyncParameters(base::TimeTicks timebase, | |
118 base::TimeDelta interval) override {} | |
119 void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {} | |
120 void SetMaxSwapsPendingOnImplThread(int max) override {} | |
121 void DidSwapBuffersOnImplThread() override {} | |
122 void DidSwapBuffersCompleteOnImplThread() override {} | |
123 void OnCanDrawStateChanged(bool can_draw) override { | |
124 on_can_draw_state_changed_called_ = true; | |
125 } | |
126 void NotifyReadyToActivate() override { | |
127 did_notify_ready_to_activate_ = true; | |
128 host_impl_->ActivateSyncTree(); | |
129 } | |
130 void NotifyReadyToDraw() override {} | |
131 void SetNeedsRedrawOnImplThread() override { did_request_redraw_ = true; } | |
132 void SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) override { | |
133 did_request_redraw_ = true; | |
134 } | |
135 void SetNeedsAnimateOnImplThread() override { did_request_animate_ = true; } | |
136 void SetNeedsPrepareTilesOnImplThread() override { | |
137 did_request_prepare_tiles_ = true; | |
138 } | |
139 void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; } | |
140 void PostAnimationEventsToMainThreadOnImplThread( | |
141 scoped_ptr<AnimationEventsVector> events) override {} | |
142 bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes, | |
143 int priority_cutoff) override { | |
144 current_limit_bytes_ = limit_bytes; | |
145 current_priority_cutoff_value_ = priority_cutoff; | |
146 return reduce_memory_result_; | |
147 } | |
148 bool IsInsideDraw() override { return false; } | |
149 void RenewTreePriority() override {} | |
150 void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, | |
151 base::TimeDelta delay) override { | |
152 animation_task_ = task; | |
153 requested_animation_delay_ = delay; | |
154 } | |
155 void DidActivateSyncTree() override {} | |
156 void DidPrepareTiles() override {} | |
157 void DidCompletePageScaleAnimationOnImplThread() override { | |
158 did_complete_page_scale_animation_ = true; | |
159 } | |
160 | |
161 void set_reduce_memory_result(bool reduce_memory_result) { | |
162 reduce_memory_result_ = reduce_memory_result; | |
163 } | |
164 | |
165 virtual bool CreateHostImpl(const LayerTreeSettings& settings, | |
166 scoped_ptr<OutputSurface> output_surface) { | |
167 host_impl_ = LayerTreeHostImpl::Create( | |
168 settings, this, &proxy_, &stats_instrumentation_, | |
169 shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), | |
170 task_graph_runner_.get(), 0); | |
171 bool init = host_impl_->InitializeRenderer(output_surface.Pass()); | |
172 host_impl_->SetViewportSize(gfx::Size(10, 10)); | |
173 return init; | |
174 } | |
175 | |
176 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) { | |
177 root->SetPosition(gfx::PointF()); | |
178 root->SetBounds(gfx::Size(10, 10)); | |
179 root->SetContentBounds(gfx::Size(10, 10)); | |
180 root->SetDrawsContent(true); | |
181 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10); | |
182 root->SetHasRenderSurface(true); | |
183 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
184 } | |
185 | |
186 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) { | |
187 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d()); | |
188 for (size_t i = 0; i < layer->children().size(); ++i) | |
189 ExpectClearedScrollDeltasRecursive(layer->children()[i]); | |
190 } | |
191 | |
192 static void ExpectContains(const ScrollAndScaleSet& scroll_info, | |
193 int id, | |
194 const gfx::Vector2d& scroll_delta) { | |
195 int times_encountered = 0; | |
196 | |
197 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) { | |
198 if (scroll_info.scrolls[i].layer_id != id) | |
199 continue; | |
200 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta); | |
201 times_encountered++; | |
202 } | |
203 | |
204 ASSERT_EQ(1, times_encountered); | |
205 } | |
206 | |
207 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) { | |
208 int times_encountered = 0; | |
209 | |
210 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) { | |
211 if (scroll_info.scrolls[i].layer_id != id) | |
212 continue; | |
213 times_encountered++; | |
214 } | |
215 | |
216 ASSERT_EQ(0, times_encountered); | |
217 } | |
218 | |
219 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl, | |
220 const gfx::Size& content_size) { | |
221 const int kInnerViewportScrollLayerId = 2; | |
222 const int kInnerViewportClipLayerId = 4; | |
223 const int kPageScaleLayerId = 5; | |
224 scoped_ptr<LayerImpl> root = | |
225 LayerImpl::Create(layer_tree_impl, 1); | |
226 root->SetBounds(content_size); | |
227 root->SetContentBounds(content_size); | |
228 root->SetPosition(gfx::PointF()); | |
229 root->SetHasRenderSurface(true); | |
230 | |
231 scoped_ptr<LayerImpl> scroll = | |
232 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId); | |
233 LayerImpl* scroll_layer = scroll.get(); | |
234 scroll->SetIsContainerForFixedPositionLayers(true); | |
235 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset()); | |
236 | |
237 scoped_ptr<LayerImpl> clip = | |
238 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId); | |
239 clip->SetBounds( | |
240 gfx::Size(content_size.width() / 2, content_size.height() / 2)); | |
241 | |
242 scoped_ptr<LayerImpl> page_scale = | |
243 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId); | |
244 | |
245 scroll->SetScrollClipLayer(clip->id()); | |
246 scroll->SetBounds(content_size); | |
247 scroll->SetContentBounds(content_size); | |
248 scroll->SetPosition(gfx::PointF()); | |
249 scroll->SetIsContainerForFixedPositionLayers(true); | |
250 | |
251 scoped_ptr<LayerImpl> contents = | |
252 LayerImpl::Create(layer_tree_impl, 3); | |
253 contents->SetDrawsContent(true); | |
254 contents->SetBounds(content_size); | |
255 contents->SetContentBounds(content_size); | |
256 contents->SetPosition(gfx::PointF()); | |
257 | |
258 scroll->AddChild(contents.Pass()); | |
259 page_scale->AddChild(scroll.Pass()); | |
260 clip->AddChild(page_scale.Pass()); | |
261 root->AddChild(clip.Pass()); | |
262 | |
263 layer_tree_impl->SetRootLayer(root.Pass()); | |
264 layer_tree_impl->SetViewportLayersFromIds( | |
265 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId, | |
266 Layer::INVALID_ID); | |
267 | |
268 return scroll_layer; | |
269 } | |
270 | |
271 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) { | |
272 LayerImpl* scroll_layer = CreateScrollAndContentsLayers( | |
273 host_impl_->active_tree(), content_size); | |
274 host_impl_->active_tree()->DidBecomeActive(); | |
275 return scroll_layer; | |
276 } | |
277 | |
278 // TODO(wjmaclean) Add clip-layer pointer to parameters. | |
279 scoped_ptr<LayerImpl> CreateScrollableLayer(int id, | |
280 const gfx::Size& size, | |
281 LayerImpl* clip_layer) { | |
282 DCHECK(clip_layer); | |
283 DCHECK(id != clip_layer->id()); | |
284 scoped_ptr<LayerImpl> layer = | |
285 LayerImpl::Create(host_impl_->active_tree(), id); | |
286 layer->SetScrollClipLayer(clip_layer->id()); | |
287 layer->SetDrawsContent(true); | |
288 layer->SetBounds(size); | |
289 layer->SetContentBounds(size); | |
290 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2)); | |
291 return layer.Pass(); | |
292 } | |
293 | |
294 void DrawFrame() { | |
295 LayerTreeHostImpl::FrameData frame; | |
296 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
297 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
298 host_impl_->DidDrawAllLayers(frame); | |
299 } | |
300 | |
301 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor); | |
302 void pinch_zoom_pan_viewport_test(float device_scale_factor); | |
303 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor); | |
304 void pinch_zoom_pan_viewport_and_scroll_boundary_test( | |
305 float device_scale_factor); | |
306 | |
307 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) { | |
308 // Note: It is not possible to disable the renderer once it has been set, | |
309 // so we do not need to test that disabling the renderer notifies us | |
310 // that can_draw changed. | |
311 EXPECT_FALSE(host_impl_->CanDraw()); | |
312 on_can_draw_state_changed_called_ = false; | |
313 | |
314 // Set up the root layer, which allows us to draw. | |
315 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
316 EXPECT_TRUE(host_impl_->CanDraw()); | |
317 EXPECT_TRUE(on_can_draw_state_changed_called_); | |
318 on_can_draw_state_changed_called_ = false; | |
319 | |
320 // Toggle the root layer to make sure it toggles can_draw | |
321 host_impl_->active_tree()->SetRootLayer(nullptr); | |
322 EXPECT_FALSE(host_impl_->CanDraw()); | |
323 EXPECT_TRUE(on_can_draw_state_changed_called_); | |
324 on_can_draw_state_changed_called_ = false; | |
325 | |
326 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
327 EXPECT_TRUE(host_impl_->CanDraw()); | |
328 EXPECT_TRUE(on_can_draw_state_changed_called_); | |
329 on_can_draw_state_changed_called_ = false; | |
330 | |
331 // Toggle the device viewport size to make sure it toggles can_draw. | |
332 host_impl_->SetViewportSize(gfx::Size()); | |
333 if (always_draw) { | |
334 EXPECT_TRUE(host_impl_->CanDraw()); | |
335 } else { | |
336 EXPECT_FALSE(host_impl_->CanDraw()); | |
337 } | |
338 EXPECT_TRUE(on_can_draw_state_changed_called_); | |
339 on_can_draw_state_changed_called_ = false; | |
340 | |
341 host_impl_->SetViewportSize(gfx::Size(100, 100)); | |
342 EXPECT_TRUE(host_impl_->CanDraw()); | |
343 EXPECT_TRUE(on_can_draw_state_changed_called_); | |
344 on_can_draw_state_changed_called_ = false; | |
345 | |
346 // Toggle contents textures purged without causing any evictions, | |
347 // and make sure that it does not change can_draw. | |
348 set_reduce_memory_result(false); | |
349 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy( | |
350 host_impl_->memory_allocation_limit_bytes() - 1)); | |
351 EXPECT_TRUE(host_impl_->CanDraw()); | |
352 EXPECT_FALSE(on_can_draw_state_changed_called_); | |
353 on_can_draw_state_changed_called_ = false; | |
354 | |
355 // Toggle contents textures purged to make sure it toggles can_draw. | |
356 set_reduce_memory_result(true); | |
357 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy( | |
358 host_impl_->memory_allocation_limit_bytes() - 1)); | |
359 if (always_draw) { | |
360 EXPECT_TRUE(host_impl_->CanDraw()); | |
361 } else { | |
362 EXPECT_FALSE(host_impl_->CanDraw()); | |
363 } | |
364 EXPECT_TRUE(on_can_draw_state_changed_called_); | |
365 on_can_draw_state_changed_called_ = false; | |
366 | |
367 host_impl_->active_tree()->ResetContentsTexturesPurged(); | |
368 EXPECT_TRUE(host_impl_->CanDraw()); | |
369 EXPECT_TRUE(on_can_draw_state_changed_called_); | |
370 on_can_draw_state_changed_called_ = false; | |
371 } | |
372 | |
373 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor); | |
374 | |
375 protected: | |
376 virtual scoped_ptr<OutputSurface> CreateOutputSurface() { | |
377 return FakeOutputSurface::Create3d(); | |
378 } | |
379 | |
380 void DrawOneFrame() { | |
381 LayerTreeHostImpl::FrameData frame_data; | |
382 host_impl_->PrepareToDraw(&frame_data); | |
383 host_impl_->DidDrawAllLayers(frame_data); | |
384 } | |
385 | |
386 FakeProxy proxy_; | |
387 DebugScopedSetImplThread always_impl_thread_; | |
388 DebugScopedSetMainThreadBlocked always_main_thread_blocked_; | |
389 | |
390 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_; | |
391 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_; | |
392 scoped_ptr<TestTaskGraphRunner> task_graph_runner_; | |
393 scoped_ptr<LayerTreeHostImpl> host_impl_; | |
394 FakeRenderingStatsInstrumentation stats_instrumentation_; | |
395 bool on_can_draw_state_changed_called_; | |
396 bool did_notify_ready_to_activate_; | |
397 bool did_request_commit_; | |
398 bool did_request_redraw_; | |
399 bool did_request_animate_; | |
400 bool did_request_prepare_tiles_; | |
401 bool did_complete_page_scale_animation_; | |
402 bool reduce_memory_result_; | |
403 base::Closure animation_task_; | |
404 base::TimeDelta requested_animation_delay_; | |
405 size_t current_limit_bytes_; | |
406 int current_priority_cutoff_value_; | |
407 }; | |
408 | |
409 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) { | |
410 bool always_draw = false; | |
411 CheckNotifyCalledIfCanDrawChanged(always_draw); | |
412 } | |
413 | |
414 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) { | |
415 CreateHostImpl(DefaultSettings(), | |
416 FakeOutputSurface::CreateAlwaysDrawAndSwap3d()); | |
417 | |
418 bool always_draw = true; | |
419 CheckNotifyCalledIfCanDrawChanged(always_draw); | |
420 } | |
421 | |
422 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) { | |
423 ASSERT_FALSE(host_impl_->active_tree()->root_layer()); | |
424 | |
425 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); | |
426 ASSERT_EQ(scroll_info->scrolls.size(), 0u); | |
427 } | |
428 | |
429 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) { | |
430 { | |
431 scoped_ptr<LayerImpl> root = | |
432 LayerImpl::Create(host_impl_->active_tree(), 1); | |
433 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2)); | |
434 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3)); | |
435 root->children()[1]->AddChild( | |
436 LayerImpl::Create(host_impl_->active_tree(), 4)); | |
437 root->children()[1]->AddChild( | |
438 LayerImpl::Create(host_impl_->active_tree(), 5)); | |
439 root->children()[1]->children()[0]->AddChild( | |
440 LayerImpl::Create(host_impl_->active_tree(), 6)); | |
441 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
442 } | |
443 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
444 | |
445 ExpectClearedScrollDeltasRecursive(root); | |
446 | |
447 scoped_ptr<ScrollAndScaleSet> scroll_info; | |
448 | |
449 scroll_info = host_impl_->ProcessScrollDeltas(); | |
450 ASSERT_EQ(scroll_info->scrolls.size(), 0u); | |
451 ExpectClearedScrollDeltasRecursive(root); | |
452 | |
453 scroll_info = host_impl_->ProcessScrollDeltas(); | |
454 ASSERT_EQ(scroll_info->scrolls.size(), 0u); | |
455 ExpectClearedScrollDeltasRecursive(root); | |
456 } | |
457 | |
458 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) { | |
459 gfx::ScrollOffset scroll_offset(20, 30); | |
460 gfx::Vector2d scroll_delta(11, -15); | |
461 { | |
462 scoped_ptr<LayerImpl> root_clip = | |
463 LayerImpl::Create(host_impl_->active_tree(), 2); | |
464 scoped_ptr<LayerImpl> root = | |
465 LayerImpl::Create(host_impl_->active_tree(), 1); | |
466 root_clip->SetBounds(gfx::Size(10, 10)); | |
467 LayerImpl* root_layer = root.get(); | |
468 root_clip->AddChild(root.Pass()); | |
469 root_layer->SetBounds(gfx::Size(110, 110)); | |
470 root_layer->SetScrollClipLayer(root_clip->id()); | |
471 root_layer->PushScrollOffsetFromMainThread(scroll_offset); | |
472 root_layer->ScrollBy(scroll_delta); | |
473 host_impl_->active_tree()->SetRootLayer(root_clip.Pass()); | |
474 } | |
475 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0]; | |
476 | |
477 scoped_ptr<ScrollAndScaleSet> scroll_info; | |
478 | |
479 scroll_info = host_impl_->ProcessScrollDeltas(); | |
480 ASSERT_EQ(scroll_info->scrolls.size(), 1u); | |
481 ExpectContains(*scroll_info, root->id(), scroll_delta); | |
482 | |
483 gfx::Vector2d scroll_delta2(-5, 27); | |
484 root->ScrollBy(scroll_delta2); | |
485 scroll_info = host_impl_->ProcessScrollDeltas(); | |
486 ASSERT_EQ(scroll_info->scrolls.size(), 1u); | |
487 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2); | |
488 | |
489 root->ScrollBy(gfx::Vector2d()); | |
490 scroll_info = host_impl_->ProcessScrollDeltas(); | |
491 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2); | |
492 } | |
493 | |
494 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) { | |
495 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
496 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
497 DrawFrame(); | |
498 | |
499 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
500 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
501 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(), | |
502 InputHandler::WHEEL)); | |
503 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); | |
504 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10), | |
505 InputHandler::WHEEL)); | |
506 host_impl_->ScrollEnd(); | |
507 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(), | |
508 InputHandler::WHEEL)); | |
509 EXPECT_TRUE(did_request_redraw_); | |
510 EXPECT_TRUE(did_request_commit_); | |
511 } | |
512 | |
513 TEST_F(LayerTreeHostImplTest, ScrollActiveOnlyAfterScrollMovement) { | |
514 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
515 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
516 DrawFrame(); | |
517 | |
518 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
519 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
520 EXPECT_FALSE(host_impl_->IsActivelyScrolling()); | |
521 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); | |
522 EXPECT_TRUE(host_impl_->IsActivelyScrolling()); | |
523 host_impl_->ScrollEnd(); | |
524 EXPECT_FALSE(host_impl_->IsActivelyScrolling()); | |
525 } | |
526 | |
527 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) { | |
528 // We should not crash when trying to scroll an empty layer tree. | |
529 EXPECT_EQ(InputHandler::SCROLL_IGNORED, | |
530 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
531 } | |
532 | |
533 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) { | |
534 scoped_ptr<TestWebGraphicsContext3D> context_owned = | |
535 TestWebGraphicsContext3D::Create(); | |
536 context_owned->set_context_lost(true); | |
537 | |
538 // Initialization will fail. | |
539 EXPECT_FALSE(CreateHostImpl( | |
540 DefaultSettings(), FakeOutputSurface::Create3d(context_owned.Pass()))); | |
541 | |
542 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
543 | |
544 // We should not crash when trying to scroll after the renderer initialization | |
545 // fails. | |
546 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
547 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
548 } | |
549 | |
550 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) { | |
551 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
552 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
553 DrawFrame(); | |
554 | |
555 // We should not crash if the tree is replaced while we are scrolling. | |
556 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
557 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
558 host_impl_->active_tree()->DetachLayerTree(); | |
559 | |
560 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
561 | |
562 // We should still be scrolling, because the scrolled layer also exists in the | |
563 // new tree. | |
564 gfx::Vector2d scroll_delta(0, 10); | |
565 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
566 host_impl_->ScrollEnd(); | |
567 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); | |
568 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta); | |
569 } | |
570 | |
571 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) { | |
572 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
573 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
574 DrawFrame(); | |
575 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
576 | |
577 // With registered event handlers, wheel scrolls don't necessarily | |
578 // have to go to the main thread. | |
579 root->SetHaveWheelEventHandlers(true); | |
580 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
581 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
582 host_impl_->ScrollEnd(); | |
583 | |
584 // But typically the scroll-blocks-on mode will require them to. | |
585 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT | | |
586 SCROLL_BLOCKS_ON_START_TOUCH); | |
587 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
588 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
589 | |
590 // But gesture scrolls can still be handled. | |
591 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
592 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
593 host_impl_->ScrollEnd(); | |
594 | |
595 // And if the handlers go away, wheel scrolls can again be processed | |
596 // on impl (despite the scroll-blocks-on mode). | |
597 root->SetHaveWheelEventHandlers(false); | |
598 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
599 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
600 host_impl_->ScrollEnd(); | |
601 } | |
602 | |
603 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) { | |
604 LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
605 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
606 DrawFrame(); | |
607 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
608 | |
609 LayerImpl* child = 0; | |
610 { | |
611 scoped_ptr<LayerImpl> child_layer = | |
612 LayerImpl::Create(host_impl_->active_tree(), 6); | |
613 child = child_layer.get(); | |
614 child_layer->SetDrawsContent(true); | |
615 child_layer->SetPosition(gfx::PointF(0, 20)); | |
616 child_layer->SetBounds(gfx::Size(50, 50)); | |
617 child_layer->SetContentBounds(gfx::Size(50, 50)); | |
618 scroll->AddChild(child_layer.Pass()); | |
619 } | |
620 | |
621 // Touch handler regions determine whether touch events block scroll. | |
622 root->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100)); | |
623 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10))); | |
624 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH | | |
625 SCROLL_BLOCKS_ON_WHEEL_EVENT); | |
626 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10))); | |
627 | |
628 // But they don't influence the actual handling of the scroll gestures. | |
629 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
630 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
631 host_impl_->ScrollEnd(); | |
632 | |
633 // It's the union of scroll-blocks-on mode bits across all layers in the | |
634 // scroll paret chain that matters. | |
635 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30))); | |
636 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE); | |
637 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30))); | |
638 child->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH); | |
639 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30))); | |
640 } | |
641 | |
642 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnScrollEventHandlers) { | |
643 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
644 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
645 DrawFrame(); | |
646 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
647 | |
648 // With registered scroll handlers, scrolls don't generally have to go | |
649 // to the main thread. | |
650 root->SetHaveScrollEventHandlers(true); | |
651 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
652 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
653 host_impl_->ScrollEnd(); | |
654 | |
655 // Even the default scroll blocks on mode doesn't require this. | |
656 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT | | |
657 SCROLL_BLOCKS_ON_START_TOUCH); | |
658 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
659 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
660 host_impl_->ScrollEnd(); | |
661 | |
662 // But the page can opt in to blocking on scroll event handlers. | |
663 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT); | |
664 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
665 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
666 | |
667 // GESTURE and WHEEL scrolls behave identically in this regard. | |
668 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
669 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
670 | |
671 // And if the handlers go away, scrolls can again be processed on impl | |
672 // (despite the scroll-blocks-on mode). | |
673 root->SetHaveScrollEventHandlers(false); | |
674 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
675 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
676 host_impl_->ScrollEnd(); | |
677 } | |
678 | |
679 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) { | |
680 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
681 | |
682 // Create a normal scrollable root layer | |
683 LayerImpl* root_scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
684 LayerImpl* root_child = root_scroll->children()[0]; | |
685 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
686 DrawFrame(); | |
687 | |
688 // Create two child scrollable layers | |
689 LayerImpl* child1 = 0; | |
690 { | |
691 scoped_ptr<LayerImpl> scrollable_child_clip_1 = | |
692 LayerImpl::Create(host_impl_->active_tree(), 6); | |
693 scoped_ptr<LayerImpl> scrollable_child_1 = CreateScrollableLayer( | |
694 7, gfx::Size(10, 10), scrollable_child_clip_1.get()); | |
695 child1 = scrollable_child_1.get(); | |
696 scrollable_child_1->SetPosition(gfx::Point(5, 5)); | |
697 scrollable_child_1->SetHaveWheelEventHandlers(true); | |
698 scrollable_child_1->SetHaveScrollEventHandlers(true); | |
699 scrollable_child_clip_1->AddChild(scrollable_child_1.Pass()); | |
700 root_child->AddChild(scrollable_child_clip_1.Pass()); | |
701 } | |
702 | |
703 LayerImpl* child2 = 0; | |
704 { | |
705 scoped_ptr<LayerImpl> scrollable_child_clip_2 = | |
706 LayerImpl::Create(host_impl_->active_tree(), 8); | |
707 scoped_ptr<LayerImpl> scrollable_child_2 = CreateScrollableLayer( | |
708 9, gfx::Size(10, 10), scrollable_child_clip_2.get()); | |
709 child2 = scrollable_child_2.get(); | |
710 scrollable_child_2->SetPosition(gfx::Point(5, 20)); | |
711 scrollable_child_2->SetHaveWheelEventHandlers(true); | |
712 scrollable_child_2->SetHaveScrollEventHandlers(true); | |
713 scrollable_child_clip_2->AddChild(scrollable_child_2.Pass()); | |
714 root_child->AddChild(scrollable_child_clip_2.Pass()); | |
715 } | |
716 | |
717 // Scroll-blocks-on on a layer affects scrolls that hit that layer. | |
718 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
719 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE)); | |
720 host_impl_->ScrollEnd(); | |
721 child1->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT); | |
722 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
723 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE)); | |
724 | |
725 // But not those that hit only other layers. | |
726 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
727 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE)); | |
728 host_impl_->ScrollEnd(); | |
729 | |
730 // It's the union of bits set across the scroll ancestor chain that matters. | |
731 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
732 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE)); | |
733 host_impl_->ScrollEnd(); | |
734 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
735 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL)); | |
736 host_impl_->ScrollEnd(); | |
737 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT); | |
738 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
739 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE)); | |
740 host_impl_->ScrollEnd(); | |
741 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
742 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL)); | |
743 child2->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT); | |
744 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
745 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL)); | |
746 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
747 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE)); | |
748 } | |
749 | |
750 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) { | |
751 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
752 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
753 DrawFrame(); | |
754 | |
755 // Ignore the fling since no layer is being scrolled | |
756 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin()); | |
757 | |
758 // Start scrolling a layer | |
759 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
760 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
761 | |
762 // Now the fling should go ahead since we've started scrolling a layer | |
763 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); | |
764 } | |
765 | |
766 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) { | |
767 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
768 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
769 DrawFrame(); | |
770 | |
771 // Ignore the fling since no layer is being scrolled | |
772 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin()); | |
773 | |
774 // Start scrolling a layer | |
775 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
776 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
777 | |
778 // Now the fling should go ahead since we've started scrolling a layer | |
779 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); | |
780 } | |
781 | |
782 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) { | |
783 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
784 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
785 DrawFrame(); | |
786 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
787 | |
788 root->SetShouldScrollOnMainThread(true); | |
789 | |
790 // Start scrolling a layer | |
791 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
792 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
793 | |
794 // The fling should be ignored since there's no layer being scrolled impl-side | |
795 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin()); | |
796 } | |
797 | |
798 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) { | |
799 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
800 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
801 DrawFrame(); | |
802 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
803 | |
804 root->SetShouldScrollOnMainThread(true); | |
805 | |
806 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
807 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
808 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
809 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
810 } | |
811 | |
812 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) { | |
813 SetupScrollAndContentsLayers(gfx::Size(200, 200)); | |
814 host_impl_->SetViewportSize(gfx::Size(100, 100)); | |
815 | |
816 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
817 root->SetContentsScale(2.f, 2.f); | |
818 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50)); | |
819 | |
820 DrawFrame(); | |
821 | |
822 // All scroll types inside the non-fast scrollable region should fail. | |
823 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
824 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL)); | |
825 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25), | |
826 InputHandler::WHEEL)); | |
827 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
828 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE)); | |
829 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25), | |
830 InputHandler::GESTURE)); | |
831 | |
832 // All scroll types outside this region should succeed. | |
833 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
834 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL)); | |
835 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75), | |
836 InputHandler::GESTURE)); | |
837 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); | |
838 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25), | |
839 InputHandler::GESTURE)); | |
840 host_impl_->ScrollEnd(); | |
841 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75), | |
842 InputHandler::GESTURE)); | |
843 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
844 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE)); | |
845 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75), | |
846 InputHandler::GESTURE)); | |
847 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); | |
848 host_impl_->ScrollEnd(); | |
849 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75), | |
850 InputHandler::GESTURE)); | |
851 } | |
852 | |
853 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) { | |
854 SetupScrollAndContentsLayers(gfx::Size(200, 200)); | |
855 host_impl_->SetViewportSize(gfx::Size(100, 100)); | |
856 | |
857 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
858 root->SetContentsScale(2.f, 2.f); | |
859 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50)); | |
860 root->SetPosition(gfx::PointF(-25.f, 0.f)); | |
861 | |
862 DrawFrame(); | |
863 | |
864 // This point would fall into the non-fast scrollable region except that we've | |
865 // moved the layer down by 25 pixels. | |
866 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
867 host_impl_->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL)); | |
868 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10), | |
869 InputHandler::WHEEL)); | |
870 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1)); | |
871 host_impl_->ScrollEnd(); | |
872 | |
873 // This point is still inside the non-fast region. | |
874 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
875 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL)); | |
876 } | |
877 | |
878 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) { | |
879 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200)); | |
880 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers()); | |
881 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
882 DrawFrame(); | |
883 | |
884 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler()); | |
885 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE); | |
886 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler()); | |
887 host_impl_->ScrollEnd(); | |
888 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler()); | |
889 } | |
890 | |
891 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) { | |
892 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200)); | |
893 scroll_layer->SetHaveScrollEventHandlers(true); | |
894 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
895 DrawFrame(); | |
896 | |
897 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler()); | |
898 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE); | |
899 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler()); | |
900 host_impl_->ScrollEnd(); | |
901 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler()); | |
902 } | |
903 | |
904 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) { | |
905 SetupScrollAndContentsLayers(gfx::Size(200, 200)); | |
906 host_impl_->SetViewportSize(gfx::Size(100, 100)); | |
907 | |
908 DrawFrame(); | |
909 | |
910 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
911 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
912 | |
913 // Trying to scroll to the left/top will not succeed. | |
914 EXPECT_FALSE( | |
915 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll); | |
916 EXPECT_FALSE( | |
917 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll); | |
918 EXPECT_FALSE( | |
919 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll); | |
920 | |
921 // Scrolling to the right/bottom will succeed. | |
922 EXPECT_TRUE( | |
923 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll); | |
924 EXPECT_TRUE( | |
925 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll); | |
926 EXPECT_TRUE( | |
927 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll); | |
928 | |
929 // Scrolling to left/top will now succeed. | |
930 EXPECT_TRUE( | |
931 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll); | |
932 EXPECT_TRUE( | |
933 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll); | |
934 EXPECT_TRUE( | |
935 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll); | |
936 | |
937 // Scrolling diagonally against an edge will succeed. | |
938 EXPECT_TRUE( | |
939 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll); | |
940 EXPECT_TRUE( | |
941 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll); | |
942 EXPECT_TRUE( | |
943 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll); | |
944 | |
945 // Trying to scroll more than the available space will also succeed. | |
946 EXPECT_TRUE( | |
947 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll); | |
948 } | |
949 | |
950 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) { | |
951 SetupScrollAndContentsLayers(gfx::Size(200, 2000)); | |
952 host_impl_->SetViewportSize(gfx::Size(100, 1000)); | |
953 | |
954 DrawFrame(); | |
955 | |
956 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
957 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
958 | |
959 // Trying to scroll without a vertical scrollbar will fail. | |
960 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage( | |
961 gfx::Point(), SCROLL_FORWARD)); | |
962 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage( | |
963 gfx::Point(), SCROLL_BACKWARD)); | |
964 | |
965 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar( | |
966 PaintedScrollbarLayerImpl::Create( | |
967 host_impl_->active_tree(), | |
968 20, | |
969 VERTICAL)); | |
970 vertical_scrollbar->SetBounds(gfx::Size(15, 1000)); | |
971 host_impl_->InnerViewportScrollLayer()->AddScrollbar( | |
972 vertical_scrollbar.get()); | |
973 | |
974 // Trying to scroll with a vertical scrollbar will succeed. | |
975 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage( | |
976 gfx::Point(), SCROLL_FORWARD)); | |
977 EXPECT_FLOAT_EQ(875.f, | |
978 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y()); | |
979 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage( | |
980 gfx::Point(), SCROLL_BACKWARD)); | |
981 } | |
982 | |
983 TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { | |
984 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200)); | |
985 host_impl_->SetViewportSize(gfx::Size(100, 100)); | |
986 | |
987 gfx::Size overflow_size(400, 400); | |
988 ASSERT_EQ(1u, scroll_layer->children().size()); | |
989 LayerImpl* overflow = scroll_layer->children()[0]; | |
990 overflow->SetBounds(overflow_size); | |
991 overflow->SetContentBounds(overflow_size); | |
992 overflow->SetScrollClipLayer(scroll_layer->parent()->id()); | |
993 overflow->PushScrollOffsetFromMainThread(gfx::ScrollOffset()); | |
994 overflow->SetPosition(gfx::PointF()); | |
995 | |
996 DrawFrame(); | |
997 gfx::Point scroll_position(10, 10); | |
998 | |
999 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
1000 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL)); | |
1001 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset()); | |
1002 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->CurrentScrollOffset()); | |
1003 | |
1004 gfx::Vector2dF scroll_delta(10, 10); | |
1005 host_impl_->ScrollBy(scroll_position, scroll_delta); | |
1006 host_impl_->ScrollEnd(); | |
1007 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset()); | |
1008 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset()); | |
1009 | |
1010 overflow->set_user_scrollable_horizontal(false); | |
1011 | |
1012 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
1013 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL)); | |
1014 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset()); | |
1015 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset()); | |
1016 | |
1017 host_impl_->ScrollBy(scroll_position, scroll_delta); | |
1018 host_impl_->ScrollEnd(); | |
1019 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset()); | |
1020 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset()); | |
1021 | |
1022 overflow->set_user_scrollable_vertical(false); | |
1023 | |
1024 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
1025 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL)); | |
1026 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset()); | |
1027 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset()); | |
1028 | |
1029 host_impl_->ScrollBy(scroll_position, scroll_delta); | |
1030 host_impl_->ScrollEnd(); | |
1031 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->CurrentScrollOffset()); | |
1032 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset()); | |
1033 } | |
1034 | |
1035 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) { | |
1036 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
1037 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
1038 DrawFrame(); | |
1039 | |
1040 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer()); | |
1041 LayerImpl* container_layer = scroll_layer->scroll_clip_layer(); | |
1042 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds()); | |
1043 | |
1044 float min_page_scale = 1.f, max_page_scale = 4.f; | |
1045 float page_scale_factor = 1.f; | |
1046 | |
1047 // The impl-based pinch zoom should adjust the max scroll position. | |
1048 { | |
1049 host_impl_->active_tree()->PushPageScaleFromMainThread( | |
1050 page_scale_factor, min_page_scale, max_page_scale); | |
1051 host_impl_->SetPageScaleOnActiveTree(page_scale_factor); | |
1052 scroll_layer->SetScrollDelta(gfx::Vector2d()); | |
1053 | |
1054 float page_scale_delta = 2.f; | |
1055 | |
1056 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE); | |
1057 host_impl_->PinchGestureBegin(); | |
1058 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50)); | |
1059 host_impl_->PinchGestureEnd(); | |
1060 host_impl_->ScrollEnd(); | |
1061 EXPECT_FALSE(did_request_animate_); | |
1062 EXPECT_TRUE(did_request_redraw_); | |
1063 EXPECT_TRUE(did_request_commit_); | |
1064 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds()); | |
1065 | |
1066 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1067 host_impl_->ProcessScrollDeltas(); | |
1068 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta); | |
1069 | |
1070 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(), | |
1071 scroll_layer->MaxScrollOffset().ToString()); | |
1072 } | |
1073 | |
1074 // Scrolling after a pinch gesture should always be in local space. The | |
1075 // scroll deltas have the page scale factor applied. | |
1076 { | |
1077 host_impl_->active_tree()->PushPageScaleFromMainThread( | |
1078 page_scale_factor, min_page_scale, max_page_scale); | |
1079 host_impl_->SetPageScaleOnActiveTree(page_scale_factor); | |
1080 scroll_layer->SetScrollDelta(gfx::Vector2d()); | |
1081 | |
1082 float page_scale_delta = 2.f; | |
1083 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE); | |
1084 host_impl_->PinchGestureBegin(); | |
1085 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point()); | |
1086 host_impl_->PinchGestureEnd(); | |
1087 host_impl_->ScrollEnd(); | |
1088 | |
1089 gfx::Vector2d scroll_delta(0, 10); | |
1090 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
1091 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL)); | |
1092 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
1093 host_impl_->ScrollEnd(); | |
1094 | |
1095 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1096 host_impl_->ProcessScrollDeltas(); | |
1097 ExpectContains(*scroll_info.get(), scroll_layer->id(), | |
1098 gfx::Vector2d(0, scroll_delta.y() / page_scale_delta)); | |
1099 } | |
1100 } | |
1101 | |
1102 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) { | |
1103 ui::LatencyInfo latency_info; | |
1104 latency_info.trace_id = 1234; | |
1105 scoped_ptr<SwapPromise> swap_promise( | |
1106 new LatencyInfoSwapPromise(latency_info)); | |
1107 | |
1108 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
1109 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
1110 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
1111 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); | |
1112 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass()); | |
1113 host_impl_->ScrollEnd(); | |
1114 | |
1115 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); | |
1116 EXPECT_EQ(1u, scroll_info->swap_promises.size()); | |
1117 EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId()); | |
1118 } | |
1119 | |
1120 TEST_F(LayerTreeHostImplTest, PinchGesture) { | |
1121 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
1122 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
1123 DrawFrame(); | |
1124 | |
1125 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer(); | |
1126 DCHECK(scroll_layer); | |
1127 | |
1128 float min_page_scale = 1.f; | |
1129 float max_page_scale = 4.f; | |
1130 | |
1131 // Basic pinch zoom in gesture | |
1132 { | |
1133 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, | |
1134 max_page_scale); | |
1135 scroll_layer->SetScrollDelta(gfx::Vector2d()); | |
1136 | |
1137 float page_scale_delta = 2.f; | |
1138 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE); | |
1139 host_impl_->PinchGestureBegin(); | |
1140 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50)); | |
1141 host_impl_->PinchGestureEnd(); | |
1142 host_impl_->ScrollEnd(); | |
1143 EXPECT_FALSE(did_request_animate_); | |
1144 EXPECT_TRUE(did_request_redraw_); | |
1145 EXPECT_TRUE(did_request_commit_); | |
1146 | |
1147 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1148 host_impl_->ProcessScrollDeltas(); | |
1149 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta); | |
1150 } | |
1151 | |
1152 // Zoom-in clamping | |
1153 { | |
1154 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, | |
1155 max_page_scale); | |
1156 scroll_layer->SetScrollDelta(gfx::Vector2d()); | |
1157 float page_scale_delta = 10.f; | |
1158 | |
1159 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE); | |
1160 host_impl_->PinchGestureBegin(); | |
1161 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50)); | |
1162 host_impl_->PinchGestureEnd(); | |
1163 host_impl_->ScrollEnd(); | |
1164 | |
1165 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1166 host_impl_->ProcessScrollDeltas(); | |
1167 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale); | |
1168 } | |
1169 | |
1170 // Zoom-out clamping | |
1171 { | |
1172 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, | |
1173 max_page_scale); | |
1174 scroll_layer->SetScrollDelta(gfx::Vector2d()); | |
1175 scroll_layer->PullDeltaForMainThread(); | |
1176 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50)); | |
1177 | |
1178 float page_scale_delta = 0.1f; | |
1179 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE); | |
1180 host_impl_->PinchGestureBegin(); | |
1181 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point()); | |
1182 host_impl_->PinchGestureEnd(); | |
1183 host_impl_->ScrollEnd(); | |
1184 | |
1185 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1186 host_impl_->ProcessScrollDeltas(); | |
1187 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale); | |
1188 | |
1189 EXPECT_TRUE(scroll_info->scrolls.empty()); | |
1190 } | |
1191 | |
1192 // Two-finger panning should not happen based on pinch events only | |
1193 { | |
1194 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, | |
1195 max_page_scale); | |
1196 scroll_layer->SetScrollDelta(gfx::Vector2d()); | |
1197 scroll_layer->PullDeltaForMainThread(); | |
1198 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20)); | |
1199 | |
1200 float page_scale_delta = 1.f; | |
1201 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE); | |
1202 host_impl_->PinchGestureBegin(); | |
1203 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10)); | |
1204 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20)); | |
1205 host_impl_->PinchGestureEnd(); | |
1206 host_impl_->ScrollEnd(); | |
1207 | |
1208 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1209 host_impl_->ProcessScrollDeltas(); | |
1210 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta); | |
1211 EXPECT_TRUE(scroll_info->scrolls.empty()); | |
1212 } | |
1213 | |
1214 // Two-finger panning should work with interleaved scroll events | |
1215 { | |
1216 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, | |
1217 max_page_scale); | |
1218 scroll_layer->SetScrollDelta(gfx::Vector2d()); | |
1219 scroll_layer->PullDeltaForMainThread(); | |
1220 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20)); | |
1221 | |
1222 float page_scale_delta = 1.f; | |
1223 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE); | |
1224 host_impl_->PinchGestureBegin(); | |
1225 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10)); | |
1226 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10)); | |
1227 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20)); | |
1228 host_impl_->PinchGestureEnd(); | |
1229 host_impl_->ScrollEnd(); | |
1230 | |
1231 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1232 host_impl_->ProcessScrollDeltas(); | |
1233 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta); | |
1234 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10)); | |
1235 } | |
1236 | |
1237 // Two-finger panning should work when starting fully zoomed out. | |
1238 { | |
1239 host_impl_->active_tree()->PushPageScaleFromMainThread(0.5f, 0.5f, 4.f); | |
1240 scroll_layer->SetScrollDelta(gfx::Vector2d()); | |
1241 scroll_layer->PullDeltaForMainThread(); | |
1242 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0)); | |
1243 | |
1244 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE); | |
1245 host_impl_->PinchGestureBegin(); | |
1246 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0)); | |
1247 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0)); | |
1248 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10)); | |
1249 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10)); | |
1250 host_impl_->PinchGestureEnd(); | |
1251 host_impl_->ScrollEnd(); | |
1252 | |
1253 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1254 host_impl_->ProcessScrollDeltas(); | |
1255 EXPECT_EQ(scroll_info->page_scale_delta, 2.f); | |
1256 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20)); | |
1257 } | |
1258 } | |
1259 | |
1260 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) { | |
1261 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
1262 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
1263 DrawFrame(); | |
1264 | |
1265 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer(); | |
1266 DCHECK(scroll_layer); | |
1267 | |
1268 float min_page_scale = 0.5f; | |
1269 float max_page_scale = 4.f; | |
1270 base::TimeTicks start_time = base::TimeTicks() + | |
1271 base::TimeDelta::FromSeconds(1); | |
1272 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100); | |
1273 base::TimeTicks halfway_through_animation = start_time + duration / 2; | |
1274 base::TimeTicks end_time = start_time + duration; | |
1275 | |
1276 // Non-anchor zoom-in | |
1277 { | |
1278 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, | |
1279 max_page_scale); | |
1280 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50)); | |
1281 | |
1282 did_request_redraw_ = false; | |
1283 did_request_animate_ = false; | |
1284 host_impl_->active_tree()->SetPendingPageScaleAnimation( | |
1285 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation( | |
1286 gfx::Vector2d(), | |
1287 false, | |
1288 2.f, | |
1289 duration))); | |
1290 host_impl_->ActivateSyncTree(); | |
1291 EXPECT_FALSE(did_request_redraw_); | |
1292 EXPECT_TRUE(did_request_animate_); | |
1293 | |
1294 did_request_redraw_ = false; | |
1295 did_request_animate_ = false; | |
1296 host_impl_->Animate(start_time); | |
1297 EXPECT_TRUE(did_request_redraw_); | |
1298 EXPECT_TRUE(did_request_animate_); | |
1299 | |
1300 did_request_redraw_ = false; | |
1301 did_request_animate_ = false; | |
1302 host_impl_->Animate(halfway_through_animation); | |
1303 EXPECT_TRUE(did_request_redraw_); | |
1304 EXPECT_TRUE(did_request_animate_); | |
1305 | |
1306 did_request_redraw_ = false; | |
1307 did_request_animate_ = false; | |
1308 did_request_commit_ = false; | |
1309 host_impl_->Animate(end_time); | |
1310 EXPECT_TRUE(did_request_commit_); | |
1311 EXPECT_FALSE(did_request_animate_); | |
1312 | |
1313 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1314 host_impl_->ProcessScrollDeltas(); | |
1315 EXPECT_EQ(scroll_info->page_scale_delta, 2); | |
1316 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50)); | |
1317 } | |
1318 | |
1319 // Anchor zoom-out | |
1320 { | |
1321 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, | |
1322 max_page_scale); | |
1323 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50)); | |
1324 | |
1325 did_request_redraw_ = false; | |
1326 did_request_animate_ = false; | |
1327 host_impl_->active_tree()->SetPendingPageScaleAnimation( | |
1328 scoped_ptr<PendingPageScaleAnimation> (new PendingPageScaleAnimation( | |
1329 gfx::Vector2d(25, 25), | |
1330 true, | |
1331 min_page_scale, | |
1332 duration))); | |
1333 host_impl_->ActivateSyncTree(); | |
1334 EXPECT_FALSE(did_request_redraw_); | |
1335 EXPECT_TRUE(did_request_animate_); | |
1336 | |
1337 did_request_redraw_ = false; | |
1338 did_request_animate_ = false; | |
1339 host_impl_->Animate(start_time); | |
1340 EXPECT_TRUE(did_request_redraw_); | |
1341 EXPECT_TRUE(did_request_animate_); | |
1342 | |
1343 did_request_redraw_ = false; | |
1344 did_request_commit_ = false; | |
1345 did_request_animate_ = false; | |
1346 host_impl_->Animate(end_time); | |
1347 EXPECT_TRUE(did_request_redraw_); | |
1348 EXPECT_FALSE(did_request_animate_); | |
1349 EXPECT_TRUE(did_request_commit_); | |
1350 | |
1351 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1352 host_impl_->ProcessScrollDeltas(); | |
1353 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale); | |
1354 // Pushed to (0,0) via clamping against contents layer size. | |
1355 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50)); | |
1356 } | |
1357 } | |
1358 | |
1359 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) { | |
1360 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
1361 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
1362 DrawFrame(); | |
1363 | |
1364 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer(); | |
1365 DCHECK(scroll_layer); | |
1366 | |
1367 float min_page_scale = 0.5f; | |
1368 float max_page_scale = 4.f; | |
1369 base::TimeTicks start_time = base::TimeTicks() + | |
1370 base::TimeDelta::FromSeconds(1); | |
1371 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100); | |
1372 base::TimeTicks halfway_through_animation = start_time + duration / 2; | |
1373 base::TimeTicks end_time = start_time + duration; | |
1374 | |
1375 // Anchor zoom with unchanged page scale should not change scroll or scale. | |
1376 { | |
1377 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, | |
1378 max_page_scale); | |
1379 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50)); | |
1380 | |
1381 host_impl_->active_tree()->SetPendingPageScaleAnimation( | |
1382 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation( | |
1383 gfx::Vector2d(), | |
1384 true, | |
1385 1.f, | |
1386 duration))); | |
1387 host_impl_->ActivateSyncTree(); | |
1388 host_impl_->Animate(start_time); | |
1389 host_impl_->Animate(halfway_through_animation); | |
1390 EXPECT_TRUE(did_request_redraw_); | |
1391 host_impl_->Animate(end_time); | |
1392 EXPECT_TRUE(did_request_commit_); | |
1393 | |
1394 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1395 host_impl_->ProcessScrollDeltas(); | |
1396 EXPECT_EQ(scroll_info->page_scale_delta, 1); | |
1397 ExpectNone(*scroll_info, scroll_layer->id()); | |
1398 } | |
1399 } | |
1400 | |
1401 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) { | |
1402 host_impl_->CreatePendingTree(); | |
1403 CreateScrollAndContentsLayers( | |
1404 host_impl_->pending_tree(), | |
1405 gfx::Size(100, 100)); | |
1406 host_impl_->ActivateSyncTree(); | |
1407 DrawFrame(); | |
1408 | |
1409 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer(); | |
1410 DCHECK(scroll_layer); | |
1411 | |
1412 float min_page_scale = 0.5f; | |
1413 float max_page_scale = 4.f; | |
1414 host_impl_->sync_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, | |
1415 max_page_scale); | |
1416 host_impl_->ActivateSyncTree(); | |
1417 | |
1418 base::TimeTicks start_time = base::TimeTicks() + | |
1419 base::TimeDelta::FromSeconds(1); | |
1420 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100); | |
1421 base::TimeTicks third_through_animation = start_time + duration / 3; | |
1422 base::TimeTicks halfway_through_animation = start_time + duration / 2; | |
1423 base::TimeTicks end_time = start_time + duration; | |
1424 float target_scale = 2.f; | |
1425 | |
1426 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50)); | |
1427 | |
1428 // Make sure TakePageScaleAnimation works properly. | |
1429 | |
1430 host_impl_->sync_tree()->SetPendingPageScaleAnimation( | |
1431 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation( | |
1432 gfx::Vector2d(), | |
1433 false, | |
1434 target_scale, | |
1435 duration))); | |
1436 scoped_ptr<PendingPageScaleAnimation> psa = | |
1437 host_impl_->sync_tree()->TakePendingPageScaleAnimation(); | |
1438 EXPECT_EQ(target_scale, psa->scale); | |
1439 EXPECT_EQ(duration, psa->duration); | |
1440 EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePendingPageScaleAnimation()); | |
1441 | |
1442 // Recreate the PSA. Nothing should happen here since the tree containing the | |
1443 // PSA hasn't been activated yet. | |
1444 did_request_redraw_ = false; | |
1445 did_request_animate_ = false; | |
1446 host_impl_->sync_tree()->SetPendingPageScaleAnimation( | |
1447 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation( | |
1448 gfx::Vector2d(), | |
1449 false, | |
1450 target_scale, | |
1451 duration))); | |
1452 host_impl_->Animate(halfway_through_animation); | |
1453 EXPECT_FALSE(did_request_animate_); | |
1454 EXPECT_FALSE(did_request_redraw_); | |
1455 | |
1456 // Activate the sync tree. This should cause the animation to become enabled. | |
1457 // It should also clear the pointer on the sync tree. | |
1458 host_impl_->ActivateSyncTree(); | |
1459 EXPECT_EQ(nullptr, | |
1460 host_impl_->sync_tree()->TakePendingPageScaleAnimation().get()); | |
1461 EXPECT_FALSE(did_request_redraw_); | |
1462 EXPECT_TRUE(did_request_animate_); | |
1463 | |
1464 // From here on, make sure the animation runs as normal. | |
1465 did_request_redraw_ = false; | |
1466 did_request_animate_ = false; | |
1467 host_impl_->Animate(start_time); | |
1468 EXPECT_TRUE(did_request_redraw_); | |
1469 EXPECT_TRUE(did_request_animate_); | |
1470 | |
1471 did_request_redraw_ = false; | |
1472 did_request_animate_ = false; | |
1473 host_impl_->Animate(third_through_animation); | |
1474 EXPECT_TRUE(did_request_redraw_); | |
1475 EXPECT_TRUE(did_request_animate_); | |
1476 | |
1477 // Another activation shouldn't have any effect on the animation. | |
1478 host_impl_->ActivateSyncTree(); | |
1479 | |
1480 did_request_redraw_ = false; | |
1481 did_request_animate_ = false; | |
1482 host_impl_->Animate(halfway_through_animation); | |
1483 EXPECT_TRUE(did_request_redraw_); | |
1484 EXPECT_TRUE(did_request_animate_); | |
1485 | |
1486 did_request_redraw_ = false; | |
1487 did_request_animate_ = false; | |
1488 did_request_commit_ = false; | |
1489 host_impl_->Animate(end_time); | |
1490 EXPECT_TRUE(did_request_commit_); | |
1491 EXPECT_FALSE(did_request_animate_); | |
1492 | |
1493 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
1494 host_impl_->ProcessScrollDeltas(); | |
1495 EXPECT_EQ(scroll_info->page_scale_delta, target_scale); | |
1496 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50)); | |
1497 } | |
1498 | |
1499 TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) { | |
1500 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
1501 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
1502 DrawFrame(); | |
1503 | |
1504 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer(); | |
1505 DCHECK(scroll_layer); | |
1506 | |
1507 base::TimeTicks start_time = | |
1508 base::TimeTicks() + base::TimeDelta::FromSeconds(1); | |
1509 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100); | |
1510 base::TimeTicks halfway_through_animation = start_time + duration / 2; | |
1511 base::TimeTicks end_time = start_time + duration; | |
1512 | |
1513 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f); | |
1514 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50)); | |
1515 | |
1516 did_complete_page_scale_animation_ = false; | |
1517 host_impl_->active_tree()->SetPendingPageScaleAnimation( | |
1518 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation( | |
1519 gfx::Vector2d(), false, 2.f, duration))); | |
1520 host_impl_->ActivateSyncTree(); | |
1521 host_impl_->Animate(start_time); | |
1522 EXPECT_FALSE(did_complete_page_scale_animation_); | |
1523 | |
1524 host_impl_->Animate(halfway_through_animation); | |
1525 EXPECT_FALSE(did_complete_page_scale_animation_); | |
1526 | |
1527 host_impl_->Animate(end_time); | |
1528 EXPECT_TRUE(did_complete_page_scale_animation_); | |
1529 } | |
1530 | |
1531 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl { | |
1532 public: | |
1533 LayerTreeHostImplOverridePhysicalTime( | |
1534 const LayerTreeSettings& settings, | |
1535 LayerTreeHostImplClient* client, | |
1536 Proxy* proxy, | |
1537 SharedBitmapManager* manager, | |
1538 RenderingStatsInstrumentation* rendering_stats_instrumentation) | |
1539 : LayerTreeHostImpl(settings, | |
1540 client, | |
1541 proxy, | |
1542 rendering_stats_instrumentation, | |
1543 manager, | |
1544 NULL, | |
1545 NULL, | |
1546 0) {} | |
1547 | |
1548 BeginFrameArgs CurrentBeginFrameArgs() const override { | |
1549 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, | |
1550 fake_current_physical_time_); | |
1551 } | |
1552 | |
1553 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) { | |
1554 fake_current_physical_time_ = fake_now; | |
1555 } | |
1556 | |
1557 private: | |
1558 base::TimeTicks fake_current_physical_time_; | |
1559 }; | |
1560 | |
1561 class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { | |
1562 protected: | |
1563 void SetupLayers(LayerTreeSettings settings) { | |
1564 gfx::Size viewport_size(10, 10); | |
1565 gfx::Size content_size(100, 100); | |
1566 | |
1567 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = | |
1568 new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_, | |
1569 shared_bitmap_manager_.get(), | |
1570 &stats_instrumentation_); | |
1571 host_impl_ = make_scoped_ptr(host_impl_override_time); | |
1572 host_impl_->InitializeRenderer(CreateOutputSurface()); | |
1573 host_impl_->SetViewportSize(viewport_size); | |
1574 | |
1575 scoped_ptr<LayerImpl> root = | |
1576 LayerImpl::Create(host_impl_->active_tree(), 1); | |
1577 root->SetBounds(viewport_size); | |
1578 | |
1579 scoped_ptr<LayerImpl> scroll = | |
1580 LayerImpl::Create(host_impl_->active_tree(), 2); | |
1581 scroll->SetScrollClipLayer(root->id()); | |
1582 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset()); | |
1583 root->SetBounds(viewport_size); | |
1584 scroll->SetBounds(content_size); | |
1585 scroll->SetContentBounds(content_size); | |
1586 scroll->SetIsContainerForFixedPositionLayers(true); | |
1587 | |
1588 scoped_ptr<LayerImpl> contents = | |
1589 LayerImpl::Create(host_impl_->active_tree(), 3); | |
1590 contents->SetDrawsContent(true); | |
1591 contents->SetBounds(content_size); | |
1592 contents->SetContentBounds(content_size); | |
1593 | |
1594 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = | |
1595 SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4, | |
1596 VERTICAL, 10, 0, false, true); | |
1597 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); | |
1598 | |
1599 scroll->AddChild(contents.Pass()); | |
1600 root->AddChild(scroll.Pass()); | |
1601 root->SetHasRenderSurface(true); | |
1602 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1); | |
1603 root->AddChild(scrollbar.Pass()); | |
1604 | |
1605 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
1606 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2, | |
1607 Layer::INVALID_ID); | |
1608 host_impl_->active_tree()->DidBecomeActive(); | |
1609 DrawFrame(); | |
1610 } | |
1611 | |
1612 void RunTest(LayerTreeSettings::ScrollbarAnimator animator) { | |
1613 LayerTreeSettings settings; | |
1614 settings.scrollbar_animator = animator; | |
1615 settings.scrollbar_fade_delay_ms = 20; | |
1616 settings.scrollbar_fade_duration_ms = 20; | |
1617 | |
1618 SetupLayers(settings); | |
1619 | |
1620 base::TimeTicks fake_now = gfx::FrameTime::Now(); | |
1621 | |
1622 EXPECT_FALSE(did_request_animate_); | |
1623 EXPECT_FALSE(did_request_redraw_); | |
1624 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); | |
1625 EXPECT_TRUE(animation_task_.Equals(base::Closure())); | |
1626 | |
1627 // If no scroll happened during a scroll gesture, it should have no effect. | |
1628 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); | |
1629 host_impl_->ScrollEnd(); | |
1630 EXPECT_FALSE(did_request_animate_); | |
1631 EXPECT_FALSE(did_request_redraw_); | |
1632 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); | |
1633 EXPECT_TRUE(animation_task_.Equals(base::Closure())); | |
1634 | |
1635 // After a scroll, a scrollbar animation should be scheduled about 20ms from | |
1636 // now. | |
1637 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); | |
1638 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5)); | |
1639 EXPECT_FALSE(did_request_animate_); | |
1640 EXPECT_TRUE(did_request_redraw_); | |
1641 did_request_redraw_ = false; | |
1642 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); | |
1643 EXPECT_TRUE(animation_task_.Equals(base::Closure())); | |
1644 | |
1645 host_impl_->ScrollEnd(); | |
1646 EXPECT_FALSE(did_request_animate_); | |
1647 EXPECT_FALSE(did_request_redraw_); | |
1648 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), | |
1649 requested_animation_delay_); | |
1650 EXPECT_FALSE(animation_task_.Equals(base::Closure())); | |
1651 | |
1652 fake_now += requested_animation_delay_; | |
1653 requested_animation_delay_ = base::TimeDelta(); | |
1654 animation_task_.Run(); | |
1655 animation_task_ = base::Closure(); | |
1656 EXPECT_TRUE(did_request_animate_); | |
1657 did_request_animate_ = false; | |
1658 EXPECT_FALSE(did_request_redraw_); | |
1659 | |
1660 // After the scrollbar animation begins, we should start getting redraws. | |
1661 host_impl_->Animate(fake_now); | |
1662 EXPECT_TRUE(did_request_animate_); | |
1663 did_request_animate_ = false; | |
1664 EXPECT_TRUE(did_request_redraw_); | |
1665 did_request_redraw_ = false; | |
1666 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); | |
1667 EXPECT_TRUE(animation_task_.Equals(base::Closure())); | |
1668 | |
1669 // Setting the scroll offset outside a scroll should also cause the | |
1670 // scrollbar to appear and to schedule a scrollbar animation. | |
1671 host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread( | |
1672 gfx::ScrollOffset(5, 5)); | |
1673 EXPECT_FALSE(did_request_animate_); | |
1674 EXPECT_FALSE(did_request_redraw_); | |
1675 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), | |
1676 requested_animation_delay_); | |
1677 EXPECT_FALSE(animation_task_.Equals(base::Closure())); | |
1678 requested_animation_delay_ = base::TimeDelta(); | |
1679 animation_task_ = base::Closure(); | |
1680 | |
1681 // Scrollbar animation is not triggered unnecessarily. | |
1682 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); | |
1683 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0)); | |
1684 EXPECT_FALSE(did_request_animate_); | |
1685 EXPECT_TRUE(did_request_redraw_); | |
1686 did_request_redraw_ = false; | |
1687 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); | |
1688 EXPECT_TRUE(animation_task_.Equals(base::Closure())); | |
1689 | |
1690 host_impl_->ScrollEnd(); | |
1691 EXPECT_FALSE(did_request_animate_); | |
1692 EXPECT_FALSE(did_request_redraw_); | |
1693 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); | |
1694 EXPECT_TRUE(animation_task_.Equals(base::Closure())); | |
1695 | |
1696 // Changing page scale triggers scrollbar animation. | |
1697 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f); | |
1698 host_impl_->SetPageScaleOnActiveTree(1.1f); | |
1699 EXPECT_FALSE(did_request_animate_); | |
1700 EXPECT_FALSE(did_request_redraw_); | |
1701 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), | |
1702 requested_animation_delay_); | |
1703 EXPECT_FALSE(animation_task_.Equals(base::Closure())); | |
1704 requested_animation_delay_ = base::TimeDelta(); | |
1705 animation_task_ = base::Closure(); | |
1706 } | |
1707 }; | |
1708 | |
1709 TEST_F(LayerTreeHostImplTestScrollbarAnimation, LinearFade) { | |
1710 RunTest(LayerTreeSettings::LINEAR_FADE); | |
1711 } | |
1712 | |
1713 TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) { | |
1714 RunTest(LayerTreeSettings::THINNING); | |
1715 } | |
1716 | |
1717 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale( | |
1718 float device_scale_factor) { | |
1719 LayerTreeSettings settings; | |
1720 settings.scrollbar_fade_delay_ms = 500; | |
1721 settings.scrollbar_fade_duration_ms = 300; | |
1722 settings.scrollbar_animator = LayerTreeSettings::THINNING; | |
1723 | |
1724 gfx::Size viewport_size(300, 200); | |
1725 gfx::Size device_viewport_size = gfx::ToFlooredSize( | |
1726 gfx::ScaleSize(viewport_size, device_scale_factor)); | |
1727 gfx::Size content_size(1000, 1000); | |
1728 | |
1729 CreateHostImpl(settings, CreateOutputSurface()); | |
1730 host_impl_->SetDeviceScaleFactor(device_scale_factor); | |
1731 host_impl_->SetViewportSize(device_viewport_size); | |
1732 | |
1733 scoped_ptr<LayerImpl> root = | |
1734 LayerImpl::Create(host_impl_->active_tree(), 1); | |
1735 root->SetBounds(viewport_size); | |
1736 root->SetHasRenderSurface(true); | |
1737 | |
1738 scoped_ptr<LayerImpl> scroll = | |
1739 LayerImpl::Create(host_impl_->active_tree(), 2); | |
1740 scroll->SetScrollClipLayer(root->id()); | |
1741 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset()); | |
1742 scroll->SetBounds(content_size); | |
1743 scroll->SetContentBounds(content_size); | |
1744 scroll->SetIsContainerForFixedPositionLayers(true); | |
1745 | |
1746 scoped_ptr<LayerImpl> contents = | |
1747 LayerImpl::Create(host_impl_->active_tree(), 3); | |
1748 contents->SetDrawsContent(true); | |
1749 contents->SetBounds(content_size); | |
1750 contents->SetContentBounds(content_size); | |
1751 | |
1752 // The scrollbar is on the right side. | |
1753 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar = | |
1754 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL); | |
1755 scrollbar->SetDrawsContent(true); | |
1756 scrollbar->SetBounds(gfx::Size(15, viewport_size.height())); | |
1757 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height())); | |
1758 scrollbar->SetPosition(gfx::Point(285, 0)); | |
1759 | |
1760 scroll->AddChild(contents.Pass()); | |
1761 root->AddChild(scroll.Pass()); | |
1762 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1); | |
1763 root->AddChild(scrollbar.Pass()); | |
1764 | |
1765 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
1766 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2, | |
1767 Layer::INVALID_ID); | |
1768 host_impl_->active_tree()->DidBecomeActive(); | |
1769 DrawFrame(); | |
1770 | |
1771 LayerImpl* root_scroll = | |
1772 host_impl_->active_tree()->InnerViewportScrollLayer(); | |
1773 ASSERT_TRUE(root_scroll->scrollbar_animation_controller()); | |
1774 ScrollbarAnimationControllerThinning* scrollbar_animation_controller = | |
1775 static_cast<ScrollbarAnimationControllerThinning*>( | |
1776 root_scroll->scrollbar_animation_controller()); | |
1777 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f); | |
1778 | |
1779 host_impl_->MouseMoveAt(gfx::Point(1, 1)); | |
1780 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar()); | |
1781 | |
1782 host_impl_->MouseMoveAt(gfx::Point(200, 50)); | |
1783 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar()); | |
1784 | |
1785 host_impl_->MouseMoveAt(gfx::Point(184, 100)); | |
1786 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar()); | |
1787 | |
1788 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f); | |
1789 host_impl_->MouseMoveAt(gfx::Point(184, 100)); | |
1790 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar()); | |
1791 | |
1792 did_request_redraw_ = false; | |
1793 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar()); | |
1794 host_impl_->MouseMoveAt(gfx::Point(290, 100)); | |
1795 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar()); | |
1796 host_impl_->MouseMoveAt(gfx::Point(290, 120)); | |
1797 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar()); | |
1798 host_impl_->MouseMoveAt(gfx::Point(150, 120)); | |
1799 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar()); | |
1800 } | |
1801 | |
1802 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) { | |
1803 SetupMouseMoveAtWithDeviceScale(1.f); | |
1804 } | |
1805 | |
1806 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) { | |
1807 SetupMouseMoveAtWithDeviceScale(2.f); | |
1808 } | |
1809 | |
1810 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) { | |
1811 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
1812 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
1813 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f); | |
1814 DrawFrame(); | |
1815 { | |
1816 CompositorFrameMetadata metadata = | |
1817 host_impl_->MakeCompositorFrameMetadata(); | |
1818 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset); | |
1819 EXPECT_EQ(1.f, metadata.page_scale_factor); | |
1820 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size); | |
1821 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size); | |
1822 EXPECT_EQ(0.5f, metadata.min_page_scale_factor); | |
1823 EXPECT_EQ(4.f, metadata.max_page_scale_factor); | |
1824 EXPECT_FALSE(metadata.root_overflow_x_hidden); | |
1825 EXPECT_FALSE(metadata.root_overflow_y_hidden); | |
1826 } | |
1827 | |
1828 // Scrolling should update metadata immediately. | |
1829 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
1830 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
1831 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); | |
1832 { | |
1833 CompositorFrameMetadata metadata = | |
1834 host_impl_->MakeCompositorFrameMetadata(); | |
1835 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset); | |
1836 } | |
1837 host_impl_->ScrollEnd(); | |
1838 { | |
1839 CompositorFrameMetadata metadata = | |
1840 host_impl_->MakeCompositorFrameMetadata(); | |
1841 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset); | |
1842 } | |
1843 | |
1844 // Root "overflow: hidden" properties should be reflected. | |
1845 { | |
1846 host_impl_->active_tree() | |
1847 ->InnerViewportScrollLayer() | |
1848 ->set_user_scrollable_horizontal(false); | |
1849 CompositorFrameMetadata metadata = | |
1850 host_impl_->MakeCompositorFrameMetadata(); | |
1851 EXPECT_TRUE(metadata.root_overflow_x_hidden); | |
1852 EXPECT_FALSE(metadata.root_overflow_y_hidden); | |
1853 | |
1854 host_impl_->active_tree() | |
1855 ->InnerViewportScrollLayer() | |
1856 ->set_user_scrollable_vertical(false); | |
1857 metadata = host_impl_->MakeCompositorFrameMetadata(); | |
1858 EXPECT_TRUE(metadata.root_overflow_x_hidden); | |
1859 EXPECT_TRUE(metadata.root_overflow_y_hidden); | |
1860 } | |
1861 | |
1862 // Page scale should update metadata correctly (shrinking only the viewport). | |
1863 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE); | |
1864 host_impl_->PinchGestureBegin(); | |
1865 host_impl_->PinchGestureUpdate(2.f, gfx::Point()); | |
1866 host_impl_->PinchGestureEnd(); | |
1867 host_impl_->ScrollEnd(); | |
1868 { | |
1869 CompositorFrameMetadata metadata = | |
1870 host_impl_->MakeCompositorFrameMetadata(); | |
1871 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset); | |
1872 EXPECT_EQ(2.f, metadata.page_scale_factor); | |
1873 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size); | |
1874 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size); | |
1875 EXPECT_EQ(0.5f, metadata.min_page_scale_factor); | |
1876 EXPECT_EQ(4.f, metadata.max_page_scale_factor); | |
1877 } | |
1878 | |
1879 // Likewise if set from the main thread. | |
1880 host_impl_->ProcessScrollDeltas(); | |
1881 host_impl_->active_tree()->PushPageScaleFromMainThread(4.f, 0.5f, 4.f); | |
1882 host_impl_->SetPageScaleOnActiveTree(4.f); | |
1883 { | |
1884 CompositorFrameMetadata metadata = | |
1885 host_impl_->MakeCompositorFrameMetadata(); | |
1886 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset); | |
1887 EXPECT_EQ(4.f, metadata.page_scale_factor); | |
1888 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size); | |
1889 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size); | |
1890 EXPECT_EQ(0.5f, metadata.min_page_scale_factor); | |
1891 EXPECT_EQ(4.f, metadata.max_page_scale_factor); | |
1892 } | |
1893 } | |
1894 | |
1895 class DidDrawCheckLayer : public LayerImpl { | |
1896 public: | |
1897 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) { | |
1898 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl, id)); | |
1899 } | |
1900 | |
1901 bool WillDraw(DrawMode draw_mode, ResourceProvider* provider) override { | |
1902 will_draw_called_ = true; | |
1903 if (will_draw_returns_false_) | |
1904 return false; | |
1905 return LayerImpl::WillDraw(draw_mode, provider); | |
1906 } | |
1907 | |
1908 void AppendQuads(RenderPass* render_pass, | |
1909 AppendQuadsData* append_quads_data) override { | |
1910 append_quads_called_ = true; | |
1911 LayerImpl::AppendQuads(render_pass, append_quads_data); | |
1912 } | |
1913 | |
1914 void DidDraw(ResourceProvider* provider) override { | |
1915 did_draw_called_ = true; | |
1916 LayerImpl::DidDraw(provider); | |
1917 } | |
1918 | |
1919 bool will_draw_called() const { return will_draw_called_; } | |
1920 bool append_quads_called() const { return append_quads_called_; } | |
1921 bool did_draw_called() const { return did_draw_called_; } | |
1922 | |
1923 void set_will_draw_returns_false() { will_draw_returns_false_ = true; } | |
1924 | |
1925 void ClearDidDrawCheck() { | |
1926 will_draw_called_ = false; | |
1927 append_quads_called_ = false; | |
1928 did_draw_called_ = false; | |
1929 } | |
1930 | |
1931 static void IgnoreResult(scoped_ptr<CopyOutputResult> result) {} | |
1932 | |
1933 void AddCopyRequest() { | |
1934 ScopedPtrVector<CopyOutputRequest> requests; | |
1935 requests.push_back( | |
1936 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult))); | |
1937 SetHasRenderSurface(true); | |
1938 PassCopyRequests(&requests); | |
1939 } | |
1940 | |
1941 protected: | |
1942 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id) | |
1943 : LayerImpl(tree_impl, id), | |
1944 will_draw_returns_false_(false), | |
1945 will_draw_called_(false), | |
1946 append_quads_called_(false), | |
1947 did_draw_called_(false) { | |
1948 SetBounds(gfx::Size(10, 10)); | |
1949 SetContentBounds(gfx::Size(10, 10)); | |
1950 SetDrawsContent(true); | |
1951 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10); | |
1952 } | |
1953 | |
1954 private: | |
1955 bool will_draw_returns_false_; | |
1956 bool will_draw_called_; | |
1957 bool append_quads_called_; | |
1958 bool did_draw_called_; | |
1959 }; | |
1960 | |
1961 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) { | |
1962 // The root layer is always drawn, so run this test on a child layer that | |
1963 // will be masked out by the root layer's bounds. | |
1964 host_impl_->active_tree()->SetRootLayer( | |
1965 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1)); | |
1966 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>( | |
1967 host_impl_->active_tree()->root_layer()); | |
1968 | |
1969 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2)); | |
1970 root->SetHasRenderSurface(true); | |
1971 DidDrawCheckLayer* layer = | |
1972 static_cast<DidDrawCheckLayer*>(root->children()[0]); | |
1973 | |
1974 { | |
1975 LayerTreeHostImpl::FrameData frame; | |
1976 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
1977 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
1978 host_impl_->DidDrawAllLayers(frame); | |
1979 | |
1980 EXPECT_TRUE(layer->will_draw_called()); | |
1981 EXPECT_TRUE(layer->append_quads_called()); | |
1982 EXPECT_TRUE(layer->did_draw_called()); | |
1983 } | |
1984 | |
1985 host_impl_->SetViewportDamage(gfx::Rect(10, 10)); | |
1986 | |
1987 { | |
1988 LayerTreeHostImpl::FrameData frame; | |
1989 | |
1990 layer->set_will_draw_returns_false(); | |
1991 layer->ClearDidDrawCheck(); | |
1992 | |
1993 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
1994 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
1995 host_impl_->DidDrawAllLayers(frame); | |
1996 | |
1997 EXPECT_TRUE(layer->will_draw_called()); | |
1998 EXPECT_FALSE(layer->append_quads_called()); | |
1999 EXPECT_FALSE(layer->did_draw_called()); | |
2000 } | |
2001 } | |
2002 | |
2003 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) { | |
2004 // The root layer is always drawn, so run this test on a child layer that | |
2005 // will be masked out by the root layer's bounds. | |
2006 host_impl_->active_tree()->SetRootLayer( | |
2007 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1)); | |
2008 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>( | |
2009 host_impl_->active_tree()->root_layer()); | |
2010 root->SetMasksToBounds(true); | |
2011 root->SetHasRenderSurface(true); | |
2012 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2)); | |
2013 DidDrawCheckLayer* layer = | |
2014 static_cast<DidDrawCheckLayer*>(root->children()[0]); | |
2015 // Ensure visible_content_rect for layer is empty. | |
2016 layer->SetPosition(gfx::PointF(100.f, 100.f)); | |
2017 layer->SetBounds(gfx::Size(10, 10)); | |
2018 layer->SetContentBounds(gfx::Size(10, 10)); | |
2019 | |
2020 LayerTreeHostImpl::FrameData frame; | |
2021 | |
2022 EXPECT_FALSE(layer->will_draw_called()); | |
2023 EXPECT_FALSE(layer->did_draw_called()); | |
2024 | |
2025 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
2026 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
2027 host_impl_->DidDrawAllLayers(frame); | |
2028 | |
2029 EXPECT_FALSE(layer->will_draw_called()); | |
2030 EXPECT_FALSE(layer->did_draw_called()); | |
2031 | |
2032 EXPECT_TRUE(layer->visible_content_rect().IsEmpty()); | |
2033 | |
2034 // Ensure visible_content_rect for layer is not empty | |
2035 layer->SetPosition(gfx::PointF()); | |
2036 | |
2037 EXPECT_FALSE(layer->will_draw_called()); | |
2038 EXPECT_FALSE(layer->did_draw_called()); | |
2039 | |
2040 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
2041 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
2042 host_impl_->DidDrawAllLayers(frame); | |
2043 | |
2044 EXPECT_TRUE(layer->will_draw_called()); | |
2045 EXPECT_TRUE(layer->did_draw_called()); | |
2046 | |
2047 EXPECT_FALSE(layer->visible_content_rect().IsEmpty()); | |
2048 } | |
2049 | |
2050 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) { | |
2051 gfx::Size big_size(1000, 1000); | |
2052 host_impl_->SetViewportSize(big_size); | |
2053 | |
2054 host_impl_->active_tree()->SetRootLayer( | |
2055 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1)); | |
2056 DidDrawCheckLayer* root = | |
2057 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); | |
2058 | |
2059 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2)); | |
2060 DidDrawCheckLayer* occluded_layer = | |
2061 static_cast<DidDrawCheckLayer*>(root->children()[0]); | |
2062 | |
2063 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3)); | |
2064 root->SetHasRenderSurface(true); | |
2065 DidDrawCheckLayer* top_layer = | |
2066 static_cast<DidDrawCheckLayer*>(root->children()[1]); | |
2067 // This layer covers the occluded_layer above. Make this layer large so it can | |
2068 // occlude. | |
2069 top_layer->SetBounds(big_size); | |
2070 top_layer->SetContentBounds(big_size); | |
2071 top_layer->SetContentsOpaque(true); | |
2072 | |
2073 LayerTreeHostImpl::FrameData frame; | |
2074 | |
2075 EXPECT_FALSE(occluded_layer->will_draw_called()); | |
2076 EXPECT_FALSE(occluded_layer->did_draw_called()); | |
2077 EXPECT_FALSE(top_layer->will_draw_called()); | |
2078 EXPECT_FALSE(top_layer->did_draw_called()); | |
2079 | |
2080 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
2081 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
2082 host_impl_->DidDrawAllLayers(frame); | |
2083 | |
2084 EXPECT_FALSE(occluded_layer->will_draw_called()); | |
2085 EXPECT_FALSE(occluded_layer->did_draw_called()); | |
2086 EXPECT_TRUE(top_layer->will_draw_called()); | |
2087 EXPECT_TRUE(top_layer->did_draw_called()); | |
2088 } | |
2089 | |
2090 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) { | |
2091 host_impl_->active_tree()->SetRootLayer( | |
2092 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1)); | |
2093 DidDrawCheckLayer* root = | |
2094 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); | |
2095 | |
2096 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2)); | |
2097 root->SetHasRenderSurface(true); | |
2098 DidDrawCheckLayer* layer1 = | |
2099 static_cast<DidDrawCheckLayer*>(root->children()[0]); | |
2100 | |
2101 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3)); | |
2102 DidDrawCheckLayer* layer2 = | |
2103 static_cast<DidDrawCheckLayer*>(layer1->children()[0]); | |
2104 | |
2105 layer1->SetHasRenderSurface(true); | |
2106 layer1->SetShouldFlattenTransform(true); | |
2107 | |
2108 EXPECT_FALSE(root->did_draw_called()); | |
2109 EXPECT_FALSE(layer1->did_draw_called()); | |
2110 EXPECT_FALSE(layer2->did_draw_called()); | |
2111 | |
2112 LayerTreeHostImpl::FrameData frame; | |
2113 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren( | |
2114 host_impl_->active_tree()->root_layer()); | |
2115 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
2116 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
2117 host_impl_->DidDrawAllLayers(frame); | |
2118 | |
2119 EXPECT_TRUE(root->did_draw_called()); | |
2120 EXPECT_TRUE(layer1->did_draw_called()); | |
2121 EXPECT_TRUE(layer2->did_draw_called()); | |
2122 | |
2123 EXPECT_NE(root->render_surface(), layer1->render_surface()); | |
2124 EXPECT_TRUE(!!layer1->render_surface()); | |
2125 } | |
2126 | |
2127 class MissingTextureAnimatingLayer : public DidDrawCheckLayer { | |
2128 public: | |
2129 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, | |
2130 int id, | |
2131 bool tile_missing, | |
2132 bool had_incomplete_tile, | |
2133 bool animating, | |
2134 ResourceProvider* resource_provider) { | |
2135 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl, | |
2136 id, | |
2137 tile_missing, | |
2138 had_incomplete_tile, | |
2139 animating, | |
2140 resource_provider)); | |
2141 } | |
2142 | |
2143 void AppendQuads(RenderPass* render_pass, | |
2144 AppendQuadsData* append_quads_data) override { | |
2145 LayerImpl::AppendQuads(render_pass, append_quads_data); | |
2146 if (had_incomplete_tile_) | |
2147 append_quads_data->num_incomplete_tiles++; | |
2148 if (tile_missing_) | |
2149 append_quads_data->num_missing_tiles++; | |
2150 } | |
2151 | |
2152 private: | |
2153 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl, | |
2154 int id, | |
2155 bool tile_missing, | |
2156 bool had_incomplete_tile, | |
2157 bool animating, | |
2158 ResourceProvider* resource_provider) | |
2159 : DidDrawCheckLayer(tree_impl, id), | |
2160 tile_missing_(tile_missing), | |
2161 had_incomplete_tile_(had_incomplete_tile) { | |
2162 if (animating) | |
2163 AddAnimatedTransformToLayer(this, 10.0, 3, 0); | |
2164 } | |
2165 | |
2166 bool tile_missing_; | |
2167 bool had_incomplete_tile_; | |
2168 }; | |
2169 | |
2170 struct PrepareToDrawSuccessTestCase { | |
2171 struct State { | |
2172 bool has_missing_tile = false; | |
2173 bool has_incomplete_tile = false; | |
2174 bool is_animating = false; | |
2175 bool has_copy_request = false; | |
2176 }; | |
2177 bool high_res_required = false; | |
2178 State layer_before; | |
2179 State layer_between; | |
2180 State layer_after; | |
2181 DrawResult expected_result; | |
2182 | |
2183 explicit PrepareToDrawSuccessTestCase(DrawResult result) | |
2184 : expected_result(result) {} | |
2185 }; | |
2186 | |
2187 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) { | |
2188 std::vector<PrepareToDrawSuccessTestCase> cases; | |
2189 | |
2190 // 0. Default case. | |
2191 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2192 // 1. Animated layer first. | |
2193 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2194 cases.back().layer_before.is_animating = true; | |
2195 // 2. Animated layer between. | |
2196 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2197 cases.back().layer_between.is_animating = true; | |
2198 // 3. Animated layer last. | |
2199 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2200 cases.back().layer_after.is_animating = true; | |
2201 // 4. Missing tile first. | |
2202 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2203 cases.back().layer_before.has_missing_tile = true; | |
2204 // 5. Missing tile between. | |
2205 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2206 cases.back().layer_between.has_missing_tile = true; | |
2207 // 6. Missing tile last. | |
2208 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2209 cases.back().layer_after.has_missing_tile = true; | |
2210 // 7. Incomplete tile first. | |
2211 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2212 cases.back().layer_before.has_incomplete_tile = true; | |
2213 // 8. Incomplete tile between. | |
2214 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2215 cases.back().layer_between.has_incomplete_tile = true; | |
2216 // 9. Incomplete tile last. | |
2217 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2218 cases.back().layer_after.has_incomplete_tile = true; | |
2219 // 10. Animation with missing tile. | |
2220 cases.push_back( | |
2221 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS)); | |
2222 cases.back().layer_between.has_missing_tile = true; | |
2223 cases.back().layer_between.is_animating = true; | |
2224 // 11. Animation with missing tile and copy request after. Must succeed | |
2225 // because the animation checkerboard means we'll get a new frame and the copy | |
2226 // request's layer may be destroyed. | |
2227 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2228 cases.back().layer_between.has_missing_tile = true; | |
2229 cases.back().layer_between.is_animating = true; | |
2230 cases.back().layer_after.has_copy_request = true; | |
2231 // 12. Animation with missing tile and copy request before. Must succeed | |
2232 // because the animation checkerboard means we'll get a new frame and the copy | |
2233 // request's layer may be destroyed. | |
2234 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2235 cases.back().layer_between.has_missing_tile = true; | |
2236 cases.back().layer_between.is_animating = true; | |
2237 cases.back().layer_before.has_copy_request = true; | |
2238 // 13. Animation with incomplete tile. | |
2239 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2240 cases.back().layer_between.has_incomplete_tile = true; | |
2241 cases.back().layer_between.is_animating = true; | |
2242 | |
2243 // 14. High res required. | |
2244 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2245 cases.back().high_res_required = true; | |
2246 // 15. High res required with incomplete tile. | |
2247 cases.push_back( | |
2248 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); | |
2249 cases.back().high_res_required = true; | |
2250 cases.back().layer_between.has_incomplete_tile = true; | |
2251 // 16. High res required with missing tile. | |
2252 cases.push_back( | |
2253 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); | |
2254 cases.back().high_res_required = true; | |
2255 cases.back().layer_between.has_missing_tile = true; | |
2256 | |
2257 // 17. High res required is higher priority than animating missing tiles. | |
2258 cases.push_back( | |
2259 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); | |
2260 cases.back().high_res_required = true; | |
2261 cases.back().layer_between.has_missing_tile = true; | |
2262 cases.back().layer_after.has_missing_tile = true; | |
2263 cases.back().layer_after.is_animating = true; | |
2264 // 18. High res required is higher priority than animating missing tiles. | |
2265 cases.push_back( | |
2266 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); | |
2267 cases.back().high_res_required = true; | |
2268 cases.back().layer_between.has_missing_tile = true; | |
2269 cases.back().layer_before.has_missing_tile = true; | |
2270 cases.back().layer_before.is_animating = true; | |
2271 | |
2272 // 19. High res required is higher priority than copy requests. | |
2273 cases.push_back( | |
2274 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); | |
2275 cases.back().high_res_required = true; | |
2276 cases.back().layer_between.has_missing_tile = true; | |
2277 cases.back().layer_after.has_copy_request = true; | |
2278 // 20. High res required is higher priority than copy requests. | |
2279 cases.push_back( | |
2280 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); | |
2281 cases.back().high_res_required = true; | |
2282 cases.back().layer_between.has_missing_tile = true; | |
2283 cases.back().layer_before.has_copy_request = true; | |
2284 // 21. High res required is higher priority than copy requests. | |
2285 cases.push_back( | |
2286 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); | |
2287 cases.back().high_res_required = true; | |
2288 cases.back().layer_between.has_missing_tile = true; | |
2289 cases.back().layer_between.has_copy_request = true; | |
2290 | |
2291 host_impl_->active_tree()->SetRootLayer( | |
2292 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1)); | |
2293 DidDrawCheckLayer* root = | |
2294 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); | |
2295 root->SetHasRenderSurface(true); | |
2296 | |
2297 LayerTreeHostImpl::FrameData frame; | |
2298 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
2299 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
2300 host_impl_->DidDrawAllLayers(frame); | |
2301 host_impl_->SwapBuffers(frame); | |
2302 | |
2303 for (size_t i = 0; i < cases.size(); ++i) { | |
2304 const auto& testcase = cases[i]; | |
2305 std::vector<LayerImpl*> to_remove; | |
2306 for (auto* child : root->children()) | |
2307 to_remove.push_back(child); | |
2308 for (auto* child : to_remove) | |
2309 root->RemoveChild(child); | |
2310 | |
2311 std::ostringstream scope; | |
2312 scope << "Test case: " << i; | |
2313 SCOPED_TRACE(scope.str()); | |
2314 | |
2315 root->AddChild(MissingTextureAnimatingLayer::Create( | |
2316 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile, | |
2317 testcase.layer_before.has_incomplete_tile, | |
2318 testcase.layer_before.is_animating, host_impl_->resource_provider())); | |
2319 DidDrawCheckLayer* before = | |
2320 static_cast<DidDrawCheckLayer*>(root->children().back()); | |
2321 if (testcase.layer_before.has_copy_request) | |
2322 before->AddCopyRequest(); | |
2323 | |
2324 root->AddChild(MissingTextureAnimatingLayer::Create( | |
2325 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile, | |
2326 testcase.layer_between.has_incomplete_tile, | |
2327 testcase.layer_between.is_animating, host_impl_->resource_provider())); | |
2328 DidDrawCheckLayer* between = | |
2329 static_cast<DidDrawCheckLayer*>(root->children().back()); | |
2330 if (testcase.layer_between.has_copy_request) | |
2331 between->AddCopyRequest(); | |
2332 | |
2333 root->AddChild(MissingTextureAnimatingLayer::Create( | |
2334 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile, | |
2335 testcase.layer_after.has_incomplete_tile, | |
2336 testcase.layer_after.is_animating, host_impl_->resource_provider())); | |
2337 DidDrawCheckLayer* after = | |
2338 static_cast<DidDrawCheckLayer*>(root->children().back()); | |
2339 if (testcase.layer_after.has_copy_request) | |
2340 after->AddCopyRequest(); | |
2341 | |
2342 if (testcase.high_res_required) | |
2343 host_impl_->SetRequiresHighResToDraw(); | |
2344 | |
2345 LayerTreeHostImpl::FrameData frame; | |
2346 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame)); | |
2347 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
2348 host_impl_->DidDrawAllLayers(frame); | |
2349 host_impl_->SwapBuffers(frame); | |
2350 } | |
2351 } | |
2352 | |
2353 TEST_F(LayerTreeHostImplTest, | |
2354 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) { | |
2355 CreateHostImpl(DefaultSettings(), | |
2356 FakeOutputSurface::CreateAlwaysDrawAndSwap3d()); | |
2357 EXPECT_TRUE(host_impl_->output_surface() | |
2358 ->capabilities() | |
2359 .draw_and_swap_full_viewport_every_frame); | |
2360 | |
2361 std::vector<PrepareToDrawSuccessTestCase> cases; | |
2362 | |
2363 // 0. Default case. | |
2364 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2365 // 1. Animation with missing tile. | |
2366 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2367 cases.back().layer_between.has_missing_tile = true; | |
2368 cases.back().layer_between.is_animating = true; | |
2369 // 2. High res required with incomplete tile. | |
2370 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2371 cases.back().high_res_required = true; | |
2372 cases.back().layer_between.has_incomplete_tile = true; | |
2373 // 3. High res required with missing tile. | |
2374 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); | |
2375 cases.back().high_res_required = true; | |
2376 cases.back().layer_between.has_missing_tile = true; | |
2377 | |
2378 host_impl_->active_tree()->SetRootLayer( | |
2379 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1)); | |
2380 DidDrawCheckLayer* root = | |
2381 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); | |
2382 root->SetHasRenderSurface(true); | |
2383 | |
2384 LayerTreeHostImpl::FrameData frame; | |
2385 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
2386 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
2387 host_impl_->DidDrawAllLayers(frame); | |
2388 host_impl_->SwapBuffers(frame); | |
2389 | |
2390 for (size_t i = 0; i < cases.size(); ++i) { | |
2391 const auto& testcase = cases[i]; | |
2392 std::vector<LayerImpl*> to_remove; | |
2393 for (auto* child : root->children()) | |
2394 to_remove.push_back(child); | |
2395 for (auto* child : to_remove) | |
2396 root->RemoveChild(child); | |
2397 | |
2398 std::ostringstream scope; | |
2399 scope << "Test case: " << i; | |
2400 SCOPED_TRACE(scope.str()); | |
2401 | |
2402 root->AddChild(MissingTextureAnimatingLayer::Create( | |
2403 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile, | |
2404 testcase.layer_before.has_incomplete_tile, | |
2405 testcase.layer_before.is_animating, host_impl_->resource_provider())); | |
2406 DidDrawCheckLayer* before = | |
2407 static_cast<DidDrawCheckLayer*>(root->children().back()); | |
2408 if (testcase.layer_before.has_copy_request) | |
2409 before->AddCopyRequest(); | |
2410 | |
2411 root->AddChild(MissingTextureAnimatingLayer::Create( | |
2412 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile, | |
2413 testcase.layer_between.has_incomplete_tile, | |
2414 testcase.layer_between.is_animating, host_impl_->resource_provider())); | |
2415 DidDrawCheckLayer* between = | |
2416 static_cast<DidDrawCheckLayer*>(root->children().back()); | |
2417 if (testcase.layer_between.has_copy_request) | |
2418 between->AddCopyRequest(); | |
2419 | |
2420 root->AddChild(MissingTextureAnimatingLayer::Create( | |
2421 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile, | |
2422 testcase.layer_after.has_incomplete_tile, | |
2423 testcase.layer_after.is_animating, host_impl_->resource_provider())); | |
2424 DidDrawCheckLayer* after = | |
2425 static_cast<DidDrawCheckLayer*>(root->children().back()); | |
2426 if (testcase.layer_after.has_copy_request) | |
2427 after->AddCopyRequest(); | |
2428 | |
2429 if (testcase.high_res_required) | |
2430 host_impl_->SetRequiresHighResToDraw(); | |
2431 | |
2432 LayerTreeHostImpl::FrameData frame; | |
2433 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame)); | |
2434 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
2435 host_impl_->DidDrawAllLayers(frame); | |
2436 host_impl_->SwapBuffers(frame); | |
2437 } | |
2438 } | |
2439 | |
2440 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) { | |
2441 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1); | |
2442 root->SetScrollClipLayer(Layer::INVALID_ID); | |
2443 root->SetHasRenderSurface(true); | |
2444 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
2445 DrawFrame(); | |
2446 | |
2447 // Scroll event is ignored because layer is not scrollable. | |
2448 EXPECT_EQ(InputHandler::SCROLL_IGNORED, | |
2449 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
2450 EXPECT_FALSE(did_request_redraw_); | |
2451 EXPECT_FALSE(did_request_commit_); | |
2452 } | |
2453 | |
2454 // TODO(bokan): Convert these tests to create inner and outer viewports. | |
2455 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest { | |
2456 public: | |
2457 LayerTreeHostImplTopControlsTest() | |
2458 // Make the clip size the same as the layer (content) size so the layer is | |
2459 // non-scrollable. | |
2460 : layer_size_(10, 10), | |
2461 clip_size_(layer_size_), | |
2462 top_controls_height_(50) { | |
2463 settings_.use_pinch_virtual_viewport = true; | |
2464 | |
2465 viewport_size_ = gfx::Size(clip_size_.width(), | |
2466 clip_size_.height() + top_controls_height_); | |
2467 } | |
2468 | |
2469 bool CreateHostImpl(const LayerTreeSettings& settings, | |
2470 scoped_ptr<OutputSurface> output_surface) override { | |
2471 bool init = | |
2472 LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass()); | |
2473 if (init) { | |
2474 host_impl_->active_tree()->set_top_controls_height(top_controls_height_); | |
2475 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f); | |
2476 } | |
2477 return init; | |
2478 } | |
2479 | |
2480 void SetupTopControlsAndScrollLayer() { | |
2481 scoped_ptr<LayerImpl> root = | |
2482 LayerImpl::Create(host_impl_->active_tree(), 1); | |
2483 scoped_ptr<LayerImpl> root_clip = | |
2484 LayerImpl::Create(host_impl_->active_tree(), 2); | |
2485 root_clip->SetBounds(clip_size_); | |
2486 root->SetScrollClipLayer(root_clip->id()); | |
2487 root->SetBounds(layer_size_); | |
2488 root->SetContentBounds(layer_size_); | |
2489 root->SetPosition(gfx::PointF()); | |
2490 root->SetDrawsContent(false); | |
2491 root->SetIsContainerForFixedPositionLayers(true); | |
2492 int inner_viewport_scroll_layer_id = root->id(); | |
2493 int page_scale_layer_id = root_clip->id(); | |
2494 root_clip->SetHasRenderSurface(true); | |
2495 root_clip->AddChild(root.Pass()); | |
2496 root_clip->SetHasRenderSurface(true); | |
2497 host_impl_->active_tree()->SetRootLayer(root_clip.Pass()); | |
2498 host_impl_->active_tree()->SetViewportLayersFromIds( | |
2499 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id, | |
2500 Layer::INVALID_ID); | |
2501 // Set a viewport size that is large enough to contain both the top controls | |
2502 // and some content. | |
2503 host_impl_->SetViewportSize(viewport_size_); | |
2504 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true); | |
2505 | |
2506 host_impl_->DidChangeTopControlsPosition(); | |
2507 | |
2508 host_impl_->CreatePendingTree(); | |
2509 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_); | |
2510 root = | |
2511 LayerImpl::Create(host_impl_->sync_tree(), 1); | |
2512 root_clip = | |
2513 LayerImpl::Create(host_impl_->sync_tree(), 2); | |
2514 root_clip->SetBounds(clip_size_); | |
2515 root->SetScrollClipLayer(root_clip->id()); | |
2516 root->SetBounds(layer_size_); | |
2517 root->SetContentBounds(layer_size_); | |
2518 root->SetPosition(gfx::PointF()); | |
2519 root->SetDrawsContent(false); | |
2520 root->SetIsContainerForFixedPositionLayers(true); | |
2521 inner_viewport_scroll_layer_id = root->id(); | |
2522 page_scale_layer_id = root_clip->id(); | |
2523 root_clip->AddChild(root.Pass()); | |
2524 host_impl_->sync_tree()->SetRootLayer(root_clip.Pass()); | |
2525 host_impl_->sync_tree()->SetViewportLayersFromIds( | |
2526 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id, | |
2527 Layer::INVALID_ID); | |
2528 // Set a viewport size that is large enough to contain both the top controls | |
2529 // and some content. | |
2530 host_impl_->SetViewportSize(viewport_size_); | |
2531 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true); | |
2532 host_impl_->DidChangeTopControlsPosition(); | |
2533 } | |
2534 | |
2535 void SetupTopControlsAndScrollLayerWithVirtualViewport( | |
2536 const gfx::Size& inner_viewport_size, | |
2537 const gfx::Size& outer_viewport_size, | |
2538 const gfx::Size& scroll_layer_size) { | |
2539 CreateHostImpl(settings_, CreateOutputSurface()); | |
2540 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true); | |
2541 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_); | |
2542 host_impl_->DidChangeTopControlsPosition(); | |
2543 | |
2544 scoped_ptr<LayerImpl> root = | |
2545 LayerImpl::Create(host_impl_->active_tree(), 1); | |
2546 scoped_ptr<LayerImpl> root_clip = | |
2547 LayerImpl::Create(host_impl_->active_tree(), 2); | |
2548 scoped_ptr<LayerImpl> page_scale = | |
2549 LayerImpl::Create(host_impl_->active_tree(), 3); | |
2550 | |
2551 scoped_ptr<LayerImpl> outer_scroll = | |
2552 LayerImpl::Create(host_impl_->active_tree(), 4); | |
2553 scoped_ptr<LayerImpl> outer_clip = | |
2554 LayerImpl::Create(host_impl_->active_tree(), 5); | |
2555 | |
2556 root_clip->SetBounds(inner_viewport_size); | |
2557 root->SetScrollClipLayer(root_clip->id()); | |
2558 root->SetBounds(outer_viewport_size); | |
2559 root->SetContentBounds(outer_viewport_size); | |
2560 root->SetPosition(gfx::PointF()); | |
2561 root->SetDrawsContent(false); | |
2562 root->SetIsContainerForFixedPositionLayers(true); | |
2563 root_clip->SetHasRenderSurface(true); | |
2564 outer_clip->SetBounds(outer_viewport_size); | |
2565 outer_scroll->SetScrollClipLayer(outer_clip->id()); | |
2566 outer_scroll->SetBounds(scroll_layer_size); | |
2567 outer_scroll->SetContentBounds(scroll_layer_size); | |
2568 outer_scroll->SetPosition(gfx::PointF()); | |
2569 outer_scroll->SetDrawsContent(false); | |
2570 outer_scroll->SetIsContainerForFixedPositionLayers(true); | |
2571 | |
2572 int inner_viewport_scroll_layer_id = root->id(); | |
2573 int outer_viewport_scroll_layer_id = outer_scroll->id(); | |
2574 int page_scale_layer_id = page_scale->id(); | |
2575 | |
2576 outer_clip->AddChild(outer_scroll.Pass()); | |
2577 root->AddChild(outer_clip.Pass()); | |
2578 page_scale->AddChild(root.Pass()); | |
2579 root_clip->AddChild(page_scale.Pass()); | |
2580 | |
2581 host_impl_->active_tree()->SetRootLayer(root_clip.Pass()); | |
2582 host_impl_->active_tree()->SetViewportLayersFromIds( | |
2583 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id, | |
2584 outer_viewport_scroll_layer_id); | |
2585 | |
2586 host_impl_->SetViewportSize(inner_viewport_size); | |
2587 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer(); | |
2588 EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds()); | |
2589 } | |
2590 | |
2591 protected: | |
2592 gfx::Size layer_size_; | |
2593 gfx::Size clip_size_; | |
2594 gfx::Size viewport_size_; | |
2595 float top_controls_height_; | |
2596 | |
2597 LayerTreeSettings settings_; | |
2598 }; // class LayerTreeHostImplTopControlsTest | |
2599 | |
2600 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) { | |
2601 SetupTopControlsAndScrollLayerWithVirtualViewport( | |
2602 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10)); | |
2603 DrawFrame(); | |
2604 | |
2605 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
2606 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
2607 | |
2608 // Make the test scroll delta a fractional amount, to verify that the | |
2609 // fixed container size delta is (1) non-zero, and (2) fractional, and | |
2610 // (3) matches the movement of the top controls. | |
2611 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f); | |
2612 host_impl_->top_controls_manager()->ScrollBegin(); | |
2613 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta); | |
2614 host_impl_->top_controls_manager()->ScrollEnd(); | |
2615 | |
2616 LayerImpl* inner_viewport_scroll_layer = | |
2617 host_impl_->active_tree()->InnerViewportScrollLayer(); | |
2618 DCHECK(inner_viewport_scroll_layer); | |
2619 host_impl_->ScrollEnd(); | |
2620 EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(), | |
2621 inner_viewport_scroll_layer->FixedContainerSizeDelta().y()); | |
2622 } | |
2623 | |
2624 // In this test, the outer viewport is initially unscrollable. We test that a | |
2625 // scroll initiated on the inner viewport, causing the top controls to show and | |
2626 // thus making the outer viewport scrollable, still scrolls the outer viewport. | |
2627 TEST_F(LayerTreeHostImplTopControlsTest, | |
2628 TopControlsOuterViewportBecomesScrollable) { | |
2629 SetupTopControlsAndScrollLayerWithVirtualViewport( | |
2630 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100)); | |
2631 DrawFrame(); | |
2632 | |
2633 LayerImpl *inner_scroll = | |
2634 host_impl_->active_tree()->InnerViewportScrollLayer(); | |
2635 LayerImpl *inner_container = | |
2636 host_impl_->active_tree()->InnerViewportContainerLayer(); | |
2637 LayerImpl *outer_scroll = | |
2638 host_impl_->active_tree()->OuterViewportScrollLayer(); | |
2639 LayerImpl *outer_container = | |
2640 host_impl_->active_tree()->OuterViewportContainerLayer(); | |
2641 | |
2642 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer. | |
2643 outer_scroll->SetDrawsContent(true); | |
2644 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 1.f, 2.f); | |
2645 | |
2646 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
2647 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
2648 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 50.f)); | |
2649 | |
2650 // The entire scroll delta should have been used to hide the top controls. | |
2651 // The viewport layers should be resized back to their full sizes. | |
2652 EXPECT_EQ(0.f, host_impl_->active_tree()->CurrentTopControlsShownRatio()); | |
2653 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y()); | |
2654 EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height()); | |
2655 EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height()); | |
2656 | |
2657 // The inner viewport should be scrollable by 50px * page_scale. | |
2658 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 100.f)); | |
2659 EXPECT_EQ(50.f, inner_scroll->CurrentScrollOffset().y()); | |
2660 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y()); | |
2661 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset()); | |
2662 | |
2663 host_impl_->ScrollEnd(); | |
2664 | |
2665 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
2666 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
2667 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll); | |
2668 | |
2669 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f)); | |
2670 | |
2671 // The entire scroll delta should have been used to show the top controls. | |
2672 // The outer viewport should be resized to accomodate and scrolled to the | |
2673 // bottom of the document to keep the viewport in place. | |
2674 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio()); | |
2675 EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height()); | |
2676 EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height()); | |
2677 EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y()); | |
2678 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y()); | |
2679 | |
2680 // Now when we continue scrolling, make sure the outer viewport gets scrolled | |
2681 // since it wasn't scrollable when the scroll began. | |
2682 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f)); | |
2683 EXPECT_EQ(15.f, outer_scroll->CurrentScrollOffset().y()); | |
2684 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y()); | |
2685 | |
2686 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f)); | |
2687 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y()); | |
2688 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y()); | |
2689 | |
2690 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f)); | |
2691 host_impl_->ScrollEnd(); | |
2692 | |
2693 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y()); | |
2694 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y()); | |
2695 } | |
2696 | |
2697 // Test that the fixed position container delta is appropriately adjusted | |
2698 // by the top controls showing/hiding and page scale doesn't affect it. | |
2699 TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) { | |
2700 SetupTopControlsAndScrollLayerWithVirtualViewport( | |
2701 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100)); | |
2702 DrawFrame(); | |
2703 | |
2704 float page_scale = 1.5f; | |
2705 LayerImpl* outer_viewport_scroll_layer = | |
2706 host_impl_->active_tree()->OuterViewportScrollLayer(); | |
2707 | |
2708 // Zoom in, since the fixed container is the outer viewport, the delta should | |
2709 // not be scaled. | |
2710 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f); | |
2711 | |
2712 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
2713 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
2714 | |
2715 // Scroll down, the top controls hiding should expand the viewport size so | |
2716 // the delta should be equal to the scroll distance. | |
2717 gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f); | |
2718 host_impl_->top_controls_manager()->ScrollBegin(); | |
2719 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta); | |
2720 EXPECT_FLOAT_EQ(top_controls_height_ - top_controls_scroll_delta.y(), | |
2721 host_impl_->top_controls_manager()->ContentTopOffset()); | |
2722 EXPECT_VECTOR_EQ(top_controls_scroll_delta, | |
2723 outer_viewport_scroll_layer->FixedContainerSizeDelta()); | |
2724 host_impl_->ScrollEnd(); | |
2725 | |
2726 // Scroll past the maximum extent. The delta shouldn't be greater than the | |
2727 // top controls height. | |
2728 host_impl_->top_controls_manager()->ScrollBegin(); | |
2729 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta); | |
2730 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta); | |
2731 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta); | |
2732 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset()); | |
2733 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_), | |
2734 outer_viewport_scroll_layer->FixedContainerSizeDelta()); | |
2735 host_impl_->ScrollEnd(); | |
2736 | |
2737 // Scroll in the direction to make the top controls show. | |
2738 host_impl_->top_controls_manager()->ScrollBegin(); | |
2739 host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta); | |
2740 EXPECT_EQ(top_controls_scroll_delta.y(), | |
2741 host_impl_->top_controls_manager()->ContentTopOffset()); | |
2742 EXPECT_VECTOR_EQ( | |
2743 gfx::Vector2dF(0, top_controls_height_ - top_controls_scroll_delta.y()), | |
2744 outer_viewport_scroll_layer->FixedContainerSizeDelta()); | |
2745 host_impl_->top_controls_manager()->ScrollEnd(); | |
2746 } | |
2747 | |
2748 // Test that if a scrollable sublayer doesn't consume the scroll, | |
2749 // top controls should hide when scrolling down. | |
2750 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) { | |
2751 gfx::Size sub_content_size(100, 400); | |
2752 gfx::Size sub_content_layer_size(100, 300); | |
2753 SetupTopControlsAndScrollLayerWithVirtualViewport( | |
2754 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100)); | |
2755 DrawFrame(); | |
2756 | |
2757 // Show top controls | |
2758 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio()); | |
2759 | |
2760 LayerImpl* outer_viewport_scroll_layer = | |
2761 host_impl_->active_tree()->OuterViewportScrollLayer(); | |
2762 int id = outer_viewport_scroll_layer->id(); | |
2763 | |
2764 scoped_ptr<LayerImpl> child = | |
2765 LayerImpl::Create(host_impl_->active_tree(), id + 2); | |
2766 scoped_ptr<LayerImpl> child_clip = | |
2767 LayerImpl::Create(host_impl_->active_tree(), id + 3); | |
2768 | |
2769 child_clip->SetBounds(sub_content_layer_size); | |
2770 child->SetScrollClipLayer(child_clip->id()); | |
2771 child->SetBounds(sub_content_size); | |
2772 child->SetContentBounds(sub_content_size); | |
2773 child->SetPosition(gfx::PointF()); | |
2774 child->SetDrawsContent(true); | |
2775 child->SetIsContainerForFixedPositionLayers(true); | |
2776 | |
2777 // scroll child to limit | |
2778 child->SetScrollDelta(gfx::Vector2dF(0, 100.f)); | |
2779 child_clip->AddChild(child.Pass()); | |
2780 outer_viewport_scroll_layer->AddChild(child_clip.Pass()); | |
2781 | |
2782 // Scroll 25px to hide top controls | |
2783 gfx::Vector2dF scroll_delta(0.f, 25.f); | |
2784 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
2785 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
2786 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
2787 host_impl_->ScrollEnd(); | |
2788 | |
2789 // Top controls should be hidden | |
2790 EXPECT_EQ(scroll_delta.y(), | |
2791 top_controls_height_ - | |
2792 host_impl_->top_controls_manager()->ContentTopOffset()); | |
2793 } | |
2794 | |
2795 // Ensure setting the top controls position explicitly using the setters on the | |
2796 // TreeImpl correctly affects the top controls manager and viewport bounds. | |
2797 TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) { | |
2798 CreateHostImpl(settings_, CreateOutputSurface()); | |
2799 SetupTopControlsAndScrollLayer(); | |
2800 DrawFrame(); | |
2801 | |
2802 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f); | |
2803 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread( | |
2804 30.f / top_controls_height_); | |
2805 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive(); | |
2806 EXPECT_FLOAT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset()); | |
2807 EXPECT_FLOAT_EQ(-20.f, | |
2808 host_impl_->top_controls_manager()->ControlsTopOffset()); | |
2809 | |
2810 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f); | |
2811 EXPECT_FLOAT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset()); | |
2812 EXPECT_FLOAT_EQ(-50.f, | |
2813 host_impl_->top_controls_manager()->ControlsTopOffset()); | |
2814 | |
2815 host_impl_->DidChangeTopControlsPosition(); | |
2816 | |
2817 // Now that top controls have moved, expect the clip to resize. | |
2818 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer(); | |
2819 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds()); | |
2820 } | |
2821 | |
2822 // Test that the top_controls delta and sent delta are appropriately | |
2823 // applied on sync tree activation. The total top controls offset shouldn't | |
2824 // change after the activation. | |
2825 TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) { | |
2826 CreateHostImpl(settings_, CreateOutputSurface()); | |
2827 SetupTopControlsAndScrollLayer(); | |
2828 DrawFrame(); | |
2829 | |
2830 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread( | |
2831 20.f / top_controls_height_); | |
2832 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive(); | |
2833 host_impl_->active_tree()->SetCurrentTopControlsShownRatio( | |
2834 15.f / top_controls_height_); | |
2835 host_impl_->active_tree() | |
2836 ->top_controls_shown_ratio() | |
2837 ->PullDeltaForMainThread(); | |
2838 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f); | |
2839 host_impl_->sync_tree()->PushTopControlsFromMainThread(15.f / | |
2840 top_controls_height_); | |
2841 | |
2842 host_impl_->DidChangeTopControlsPosition(); | |
2843 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer(); | |
2844 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds()); | |
2845 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset()); | |
2846 | |
2847 host_impl_->ActivateSyncTree(); | |
2848 | |
2849 root_clip_ptr = host_impl_->active_tree()->root_layer(); | |
2850 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset()); | |
2851 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds()); | |
2852 | |
2853 EXPECT_FLOAT_EQ( | |
2854 -15.f, host_impl_->active_tree()->top_controls_shown_ratio()->Delta() * | |
2855 top_controls_height_); | |
2856 EXPECT_FLOAT_EQ( | |
2857 15.f, | |
2858 host_impl_->active_tree()->top_controls_shown_ratio()->ActiveBase() * | |
2859 top_controls_height_); | |
2860 } | |
2861 | |
2862 // Test that changing the top controls layout height is correctly applied to | |
2863 // the inner viewport container bounds. That is, the top controls layout | |
2864 // height is the amount that the inner viewport container was shrunk outside | |
2865 // the compositor to accommodate the top controls. | |
2866 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) { | |
2867 CreateHostImpl(settings_, CreateOutputSurface()); | |
2868 SetupTopControlsAndScrollLayer(); | |
2869 DrawFrame(); | |
2870 | |
2871 host_impl_->sync_tree()->PushTopControlsFromMainThread(1.f); | |
2872 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true); | |
2873 | |
2874 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread( | |
2875 1.f); | |
2876 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive(); | |
2877 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f); | |
2878 | |
2879 host_impl_->DidChangeTopControlsPosition(); | |
2880 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer(); | |
2881 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds()); | |
2882 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset()); | |
2883 | |
2884 host_impl_->sync_tree()->root_layer()->SetBounds( | |
2885 gfx::Size(root_clip_ptr->bounds().width(), | |
2886 root_clip_ptr->bounds().height() - 50.f)); | |
2887 | |
2888 host_impl_->ActivateSyncTree(); | |
2889 | |
2890 root_clip_ptr = host_impl_->active_tree()->root_layer(); | |
2891 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset()); | |
2892 | |
2893 // The total bounds should remain unchanged since the bounds delta should | |
2894 // account for the difference between the layout height and the current | |
2895 // top controls offset. | |
2896 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds()); | |
2897 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), root_clip_ptr->bounds_delta()); | |
2898 | |
2899 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f); | |
2900 host_impl_->DidChangeTopControlsPosition(); | |
2901 | |
2902 EXPECT_EQ(1.f, host_impl_->top_controls_manager()->TopControlsShownRatio()); | |
2903 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->TopControlsHeight()); | |
2904 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset()); | |
2905 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), root_clip_ptr->bounds_delta()); | |
2906 EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f), | |
2907 root_clip_ptr->bounds()); | |
2908 } | |
2909 | |
2910 // Test that showing/hiding the top controls when the viewport is fully scrolled | |
2911 // doesn't incorrectly change the viewport offset due to clamping from changing | |
2912 // viewport bounds. | |
2913 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) { | |
2914 SetupTopControlsAndScrollLayerWithVirtualViewport( | |
2915 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400)); | |
2916 DrawFrame(); | |
2917 | |
2918 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio()); | |
2919 | |
2920 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer(); | |
2921 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer(); | |
2922 | |
2923 // Scroll the viewports to max scroll offset. | |
2924 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f)); | |
2925 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f)); | |
2926 | |
2927 gfx::ScrollOffset viewport_offset = | |
2928 host_impl_->active_tree()->TotalScrollOffset(); | |
2929 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset); | |
2930 | |
2931 // Hide the top controls by 25px. | |
2932 gfx::Vector2dF scroll_delta(0.f, 25.f); | |
2933 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
2934 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
2935 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
2936 | |
2937 // scrolling down at the max extents no longer hides the top controls | |
2938 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio()); | |
2939 | |
2940 // forcefully hide the top controls by 25px | |
2941 host_impl_->top_controls_manager()->ScrollBy(scroll_delta); | |
2942 host_impl_->ScrollEnd(); | |
2943 | |
2944 EXPECT_FLOAT_EQ(scroll_delta.y(), | |
2945 top_controls_height_ - | |
2946 host_impl_->top_controls_manager()->ContentTopOffset()); | |
2947 | |
2948 inner_scroll->ClampScrollToMaxScrollOffset(); | |
2949 outer_scroll->ClampScrollToMaxScrollOffset(); | |
2950 | |
2951 // We should still be fully scrolled. | |
2952 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), | |
2953 host_impl_->active_tree()->TotalScrollOffset()); | |
2954 | |
2955 viewport_offset = host_impl_->active_tree()->TotalScrollOffset(); | |
2956 | |
2957 // Bring the top controls down by 25px. | |
2958 scroll_delta = gfx::Vector2dF(0.f, -25.f); | |
2959 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
2960 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
2961 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
2962 host_impl_->ScrollEnd(); | |
2963 | |
2964 // The viewport offset shouldn't have changed. | |
2965 EXPECT_EQ(viewport_offset, | |
2966 host_impl_->active_tree()->TotalScrollOffset()); | |
2967 | |
2968 // Scroll the viewports to max scroll offset. | |
2969 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f)); | |
2970 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f)); | |
2971 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), | |
2972 host_impl_->active_tree()->TotalScrollOffset()); | |
2973 } | |
2974 | |
2975 // Test that the top controls coming in and out maintains the same aspect ratio | |
2976 // between the inner and outer viewports. | |
2977 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) { | |
2978 SetupTopControlsAndScrollLayerWithVirtualViewport( | |
2979 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400)); | |
2980 DrawFrame(); | |
2981 | |
2982 EXPECT_FLOAT_EQ(top_controls_height_, | |
2983 host_impl_->top_controls_manager()->ContentTopOffset()); | |
2984 | |
2985 gfx::Vector2dF scroll_delta(0.f, 25.f); | |
2986 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
2987 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
2988 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
2989 host_impl_->ScrollEnd(); | |
2990 | |
2991 EXPECT_FLOAT_EQ(scroll_delta.y(), | |
2992 top_controls_height_ - | |
2993 host_impl_->top_controls_manager()->ContentTopOffset()); | |
2994 | |
2995 // Top controls were hidden by 25px so the inner viewport should have expanded | |
2996 // by that much. | |
2997 LayerImpl* outer_container = | |
2998 host_impl_->active_tree()->OuterViewportContainerLayer(); | |
2999 LayerImpl* inner_container = | |
3000 host_impl_->active_tree()->InnerViewportContainerLayer(); | |
3001 EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling()); | |
3002 | |
3003 // Outer viewport should match inner's aspect ratio. The bounds are ceiled. | |
3004 float aspect_ratio = inner_container->BoundsForScrolling().width() / | |
3005 inner_container->BoundsForScrolling().height(); | |
3006 gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio)); | |
3007 EXPECT_EQ(expected, outer_container->BoundsForScrolling()); | |
3008 EXPECT_EQ(expected, | |
3009 host_impl_->InnerViewportScrollLayer()->BoundsForScrolling()); | |
3010 } | |
3011 | |
3012 // Test that scrolling the outer viewport affects the top controls. | |
3013 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) { | |
3014 SetupTopControlsAndScrollLayerWithVirtualViewport( | |
3015 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400)); | |
3016 DrawFrame(); | |
3017 | |
3018 EXPECT_EQ(top_controls_height_, | |
3019 host_impl_->top_controls_manager()->ContentTopOffset()); | |
3020 | |
3021 // Send a gesture scroll that will scroll the outer viewport, make sure the | |
3022 // top controls get scrolled. | |
3023 gfx::Vector2dF scroll_delta(0.f, 15.f); | |
3024 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3025 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
3026 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3027 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(), | |
3028 host_impl_->CurrentlyScrollingLayer()); | |
3029 host_impl_->ScrollEnd(); | |
3030 | |
3031 EXPECT_FLOAT_EQ(scroll_delta.y(), | |
3032 top_controls_height_ - | |
3033 host_impl_->top_controls_manager()->ContentTopOffset()); | |
3034 | |
3035 scroll_delta = gfx::Vector2dF(0.f, 50.f); | |
3036 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3037 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
3038 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3039 | |
3040 EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset()); | |
3041 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(), | |
3042 host_impl_->CurrentlyScrollingLayer()); | |
3043 | |
3044 host_impl_->ScrollEnd(); | |
3045 | |
3046 // Position the viewports such that the inner viewport will be scrolled. | |
3047 gfx::Vector2dF inner_viewport_offset(0.f, 25.f); | |
3048 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF()); | |
3049 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset); | |
3050 | |
3051 scroll_delta = gfx::Vector2dF(0.f, -65.f); | |
3052 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3053 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
3054 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3055 | |
3056 EXPECT_EQ(top_controls_height_, | |
3057 host_impl_->top_controls_manager()->ContentTopOffset()); | |
3058 EXPECT_FLOAT_EQ( | |
3059 inner_viewport_offset.y() + (scroll_delta.y() + top_controls_height_), | |
3060 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y()); | |
3061 | |
3062 host_impl_->ScrollEnd(); | |
3063 } | |
3064 | |
3065 TEST_F(LayerTreeHostImplTopControlsTest, | |
3066 ScrollNonScrollableRootWithTopControls) { | |
3067 CreateHostImpl(settings_, CreateOutputSurface()); | |
3068 SetupTopControlsAndScrollLayer(); | |
3069 DrawFrame(); | |
3070 | |
3071 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3072 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
3073 | |
3074 host_impl_->top_controls_manager()->ScrollBegin(); | |
3075 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f)); | |
3076 host_impl_->top_controls_manager()->ScrollEnd(); | |
3077 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset()); | |
3078 // Now that top controls have moved, expect the clip to resize. | |
3079 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer(); | |
3080 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds()); | |
3081 | |
3082 host_impl_->ScrollEnd(); | |
3083 | |
3084 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3085 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
3086 | |
3087 float scroll_increment_y = -25.f; | |
3088 host_impl_->top_controls_manager()->ScrollBegin(); | |
3089 host_impl_->top_controls_manager()->ScrollBy( | |
3090 gfx::Vector2dF(0.f, scroll_increment_y)); | |
3091 EXPECT_FLOAT_EQ(-scroll_increment_y, | |
3092 host_impl_->top_controls_manager()->ContentTopOffset()); | |
3093 // Now that top controls have moved, expect the clip to resize. | |
3094 EXPECT_EQ(gfx::Size(viewport_size_.width(), | |
3095 viewport_size_.height() + scroll_increment_y), | |
3096 root_clip_ptr->bounds()); | |
3097 | |
3098 host_impl_->top_controls_manager()->ScrollBy( | |
3099 gfx::Vector2dF(0.f, scroll_increment_y)); | |
3100 host_impl_->top_controls_manager()->ScrollEnd(); | |
3101 EXPECT_FLOAT_EQ(-2 * scroll_increment_y, | |
3102 host_impl_->top_controls_manager()->ContentTopOffset()); | |
3103 // Now that top controls have moved, expect the clip to resize. | |
3104 EXPECT_EQ(clip_size_, root_clip_ptr->bounds()); | |
3105 | |
3106 host_impl_->ScrollEnd(); | |
3107 | |
3108 // Verify the layer is once-again non-scrollable. | |
3109 EXPECT_EQ( | |
3110 gfx::ScrollOffset(), | |
3111 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset()); | |
3112 | |
3113 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3114 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
3115 } | |
3116 | |
3117 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) { | |
3118 // Test the configuration where a non-composited root layer is embedded in a | |
3119 // scrollable outer layer. | |
3120 gfx::Size surface_size(10, 10); | |
3121 gfx::Size contents_size(20, 20); | |
3122 | |
3123 scoped_ptr<LayerImpl> content_layer = | |
3124 LayerImpl::Create(host_impl_->active_tree(), 1); | |
3125 content_layer->SetDrawsContent(true); | |
3126 content_layer->SetPosition(gfx::PointF()); | |
3127 content_layer->SetBounds(contents_size); | |
3128 content_layer->SetContentBounds(contents_size); | |
3129 content_layer->SetContentsScale(2.f, 2.f); | |
3130 | |
3131 scoped_ptr<LayerImpl> scroll_clip_layer = | |
3132 LayerImpl::Create(host_impl_->active_tree(), 3); | |
3133 scroll_clip_layer->SetBounds(surface_size); | |
3134 | |
3135 scoped_ptr<LayerImpl> scroll_layer = | |
3136 LayerImpl::Create(host_impl_->active_tree(), 2); | |
3137 scroll_layer->SetScrollClipLayer(3); | |
3138 scroll_layer->SetBounds(contents_size); | |
3139 scroll_layer->SetContentBounds(contents_size); | |
3140 scroll_layer->SetPosition(gfx::PointF()); | |
3141 scroll_layer->AddChild(content_layer.Pass()); | |
3142 scroll_clip_layer->AddChild(scroll_layer.Pass()); | |
3143 | |
3144 scroll_clip_layer->SetHasRenderSurface(true); | |
3145 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass()); | |
3146 host_impl_->SetViewportSize(surface_size); | |
3147 DrawFrame(); | |
3148 | |
3149 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3150 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL)); | |
3151 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); | |
3152 host_impl_->ScrollEnd(); | |
3153 EXPECT_TRUE(did_request_redraw_); | |
3154 EXPECT_TRUE(did_request_commit_); | |
3155 } | |
3156 | |
3157 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) { | |
3158 gfx::Size surface_size(10, 10); | |
3159 gfx::Size contents_size(20, 20); | |
3160 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1); | |
3161 root->SetBounds(surface_size); | |
3162 root->SetContentBounds(contents_size); | |
3163 root->AddChild(CreateScrollableLayer(2, contents_size, root.get())); | |
3164 root->SetHasRenderSurface(true); | |
3165 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
3166 host_impl_->SetViewportSize(surface_size); | |
3167 DrawFrame(); | |
3168 | |
3169 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3170 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL)); | |
3171 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); | |
3172 host_impl_->ScrollEnd(); | |
3173 EXPECT_TRUE(did_request_redraw_); | |
3174 EXPECT_TRUE(did_request_commit_); | |
3175 } | |
3176 | |
3177 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) { | |
3178 gfx::Size surface_size(10, 10); | |
3179 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1); | |
3180 root->AddChild(CreateScrollableLayer(2, surface_size, root.get())); | |
3181 root->SetHasRenderSurface(true); | |
3182 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
3183 host_impl_->SetViewportSize(surface_size); | |
3184 DrawFrame(); | |
3185 | |
3186 // Scroll event is ignored because the input coordinate is outside the layer | |
3187 // boundaries. | |
3188 EXPECT_EQ(InputHandler::SCROLL_IGNORED, | |
3189 host_impl_->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL)); | |
3190 EXPECT_FALSE(did_request_redraw_); | |
3191 EXPECT_FALSE(did_request_commit_); | |
3192 } | |
3193 | |
3194 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) { | |
3195 gfx::Size surface_size(10, 10); | |
3196 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1); | |
3197 root->SetHasRenderSurface(true); | |
3198 scoped_ptr<LayerImpl> child = | |
3199 CreateScrollableLayer(2, surface_size, root.get()); | |
3200 host_impl_->SetViewportSize(surface_size); | |
3201 | |
3202 gfx::Transform matrix; | |
3203 matrix.RotateAboutXAxis(180.0); | |
3204 child->SetTransform(matrix); | |
3205 child->SetDoubleSided(false); | |
3206 | |
3207 root->AddChild(child.Pass()); | |
3208 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
3209 DrawFrame(); | |
3210 | |
3211 // Scroll event is ignored because the scrollable layer is not facing the | |
3212 // viewer and there is nothing scrollable behind it. | |
3213 EXPECT_EQ(InputHandler::SCROLL_IGNORED, | |
3214 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL)); | |
3215 EXPECT_FALSE(did_request_redraw_); | |
3216 EXPECT_FALSE(did_request_commit_); | |
3217 } | |
3218 | |
3219 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) { | |
3220 gfx::Size surface_size(10, 10); | |
3221 scoped_ptr<LayerImpl> clip_layer = | |
3222 LayerImpl::Create(host_impl_->active_tree(), 3); | |
3223 scoped_ptr<LayerImpl> content_layer = | |
3224 CreateScrollableLayer(1, surface_size, clip_layer.get()); | |
3225 content_layer->SetShouldScrollOnMainThread(true); | |
3226 content_layer->SetScrollClipLayer(Layer::INVALID_ID); | |
3227 | |
3228 // Note: we can use the same clip layer for both since both calls to | |
3229 // CreateScrollableLayer() use the same surface size. | |
3230 scoped_ptr<LayerImpl> scroll_layer = | |
3231 CreateScrollableLayer(2, surface_size, clip_layer.get()); | |
3232 scroll_layer->AddChild(content_layer.Pass()); | |
3233 clip_layer->AddChild(scroll_layer.Pass()); | |
3234 clip_layer->SetHasRenderSurface(true); | |
3235 | |
3236 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass()); | |
3237 host_impl_->SetViewportSize(surface_size); | |
3238 DrawFrame(); | |
3239 | |
3240 // Scrolling fails because the content layer is asking to be scrolled on the | |
3241 // main thread. | |
3242 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, | |
3243 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL)); | |
3244 } | |
3245 | |
3246 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) { | |
3247 gfx::Size surface_size(20, 20); | |
3248 gfx::Size viewport_size(10, 10); | |
3249 float page_scale = 2.f; | |
3250 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1); | |
3251 scoped_ptr<LayerImpl> root_clip = | |
3252 LayerImpl::Create(host_impl_->active_tree(), 2); | |
3253 scoped_ptr<LayerImpl> root_scrolling = | |
3254 CreateScrollableLayer(3, surface_size, root_clip.get()); | |
3255 EXPECT_EQ(viewport_size, root_clip->bounds()); | |
3256 root_scrolling->SetIsContainerForFixedPositionLayers(true); | |
3257 root_clip->AddChild(root_scrolling.Pass()); | |
3258 root->AddChild(root_clip.Pass()); | |
3259 root->SetHasRenderSurface(true); | |
3260 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
3261 // The behaviour in this test assumes the page scale is applied at a layer | |
3262 // above the clip layer. | |
3263 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3, | |
3264 Layer::INVALID_ID); | |
3265 host_impl_->active_tree()->DidBecomeActive(); | |
3266 host_impl_->SetViewportSize(viewport_size); | |
3267 DrawFrame(); | |
3268 | |
3269 LayerImpl* root_scroll = | |
3270 host_impl_->active_tree()->InnerViewportScrollLayer(); | |
3271 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds()); | |
3272 | |
3273 gfx::Vector2d scroll_delta(0, 10); | |
3274 gfx::Vector2d expected_scroll_delta = scroll_delta; | |
3275 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset(); | |
3276 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3277 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL)); | |
3278 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3279 host_impl_->ScrollEnd(); | |
3280 | |
3281 // Set new page scale from main thread. | |
3282 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, page_scale, | |
3283 page_scale); | |
3284 | |
3285 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); | |
3286 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta); | |
3287 | |
3288 // The scroll range should also have been updated. | |
3289 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset()); | |
3290 | |
3291 // The page scale delta remains constant because the impl thread did not | |
3292 // scale. | |
3293 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta()); | |
3294 } | |
3295 | |
3296 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) { | |
3297 gfx::Size surface_size(20, 20); | |
3298 gfx::Size viewport_size(10, 10); | |
3299 float page_scale = 2.f; | |
3300 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1); | |
3301 scoped_ptr<LayerImpl> root_clip = | |
3302 LayerImpl::Create(host_impl_->active_tree(), 2); | |
3303 scoped_ptr<LayerImpl> root_scrolling = | |
3304 CreateScrollableLayer(3, surface_size, root_clip.get()); | |
3305 EXPECT_EQ(viewport_size, root_clip->bounds()); | |
3306 root_scrolling->SetIsContainerForFixedPositionLayers(true); | |
3307 root_clip->AddChild(root_scrolling.Pass()); | |
3308 root->AddChild(root_clip.Pass()); | |
3309 root->SetHasRenderSurface(true); | |
3310 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
3311 // The behaviour in this test assumes the page scale is applied at a layer | |
3312 // above the clip layer. | |
3313 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3, | |
3314 Layer::INVALID_ID); | |
3315 host_impl_->active_tree()->DidBecomeActive(); | |
3316 host_impl_->SetViewportSize(viewport_size); | |
3317 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, page_scale); | |
3318 DrawFrame(); | |
3319 | |
3320 LayerImpl* root_scroll = | |
3321 host_impl_->active_tree()->InnerViewportScrollLayer(); | |
3322 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds()); | |
3323 | |
3324 gfx::Vector2d scroll_delta(0, 10); | |
3325 gfx::Vector2d expected_scroll_delta = scroll_delta; | |
3326 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset(); | |
3327 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3328 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL)); | |
3329 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3330 host_impl_->ScrollEnd(); | |
3331 | |
3332 // Set new page scale on impl thread by pinching. | |
3333 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE); | |
3334 host_impl_->PinchGestureBegin(); | |
3335 host_impl_->PinchGestureUpdate(page_scale, gfx::Point()); | |
3336 host_impl_->PinchGestureEnd(); | |
3337 host_impl_->ScrollEnd(); | |
3338 DrawOneFrame(); | |
3339 | |
3340 // The scroll delta is not scaled because the main thread did not scale. | |
3341 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); | |
3342 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta); | |
3343 | |
3344 // The scroll range should also have been updated. | |
3345 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset()); | |
3346 | |
3347 // The page scale delta should match the new scale on the impl side. | |
3348 EXPECT_EQ(page_scale, host_impl_->active_tree()->current_page_scale_factor()); | |
3349 } | |
3350 | |
3351 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) { | |
3352 gfx::Size surface_size(10, 10); | |
3353 float default_page_scale = 1.f; | |
3354 gfx::Transform default_page_scale_matrix; | |
3355 default_page_scale_matrix.Scale(default_page_scale, default_page_scale); | |
3356 | |
3357 float new_page_scale = 2.f; | |
3358 gfx::Transform new_page_scale_matrix; | |
3359 new_page_scale_matrix.Scale(new_page_scale, new_page_scale); | |
3360 | |
3361 // Create a normal scrollable root layer and another scrollable child layer. | |
3362 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size); | |
3363 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
3364 LayerImpl* child = scroll->children()[0]; | |
3365 | |
3366 scoped_ptr<LayerImpl> scrollable_child_clip = | |
3367 LayerImpl::Create(host_impl_->active_tree(), 6); | |
3368 scoped_ptr<LayerImpl> scrollable_child = | |
3369 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get()); | |
3370 scrollable_child_clip->AddChild(scrollable_child.Pass()); | |
3371 child->AddChild(scrollable_child_clip.Pass()); | |
3372 LayerImpl* grand_child = child->children()[0]; | |
3373 | |
3374 // Set new page scale on impl thread by pinching. | |
3375 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE); | |
3376 host_impl_->PinchGestureBegin(); | |
3377 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point()); | |
3378 host_impl_->PinchGestureEnd(); | |
3379 host_impl_->ScrollEnd(); | |
3380 DrawOneFrame(); | |
3381 | |
3382 EXPECT_EQ(1.f, root->contents_scale_x()); | |
3383 EXPECT_EQ(1.f, root->contents_scale_y()); | |
3384 EXPECT_EQ(1.f, scroll->contents_scale_x()); | |
3385 EXPECT_EQ(1.f, scroll->contents_scale_y()); | |
3386 EXPECT_EQ(1.f, child->contents_scale_x()); | |
3387 EXPECT_EQ(1.f, child->contents_scale_y()); | |
3388 EXPECT_EQ(1.f, grand_child->contents_scale_x()); | |
3389 EXPECT_EQ(1.f, grand_child->contents_scale_y()); | |
3390 | |
3391 // Make sure all the layers are drawn with the page scale delta applied, i.e., | |
3392 // the page scale delta on the root layer is applied hierarchically. | |
3393 LayerTreeHostImpl::FrameData frame; | |
3394 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
3395 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
3396 host_impl_->DidDrawAllLayers(frame); | |
3397 | |
3398 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0)); | |
3399 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1)); | |
3400 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0)); | |
3401 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1)); | |
3402 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0)); | |
3403 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1)); | |
3404 EXPECT_EQ(new_page_scale, | |
3405 grand_child->draw_transform().matrix().getDouble(0, 0)); | |
3406 EXPECT_EQ(new_page_scale, | |
3407 grand_child->draw_transform().matrix().getDouble(1, 1)); | |
3408 } | |
3409 | |
3410 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) { | |
3411 gfx::Size surface_size(30, 30); | |
3412 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1); | |
3413 root->SetBounds(gfx::Size(5, 5)); | |
3414 root->SetHasRenderSurface(true); | |
3415 scoped_ptr<LayerImpl> root_scrolling = | |
3416 LayerImpl::Create(host_impl_->active_tree(), 2); | |
3417 root_scrolling->SetBounds(surface_size); | |
3418 root_scrolling->SetContentBounds(surface_size); | |
3419 root_scrolling->SetScrollClipLayer(root->id()); | |
3420 root_scrolling->SetIsContainerForFixedPositionLayers(true); | |
3421 LayerImpl* root_scrolling_ptr = root_scrolling.get(); | |
3422 root->AddChild(root_scrolling.Pass()); | |
3423 int child_scroll_layer_id = 3; | |
3424 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer( | |
3425 child_scroll_layer_id, surface_size, root_scrolling_ptr); | |
3426 LayerImpl* child = child_scrolling.get(); | |
3427 root_scrolling_ptr->AddChild(child_scrolling.Pass()); | |
3428 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
3429 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2, | |
3430 Layer::INVALID_ID); | |
3431 host_impl_->active_tree()->DidBecomeActive(); | |
3432 host_impl_->SetViewportSize(surface_size); | |
3433 DrawFrame(); | |
3434 | |
3435 gfx::Vector2d scroll_delta(0, 10); | |
3436 gfx::Vector2d expected_scroll_delta(scroll_delta); | |
3437 gfx::ScrollOffset expected_max_scroll(child->MaxScrollOffset()); | |
3438 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3439 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL)); | |
3440 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3441 host_impl_->ScrollEnd(); | |
3442 | |
3443 float page_scale = 2.f; | |
3444 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, | |
3445 page_scale); | |
3446 | |
3447 DrawOneFrame(); | |
3448 | |
3449 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); | |
3450 ExpectContains( | |
3451 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta); | |
3452 | |
3453 // The scroll range should not have changed. | |
3454 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll); | |
3455 | |
3456 // The page scale delta remains constant because the impl thread did not | |
3457 // scale. | |
3458 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta()); | |
3459 } | |
3460 | |
3461 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) { | |
3462 // Scroll a child layer beyond its maximum scroll range and make sure the | |
3463 // parent layer is scrolled on the axis on which the child was unable to | |
3464 // scroll. | |
3465 gfx::Size surface_size(10, 10); | |
3466 gfx::Size content_size(20, 20); | |
3467 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1); | |
3468 root->SetBounds(surface_size); | |
3469 root->SetHasRenderSurface(true); | |
3470 scoped_ptr<LayerImpl> grand_child = | |
3471 CreateScrollableLayer(3, content_size, root.get()); | |
3472 | |
3473 scoped_ptr<LayerImpl> child = | |
3474 CreateScrollableLayer(2, content_size, root.get()); | |
3475 LayerImpl* grand_child_layer = grand_child.get(); | |
3476 child->AddChild(grand_child.Pass()); | |
3477 | |
3478 LayerImpl* child_layer = child.get(); | |
3479 root->AddChild(child.Pass()); | |
3480 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
3481 host_impl_->active_tree()->DidBecomeActive(); | |
3482 host_impl_->SetViewportSize(surface_size); | |
3483 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5)); | |
3484 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0)); | |
3485 | |
3486 DrawFrame(); | |
3487 { | |
3488 gfx::Vector2d scroll_delta(-8, -7); | |
3489 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3490 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
3491 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3492 host_impl_->ScrollEnd(); | |
3493 | |
3494 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
3495 host_impl_->ProcessScrollDeltas(); | |
3496 | |
3497 // The grand child should have scrolled up to its limit. | |
3498 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0]; | |
3499 LayerImpl* grand_child = child->children()[0]; | |
3500 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5)); | |
3501 | |
3502 // The child should have only scrolled on the other axis. | |
3503 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0)); | |
3504 } | |
3505 } | |
3506 | |
3507 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) { | |
3508 // Scroll a child layer beyond its maximum scroll range and make sure the | |
3509 // the scroll doesn't bubble up to the parent layer. | |
3510 gfx::Size surface_size(20, 20); | |
3511 gfx::Size viewport_size(10, 10); | |
3512 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1); | |
3513 root->SetHasRenderSurface(true); | |
3514 scoped_ptr<LayerImpl> root_scrolling = | |
3515 CreateScrollableLayer(2, surface_size, root.get()); | |
3516 root_scrolling->SetIsContainerForFixedPositionLayers(true); | |
3517 | |
3518 scoped_ptr<LayerImpl> grand_child = | |
3519 CreateScrollableLayer(4, surface_size, root.get()); | |
3520 | |
3521 scoped_ptr<LayerImpl> child = | |
3522 CreateScrollableLayer(3, surface_size, root.get()); | |
3523 LayerImpl* grand_child_layer = grand_child.get(); | |
3524 child->AddChild(grand_child.Pass()); | |
3525 | |
3526 LayerImpl* child_layer = child.get(); | |
3527 root_scrolling->AddChild(child.Pass()); | |
3528 root->AddChild(root_scrolling.Pass()); | |
3529 EXPECT_EQ(viewport_size, root->bounds()); | |
3530 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
3531 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2, | |
3532 Layer::INVALID_ID); | |
3533 host_impl_->active_tree()->DidBecomeActive(); | |
3534 host_impl_->SetViewportSize(viewport_size); | |
3535 | |
3536 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2)); | |
3537 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3)); | |
3538 | |
3539 DrawFrame(); | |
3540 { | |
3541 gfx::Vector2d scroll_delta(0, -10); | |
3542 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3543 host_impl_->ScrollBegin(gfx::Point(), | |
3544 InputHandler::NON_BUBBLING_GESTURE)); | |
3545 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3546 host_impl_->ScrollEnd(); | |
3547 | |
3548 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
3549 host_impl_->ProcessScrollDeltas(); | |
3550 | |
3551 // The grand child should have scrolled up to its limit. | |
3552 LayerImpl* child = | |
3553 host_impl_->active_tree()->root_layer()->children()[0]->children()[0]; | |
3554 LayerImpl* grand_child = child->children()[0]; | |
3555 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2)); | |
3556 | |
3557 // The child should not have scrolled. | |
3558 ExpectNone(*scroll_info.get(), child->id()); | |
3559 | |
3560 // The next time we scroll we should only scroll the parent. | |
3561 scroll_delta = gfx::Vector2d(0, -3); | |
3562 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3563 host_impl_->ScrollBegin(gfx::Point(5, 5), | |
3564 InputHandler::NON_BUBBLING_GESTURE)); | |
3565 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child); | |
3566 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3567 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child); | |
3568 host_impl_->ScrollEnd(); | |
3569 | |
3570 scroll_info = host_impl_->ProcessScrollDeltas(); | |
3571 | |
3572 // The child should have scrolled up to its limit. | |
3573 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3)); | |
3574 | |
3575 // The grand child should not have scrolled. | |
3576 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2)); | |
3577 | |
3578 // After scrolling the parent, another scroll on the opposite direction | |
3579 // should still scroll the child. | |
3580 scroll_delta = gfx::Vector2d(0, 7); | |
3581 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3582 host_impl_->ScrollBegin(gfx::Point(5, 5), | |
3583 InputHandler::NON_BUBBLING_GESTURE)); | |
3584 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child); | |
3585 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3586 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child); | |
3587 host_impl_->ScrollEnd(); | |
3588 | |
3589 scroll_info = host_impl_->ProcessScrollDeltas(); | |
3590 | |
3591 // The grand child should have scrolled. | |
3592 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5)); | |
3593 | |
3594 // The child should not have scrolled. | |
3595 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3)); | |
3596 | |
3597 | |
3598 // Scrolling should be adjusted from viewport space. | |
3599 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 2.f, 2.f); | |
3600 host_impl_->SetPageScaleOnActiveTree(2.f); | |
3601 | |
3602 scroll_delta = gfx::Vector2d(0, -2); | |
3603 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3604 host_impl_->ScrollBegin(gfx::Point(1, 1), | |
3605 InputHandler::NON_BUBBLING_GESTURE)); | |
3606 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer()); | |
3607 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3608 host_impl_->ScrollEnd(); | |
3609 | |
3610 scroll_info = host_impl_->ProcessScrollDeltas(); | |
3611 | |
3612 // Should have scrolled by half the amount in layer space (5 - 2/2) | |
3613 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4)); | |
3614 } | |
3615 } | |
3616 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) { | |
3617 // When we try to scroll a non-scrollable child layer, the scroll delta | |
3618 // should be applied to one of its ancestors if possible. | |
3619 gfx::Size surface_size(10, 10); | |
3620 gfx::Size content_size(20, 20); | |
3621 scoped_ptr<LayerImpl> root_clip = | |
3622 LayerImpl::Create(host_impl_->active_tree(), 3); | |
3623 root_clip->SetHasRenderSurface(true); | |
3624 scoped_ptr<LayerImpl> root = | |
3625 CreateScrollableLayer(1, content_size, root_clip.get()); | |
3626 // Make 'root' the clip layer for child: since they have the same sizes the | |
3627 // child will have zero max_scroll_offset and scrolls will bubble. | |
3628 scoped_ptr<LayerImpl> child = | |
3629 CreateScrollableLayer(2, content_size, root.get()); | |
3630 child->SetIsContainerForFixedPositionLayers(true); | |
3631 root->SetBounds(content_size); | |
3632 | |
3633 int root_scroll_id = root->id(); | |
3634 root->AddChild(child.Pass()); | |
3635 root_clip->AddChild(root.Pass()); | |
3636 | |
3637 host_impl_->SetViewportSize(surface_size); | |
3638 host_impl_->active_tree()->SetRootLayer(root_clip.Pass()); | |
3639 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 2, | |
3640 Layer::INVALID_ID); | |
3641 host_impl_->active_tree()->DidBecomeActive(); | |
3642 DrawFrame(); | |
3643 { | |
3644 gfx::Vector2d scroll_delta(0, 4); | |
3645 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3646 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL)); | |
3647 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3648 host_impl_->ScrollEnd(); | |
3649 | |
3650 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
3651 host_impl_->ProcessScrollDeltas(); | |
3652 | |
3653 // Only the root scroll should have scrolled. | |
3654 ASSERT_EQ(scroll_info->scrolls.size(), 1u); | |
3655 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta); | |
3656 } | |
3657 } | |
3658 | |
3659 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) { | |
3660 gfx::Size surface_size(10, 10); | |
3661 scoped_ptr<LayerImpl> root_clip = | |
3662 LayerImpl::Create(host_impl_->active_tree(), 1); | |
3663 scoped_ptr<LayerImpl> root_scroll = | |
3664 CreateScrollableLayer(2, surface_size, root_clip.get()); | |
3665 root_scroll->SetIsContainerForFixedPositionLayers(true); | |
3666 root_clip->SetHasRenderSurface(true); | |
3667 root_clip->AddChild(root_scroll.Pass()); | |
3668 host_impl_->active_tree()->SetRootLayer(root_clip.Pass()); | |
3669 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2, | |
3670 Layer::INVALID_ID); | |
3671 host_impl_->active_tree()->DidBecomeActive(); | |
3672 host_impl_->SetViewportSize(surface_size); | |
3673 | |
3674 // Draw one frame and then immediately rebuild the layer tree to mimic a tree | |
3675 // synchronization. | |
3676 DrawFrame(); | |
3677 host_impl_->active_tree()->DetachLayerTree(); | |
3678 scoped_ptr<LayerImpl> root_clip2 = | |
3679 LayerImpl::Create(host_impl_->active_tree(), 3); | |
3680 scoped_ptr<LayerImpl> root_scroll2 = | |
3681 CreateScrollableLayer(4, surface_size, root_clip2.get()); | |
3682 root_scroll2->SetIsContainerForFixedPositionLayers(true); | |
3683 root_clip2->AddChild(root_scroll2.Pass()); | |
3684 root_clip2->SetHasRenderSurface(true); | |
3685 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass()); | |
3686 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 4, | |
3687 Layer::INVALID_ID); | |
3688 host_impl_->active_tree()->DidBecomeActive(); | |
3689 | |
3690 // Scrolling should still work even though we did not draw yet. | |
3691 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3692 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL)); | |
3693 } | |
3694 | |
3695 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) { | |
3696 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
3697 | |
3698 // Rotate the root layer 90 degrees counter-clockwise about its center. | |
3699 gfx::Transform rotate_transform; | |
3700 rotate_transform.Rotate(-90.0); | |
3701 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform); | |
3702 | |
3703 gfx::Size surface_size(50, 50); | |
3704 host_impl_->SetViewportSize(surface_size); | |
3705 DrawFrame(); | |
3706 | |
3707 // Scroll to the right in screen coordinates with a gesture. | |
3708 gfx::Vector2d gesture_scroll_delta(10, 0); | |
3709 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3710 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
3711 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta); | |
3712 host_impl_->ScrollEnd(); | |
3713 | |
3714 // The layer should have scrolled down in its local coordinates. | |
3715 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); | |
3716 ExpectContains(*scroll_info.get(), scroll_layer->id(), | |
3717 gfx::Vector2d(0, gesture_scroll_delta.x())); | |
3718 | |
3719 // Reset and scroll down with the wheel. | |
3720 scroll_layer->SetScrollDelta(gfx::Vector2dF()); | |
3721 gfx::Vector2d wheel_scroll_delta(0, 10); | |
3722 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3723 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
3724 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta); | |
3725 host_impl_->ScrollEnd(); | |
3726 | |
3727 // The layer should have scrolled down in its local coordinates. | |
3728 scroll_info = host_impl_->ProcessScrollDeltas(); | |
3729 ExpectContains(*scroll_info.get(), | |
3730 scroll_layer->id(), | |
3731 wheel_scroll_delta); | |
3732 } | |
3733 | |
3734 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) { | |
3735 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
3736 int child_clip_layer_id = 6; | |
3737 int child_layer_id = 7; | |
3738 float child_layer_angle = -20.f; | |
3739 | |
3740 // Create a child layer that is rotated to a non-axis-aligned angle. | |
3741 scoped_ptr<LayerImpl> clip_layer = | |
3742 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id); | |
3743 scoped_ptr<LayerImpl> child = CreateScrollableLayer( | |
3744 child_layer_id, scroll_layer->content_bounds(), clip_layer.get()); | |
3745 gfx::Transform rotate_transform; | |
3746 rotate_transform.Translate(-50.0, -50.0); | |
3747 rotate_transform.Rotate(child_layer_angle); | |
3748 rotate_transform.Translate(50.0, 50.0); | |
3749 clip_layer->SetTransform(rotate_transform); | |
3750 | |
3751 // Only allow vertical scrolling. | |
3752 clip_layer->SetBounds( | |
3753 gfx::Size(child->bounds().width(), child->bounds().height() / 2)); | |
3754 // The rotation depends on the layer's transform origin, and the child layer | |
3755 // is a different size than the clip, so make sure the clip layer's origin | |
3756 // lines up over the child. | |
3757 clip_layer->SetTransformOrigin(gfx::Point3F( | |
3758 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f)); | |
3759 LayerImpl* child_ptr = child.get(); | |
3760 clip_layer->AddChild(child.Pass()); | |
3761 scroll_layer->AddChild(clip_layer.Pass()); | |
3762 | |
3763 gfx::Size surface_size(50, 50); | |
3764 host_impl_->SetViewportSize(surface_size); | |
3765 DrawFrame(); | |
3766 { | |
3767 // Scroll down in screen coordinates with a gesture. | |
3768 gfx::Vector2d gesture_scroll_delta(0, 10); | |
3769 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3770 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE)); | |
3771 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta); | |
3772 host_impl_->ScrollEnd(); | |
3773 | |
3774 // The child layer should have scrolled down in its local coordinates an | |
3775 // amount proportional to the angle between it and the input scroll delta. | |
3776 gfx::Vector2d expected_scroll_delta( | |
3777 0, gesture_scroll_delta.y() * | |
3778 std::cos(MathUtil::Deg2Rad(child_layer_angle))); | |
3779 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
3780 host_impl_->ProcessScrollDeltas(); | |
3781 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta); | |
3782 | |
3783 // The root scroll layer should not have scrolled, because the input delta | |
3784 // was close to the layer's axis of movement. | |
3785 EXPECT_EQ(scroll_info->scrolls.size(), 1u); | |
3786 } | |
3787 { | |
3788 // Now reset and scroll the same amount horizontally. | |
3789 child_ptr->SetScrollDelta(gfx::Vector2dF()); | |
3790 gfx::Vector2d gesture_scroll_delta(10, 0); | |
3791 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3792 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE)); | |
3793 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta); | |
3794 host_impl_->ScrollEnd(); | |
3795 | |
3796 // The child layer should have scrolled down in its local coordinates an | |
3797 // amount proportional to the angle between it and the input scroll delta. | |
3798 gfx::Vector2d expected_scroll_delta( | |
3799 0, -gesture_scroll_delta.x() * | |
3800 std::sin(MathUtil::Deg2Rad(child_layer_angle))); | |
3801 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
3802 host_impl_->ProcessScrollDeltas(); | |
3803 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta); | |
3804 | |
3805 // The root scroll layer should have scrolled more, since the input scroll | |
3806 // delta was mostly orthogonal to the child layer's vertical scroll axis. | |
3807 gfx::Vector2d expected_root_scroll_delta( | |
3808 gesture_scroll_delta.x() * | |
3809 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2), | |
3810 0); | |
3811 ExpectContains(*scroll_info.get(), | |
3812 scroll_layer->id(), | |
3813 expected_root_scroll_delta); | |
3814 } | |
3815 } | |
3816 | |
3817 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) { | |
3818 LayerImpl* scroll_layer = | |
3819 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
3820 | |
3821 // Scale the layer to twice its normal size. | |
3822 int scale = 2; | |
3823 gfx::Transform scale_transform; | |
3824 scale_transform.Scale(scale, scale); | |
3825 scroll_layer->SetTransform(scale_transform); | |
3826 | |
3827 gfx::Size surface_size(50, 50); | |
3828 host_impl_->SetViewportSize(surface_size); | |
3829 DrawFrame(); | |
3830 | |
3831 // Scroll down in screen coordinates with a gesture. | |
3832 gfx::Vector2d scroll_delta(0, 10); | |
3833 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3834 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
3835 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
3836 host_impl_->ScrollEnd(); | |
3837 | |
3838 // The layer should have scrolled down in its local coordinates, but half the | |
3839 // amount. | |
3840 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); | |
3841 ExpectContains(*scroll_info.get(), | |
3842 scroll_layer->id(), | |
3843 gfx::Vector2d(0, scroll_delta.y() / scale)); | |
3844 | |
3845 // Reset and scroll down with the wheel. | |
3846 scroll_layer->SetScrollDelta(gfx::Vector2dF()); | |
3847 gfx::Vector2d wheel_scroll_delta(0, 10); | |
3848 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
3849 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
3850 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta); | |
3851 host_impl_->ScrollEnd(); | |
3852 | |
3853 // It should apply the scale factor to the scroll delta for the wheel event. | |
3854 scroll_info = host_impl_->ProcessScrollDeltas(); | |
3855 ExpectContains(*scroll_info.get(), | |
3856 scroll_layer->id(), | |
3857 wheel_scroll_delta); | |
3858 } | |
3859 | |
3860 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) { | |
3861 int width = 332; | |
3862 int height = 20; | |
3863 int scale = 3; | |
3864 SetupScrollAndContentsLayers(gfx::Size(width, height)); | |
3865 host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds( | |
3866 gfx::Size(width * scale - 1, height * scale)); | |
3867 host_impl_->SetDeviceScaleFactor(scale); | |
3868 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f); | |
3869 | |
3870 LayerImpl* inner_viewport_scroll_layer = | |
3871 host_impl_->active_tree()->InnerViewportScrollLayer(); | |
3872 EXPECT_EQ(gfx::ScrollOffset(0, 0), | |
3873 inner_viewport_scroll_layer->MaxScrollOffset()); | |
3874 } | |
3875 | |
3876 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate { | |
3877 public: | |
3878 TestScrollOffsetDelegate() | |
3879 : page_scale_factor_(0.f), | |
3880 min_page_scale_factor_(-1.f), | |
3881 max_page_scale_factor_(-1.f) {} | |
3882 | |
3883 ~TestScrollOffsetDelegate() override {} | |
3884 | |
3885 gfx::ScrollOffset GetTotalScrollOffset() override { | |
3886 return getter_return_value_; | |
3887 } | |
3888 | |
3889 bool IsExternalFlingActive() const override { return false; } | |
3890 | |
3891 void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset, | |
3892 const gfx::ScrollOffset& max_scroll_offset, | |
3893 const gfx::SizeF& scrollable_size, | |
3894 float page_scale_factor, | |
3895 float min_page_scale_factor, | |
3896 float max_page_scale_factor) override { | |
3897 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x()); | |
3898 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y()); | |
3899 last_set_scroll_offset_ = total_scroll_offset; | |
3900 max_scroll_offset_ = max_scroll_offset; | |
3901 scrollable_size_ = scrollable_size; | |
3902 page_scale_factor_ = page_scale_factor; | |
3903 min_page_scale_factor_ = min_page_scale_factor; | |
3904 max_page_scale_factor_ = max_page_scale_factor; | |
3905 | |
3906 set_getter_return_value(last_set_scroll_offset_); | |
3907 } | |
3908 | |
3909 gfx::ScrollOffset last_set_scroll_offset() { | |
3910 return last_set_scroll_offset_; | |
3911 } | |
3912 | |
3913 void set_getter_return_value(const gfx::ScrollOffset& value) { | |
3914 getter_return_value_ = value; | |
3915 } | |
3916 | |
3917 gfx::ScrollOffset max_scroll_offset() const { | |
3918 return max_scroll_offset_; | |
3919 } | |
3920 | |
3921 gfx::SizeF scrollable_size() const { | |
3922 return scrollable_size_; | |
3923 } | |
3924 | |
3925 float page_scale_factor() const { | |
3926 return page_scale_factor_; | |
3927 } | |
3928 | |
3929 float min_page_scale_factor() const { | |
3930 return min_page_scale_factor_; | |
3931 } | |
3932 | |
3933 float max_page_scale_factor() const { | |
3934 return max_page_scale_factor_; | |
3935 } | |
3936 | |
3937 private: | |
3938 gfx::ScrollOffset last_set_scroll_offset_; | |
3939 gfx::ScrollOffset getter_return_value_; | |
3940 gfx::ScrollOffset max_scroll_offset_; | |
3941 gfx::SizeF scrollable_size_; | |
3942 float page_scale_factor_; | |
3943 float min_page_scale_factor_; | |
3944 float max_page_scale_factor_; | |
3945 }; | |
3946 | |
3947 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { | |
3948 TestScrollOffsetDelegate scroll_delegate; | |
3949 host_impl_->SetViewportSize(gfx::Size(10, 20)); | |
3950 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
3951 LayerImpl* clip_layer = scroll_layer->parent()->parent(); | |
3952 clip_layer->SetBounds(gfx::Size(10, 20)); | |
3953 | |
3954 // Setting the delegate results in the current scroll offset being set. | |
3955 gfx::Vector2dF initial_scroll_delta(10.f, 10.f); | |
3956 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset()); | |
3957 scroll_layer->SetScrollDelta(initial_scroll_delta); | |
3958 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate); | |
3959 EXPECT_EQ(initial_scroll_delta.ToString(), | |
3960 scroll_delegate.last_set_scroll_offset().ToString()); | |
3961 | |
3962 // Setting the delegate results in the scrollable_size, max_scroll_offset, | |
3963 // page_scale_factor and {min|max}_page_scale_factor being set. | |
3964 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size()); | |
3965 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset()); | |
3966 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor()); | |
3967 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor()); | |
3968 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor()); | |
3969 | |
3970 // Updating page scale immediately updates the delegate. | |
3971 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 0.5f, 4.f); | |
3972 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor()); | |
3973 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor()); | |
3974 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor()); | |
3975 host_impl_->SetPageScaleOnActiveTree(2.f * 1.5f); | |
3976 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor()); | |
3977 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor()); | |
3978 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor()); | |
3979 host_impl_->SetPageScaleOnActiveTree(2.f); | |
3980 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f); | |
3981 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor()); | |
3982 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor()); | |
3983 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor()); | |
3984 | |
3985 // The pinch gesture doesn't put the delegate into a state where the scroll | |
3986 // offset is outside of the scroll range. (this is verified by DCHECKs in the | |
3987 // delegate). | |
3988 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE); | |
3989 host_impl_->PinchGestureBegin(); | |
3990 host_impl_->PinchGestureUpdate(2.f, gfx::Point()); | |
3991 host_impl_->PinchGestureUpdate(.5f, gfx::Point()); | |
3992 host_impl_->PinchGestureEnd(); | |
3993 host_impl_->ScrollEnd(); | |
3994 | |
3995 // Scrolling should be relative to the offset as returned by the delegate. | |
3996 gfx::Vector2dF scroll_delta(0.f, 10.f); | |
3997 gfx::ScrollOffset current_offset(7.f, 8.f); | |
3998 | |
3999 scroll_delegate.set_getter_return_value(current_offset); | |
4000 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
4001 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
4002 | |
4003 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
4004 EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta), | |
4005 scroll_delegate.last_set_scroll_offset()); | |
4006 | |
4007 current_offset = gfx::ScrollOffset(42.f, 41.f); | |
4008 scroll_delegate.set_getter_return_value(current_offset); | |
4009 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
4010 EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta), | |
4011 scroll_delegate.last_set_scroll_offset()); | |
4012 host_impl_->ScrollEnd(); | |
4013 scroll_delegate.set_getter_return_value(gfx::ScrollOffset()); | |
4014 | |
4015 // Forces a full tree synchronization and ensures that the scroll delegate | |
4016 // sees the correct size of the new tree. | |
4017 gfx::Size new_size(42, 24); | |
4018 host_impl_->CreatePendingTree(); | |
4019 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size); | |
4020 host_impl_->ActivateSyncTree(); | |
4021 EXPECT_EQ(new_size, scroll_delegate.scrollable_size()); | |
4022 | |
4023 // Un-setting the delegate should propagate the delegate's current offset to | |
4024 // the root scrollable layer. | |
4025 current_offset = gfx::ScrollOffset(13.f, 12.f); | |
4026 scroll_delegate.set_getter_return_value(current_offset); | |
4027 host_impl_->SetRootLayerScrollOffsetDelegate(NULL); | |
4028 | |
4029 EXPECT_EQ(current_offset.ToString(), | |
4030 scroll_layer->CurrentScrollOffset().ToString()); | |
4031 } | |
4032 | |
4033 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) { | |
4034 const gfx::Transform target_space_transform = | |
4035 layer->draw_properties().target_space_transform; | |
4036 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation()); | |
4037 gfx::Point translated_point; | |
4038 target_space_transform.TransformPoint(&translated_point); | |
4039 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta); | |
4040 EXPECT_EQ(expected_point.ToString(), translated_point.ToString()); | |
4041 } | |
4042 | |
4043 TEST_F(LayerTreeHostImplTest, | |
4044 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) { | |
4045 TestScrollOffsetDelegate scroll_delegate; | |
4046 host_impl_->SetViewportSize(gfx::Size(10, 20)); | |
4047 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
4048 LayerImpl* clip_layer = scroll_layer->parent()->parent(); | |
4049 clip_layer->SetBounds(gfx::Size(10, 20)); | |
4050 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate); | |
4051 | |
4052 // Draw first frame to clear any pending draws and check scroll. | |
4053 DrawFrame(); | |
4054 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f)); | |
4055 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties()); | |
4056 | |
4057 // Set external scroll delta on delegate and notify LayerTreeHost. | |
4058 gfx::ScrollOffset scroll_offset(10.f, 10.f); | |
4059 scroll_delegate.set_getter_return_value(scroll_offset); | |
4060 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(); | |
4061 | |
4062 // Check scroll delta reflected in layer. | |
4063 LayerTreeHostImpl::FrameData frame; | |
4064 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4065 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4066 host_impl_->DidDrawAllLayers(frame); | |
4067 EXPECT_FALSE(frame.has_no_damage); | |
4068 CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset)); | |
4069 | |
4070 host_impl_->SetRootLayerScrollOffsetDelegate(NULL); | |
4071 } | |
4072 | |
4073 TEST_F(LayerTreeHostImplTest, OverscrollRoot) { | |
4074 InputHandlerScrollResult scroll_result; | |
4075 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
4076 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
4077 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f); | |
4078 DrawFrame(); | |
4079 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); | |
4080 | |
4081 // In-bounds scrolling does not affect overscroll. | |
4082 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
4083 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
4084 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); | |
4085 EXPECT_TRUE(scroll_result.did_scroll); | |
4086 EXPECT_FALSE(scroll_result.did_overscroll_root); | |
4087 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta); | |
4088 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); | |
4089 | |
4090 // Overscroll events are reflected immediately. | |
4091 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50)); | |
4092 EXPECT_TRUE(scroll_result.did_scroll); | |
4093 EXPECT_TRUE(scroll_result.did_overscroll_root); | |
4094 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta); | |
4095 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll()); | |
4096 EXPECT_EQ(scroll_result.accumulated_root_overscroll, | |
4097 host_impl_->accumulated_root_overscroll()); | |
4098 | |
4099 // In-bounds scrolling resets accumulated overscroll for the scrolled axes. | |
4100 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50)); | |
4101 EXPECT_TRUE(scroll_result.did_scroll); | |
4102 EXPECT_FALSE(scroll_result.did_overscroll_root); | |
4103 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta); | |
4104 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll()); | |
4105 EXPECT_EQ(scroll_result.accumulated_root_overscroll, | |
4106 host_impl_->accumulated_root_overscroll()); | |
4107 | |
4108 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)); | |
4109 EXPECT_FALSE(scroll_result.did_scroll); | |
4110 EXPECT_TRUE(scroll_result.did_overscroll_root); | |
4111 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta); | |
4112 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll()); | |
4113 EXPECT_EQ(scroll_result.accumulated_root_overscroll, | |
4114 host_impl_->accumulated_root_overscroll()); | |
4115 | |
4116 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)); | |
4117 EXPECT_TRUE(scroll_result.did_scroll); | |
4118 EXPECT_FALSE(scroll_result.did_overscroll_root); | |
4119 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta); | |
4120 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll()); | |
4121 EXPECT_EQ(scroll_result.accumulated_root_overscroll, | |
4122 host_impl_->accumulated_root_overscroll()); | |
4123 | |
4124 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0)); | |
4125 EXPECT_TRUE(scroll_result.did_scroll); | |
4126 EXPECT_TRUE(scroll_result.did_overscroll_root); | |
4127 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta); | |
4128 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll()); | |
4129 EXPECT_EQ(scroll_result.accumulated_root_overscroll, | |
4130 host_impl_->accumulated_root_overscroll()); | |
4131 | |
4132 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60)); | |
4133 EXPECT_TRUE(scroll_result.did_scroll); | |
4134 EXPECT_TRUE(scroll_result.did_overscroll_root); | |
4135 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta); | |
4136 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll()); | |
4137 EXPECT_EQ(scroll_result.accumulated_root_overscroll, | |
4138 host_impl_->accumulated_root_overscroll()); | |
4139 | |
4140 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60)); | |
4141 EXPECT_TRUE(scroll_result.did_scroll); | |
4142 EXPECT_TRUE(scroll_result.did_overscroll_root); | |
4143 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta); | |
4144 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll()); | |
4145 EXPECT_EQ(scroll_result.accumulated_root_overscroll, | |
4146 host_impl_->accumulated_root_overscroll()); | |
4147 | |
4148 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long | |
4149 // as no scroll occurs. | |
4150 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20)); | |
4151 EXPECT_FALSE(scroll_result.did_scroll); | |
4152 EXPECT_TRUE(scroll_result.did_overscroll_root); | |
4153 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta); | |
4154 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll()); | |
4155 EXPECT_EQ(scroll_result.accumulated_root_overscroll, | |
4156 host_impl_->accumulated_root_overscroll()); | |
4157 | |
4158 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20)); | |
4159 EXPECT_FALSE(scroll_result.did_scroll); | |
4160 EXPECT_TRUE(scroll_result.did_overscroll_root); | |
4161 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta); | |
4162 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll()); | |
4163 EXPECT_EQ(scroll_result.accumulated_root_overscroll, | |
4164 host_impl_->accumulated_root_overscroll()); | |
4165 | |
4166 // Overscroll resets on valid scroll. | |
4167 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); | |
4168 EXPECT_TRUE(scroll_result.did_scroll); | |
4169 EXPECT_FALSE(scroll_result.did_overscroll_root); | |
4170 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta); | |
4171 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll()); | |
4172 EXPECT_EQ(scroll_result.accumulated_root_overscroll, | |
4173 host_impl_->accumulated_root_overscroll()); | |
4174 | |
4175 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20)); | |
4176 EXPECT_TRUE(scroll_result.did_scroll); | |
4177 EXPECT_TRUE(scroll_result.did_overscroll_root); | |
4178 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta); | |
4179 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll()); | |
4180 EXPECT_EQ(scroll_result.accumulated_root_overscroll, | |
4181 host_impl_->accumulated_root_overscroll()); | |
4182 | |
4183 host_impl_->ScrollEnd(); | |
4184 } | |
4185 | |
4186 | |
4187 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) { | |
4188 // Scroll child layers beyond their maximum scroll range and make sure root | |
4189 // overscroll does not accumulate. | |
4190 gfx::Size surface_size(10, 10); | |
4191 scoped_ptr<LayerImpl> root_clip = | |
4192 LayerImpl::Create(host_impl_->active_tree(), 4); | |
4193 root_clip->SetHasRenderSurface(true); | |
4194 | |
4195 scoped_ptr<LayerImpl> root = | |
4196 CreateScrollableLayer(1, surface_size, root_clip.get()); | |
4197 | |
4198 scoped_ptr<LayerImpl> grand_child = | |
4199 CreateScrollableLayer(3, surface_size, root_clip.get()); | |
4200 | |
4201 scoped_ptr<LayerImpl> child = | |
4202 CreateScrollableLayer(2, surface_size, root_clip.get()); | |
4203 LayerImpl* grand_child_layer = grand_child.get(); | |
4204 child->AddChild(grand_child.Pass()); | |
4205 | |
4206 LayerImpl* child_layer = child.get(); | |
4207 root->AddChild(child.Pass()); | |
4208 root_clip->AddChild(root.Pass()); | |
4209 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3)); | |
4210 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2)); | |
4211 host_impl_->active_tree()->SetRootLayer(root_clip.Pass()); | |
4212 host_impl_->active_tree()->DidBecomeActive(); | |
4213 host_impl_->SetViewportSize(surface_size); | |
4214 DrawFrame(); | |
4215 { | |
4216 gfx::Vector2d scroll_delta(0, -10); | |
4217 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
4218 host_impl_->ScrollBegin(gfx::Point(), | |
4219 InputHandler::NON_BUBBLING_GESTURE)); | |
4220 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
4221 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); | |
4222 host_impl_->ScrollEnd(); | |
4223 | |
4224 // The next time we scroll we should only scroll the parent, but overscroll | |
4225 // should still not reach the root layer. | |
4226 scroll_delta = gfx::Vector2d(0, -30); | |
4227 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
4228 host_impl_->ScrollBegin(gfx::Point(5, 5), | |
4229 InputHandler::NON_BUBBLING_GESTURE)); | |
4230 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer); | |
4231 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); | |
4232 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
4233 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer); | |
4234 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); | |
4235 host_impl_->ScrollEnd(); | |
4236 | |
4237 // After scrolling the parent, another scroll on the opposite direction | |
4238 // should scroll the child. | |
4239 scroll_delta = gfx::Vector2d(0, 70); | |
4240 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
4241 host_impl_->ScrollBegin(gfx::Point(5, 5), | |
4242 InputHandler::NON_BUBBLING_GESTURE)); | |
4243 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer); | |
4244 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
4245 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer); | |
4246 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); | |
4247 host_impl_->ScrollEnd(); | |
4248 } | |
4249 } | |
4250 | |
4251 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) { | |
4252 // When we try to scroll a non-scrollable child layer, the scroll delta | |
4253 // should be applied to one of its ancestors if possible. Overscroll should | |
4254 // be reflected only when it has bubbled up to the root scrolling layer. | |
4255 gfx::Size surface_size(10, 10); | |
4256 gfx::Size content_size(20, 20); | |
4257 scoped_ptr<LayerImpl> root_clip = | |
4258 LayerImpl::Create(host_impl_->active_tree(), 3); | |
4259 root_clip->SetHasRenderSurface(true); | |
4260 | |
4261 scoped_ptr<LayerImpl> root = | |
4262 CreateScrollableLayer(1, content_size, root_clip.get()); | |
4263 root->SetIsContainerForFixedPositionLayers(true); | |
4264 scoped_ptr<LayerImpl> child = | |
4265 CreateScrollableLayer(2, content_size, root_clip.get()); | |
4266 | |
4267 child->SetScrollClipLayer(Layer::INVALID_ID); | |
4268 root->AddChild(child.Pass()); | |
4269 root_clip->AddChild(root.Pass()); | |
4270 | |
4271 host_impl_->SetViewportSize(surface_size); | |
4272 host_impl_->active_tree()->SetRootLayer(root_clip.Pass()); | |
4273 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1, | |
4274 Layer::INVALID_ID); | |
4275 host_impl_->active_tree()->DidBecomeActive(); | |
4276 DrawFrame(); | |
4277 { | |
4278 gfx::Vector2d scroll_delta(0, 8); | |
4279 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
4280 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL)); | |
4281 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
4282 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); | |
4283 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
4284 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll()); | |
4285 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
4286 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll()); | |
4287 host_impl_->ScrollEnd(); | |
4288 } | |
4289 } | |
4290 | |
4291 TEST_F(LayerTreeHostImplTest, OverscrollAlways) { | |
4292 LayerTreeSettings settings; | |
4293 CreateHostImpl(settings, CreateOutputSurface()); | |
4294 | |
4295 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50)); | |
4296 LayerImpl* clip_layer = scroll_layer->parent()->parent(); | |
4297 clip_layer->SetBounds(gfx::Size(50, 50)); | |
4298 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
4299 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f); | |
4300 DrawFrame(); | |
4301 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); | |
4302 | |
4303 // Even though the layer can't scroll the overscroll still happens. | |
4304 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
4305 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
4306 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); | |
4307 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll()); | |
4308 } | |
4309 | |
4310 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) { | |
4311 gfx::Size surface_size(980, 1439); | |
4312 gfx::Size content_size(980, 1438); | |
4313 float device_scale_factor = 1.5f; | |
4314 scoped_ptr<LayerImpl> root_clip = | |
4315 LayerImpl::Create(host_impl_->active_tree(), 3); | |
4316 root_clip->SetHasRenderSurface(true); | |
4317 | |
4318 scoped_ptr<LayerImpl> root = | |
4319 CreateScrollableLayer(1, content_size, root_clip.get()); | |
4320 root->SetIsContainerForFixedPositionLayers(true); | |
4321 scoped_ptr<LayerImpl> child = | |
4322 CreateScrollableLayer(2, content_size, root_clip.get()); | |
4323 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469)); | |
4324 host_impl_->active_tree()->PushPageScaleFromMainThread(0.326531f, 0.326531f, | |
4325 5.f); | |
4326 host_impl_->SetPageScaleOnActiveTree(0.326531f); | |
4327 child->SetScrollClipLayer(Layer::INVALID_ID); | |
4328 root->AddChild(child.Pass()); | |
4329 root_clip->AddChild(root.Pass()); | |
4330 | |
4331 host_impl_->SetViewportSize(surface_size); | |
4332 host_impl_->SetDeviceScaleFactor(device_scale_factor); | |
4333 host_impl_->active_tree()->SetRootLayer(root_clip.Pass()); | |
4334 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1, | |
4335 Layer::INVALID_ID); | |
4336 host_impl_->active_tree()->DidBecomeActive(); | |
4337 DrawFrame(); | |
4338 { | |
4339 // Horizontal & Vertical GlowEffect should not be applied when | |
4340 // content size is less then view port size. For Example Horizontal & | |
4341 // vertical GlowEffect should not be applied in about:blank page. | |
4342 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
4343 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL)); | |
4344 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1)); | |
4345 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
4346 host_impl_->accumulated_root_overscroll().ToString()); | |
4347 | |
4348 host_impl_->ScrollEnd(); | |
4349 } | |
4350 } | |
4351 | |
4352 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) { | |
4353 gfx::Size surface_size(100, 100); | |
4354 gfx::Size content_size(200, 200); | |
4355 scoped_ptr<LayerImpl> root_clip = | |
4356 LayerImpl::Create(host_impl_->active_tree(), 3); | |
4357 root_clip->SetHasRenderSurface(true); | |
4358 | |
4359 scoped_ptr<LayerImpl> root = | |
4360 CreateScrollableLayer(1, content_size, root_clip.get()); | |
4361 root->SetIsContainerForFixedPositionLayers(true); | |
4362 scoped_ptr<LayerImpl> child = | |
4363 CreateScrollableLayer(2, content_size, root_clip.get()); | |
4364 | |
4365 child->SetScrollClipLayer(Layer::INVALID_ID); | |
4366 root->AddChild(child.Pass()); | |
4367 root_clip->AddChild(root.Pass()); | |
4368 | |
4369 host_impl_->SetViewportSize(surface_size); | |
4370 host_impl_->active_tree()->SetRootLayer(root_clip.Pass()); | |
4371 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1, | |
4372 Layer::INVALID_ID); | |
4373 host_impl_->active_tree()->DidBecomeActive(); | |
4374 DrawFrame(); | |
4375 { | |
4376 // Edge glow effect should be applicable only upon reaching Edges | |
4377 // of the content. unnecessary glow effect calls shouldn't be | |
4378 // called while scrolling up without reaching the edge of the content. | |
4379 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
4380 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL)); | |
4381 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100)); | |
4382 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
4383 host_impl_->accumulated_root_overscroll().ToString()); | |
4384 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f)); | |
4385 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
4386 host_impl_->accumulated_root_overscroll().ToString()); | |
4387 host_impl_->ScrollEnd(); | |
4388 // unusedrootDelta should be subtracted from applied delta so that | |
4389 // unwanted glow effect calls are not called. | |
4390 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
4391 host_impl_->ScrollBegin(gfx::Point(0, 0), | |
4392 InputHandler::NON_BUBBLING_GESTURE)); | |
4393 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); | |
4394 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20)); | |
4395 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(), | |
4396 host_impl_->accumulated_root_overscroll().ToString()); | |
4397 | |
4398 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f)); | |
4399 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(), | |
4400 host_impl_->accumulated_root_overscroll().ToString()); | |
4401 host_impl_->ScrollEnd(); | |
4402 // TestCase to check kEpsilon, which prevents minute values to trigger | |
4403 // gloweffect without reaching edge. | |
4404 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
4405 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL)); | |
4406 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f)); | |
4407 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
4408 host_impl_->accumulated_root_overscroll().ToString()); | |
4409 host_impl_->ScrollEnd(); | |
4410 } | |
4411 } | |
4412 | |
4413 class BlendStateCheckLayer : public LayerImpl { | |
4414 public: | |
4415 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, | |
4416 int id, | |
4417 ResourceProvider* resource_provider) { | |
4418 return make_scoped_ptr( | |
4419 new BlendStateCheckLayer(tree_impl, id, resource_provider)); | |
4420 } | |
4421 | |
4422 void AppendQuads(RenderPass* render_pass, | |
4423 AppendQuadsData* append_quads_data) override { | |
4424 quads_appended_ = true; | |
4425 | |
4426 gfx::Rect opaque_rect; | |
4427 if (contents_opaque()) | |
4428 opaque_rect = quad_rect_; | |
4429 else | |
4430 opaque_rect = opaque_content_rect_; | |
4431 gfx::Rect visible_quad_rect = quad_rect_; | |
4432 | |
4433 SharedQuadState* shared_quad_state = | |
4434 render_pass->CreateAndAppendSharedQuadState(); | |
4435 PopulateSharedQuadState(shared_quad_state); | |
4436 | |
4437 TileDrawQuad* test_blending_draw_quad = | |
4438 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>(); | |
4439 test_blending_draw_quad->SetNew(shared_quad_state, | |
4440 quad_rect_, | |
4441 opaque_rect, | |
4442 visible_quad_rect, | |
4443 resource_id_, | |
4444 gfx::RectF(0.f, 0.f, 1.f, 1.f), | |
4445 gfx::Size(1, 1), | |
4446 false, | |
4447 false); | |
4448 test_blending_draw_quad->visible_rect = quad_visible_rect_; | |
4449 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending()); | |
4450 EXPECT_EQ(has_render_surface_, !!render_surface()); | |
4451 } | |
4452 | |
4453 void SetExpectation(bool blend, bool has_render_surface) { | |
4454 blend_ = blend; | |
4455 has_render_surface_ = has_render_surface; | |
4456 quads_appended_ = false; | |
4457 } | |
4458 | |
4459 bool quads_appended() const { return quads_appended_; } | |
4460 | |
4461 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; } | |
4462 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; } | |
4463 void SetOpaqueContentRect(const gfx::Rect& rect) { | |
4464 opaque_content_rect_ = rect; | |
4465 } | |
4466 | |
4467 private: | |
4468 BlendStateCheckLayer(LayerTreeImpl* tree_impl, | |
4469 int id, | |
4470 ResourceProvider* resource_provider) | |
4471 : LayerImpl(tree_impl, id), | |
4472 blend_(false), | |
4473 has_render_surface_(false), | |
4474 quads_appended_(false), | |
4475 quad_rect_(5, 5, 5, 5), | |
4476 quad_visible_rect_(5, 5, 5, 5), | |
4477 resource_id_(resource_provider->CreateResource( | |
4478 gfx::Size(1, 1), | |
4479 GL_CLAMP_TO_EDGE, | |
4480 ResourceProvider::TEXTURE_HINT_IMMUTABLE, | |
4481 RGBA_8888)) { | |
4482 resource_provider->AllocateForTesting(resource_id_); | |
4483 SetBounds(gfx::Size(10, 10)); | |
4484 SetContentBounds(gfx::Size(10, 10)); | |
4485 SetDrawsContent(true); | |
4486 } | |
4487 | |
4488 bool blend_; | |
4489 bool has_render_surface_; | |
4490 bool quads_appended_; | |
4491 gfx::Rect quad_rect_; | |
4492 gfx::Rect opaque_content_rect_; | |
4493 gfx::Rect quad_visible_rect_; | |
4494 ResourceProvider::ResourceId resource_id_; | |
4495 }; | |
4496 | |
4497 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { | |
4498 { | |
4499 scoped_ptr<LayerImpl> root = | |
4500 LayerImpl::Create(host_impl_->active_tree(), 1); | |
4501 root->SetBounds(gfx::Size(10, 10)); | |
4502 root->SetContentBounds(root->bounds()); | |
4503 root->SetDrawsContent(false); | |
4504 root->SetHasRenderSurface(true); | |
4505 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
4506 } | |
4507 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
4508 | |
4509 root->AddChild( | |
4510 BlendStateCheckLayer::Create(host_impl_->active_tree(), | |
4511 2, | |
4512 host_impl_->resource_provider())); | |
4513 BlendStateCheckLayer* layer1 = | |
4514 static_cast<BlendStateCheckLayer*>(root->children()[0]); | |
4515 layer1->SetPosition(gfx::PointF(2.f, 2.f)); | |
4516 | |
4517 LayerTreeHostImpl::FrameData frame; | |
4518 | |
4519 // Opaque layer, drawn without blending. | |
4520 layer1->SetContentsOpaque(true); | |
4521 layer1->SetExpectation(false, false); | |
4522 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4523 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4524 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4525 EXPECT_TRUE(layer1->quads_appended()); | |
4526 host_impl_->DidDrawAllLayers(frame); | |
4527 | |
4528 // Layer with translucent content and painting, so drawn with blending. | |
4529 layer1->SetContentsOpaque(false); | |
4530 layer1->SetExpectation(true, false); | |
4531 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4532 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4533 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4534 EXPECT_TRUE(layer1->quads_appended()); | |
4535 host_impl_->DidDrawAllLayers(frame); | |
4536 | |
4537 // Layer with translucent opacity, drawn with blending. | |
4538 layer1->SetContentsOpaque(true); | |
4539 layer1->SetOpacity(0.5f); | |
4540 layer1->SetExpectation(true, false); | |
4541 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4542 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4543 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4544 EXPECT_TRUE(layer1->quads_appended()); | |
4545 host_impl_->DidDrawAllLayers(frame); | |
4546 | |
4547 // Layer with translucent opacity and painting, drawn with blending. | |
4548 layer1->SetContentsOpaque(true); | |
4549 layer1->SetOpacity(0.5f); | |
4550 layer1->SetExpectation(true, false); | |
4551 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4552 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4553 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4554 EXPECT_TRUE(layer1->quads_appended()); | |
4555 host_impl_->DidDrawAllLayers(frame); | |
4556 | |
4557 layer1->AddChild( | |
4558 BlendStateCheckLayer::Create(host_impl_->active_tree(), | |
4559 3, | |
4560 host_impl_->resource_provider())); | |
4561 BlendStateCheckLayer* layer2 = | |
4562 static_cast<BlendStateCheckLayer*>(layer1->children()[0]); | |
4563 layer2->SetPosition(gfx::PointF(4.f, 4.f)); | |
4564 | |
4565 // 2 opaque layers, drawn without blending. | |
4566 layer1->SetContentsOpaque(true); | |
4567 layer1->SetOpacity(1.f); | |
4568 layer1->SetExpectation(false, false); | |
4569 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4570 layer2->SetContentsOpaque(true); | |
4571 layer2->SetOpacity(1.f); | |
4572 layer2->SetExpectation(false, false); | |
4573 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4574 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4575 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4576 EXPECT_TRUE(layer1->quads_appended()); | |
4577 EXPECT_TRUE(layer2->quads_appended()); | |
4578 host_impl_->DidDrawAllLayers(frame); | |
4579 | |
4580 // Parent layer with translucent content, drawn with blending. | |
4581 // Child layer with opaque content, drawn without blending. | |
4582 layer1->SetContentsOpaque(false); | |
4583 layer1->SetExpectation(true, false); | |
4584 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4585 layer2->SetExpectation(false, false); | |
4586 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4587 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4588 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4589 EXPECT_TRUE(layer1->quads_appended()); | |
4590 EXPECT_TRUE(layer2->quads_appended()); | |
4591 host_impl_->DidDrawAllLayers(frame); | |
4592 | |
4593 // Parent layer with translucent content but opaque painting, drawn without | |
4594 // blending. | |
4595 // Child layer with opaque content, drawn without blending. | |
4596 layer1->SetContentsOpaque(true); | |
4597 layer1->SetExpectation(false, false); | |
4598 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4599 layer2->SetExpectation(false, false); | |
4600 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4601 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4602 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4603 EXPECT_TRUE(layer1->quads_appended()); | |
4604 EXPECT_TRUE(layer2->quads_appended()); | |
4605 host_impl_->DidDrawAllLayers(frame); | |
4606 | |
4607 // Parent layer with translucent opacity and opaque content. Since it has a | |
4608 // drawing child, it's drawn to a render surface which carries the opacity, | |
4609 // so it's itself drawn without blending. | |
4610 // Child layer with opaque content, drawn without blending (parent surface | |
4611 // carries the inherited opacity). | |
4612 layer1->SetContentsOpaque(true); | |
4613 layer1->SetOpacity(0.5f); | |
4614 layer1->SetHasRenderSurface(true); | |
4615 layer1->SetExpectation(false, true); | |
4616 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4617 layer2->SetExpectation(false, false); | |
4618 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4619 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren( | |
4620 host_impl_->active_tree()->root_layer()); | |
4621 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4622 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4623 EXPECT_TRUE(layer1->quads_appended()); | |
4624 EXPECT_TRUE(layer2->quads_appended()); | |
4625 host_impl_->DidDrawAllLayers(frame); | |
4626 layer1->SetHasRenderSurface(false); | |
4627 | |
4628 // Draw again, but with child non-opaque, to make sure | |
4629 // layer1 not culled. | |
4630 layer1->SetContentsOpaque(true); | |
4631 layer1->SetOpacity(1.f); | |
4632 layer1->SetExpectation(false, false); | |
4633 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4634 layer2->SetContentsOpaque(true); | |
4635 layer2->SetOpacity(0.5f); | |
4636 layer2->SetExpectation(true, false); | |
4637 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4638 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4639 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4640 EXPECT_TRUE(layer1->quads_appended()); | |
4641 EXPECT_TRUE(layer2->quads_appended()); | |
4642 host_impl_->DidDrawAllLayers(frame); | |
4643 | |
4644 // A second way of making the child non-opaque. | |
4645 layer1->SetContentsOpaque(true); | |
4646 layer1->SetOpacity(1.f); | |
4647 layer1->SetExpectation(false, false); | |
4648 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4649 layer2->SetContentsOpaque(false); | |
4650 layer2->SetOpacity(1.f); | |
4651 layer2->SetExpectation(true, false); | |
4652 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4653 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4654 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4655 EXPECT_TRUE(layer1->quads_appended()); | |
4656 EXPECT_TRUE(layer2->quads_appended()); | |
4657 host_impl_->DidDrawAllLayers(frame); | |
4658 | |
4659 // And when the layer says its not opaque but is painted opaque, it is not | |
4660 // blended. | |
4661 layer1->SetContentsOpaque(true); | |
4662 layer1->SetOpacity(1.f); | |
4663 layer1->SetExpectation(false, false); | |
4664 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4665 layer2->SetContentsOpaque(true); | |
4666 layer2->SetOpacity(1.f); | |
4667 layer2->SetExpectation(false, false); | |
4668 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4669 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4670 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4671 EXPECT_TRUE(layer1->quads_appended()); | |
4672 EXPECT_TRUE(layer2->quads_appended()); | |
4673 host_impl_->DidDrawAllLayers(frame); | |
4674 | |
4675 // Layer with partially opaque contents, drawn with blending. | |
4676 layer1->SetContentsOpaque(false); | |
4677 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5)); | |
4678 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5)); | |
4679 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5)); | |
4680 layer1->SetExpectation(true, false); | |
4681 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4682 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4683 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4684 EXPECT_TRUE(layer1->quads_appended()); | |
4685 host_impl_->DidDrawAllLayers(frame); | |
4686 | |
4687 // Layer with partially opaque contents partially culled, drawn with blending. | |
4688 layer1->SetContentsOpaque(false); | |
4689 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5)); | |
4690 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2)); | |
4691 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5)); | |
4692 layer1->SetExpectation(true, false); | |
4693 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4694 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4695 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4696 EXPECT_TRUE(layer1->quads_appended()); | |
4697 host_impl_->DidDrawAllLayers(frame); | |
4698 | |
4699 // Layer with partially opaque contents culled, drawn with blending. | |
4700 layer1->SetContentsOpaque(false); | |
4701 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5)); | |
4702 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5)); | |
4703 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5)); | |
4704 layer1->SetExpectation(true, false); | |
4705 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4706 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4707 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4708 EXPECT_TRUE(layer1->quads_appended()); | |
4709 host_impl_->DidDrawAllLayers(frame); | |
4710 | |
4711 // Layer with partially opaque contents and translucent contents culled, drawn | |
4712 // without blending. | |
4713 layer1->SetContentsOpaque(false); | |
4714 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5)); | |
4715 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5)); | |
4716 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5)); | |
4717 layer1->SetExpectation(false, false); | |
4718 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds())); | |
4719 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4720 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
4721 EXPECT_TRUE(layer1->quads_appended()); | |
4722 host_impl_->DidDrawAllLayers(frame); | |
4723 } | |
4724 | |
4725 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { | |
4726 protected: | |
4727 LayerTreeHostImplViewportCoveredTest() : | |
4728 gutter_quad_material_(DrawQuad::SOLID_COLOR), | |
4729 child_(NULL), | |
4730 did_activate_pending_tree_(false) {} | |
4731 | |
4732 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) { | |
4733 if (always_draw) { | |
4734 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d(); | |
4735 } | |
4736 return FakeOutputSurface::Create3d(); | |
4737 } | |
4738 | |
4739 void SetupActiveTreeLayers() { | |
4740 host_impl_->active_tree()->set_background_color(SK_ColorGRAY); | |
4741 host_impl_->active_tree()->SetRootLayer( | |
4742 LayerImpl::Create(host_impl_->active_tree(), 1)); | |
4743 host_impl_->active_tree()->root_layer()->SetHasRenderSurface(true); | |
4744 host_impl_->active_tree()->root_layer()->AddChild( | |
4745 BlendStateCheckLayer::Create(host_impl_->active_tree(), | |
4746 2, | |
4747 host_impl_->resource_provider())); | |
4748 child_ = static_cast<BlendStateCheckLayer*>( | |
4749 host_impl_->active_tree()->root_layer()->children()[0]); | |
4750 child_->SetExpectation(false, false); | |
4751 child_->SetContentsOpaque(true); | |
4752 } | |
4753 | |
4754 // Expect no gutter rects. | |
4755 void TestLayerCoversFullViewport() { | |
4756 gfx::Rect layer_rect(viewport_size_); | |
4757 child_->SetPosition(layer_rect.origin()); | |
4758 child_->SetBounds(layer_rect.size()); | |
4759 child_->SetContentBounds(layer_rect.size()); | |
4760 child_->SetQuadRect(gfx::Rect(layer_rect.size())); | |
4761 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size())); | |
4762 | |
4763 LayerTreeHostImpl::FrameData frame; | |
4764 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4765 ASSERT_EQ(1u, frame.render_passes.size()); | |
4766 | |
4767 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list)); | |
4768 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size()); | |
4769 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list); | |
4770 | |
4771 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list); | |
4772 host_impl_->DidDrawAllLayers(frame); | |
4773 } | |
4774 | |
4775 // Expect fullscreen gutter rect. | |
4776 void TestEmptyLayer() { | |
4777 gfx::Rect layer_rect(0, 0, 0, 0); | |
4778 child_->SetPosition(layer_rect.origin()); | |
4779 child_->SetBounds(layer_rect.size()); | |
4780 child_->SetContentBounds(layer_rect.size()); | |
4781 child_->SetQuadRect(gfx::Rect(layer_rect.size())); | |
4782 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size())); | |
4783 | |
4784 LayerTreeHostImpl::FrameData frame; | |
4785 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4786 ASSERT_EQ(1u, frame.render_passes.size()); | |
4787 | |
4788 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list)); | |
4789 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size()); | |
4790 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list); | |
4791 | |
4792 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list); | |
4793 host_impl_->DidDrawAllLayers(frame); | |
4794 } | |
4795 | |
4796 // Expect four surrounding gutter rects. | |
4797 void TestLayerInMiddleOfViewport() { | |
4798 gfx::Rect layer_rect(500, 500, 200, 200); | |
4799 child_->SetPosition(layer_rect.origin()); | |
4800 child_->SetBounds(layer_rect.size()); | |
4801 child_->SetContentBounds(layer_rect.size()); | |
4802 child_->SetQuadRect(gfx::Rect(layer_rect.size())); | |
4803 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size())); | |
4804 | |
4805 LayerTreeHostImpl::FrameData frame; | |
4806 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4807 ASSERT_EQ(1u, frame.render_passes.size()); | |
4808 | |
4809 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list)); | |
4810 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size()); | |
4811 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list); | |
4812 | |
4813 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list); | |
4814 host_impl_->DidDrawAllLayers(frame); | |
4815 } | |
4816 | |
4817 // Expect no gutter rects. | |
4818 void TestLayerIsLargerThanViewport() { | |
4819 gfx::Rect layer_rect(viewport_size_.width() + 10, | |
4820 viewport_size_.height() + 10); | |
4821 child_->SetPosition(layer_rect.origin()); | |
4822 child_->SetBounds(layer_rect.size()); | |
4823 child_->SetContentBounds(layer_rect.size()); | |
4824 child_->SetQuadRect(gfx::Rect(layer_rect.size())); | |
4825 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size())); | |
4826 | |
4827 LayerTreeHostImpl::FrameData frame; | |
4828 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
4829 ASSERT_EQ(1u, frame.render_passes.size()); | |
4830 | |
4831 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list)); | |
4832 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size()); | |
4833 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list); | |
4834 | |
4835 host_impl_->DidDrawAllLayers(frame); | |
4836 } | |
4837 | |
4838 void DidActivateSyncTree() override { did_activate_pending_tree_ = true; } | |
4839 | |
4840 void set_gutter_quad_material(DrawQuad::Material material) { | |
4841 gutter_quad_material_ = material; | |
4842 } | |
4843 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) { | |
4844 gutter_texture_size_ = gutter_texture_size; | |
4845 } | |
4846 | |
4847 protected: | |
4848 size_t CountGutterQuads(const QuadList& quad_list) { | |
4849 size_t num_gutter_quads = 0; | |
4850 for (const auto& quad : quad_list) { | |
4851 num_gutter_quads += (quad->material == gutter_quad_material_) ? 1 : 0; | |
4852 } | |
4853 return num_gutter_quads; | |
4854 } | |
4855 | |
4856 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) { | |
4857 LayerTestCommon::VerifyQuadsExactlyCoverRect( | |
4858 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_))); | |
4859 } | |
4860 | |
4861 // Make sure that the texture coordinates match their expectations. | |
4862 void ValidateTextureDrawQuads(const QuadList& quad_list) { | |
4863 for (const auto& quad : quad_list) { | |
4864 if (quad->material != DrawQuad::TEXTURE_CONTENT) | |
4865 continue; | |
4866 const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad); | |
4867 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize( | |
4868 gutter_texture_size_, host_impl_->device_scale_factor()); | |
4869 EXPECT_EQ(texture_quad->uv_top_left.x(), | |
4870 texture_quad->rect.x() / gutter_texture_size_pixels.width()); | |
4871 EXPECT_EQ(texture_quad->uv_top_left.y(), | |
4872 texture_quad->rect.y() / gutter_texture_size_pixels.height()); | |
4873 EXPECT_EQ( | |
4874 texture_quad->uv_bottom_right.x(), | |
4875 texture_quad->rect.right() / gutter_texture_size_pixels.width()); | |
4876 EXPECT_EQ( | |
4877 texture_quad->uv_bottom_right.y(), | |
4878 texture_quad->rect.bottom() / gutter_texture_size_pixels.height()); | |
4879 } | |
4880 } | |
4881 | |
4882 gfx::Size DipSizeToPixelSize(const gfx::Size& size) { | |
4883 return gfx::ToRoundedSize( | |
4884 gfx::ScaleSize(size, host_impl_->device_scale_factor())); | |
4885 } | |
4886 | |
4887 DrawQuad::Material gutter_quad_material_; | |
4888 gfx::Size gutter_texture_size_; | |
4889 gfx::Size viewport_size_; | |
4890 BlendStateCheckLayer* child_; | |
4891 bool did_activate_pending_tree_; | |
4892 }; | |
4893 | |
4894 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) { | |
4895 viewport_size_ = gfx::Size(1000, 1000); | |
4896 | |
4897 bool always_draw = false; | |
4898 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw)); | |
4899 | |
4900 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_)); | |
4901 SetupActiveTreeLayers(); | |
4902 TestLayerCoversFullViewport(); | |
4903 TestEmptyLayer(); | |
4904 TestLayerInMiddleOfViewport(); | |
4905 TestLayerIsLargerThanViewport(); | |
4906 } | |
4907 | |
4908 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) { | |
4909 viewport_size_ = gfx::Size(1000, 1000); | |
4910 | |
4911 bool always_draw = false; | |
4912 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw)); | |
4913 | |
4914 host_impl_->SetDeviceScaleFactor(2.f); | |
4915 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_)); | |
4916 SetupActiveTreeLayers(); | |
4917 TestLayerCoversFullViewport(); | |
4918 TestEmptyLayer(); | |
4919 TestLayerInMiddleOfViewport(); | |
4920 TestLayerIsLargerThanViewport(); | |
4921 } | |
4922 | |
4923 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) { | |
4924 viewport_size_ = gfx::Size(1000, 1000); | |
4925 | |
4926 bool always_draw = true; | |
4927 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw)); | |
4928 | |
4929 // Pending tree to force active_tree size invalid. Not used otherwise. | |
4930 host_impl_->CreatePendingTree(); | |
4931 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_)); | |
4932 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid()); | |
4933 | |
4934 SetupActiveTreeLayers(); | |
4935 TestEmptyLayer(); | |
4936 TestLayerInMiddleOfViewport(); | |
4937 TestLayerIsLargerThanViewport(); | |
4938 } | |
4939 | |
4940 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) { | |
4941 viewport_size_ = gfx::Size(1000, 1000); | |
4942 | |
4943 bool always_draw = true; | |
4944 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw)); | |
4945 | |
4946 // Set larger viewport and activate it to active tree. | |
4947 host_impl_->CreatePendingTree(); | |
4948 gfx::Size larger_viewport(viewport_size_.width() + 100, | |
4949 viewport_size_.height() + 100); | |
4950 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport)); | |
4951 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid()); | |
4952 host_impl_->ActivateSyncTree(); | |
4953 EXPECT_TRUE(did_activate_pending_tree_); | |
4954 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid()); | |
4955 | |
4956 // Shrink pending tree viewport without activating. | |
4957 host_impl_->CreatePendingTree(); | |
4958 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_)); | |
4959 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid()); | |
4960 | |
4961 SetupActiveTreeLayers(); | |
4962 TestEmptyLayer(); | |
4963 TestLayerInMiddleOfViewport(); | |
4964 TestLayerIsLargerThanViewport(); | |
4965 } | |
4966 | |
4967 class FakeDrawableLayerImpl: public LayerImpl { | |
4968 public: | |
4969 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) { | |
4970 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl, id)); | |
4971 } | |
4972 protected: | |
4973 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id) | |
4974 : LayerImpl(tree_impl, id) {} | |
4975 }; | |
4976 | |
4977 // Only reshape when we know we are going to draw. Otherwise, the reshape | |
4978 // can leave the window at the wrong size if we never draw and the proper | |
4979 // viewport size is never set. | |
4980 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) { | |
4981 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create()); | |
4982 scoped_ptr<OutputSurface> output_surface( | |
4983 FakeOutputSurface::Create3d(provider)); | |
4984 CreateHostImpl(DefaultSettings(), output_surface.Pass()); | |
4985 | |
4986 scoped_ptr<LayerImpl> root = | |
4987 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1); | |
4988 root->SetBounds(gfx::Size(10, 10)); | |
4989 root->SetContentBounds(gfx::Size(10, 10)); | |
4990 root->SetDrawsContent(true); | |
4991 root->SetHasRenderSurface(true); | |
4992 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
4993 EXPECT_FALSE(provider->TestContext3d()->reshape_called()); | |
4994 provider->TestContext3d()->clear_reshape_called(); | |
4995 | |
4996 LayerTreeHostImpl::FrameData frame; | |
4997 host_impl_->SetViewportSize(gfx::Size(10, 10)); | |
4998 host_impl_->SetDeviceScaleFactor(1.f); | |
4999 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5000 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5001 EXPECT_TRUE(provider->TestContext3d()->reshape_called()); | |
5002 EXPECT_EQ(provider->TestContext3d()->width(), 10); | |
5003 EXPECT_EQ(provider->TestContext3d()->height(), 10); | |
5004 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f); | |
5005 host_impl_->DidDrawAllLayers(frame); | |
5006 provider->TestContext3d()->clear_reshape_called(); | |
5007 | |
5008 host_impl_->SetViewportSize(gfx::Size(20, 30)); | |
5009 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5010 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5011 EXPECT_TRUE(provider->TestContext3d()->reshape_called()); | |
5012 EXPECT_EQ(provider->TestContext3d()->width(), 20); | |
5013 EXPECT_EQ(provider->TestContext3d()->height(), 30); | |
5014 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f); | |
5015 host_impl_->DidDrawAllLayers(frame); | |
5016 provider->TestContext3d()->clear_reshape_called(); | |
5017 | |
5018 host_impl_->SetDeviceScaleFactor(2.f); | |
5019 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5020 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5021 EXPECT_TRUE(provider->TestContext3d()->reshape_called()); | |
5022 EXPECT_EQ(provider->TestContext3d()->width(), 20); | |
5023 EXPECT_EQ(provider->TestContext3d()->height(), 30); | |
5024 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f); | |
5025 host_impl_->DidDrawAllLayers(frame); | |
5026 provider->TestContext3d()->clear_reshape_called(); | |
5027 } | |
5028 | |
5029 // Make sure damage tracking propagates all the way to the graphics context, | |
5030 // where it should request to swap only the sub-buffer that is damaged. | |
5031 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { | |
5032 scoped_refptr<TestContextProvider> context_provider( | |
5033 TestContextProvider::Create()); | |
5034 context_provider->BindToCurrentThread(); | |
5035 context_provider->TestContext3d()->set_have_post_sub_buffer(true); | |
5036 | |
5037 scoped_ptr<FakeOutputSurface> output_surface( | |
5038 FakeOutputSurface::Create3d(context_provider)); | |
5039 FakeOutputSurface* fake_output_surface = output_surface.get(); | |
5040 | |
5041 // This test creates its own LayerTreeHostImpl, so | |
5042 // that we can force partial swap enabled. | |
5043 LayerTreeSettings settings; | |
5044 settings.renderer_settings.partial_swap_enabled = true; | |
5045 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl = | |
5046 LayerTreeHostImpl::Create( | |
5047 settings, this, &proxy_, &stats_instrumentation_, | |
5048 shared_bitmap_manager_.get(), NULL, task_graph_runner_.get(), 0); | |
5049 layer_tree_host_impl->InitializeRenderer(output_surface.Pass()); | |
5050 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500)); | |
5051 | |
5052 scoped_ptr<LayerImpl> root = | |
5053 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1); | |
5054 root->SetHasRenderSurface(true); | |
5055 scoped_ptr<LayerImpl> child = | |
5056 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2); | |
5057 child->SetPosition(gfx::PointF(12.f, 13.f)); | |
5058 child->SetBounds(gfx::Size(14, 15)); | |
5059 child->SetContentBounds(gfx::Size(14, 15)); | |
5060 child->SetDrawsContent(true); | |
5061 root->SetBounds(gfx::Size(500, 500)); | |
5062 root->SetContentBounds(gfx::Size(500, 500)); | |
5063 root->SetDrawsContent(true); | |
5064 root->AddChild(child.Pass()); | |
5065 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass()); | |
5066 | |
5067 LayerTreeHostImpl::FrameData frame; | |
5068 | |
5069 // First frame, the entire screen should get swapped. | |
5070 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame)); | |
5071 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5072 layer_tree_host_impl->DidDrawAllLayers(frame); | |
5073 layer_tree_host_impl->SwapBuffers(frame); | |
5074 gfx::Rect expected_swap_rect(0, 0, 500, 500); | |
5075 EXPECT_EQ(expected_swap_rect.ToString(), | |
5076 fake_output_surface->last_swap_rect().ToString()); | |
5077 | |
5078 // Second frame, only the damaged area should get swapped. Damage should be | |
5079 // the union of old and new child rects. | |
5080 // expected damage rect: gfx::Rect(26, 28); | |
5081 // expected swap rect: vertically flipped, with origin at bottom left corner. | |
5082 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition( | |
5083 gfx::PointF()); | |
5084 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame)); | |
5085 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5086 host_impl_->DidDrawAllLayers(frame); | |
5087 layer_tree_host_impl->SwapBuffers(frame); | |
5088 | |
5089 // Make sure that partial swap is constrained to the viewport dimensions | |
5090 // expected damage rect: gfx::Rect(500, 500); | |
5091 // expected swap rect: flipped damage rect, but also clamped to viewport | |
5092 expected_swap_rect = gfx::Rect(0, 500-28, 26, 28); | |
5093 EXPECT_EQ(expected_swap_rect.ToString(), | |
5094 fake_output_surface->last_swap_rect().ToString()); | |
5095 | |
5096 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10)); | |
5097 // This will damage everything. | |
5098 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor( | |
5099 SK_ColorBLACK); | |
5100 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame)); | |
5101 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5102 host_impl_->DidDrawAllLayers(frame); | |
5103 layer_tree_host_impl->SwapBuffers(frame); | |
5104 | |
5105 expected_swap_rect = gfx::Rect(0, 0, 10, 10); | |
5106 EXPECT_EQ(expected_swap_rect.ToString(), | |
5107 fake_output_surface->last_swap_rect().ToString()); | |
5108 } | |
5109 | |
5110 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) { | |
5111 scoped_ptr<LayerImpl> root = | |
5112 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1); | |
5113 scoped_ptr<LayerImpl> child = | |
5114 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2); | |
5115 child->SetBounds(gfx::Size(10, 10)); | |
5116 child->SetContentBounds(gfx::Size(10, 10)); | |
5117 child->SetDrawsContent(true); | |
5118 root->SetBounds(gfx::Size(10, 10)); | |
5119 root->SetContentBounds(gfx::Size(10, 10)); | |
5120 root->SetDrawsContent(true); | |
5121 root->SetHasRenderSurface(true); | |
5122 root->AddChild(child.Pass()); | |
5123 | |
5124 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
5125 | |
5126 LayerTreeHostImpl::FrameData frame; | |
5127 | |
5128 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5129 EXPECT_EQ(1u, frame.render_surface_layer_list->size()); | |
5130 EXPECT_EQ(1u, frame.render_passes.size()); | |
5131 host_impl_->DidDrawAllLayers(frame); | |
5132 } | |
5133 | |
5134 class FakeLayerWithQuads : public LayerImpl { | |
5135 public: | |
5136 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) { | |
5137 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl, id)); | |
5138 } | |
5139 | |
5140 void AppendQuads(RenderPass* render_pass, | |
5141 AppendQuadsData* append_quads_data) override { | |
5142 SharedQuadState* shared_quad_state = | |
5143 render_pass->CreateAndAppendSharedQuadState(); | |
5144 PopulateSharedQuadState(shared_quad_state); | |
5145 | |
5146 SkColor gray = SkColorSetRGB(100, 100, 100); | |
5147 gfx::Rect quad_rect(content_bounds()); | |
5148 gfx::Rect visible_quad_rect(quad_rect); | |
5149 SolidColorDrawQuad* my_quad = | |
5150 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); | |
5151 my_quad->SetNew( | |
5152 shared_quad_state, quad_rect, visible_quad_rect, gray, false); | |
5153 } | |
5154 | |
5155 private: | |
5156 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id) | |
5157 : LayerImpl(tree_impl, id) {} | |
5158 }; | |
5159 | |
5160 class MockContext : public TestWebGraphicsContext3D { | |
5161 public: | |
5162 MOCK_METHOD1(useProgram, void(GLuint program)); | |
5163 MOCK_METHOD5(uniform4f, void(GLint location, | |
5164 GLfloat x, | |
5165 GLfloat y, | |
5166 GLfloat z, | |
5167 GLfloat w)); | |
5168 MOCK_METHOD4(uniformMatrix4fv, void(GLint location, | |
5169 GLsizei count, | |
5170 GLboolean transpose, | |
5171 const GLfloat* value)); | |
5172 MOCK_METHOD4(drawElements, void(GLenum mode, | |
5173 GLsizei count, | |
5174 GLenum type, | |
5175 GLintptr offset)); | |
5176 MOCK_METHOD1(enable, void(GLenum cap)); | |
5177 MOCK_METHOD1(disable, void(GLenum cap)); | |
5178 MOCK_METHOD4(scissor, void(GLint x, | |
5179 GLint y, | |
5180 GLsizei width, | |
5181 GLsizei height)); | |
5182 }; | |
5183 | |
5184 class MockContextHarness { | |
5185 private: | |
5186 MockContext* context_; | |
5187 | |
5188 public: | |
5189 explicit MockContextHarness(MockContext* context) | |
5190 : context_(context) { | |
5191 context_->set_have_post_sub_buffer(true); | |
5192 | |
5193 // Catch "uninteresting" calls | |
5194 EXPECT_CALL(*context_, useProgram(_)) | |
5195 .Times(0); | |
5196 | |
5197 EXPECT_CALL(*context_, drawElements(_, _, _, _)) | |
5198 .Times(0); | |
5199 | |
5200 // These are not asserted | |
5201 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _)) | |
5202 .WillRepeatedly(Return()); | |
5203 | |
5204 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _)) | |
5205 .WillRepeatedly(Return()); | |
5206 | |
5207 // Any un-sanctioned calls to enable() are OK | |
5208 EXPECT_CALL(*context_, enable(_)) | |
5209 .WillRepeatedly(Return()); | |
5210 | |
5211 // Any un-sanctioned calls to disable() are OK | |
5212 EXPECT_CALL(*context_, disable(_)) | |
5213 .WillRepeatedly(Return()); | |
5214 } | |
5215 | |
5216 void MustDrawSolidQuad() { | |
5217 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0)) | |
5218 .WillOnce(Return()) | |
5219 .RetiresOnSaturation(); | |
5220 | |
5221 EXPECT_CALL(*context_, useProgram(_)) | |
5222 .WillOnce(Return()) | |
5223 .RetiresOnSaturation(); | |
5224 } | |
5225 | |
5226 void MustSetScissor(int x, int y, int width, int height) { | |
5227 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST)) | |
5228 .WillRepeatedly(Return()); | |
5229 | |
5230 EXPECT_CALL(*context_, scissor(x, y, width, height)) | |
5231 .Times(AtLeast(1)) | |
5232 .WillRepeatedly(Return()); | |
5233 } | |
5234 | |
5235 void MustSetNoScissor() { | |
5236 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST)) | |
5237 .WillRepeatedly(Return()); | |
5238 | |
5239 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST)) | |
5240 .Times(0); | |
5241 | |
5242 EXPECT_CALL(*context_, scissor(_, _, _, _)) | |
5243 .Times(0); | |
5244 } | |
5245 }; | |
5246 | |
5247 TEST_F(LayerTreeHostImplTest, NoPartialSwap) { | |
5248 scoped_ptr<MockContext> mock_context_owned(new MockContext); | |
5249 MockContext* mock_context = mock_context_owned.get(); | |
5250 MockContextHarness harness(mock_context); | |
5251 | |
5252 // Run test case | |
5253 LayerTreeSettings settings = DefaultSettings(); | |
5254 settings.renderer_settings.partial_swap_enabled = false; | |
5255 CreateHostImpl(settings, | |
5256 FakeOutputSurface::Create3d(mock_context_owned.Pass())); | |
5257 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1)); | |
5258 | |
5259 // Without partial swap, and no clipping, no scissor is set. | |
5260 harness.MustDrawSolidQuad(); | |
5261 harness.MustSetNoScissor(); | |
5262 { | |
5263 LayerTreeHostImpl::FrameData frame; | |
5264 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5265 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5266 host_impl_->DidDrawAllLayers(frame); | |
5267 } | |
5268 Mock::VerifyAndClearExpectations(&mock_context); | |
5269 | |
5270 // Without partial swap, but a layer does clip its subtree, one scissor is | |
5271 // set. | |
5272 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true); | |
5273 harness.MustDrawSolidQuad(); | |
5274 harness.MustSetScissor(0, 0, 10, 10); | |
5275 { | |
5276 LayerTreeHostImpl::FrameData frame; | |
5277 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5278 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5279 host_impl_->DidDrawAllLayers(frame); | |
5280 } | |
5281 Mock::VerifyAndClearExpectations(&mock_context); | |
5282 } | |
5283 | |
5284 TEST_F(LayerTreeHostImplTest, PartialSwap) { | |
5285 scoped_ptr<MockContext> context_owned(new MockContext); | |
5286 MockContext* mock_context = context_owned.get(); | |
5287 MockContextHarness harness(mock_context); | |
5288 | |
5289 LayerTreeSettings settings = DefaultSettings(); | |
5290 settings.renderer_settings.partial_swap_enabled = true; | |
5291 CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass())); | |
5292 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1)); | |
5293 | |
5294 // The first frame is not a partially-swapped one. No scissor should be set. | |
5295 harness.MustSetNoScissor(); | |
5296 harness.MustDrawSolidQuad(); | |
5297 { | |
5298 LayerTreeHostImpl::FrameData frame; | |
5299 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5300 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5301 host_impl_->DidDrawAllLayers(frame); | |
5302 } | |
5303 Mock::VerifyAndClearExpectations(&mock_context); | |
5304 | |
5305 // Damage a portion of the frame. | |
5306 host_impl_->active_tree()->root_layer()->SetUpdateRect( | |
5307 gfx::Rect(0, 0, 2, 3)); | |
5308 | |
5309 // The second frame will be partially-swapped (the y coordinates are flipped). | |
5310 harness.MustSetScissor(0, 7, 2, 3); | |
5311 harness.MustDrawSolidQuad(); | |
5312 { | |
5313 LayerTreeHostImpl::FrameData frame; | |
5314 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5315 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5316 host_impl_->DidDrawAllLayers(frame); | |
5317 } | |
5318 Mock::VerifyAndClearExpectations(&mock_context); | |
5319 } | |
5320 | |
5321 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity( | |
5322 bool partial_swap, | |
5323 LayerTreeHostImplClient* client, | |
5324 Proxy* proxy, | |
5325 SharedBitmapManager* manager, | |
5326 RenderingStatsInstrumentation* stats_instrumentation) { | |
5327 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create()); | |
5328 scoped_ptr<OutputSurface> output_surface( | |
5329 FakeOutputSurface::Create3d(provider)); | |
5330 provider->BindToCurrentThread(); | |
5331 provider->TestContext3d()->set_have_post_sub_buffer(true); | |
5332 | |
5333 LayerTreeSettings settings; | |
5334 settings.renderer_settings.partial_swap_enabled = partial_swap; | |
5335 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create( | |
5336 settings, client, proxy, stats_instrumentation, manager, NULL, NULL, 0); | |
5337 my_host_impl->InitializeRenderer(output_surface.Pass()); | |
5338 my_host_impl->SetViewportSize(gfx::Size(100, 100)); | |
5339 | |
5340 /* | |
5341 Layers are created as follows: | |
5342 | |
5343 +--------------------+ | |
5344 | 1 | | |
5345 | +-----------+ | | |
5346 | | 2 | | | |
5347 | | +-------------------+ | |
5348 | | | 3 | | |
5349 | | +-------------------+ | |
5350 | | | | | |
5351 | +-----------+ | | |
5352 | | | |
5353 | | | |
5354 +--------------------+ | |
5355 | |
5356 Layers 1, 2 have render surfaces | |
5357 */ | |
5358 scoped_ptr<LayerImpl> root = | |
5359 LayerImpl::Create(my_host_impl->active_tree(), 1); | |
5360 scoped_ptr<LayerImpl> child = | |
5361 LayerImpl::Create(my_host_impl->active_tree(), 2); | |
5362 scoped_ptr<LayerImpl> grand_child = | |
5363 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3); | |
5364 | |
5365 gfx::Rect root_rect(0, 0, 100, 100); | |
5366 gfx::Rect child_rect(10, 10, 50, 50); | |
5367 gfx::Rect grand_child_rect(5, 5, 150, 150); | |
5368 | |
5369 root->SetHasRenderSurface(true); | |
5370 root->SetPosition(root_rect.origin()); | |
5371 root->SetBounds(root_rect.size()); | |
5372 root->SetContentBounds(root->bounds()); | |
5373 root->draw_properties().visible_content_rect = root_rect; | |
5374 root->SetDrawsContent(false); | |
5375 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size())); | |
5376 | |
5377 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y())); | |
5378 child->SetOpacity(0.5f); | |
5379 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height())); | |
5380 child->SetContentBounds(child->bounds()); | |
5381 child->draw_properties().visible_content_rect = child_rect; | |
5382 child->SetDrawsContent(false); | |
5383 child->SetHasRenderSurface(true); | |
5384 | |
5385 grand_child->SetPosition(grand_child_rect.origin()); | |
5386 grand_child->SetBounds(grand_child_rect.size()); | |
5387 grand_child->SetContentBounds(grand_child->bounds()); | |
5388 grand_child->draw_properties().visible_content_rect = grand_child_rect; | |
5389 grand_child->SetDrawsContent(true); | |
5390 | |
5391 child->AddChild(grand_child.Pass()); | |
5392 root->AddChild(child.Pass()); | |
5393 | |
5394 my_host_impl->active_tree()->SetRootLayer(root.Pass()); | |
5395 return my_host_impl.Pass(); | |
5396 } | |
5397 | |
5398 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) { | |
5399 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
5400 new TestSharedBitmapManager()); | |
5401 scoped_ptr<LayerTreeHostImpl> my_host_impl = | |
5402 SetupLayersForOpacity(true, | |
5403 this, | |
5404 &proxy_, | |
5405 shared_bitmap_manager.get(), | |
5406 &stats_instrumentation_); | |
5407 { | |
5408 LayerTreeHostImpl::FrameData frame; | |
5409 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame)); | |
5410 | |
5411 // Verify all quads have been computed | |
5412 ASSERT_EQ(2U, frame.render_passes.size()); | |
5413 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size()); | |
5414 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size()); | |
5415 EXPECT_EQ(DrawQuad::SOLID_COLOR, | |
5416 frame.render_passes[0]->quad_list.front()->material); | |
5417 EXPECT_EQ(DrawQuad::RENDER_PASS, | |
5418 frame.render_passes[1]->quad_list.front()->material); | |
5419 | |
5420 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5421 my_host_impl->DidDrawAllLayers(frame); | |
5422 } | |
5423 } | |
5424 | |
5425 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) { | |
5426 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
5427 new TestSharedBitmapManager()); | |
5428 scoped_ptr<LayerTreeHostImpl> my_host_impl = | |
5429 SetupLayersForOpacity(false, | |
5430 this, | |
5431 &proxy_, | |
5432 shared_bitmap_manager.get(), | |
5433 &stats_instrumentation_); | |
5434 { | |
5435 LayerTreeHostImpl::FrameData frame; | |
5436 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame)); | |
5437 | |
5438 // Verify all quads have been computed | |
5439 ASSERT_EQ(2U, frame.render_passes.size()); | |
5440 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size()); | |
5441 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size()); | |
5442 EXPECT_EQ(DrawQuad::SOLID_COLOR, | |
5443 frame.render_passes[0]->quad_list.front()->material); | |
5444 EXPECT_EQ(DrawQuad::RENDER_PASS, | |
5445 frame.render_passes[1]->quad_list.front()->material); | |
5446 | |
5447 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5448 my_host_impl->DidDrawAllLayers(frame); | |
5449 } | |
5450 } | |
5451 | |
5452 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { | |
5453 scoped_ptr<TestWebGraphicsContext3D> context = | |
5454 TestWebGraphicsContext3D::Create(); | |
5455 TestWebGraphicsContext3D* context3d = context.get(); | |
5456 scoped_ptr<OutputSurface> output_surface( | |
5457 FakeOutputSurface::Create3d(context.Pass())); | |
5458 CreateHostImpl(DefaultSettings(), output_surface.Pass()); | |
5459 | |
5460 scoped_ptr<LayerImpl> root_layer = | |
5461 LayerImpl::Create(host_impl_->active_tree(), 1); | |
5462 root_layer->SetBounds(gfx::Size(10, 10)); | |
5463 root_layer->SetHasRenderSurface(true); | |
5464 | |
5465 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer = | |
5466 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5); | |
5467 io_surface_layer->SetBounds(gfx::Size(10, 10)); | |
5468 io_surface_layer->SetContentBounds(gfx::Size(10, 10)); | |
5469 io_surface_layer->SetDrawsContent(true); | |
5470 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10)); | |
5471 root_layer->AddChild(io_surface_layer.Pass()); | |
5472 | |
5473 host_impl_->active_tree()->SetRootLayer(root_layer.Pass()); | |
5474 | |
5475 EXPECT_EQ(0u, context3d->NumTextures()); | |
5476 | |
5477 LayerTreeHostImpl::FrameData frame; | |
5478 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5479 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5480 host_impl_->DidDrawAllLayers(frame); | |
5481 host_impl_->SwapBuffers(frame); | |
5482 | |
5483 EXPECT_GT(context3d->NumTextures(), 0u); | |
5484 | |
5485 // Kill the layer tree. | |
5486 host_impl_->active_tree()->SetRootLayer( | |
5487 LayerImpl::Create(host_impl_->active_tree(), 100)); | |
5488 // There should be no textures left in use after. | |
5489 EXPECT_EQ(0u, context3d->NumTextures()); | |
5490 } | |
5491 | |
5492 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D { | |
5493 public: | |
5494 MOCK_METHOD1(useProgram, void(GLuint program)); | |
5495 MOCK_METHOD4(drawElements, void(GLenum mode, | |
5496 GLsizei count, | |
5497 GLenum type, | |
5498 GLintptr offset)); | |
5499 }; | |
5500 | |
5501 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) { | |
5502 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned( | |
5503 new MockDrawQuadsToFillScreenContext); | |
5504 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get(); | |
5505 | |
5506 // Run test case | |
5507 LayerTreeSettings settings = DefaultSettings(); | |
5508 settings.renderer_settings.partial_swap_enabled = false; | |
5509 CreateHostImpl(settings, | |
5510 FakeOutputSurface::Create3d(mock_context_owned.Pass())); | |
5511 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1)); | |
5512 host_impl_->active_tree()->set_background_color(SK_ColorWHITE); | |
5513 | |
5514 // Verify one quad is drawn when transparent background set is not set. | |
5515 host_impl_->active_tree()->set_has_transparent_background(false); | |
5516 EXPECT_CALL(*mock_context, useProgram(_)) | |
5517 .Times(1); | |
5518 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)) | |
5519 .Times(1); | |
5520 LayerTreeHostImpl::FrameData frame; | |
5521 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5522 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5523 host_impl_->DidDrawAllLayers(frame); | |
5524 Mock::VerifyAndClearExpectations(&mock_context); | |
5525 | |
5526 // Verify no quads are drawn when transparent background is set. | |
5527 host_impl_->active_tree()->set_has_transparent_background(true); | |
5528 host_impl_->SetFullRootLayerDamage(); | |
5529 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5530 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5531 host_impl_->DidDrawAllLayers(frame); | |
5532 Mock::VerifyAndClearExpectations(&mock_context); | |
5533 } | |
5534 | |
5535 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) { | |
5536 set_reduce_memory_result(false); | |
5537 | |
5538 // If changing the memory limit wouldn't result in changing what was | |
5539 // committed, then no commit should be requested. | |
5540 set_reduce_memory_result(false); | |
5541 host_impl_->set_max_memory_needed_bytes( | |
5542 host_impl_->memory_allocation_limit_bytes() - 1); | |
5543 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy( | |
5544 host_impl_->memory_allocation_limit_bytes() - 1)); | |
5545 EXPECT_FALSE(did_request_commit_); | |
5546 did_request_commit_ = false; | |
5547 | |
5548 // If changing the memory limit would result in changing what was | |
5549 // committed, then a commit should be requested, even though nothing was | |
5550 // evicted. | |
5551 set_reduce_memory_result(false); | |
5552 host_impl_->set_max_memory_needed_bytes( | |
5553 host_impl_->memory_allocation_limit_bytes()); | |
5554 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy( | |
5555 host_impl_->memory_allocation_limit_bytes() - 1)); | |
5556 EXPECT_TRUE(did_request_commit_); | |
5557 did_request_commit_ = false; | |
5558 | |
5559 // Especially if changing the memory limit caused evictions, we need | |
5560 // to re-commit. | |
5561 set_reduce_memory_result(true); | |
5562 host_impl_->set_max_memory_needed_bytes(1); | |
5563 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy( | |
5564 host_impl_->memory_allocation_limit_bytes() - 1)); | |
5565 EXPECT_TRUE(did_request_commit_); | |
5566 did_request_commit_ = false; | |
5567 | |
5568 // But if we set it to the same value that it was before, we shouldn't | |
5569 // re-commit. | |
5570 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy( | |
5571 host_impl_->memory_allocation_limit_bytes())); | |
5572 EXPECT_FALSE(did_request_commit_); | |
5573 } | |
5574 | |
5575 class LayerTreeHostImplTestWithDelegatingRenderer | |
5576 : public LayerTreeHostImplTest { | |
5577 protected: | |
5578 scoped_ptr<OutputSurface> CreateOutputSurface() override { | |
5579 return FakeOutputSurface::CreateDelegating3d(); | |
5580 } | |
5581 | |
5582 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) { | |
5583 bool expect_to_draw = !expected_damage.IsEmpty(); | |
5584 | |
5585 LayerTreeHostImpl::FrameData frame; | |
5586 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5587 | |
5588 if (!expect_to_draw) { | |
5589 // With no damage, we don't draw, and no quads are created. | |
5590 ASSERT_EQ(0u, frame.render_passes.size()); | |
5591 } else { | |
5592 ASSERT_EQ(1u, frame.render_passes.size()); | |
5593 | |
5594 // Verify the damage rect for the root render pass. | |
5595 const RenderPass* root_render_pass = frame.render_passes.back(); | |
5596 EXPECT_EQ(expected_damage, root_render_pass->damage_rect); | |
5597 | |
5598 // Verify the root and child layers' quads are generated and not being | |
5599 // culled. | |
5600 ASSERT_EQ(2u, root_render_pass->quad_list.size()); | |
5601 | |
5602 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0]; | |
5603 gfx::RectF expected_child_visible_rect(child->content_bounds()); | |
5604 EXPECT_EQ(expected_child_visible_rect, | |
5605 root_render_pass->quad_list.front()->visible_rect); | |
5606 | |
5607 LayerImpl* root = host_impl_->active_tree()->root_layer(); | |
5608 gfx::RectF expected_root_visible_rect(root->content_bounds()); | |
5609 EXPECT_EQ(expected_root_visible_rect, | |
5610 root_render_pass->quad_list.ElementAt(1)->visible_rect); | |
5611 } | |
5612 | |
5613 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5614 host_impl_->DidDrawAllLayers(frame); | |
5615 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame)); | |
5616 } | |
5617 }; | |
5618 | |
5619 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) { | |
5620 scoped_ptr<SolidColorLayerImpl> root = | |
5621 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1); | |
5622 root->SetPosition(gfx::PointF()); | |
5623 root->SetBounds(gfx::Size(10, 10)); | |
5624 root->SetContentBounds(gfx::Size(10, 10)); | |
5625 root->SetDrawsContent(true); | |
5626 root->SetHasRenderSurface(true); | |
5627 | |
5628 // Child layer is in the bottom right corner. | |
5629 scoped_ptr<SolidColorLayerImpl> child = | |
5630 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2); | |
5631 child->SetPosition(gfx::PointF(9.f, 9.f)); | |
5632 child->SetBounds(gfx::Size(1, 1)); | |
5633 child->SetContentBounds(gfx::Size(1, 1)); | |
5634 child->SetDrawsContent(true); | |
5635 root->AddChild(child.Pass()); | |
5636 | |
5637 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
5638 | |
5639 // Draw a frame. In the first frame, the entire viewport should be damaged. | |
5640 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize()); | |
5641 DrawFrameAndTestDamage(full_frame_damage); | |
5642 | |
5643 // The second frame has damage that doesn't touch the child layer. Its quads | |
5644 // should still be generated. | |
5645 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1); | |
5646 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage); | |
5647 DrawFrameAndTestDamage(small_damage); | |
5648 | |
5649 // The third frame should have no damage, so no quads should be generated. | |
5650 gfx::Rect no_damage; | |
5651 DrawFrameAndTestDamage(no_damage); | |
5652 } | |
5653 | |
5654 // TODO(reveman): Remove this test and the ability to prevent on demand raster | |
5655 // when delegating renderer supports PictureDrawQuads. crbug.com/342121 | |
5656 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) { | |
5657 LayerTreeSettings settings; | |
5658 CreateHostImpl(settings, CreateOutputSurface()); | |
5659 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand); | |
5660 } | |
5661 | |
5662 class FakeMaskLayerImpl : public LayerImpl { | |
5663 public: | |
5664 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl, | |
5665 int id) { | |
5666 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id)); | |
5667 } | |
5668 | |
5669 void GetContentsResourceId(ResourceProvider::ResourceId* resource_id, | |
5670 gfx::Size* resource_size) const override { | |
5671 *resource_id = 0; | |
5672 } | |
5673 | |
5674 private: | |
5675 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id) | |
5676 : LayerImpl(tree_impl, id) {} | |
5677 }; | |
5678 | |
5679 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) { | |
5680 LayerTreeSettings settings; | |
5681 settings.layer_transforms_should_scale_layer_contents = true; | |
5682 CreateHostImpl(settings, CreateOutputSurface()); | |
5683 | |
5684 // Root | |
5685 // | | |
5686 // +-- Scaling Layer (adds a 2x scale) | |
5687 // | | |
5688 // +-- Content Layer | |
5689 // +--Mask | |
5690 scoped_ptr<LayerImpl> scoped_root = | |
5691 LayerImpl::Create(host_impl_->active_tree(), 1); | |
5692 LayerImpl* root = scoped_root.get(); | |
5693 root->SetHasRenderSurface(true); | |
5694 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass()); | |
5695 | |
5696 scoped_ptr<LayerImpl> scoped_scaling_layer = | |
5697 LayerImpl::Create(host_impl_->active_tree(), 2); | |
5698 LayerImpl* scaling_layer = scoped_scaling_layer.get(); | |
5699 root->AddChild(scoped_scaling_layer.Pass()); | |
5700 | |
5701 scoped_ptr<LayerImpl> scoped_content_layer = | |
5702 LayerImpl::Create(host_impl_->active_tree(), 3); | |
5703 LayerImpl* content_layer = scoped_content_layer.get(); | |
5704 scaling_layer->AddChild(scoped_content_layer.Pass()); | |
5705 | |
5706 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer = | |
5707 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4); | |
5708 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get(); | |
5709 content_layer->SetHasRenderSurface(true); | |
5710 content_layer->SetMaskLayer(scoped_mask_layer.Pass()); | |
5711 | |
5712 gfx::Size root_size(100, 100); | |
5713 root->SetBounds(root_size); | |
5714 root->SetContentBounds(root_size); | |
5715 root->SetPosition(gfx::PointF()); | |
5716 | |
5717 gfx::Size scaling_layer_size(50, 50); | |
5718 scaling_layer->SetBounds(scaling_layer_size); | |
5719 scaling_layer->SetContentBounds(scaling_layer_size); | |
5720 scaling_layer->SetPosition(gfx::PointF()); | |
5721 gfx::Transform scale; | |
5722 scale.Scale(2.f, 2.f); | |
5723 scaling_layer->SetTransform(scale); | |
5724 | |
5725 content_layer->SetBounds(scaling_layer_size); | |
5726 content_layer->SetContentBounds(scaling_layer_size); | |
5727 content_layer->SetPosition(gfx::PointF()); | |
5728 content_layer->SetDrawsContent(true); | |
5729 | |
5730 mask_layer->SetBounds(scaling_layer_size); | |
5731 mask_layer->SetContentBounds(scaling_layer_size); | |
5732 mask_layer->SetPosition(gfx::PointF()); | |
5733 mask_layer->SetDrawsContent(true); | |
5734 | |
5735 | |
5736 // Check that the tree scaling is correctly taken into account for the mask, | |
5737 // that should fully map onto the quad. | |
5738 float device_scale_factor = 1.f; | |
5739 host_impl_->SetViewportSize(root_size); | |
5740 host_impl_->SetDeviceScaleFactor(device_scale_factor); | |
5741 { | |
5742 LayerTreeHostImpl::FrameData frame; | |
5743 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5744 | |
5745 ASSERT_EQ(1u, frame.render_passes.size()); | |
5746 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size()); | |
5747 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
5748 frame.render_passes[0]->quad_list.front()->material); | |
5749 const RenderPassDrawQuad* render_pass_quad = | |
5750 RenderPassDrawQuad::MaterialCast( | |
5751 frame.render_passes[0]->quad_list.front()); | |
5752 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
5753 render_pass_quad->rect.ToString()); | |
5754 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), | |
5755 render_pass_quad->MaskUVRect().ToString()); | |
5756 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(), | |
5757 render_pass_quad->mask_uv_scale.ToString()); | |
5758 | |
5759 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5760 host_impl_->DidDrawAllLayers(frame); | |
5761 } | |
5762 | |
5763 | |
5764 // Applying a DSF should change the render surface size, but won't affect | |
5765 // which part of the mask is used. | |
5766 device_scale_factor = 2.f; | |
5767 gfx::Size device_viewport = | |
5768 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor)); | |
5769 host_impl_->SetViewportSize(device_viewport); | |
5770 host_impl_->SetDeviceScaleFactor(device_scale_factor); | |
5771 host_impl_->active_tree()->set_needs_update_draw_properties(); | |
5772 { | |
5773 LayerTreeHostImpl::FrameData frame; | |
5774 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5775 | |
5776 ASSERT_EQ(1u, frame.render_passes.size()); | |
5777 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size()); | |
5778 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
5779 frame.render_passes[0]->quad_list.front()->material); | |
5780 const RenderPassDrawQuad* render_pass_quad = | |
5781 RenderPassDrawQuad::MaterialCast( | |
5782 frame.render_passes[0]->quad_list.front()); | |
5783 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(), | |
5784 render_pass_quad->rect.ToString()); | |
5785 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), | |
5786 render_pass_quad->MaskUVRect().ToString()); | |
5787 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(), | |
5788 render_pass_quad->mask_uv_scale.ToString()); | |
5789 | |
5790 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5791 host_impl_->DidDrawAllLayers(frame); | |
5792 } | |
5793 | |
5794 | |
5795 // Applying an equivalent content scale on the content layer and the mask | |
5796 // should still result in the same part of the mask being used. | |
5797 gfx::Size content_bounds = | |
5798 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size, | |
5799 device_scale_factor)); | |
5800 content_layer->SetContentBounds(content_bounds); | |
5801 content_layer->SetContentsScale(device_scale_factor, device_scale_factor); | |
5802 mask_layer->SetContentBounds(content_bounds); | |
5803 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor); | |
5804 host_impl_->active_tree()->set_needs_update_draw_properties(); | |
5805 { | |
5806 LayerTreeHostImpl::FrameData frame; | |
5807 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5808 | |
5809 ASSERT_EQ(1u, frame.render_passes.size()); | |
5810 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size()); | |
5811 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
5812 frame.render_passes[0]->quad_list.front()->material); | |
5813 const RenderPassDrawQuad* render_pass_quad = | |
5814 RenderPassDrawQuad::MaterialCast( | |
5815 frame.render_passes[0]->quad_list.front()); | |
5816 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(), | |
5817 render_pass_quad->rect.ToString()); | |
5818 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), | |
5819 render_pass_quad->MaskUVRect().ToString()); | |
5820 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(), | |
5821 render_pass_quad->mask_uv_scale.ToString()); | |
5822 | |
5823 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5824 host_impl_->DidDrawAllLayers(frame); | |
5825 } | |
5826 } | |
5827 | |
5828 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) { | |
5829 // The mask layer has bounds 100x100 but is attached to a layer with bounds | |
5830 // 50x50. | |
5831 | |
5832 scoped_ptr<LayerImpl> scoped_root = | |
5833 LayerImpl::Create(host_impl_->active_tree(), 1); | |
5834 LayerImpl* root = scoped_root.get(); | |
5835 root->SetHasRenderSurface(true); | |
5836 | |
5837 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass()); | |
5838 | |
5839 scoped_ptr<LayerImpl> scoped_content_layer = | |
5840 LayerImpl::Create(host_impl_->active_tree(), 3); | |
5841 LayerImpl* content_layer = scoped_content_layer.get(); | |
5842 root->AddChild(scoped_content_layer.Pass()); | |
5843 | |
5844 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer = | |
5845 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4); | |
5846 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get(); | |
5847 content_layer->SetMaskLayer(scoped_mask_layer.Pass()); | |
5848 content_layer->SetHasRenderSurface(true); | |
5849 | |
5850 gfx::Size root_size(100, 100); | |
5851 root->SetBounds(root_size); | |
5852 root->SetContentBounds(root_size); | |
5853 root->SetPosition(gfx::PointF()); | |
5854 | |
5855 gfx::Size layer_size(50, 50); | |
5856 content_layer->SetBounds(layer_size); | |
5857 content_layer->SetContentBounds(layer_size); | |
5858 content_layer->SetPosition(gfx::PointF()); | |
5859 content_layer->SetDrawsContent(true); | |
5860 | |
5861 gfx::Size mask_size(100, 100); | |
5862 mask_layer->SetBounds(mask_size); | |
5863 mask_layer->SetContentBounds(mask_size); | |
5864 mask_layer->SetPosition(gfx::PointF()); | |
5865 mask_layer->SetDrawsContent(true); | |
5866 | |
5867 // Check that the mask fills the surface. | |
5868 float device_scale_factor = 1.f; | |
5869 host_impl_->SetViewportSize(root_size); | |
5870 host_impl_->SetDeviceScaleFactor(device_scale_factor); | |
5871 { | |
5872 LayerTreeHostImpl::FrameData frame; | |
5873 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5874 | |
5875 ASSERT_EQ(1u, frame.render_passes.size()); | |
5876 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size()); | |
5877 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
5878 frame.render_passes[0]->quad_list.front()->material); | |
5879 const RenderPassDrawQuad* render_pass_quad = | |
5880 RenderPassDrawQuad::MaterialCast( | |
5881 frame.render_passes[0]->quad_list.front()); | |
5882 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), | |
5883 render_pass_quad->rect.ToString()); | |
5884 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), | |
5885 render_pass_quad->MaskUVRect().ToString()); | |
5886 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(), | |
5887 render_pass_quad->mask_uv_scale.ToString()); | |
5888 | |
5889 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5890 host_impl_->DidDrawAllLayers(frame); | |
5891 } | |
5892 | |
5893 // Applying a DSF should change the render surface size, but won't affect | |
5894 // which part of the mask is used. | |
5895 device_scale_factor = 2.f; | |
5896 gfx::Size device_viewport = | |
5897 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor)); | |
5898 host_impl_->SetViewportSize(device_viewport); | |
5899 host_impl_->SetDeviceScaleFactor(device_scale_factor); | |
5900 host_impl_->active_tree()->set_needs_update_draw_properties(); | |
5901 { | |
5902 LayerTreeHostImpl::FrameData frame; | |
5903 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5904 | |
5905 ASSERT_EQ(1u, frame.render_passes.size()); | |
5906 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size()); | |
5907 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
5908 frame.render_passes[0]->quad_list.front()->material); | |
5909 const RenderPassDrawQuad* render_pass_quad = | |
5910 RenderPassDrawQuad::MaterialCast( | |
5911 frame.render_passes[0]->quad_list.front()); | |
5912 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
5913 render_pass_quad->rect.ToString()); | |
5914 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), | |
5915 render_pass_quad->MaskUVRect().ToString()); | |
5916 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(), | |
5917 render_pass_quad->mask_uv_scale.ToString()); | |
5918 | |
5919 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5920 host_impl_->DidDrawAllLayers(frame); | |
5921 } | |
5922 | |
5923 // Applying an equivalent content scale on the content layer and the mask | |
5924 // should still result in the same part of the mask being used. | |
5925 gfx::Size layer_size_large = | |
5926 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor)); | |
5927 content_layer->SetContentBounds(layer_size_large); | |
5928 content_layer->SetContentsScale(device_scale_factor, device_scale_factor); | |
5929 gfx::Size mask_size_large = | |
5930 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor)); | |
5931 mask_layer->SetContentBounds(mask_size_large); | |
5932 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor); | |
5933 host_impl_->active_tree()->set_needs_update_draw_properties(); | |
5934 { | |
5935 LayerTreeHostImpl::FrameData frame; | |
5936 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5937 | |
5938 ASSERT_EQ(1u, frame.render_passes.size()); | |
5939 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size()); | |
5940 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
5941 frame.render_passes[0]->quad_list.front()->material); | |
5942 const RenderPassDrawQuad* render_pass_quad = | |
5943 RenderPassDrawQuad::MaterialCast( | |
5944 frame.render_passes[0]->quad_list.front()); | |
5945 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
5946 render_pass_quad->rect.ToString()); | |
5947 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), | |
5948 render_pass_quad->MaskUVRect().ToString()); | |
5949 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(), | |
5950 render_pass_quad->mask_uv_scale.ToString()); | |
5951 | |
5952 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5953 host_impl_->DidDrawAllLayers(frame); | |
5954 } | |
5955 | |
5956 // Applying a different contents scale to the mask layer means it will have | |
5957 // a larger texture, but it should use the same tex coords to cover the | |
5958 // layer it masks. | |
5959 mask_layer->SetContentBounds(mask_size); | |
5960 mask_layer->SetContentsScale(1.f, 1.f); | |
5961 host_impl_->active_tree()->set_needs_update_draw_properties(); | |
5962 { | |
5963 LayerTreeHostImpl::FrameData frame; | |
5964 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
5965 | |
5966 ASSERT_EQ(1u, frame.render_passes.size()); | |
5967 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size()); | |
5968 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
5969 frame.render_passes[0]->quad_list.front()->material); | |
5970 const RenderPassDrawQuad* render_pass_quad = | |
5971 RenderPassDrawQuad::MaterialCast( | |
5972 frame.render_passes[0]->quad_list.front()); | |
5973 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
5974 render_pass_quad->rect.ToString()); | |
5975 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), | |
5976 render_pass_quad->MaskUVRect().ToString()); | |
5977 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(), | |
5978 render_pass_quad->mask_uv_scale.ToString()); | |
5979 | |
5980 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
5981 host_impl_->DidDrawAllLayers(frame); | |
5982 } | |
5983 } | |
5984 | |
5985 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) { | |
5986 // The replica's mask layer has bounds 100x100 but the replica is of a | |
5987 // layer with bounds 50x50. | |
5988 | |
5989 scoped_ptr<LayerImpl> scoped_root = | |
5990 LayerImpl::Create(host_impl_->active_tree(), 1); | |
5991 LayerImpl* root = scoped_root.get(); | |
5992 root->SetHasRenderSurface(true); | |
5993 | |
5994 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass()); | |
5995 | |
5996 scoped_ptr<LayerImpl> scoped_content_layer = | |
5997 LayerImpl::Create(host_impl_->active_tree(), 3); | |
5998 LayerImpl* content_layer = scoped_content_layer.get(); | |
5999 root->AddChild(scoped_content_layer.Pass()); | |
6000 | |
6001 scoped_ptr<LayerImpl> scoped_replica_layer = | |
6002 LayerImpl::Create(host_impl_->active_tree(), 2); | |
6003 LayerImpl* replica_layer = scoped_replica_layer.get(); | |
6004 content_layer->SetReplicaLayer(scoped_replica_layer.Pass()); | |
6005 content_layer->SetHasRenderSurface(true); | |
6006 | |
6007 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer = | |
6008 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4); | |
6009 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get(); | |
6010 replica_layer->SetMaskLayer(scoped_mask_layer.Pass()); | |
6011 replica_layer->SetHasRenderSurface(true); | |
6012 | |
6013 gfx::Size root_size(100, 100); | |
6014 root->SetBounds(root_size); | |
6015 root->SetContentBounds(root_size); | |
6016 root->SetPosition(gfx::PointF()); | |
6017 | |
6018 gfx::Size layer_size(50, 50); | |
6019 content_layer->SetBounds(layer_size); | |
6020 content_layer->SetContentBounds(layer_size); | |
6021 content_layer->SetPosition(gfx::PointF()); | |
6022 content_layer->SetDrawsContent(true); | |
6023 | |
6024 gfx::Size mask_size(100, 100); | |
6025 mask_layer->SetBounds(mask_size); | |
6026 mask_layer->SetContentBounds(mask_size); | |
6027 mask_layer->SetPosition(gfx::PointF()); | |
6028 mask_layer->SetDrawsContent(true); | |
6029 | |
6030 // Check that the mask fills the surface. | |
6031 float device_scale_factor = 1.f; | |
6032 host_impl_->SetViewportSize(root_size); | |
6033 host_impl_->SetDeviceScaleFactor(device_scale_factor); | |
6034 { | |
6035 LayerTreeHostImpl::FrameData frame; | |
6036 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
6037 | |
6038 ASSERT_EQ(1u, frame.render_passes.size()); | |
6039 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size()); | |
6040 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
6041 frame.render_passes[0]->quad_list.ElementAt(1)->material); | |
6042 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast( | |
6043 frame.render_passes[0]->quad_list.ElementAt(1)); | |
6044 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), | |
6045 replica_quad->rect.ToString()); | |
6046 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), | |
6047 replica_quad->MaskUVRect().ToString()); | |
6048 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(), | |
6049 replica_quad->mask_uv_scale.ToString()); | |
6050 | |
6051 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
6052 host_impl_->DidDrawAllLayers(frame); | |
6053 } | |
6054 | |
6055 // Applying a DSF should change the render surface size, but won't affect | |
6056 // which part of the mask is used. | |
6057 device_scale_factor = 2.f; | |
6058 gfx::Size device_viewport = | |
6059 gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor)); | |
6060 host_impl_->SetViewportSize(device_viewport); | |
6061 host_impl_->SetDeviceScaleFactor(device_scale_factor); | |
6062 host_impl_->active_tree()->set_needs_update_draw_properties(); | |
6063 { | |
6064 LayerTreeHostImpl::FrameData frame; | |
6065 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
6066 | |
6067 ASSERT_EQ(1u, frame.render_passes.size()); | |
6068 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size()); | |
6069 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
6070 frame.render_passes[0]->quad_list.ElementAt(1)->material); | |
6071 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast( | |
6072 frame.render_passes[0]->quad_list.ElementAt(1)); | |
6073 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
6074 replica_quad->rect.ToString()); | |
6075 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), | |
6076 replica_quad->MaskUVRect().ToString()); | |
6077 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(), | |
6078 replica_quad->mask_uv_scale.ToString()); | |
6079 | |
6080 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
6081 host_impl_->DidDrawAllLayers(frame); | |
6082 } | |
6083 | |
6084 // Applying an equivalent content scale on the content layer and the mask | |
6085 // should still result in the same part of the mask being used. | |
6086 gfx::Size layer_size_large = | |
6087 gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor)); | |
6088 content_layer->SetContentBounds(layer_size_large); | |
6089 content_layer->SetContentsScale(device_scale_factor, device_scale_factor); | |
6090 gfx::Size mask_size_large = | |
6091 gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor)); | |
6092 mask_layer->SetContentBounds(mask_size_large); | |
6093 mask_layer->SetContentsScale(device_scale_factor, device_scale_factor); | |
6094 host_impl_->active_tree()->set_needs_update_draw_properties(); | |
6095 { | |
6096 LayerTreeHostImpl::FrameData frame; | |
6097 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
6098 | |
6099 ASSERT_EQ(1u, frame.render_passes.size()); | |
6100 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size()); | |
6101 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
6102 frame.render_passes[0]->quad_list.ElementAt(1)->material); | |
6103 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast( | |
6104 frame.render_passes[0]->quad_list.ElementAt(1)); | |
6105 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
6106 replica_quad->rect.ToString()); | |
6107 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), | |
6108 replica_quad->MaskUVRect().ToString()); | |
6109 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(), | |
6110 replica_quad->mask_uv_scale.ToString()); | |
6111 | |
6112 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
6113 host_impl_->DidDrawAllLayers(frame); | |
6114 } | |
6115 | |
6116 // Applying a different contents scale to the mask layer means it will have | |
6117 // a larger texture, but it should use the same tex coords to cover the | |
6118 // layer it masks. | |
6119 mask_layer->SetContentBounds(mask_size); | |
6120 mask_layer->SetContentsScale(1.f, 1.f); | |
6121 host_impl_->active_tree()->set_needs_update_draw_properties(); | |
6122 { | |
6123 LayerTreeHostImpl::FrameData frame; | |
6124 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
6125 | |
6126 ASSERT_EQ(1u, frame.render_passes.size()); | |
6127 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size()); | |
6128 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
6129 frame.render_passes[0]->quad_list.ElementAt(1)->material); | |
6130 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast( | |
6131 frame.render_passes[0]->quad_list.ElementAt(1)); | |
6132 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
6133 replica_quad->rect.ToString()); | |
6134 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), | |
6135 replica_quad->MaskUVRect().ToString()); | |
6136 EXPECT_EQ(gfx::Vector2dF(1.f, 1.f).ToString(), | |
6137 replica_quad->mask_uv_scale.ToString()); | |
6138 | |
6139 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
6140 host_impl_->DidDrawAllLayers(frame); | |
6141 } | |
6142 } | |
6143 | |
6144 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) { | |
6145 // The replica is of a layer with bounds 50x50, but it has a child that causes | |
6146 // the surface bounds to be larger. | |
6147 | |
6148 scoped_ptr<LayerImpl> scoped_root = | |
6149 LayerImpl::Create(host_impl_->active_tree(), 1); | |
6150 LayerImpl* root = scoped_root.get(); | |
6151 root->SetHasRenderSurface(true); | |
6152 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass()); | |
6153 | |
6154 scoped_ptr<LayerImpl> scoped_content_layer = | |
6155 LayerImpl::Create(host_impl_->active_tree(), 2); | |
6156 LayerImpl* content_layer = scoped_content_layer.get(); | |
6157 root->AddChild(scoped_content_layer.Pass()); | |
6158 | |
6159 scoped_ptr<LayerImpl> scoped_content_child_layer = | |
6160 LayerImpl::Create(host_impl_->active_tree(), 3); | |
6161 LayerImpl* content_child_layer = scoped_content_child_layer.get(); | |
6162 content_layer->AddChild(scoped_content_child_layer.Pass()); | |
6163 | |
6164 scoped_ptr<LayerImpl> scoped_replica_layer = | |
6165 LayerImpl::Create(host_impl_->active_tree(), 4); | |
6166 LayerImpl* replica_layer = scoped_replica_layer.get(); | |
6167 content_layer->SetReplicaLayer(scoped_replica_layer.Pass()); | |
6168 content_layer->SetHasRenderSurface(true); | |
6169 | |
6170 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer = | |
6171 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5); | |
6172 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get(); | |
6173 replica_layer->SetMaskLayer(scoped_mask_layer.Pass()); | |
6174 replica_layer->SetHasRenderSurface(true); | |
6175 | |
6176 gfx::Size root_size(100, 100); | |
6177 root->SetBounds(root_size); | |
6178 root->SetContentBounds(root_size); | |
6179 root->SetPosition(gfx::PointF()); | |
6180 | |
6181 gfx::Size layer_size(50, 50); | |
6182 content_layer->SetBounds(layer_size); | |
6183 content_layer->SetContentBounds(layer_size); | |
6184 content_layer->SetPosition(gfx::PointF()); | |
6185 content_layer->SetDrawsContent(true); | |
6186 | |
6187 gfx::Size child_size(50, 50); | |
6188 content_child_layer->SetBounds(child_size); | |
6189 content_child_layer->SetContentBounds(child_size); | |
6190 content_child_layer->SetPosition(gfx::Point(50, 0)); | |
6191 content_child_layer->SetDrawsContent(true); | |
6192 | |
6193 gfx::Size mask_size(50, 50); | |
6194 mask_layer->SetBounds(mask_size); | |
6195 mask_layer->SetContentBounds(mask_size); | |
6196 mask_layer->SetPosition(gfx::PointF()); | |
6197 mask_layer->SetDrawsContent(true); | |
6198 | |
6199 float device_scale_factor = 1.f; | |
6200 host_impl_->SetViewportSize(root_size); | |
6201 host_impl_->SetDeviceScaleFactor(device_scale_factor); | |
6202 { | |
6203 LayerTreeHostImpl::FrameData frame; | |
6204 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
6205 | |
6206 ASSERT_EQ(1u, frame.render_passes.size()); | |
6207 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size()); | |
6208 | |
6209 // The surface is 100x50. | |
6210 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
6211 frame.render_passes[0]->quad_list.front()->material); | |
6212 const RenderPassDrawQuad* render_pass_quad = | |
6213 RenderPassDrawQuad::MaterialCast( | |
6214 frame.render_passes[0]->quad_list.front()); | |
6215 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(), | |
6216 render_pass_quad->rect.ToString()); | |
6217 | |
6218 // The mask covers the owning layer only. | |
6219 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
6220 frame.render_passes[0]->quad_list.ElementAt(1)->material); | |
6221 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast( | |
6222 frame.render_passes[0]->quad_list.ElementAt(1)); | |
6223 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(), | |
6224 replica_quad->rect.ToString()); | |
6225 EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(), | |
6226 replica_quad->MaskUVRect().ToString()); | |
6227 EXPECT_EQ(gfx::Vector2dF(2.f, 1.f).ToString(), | |
6228 replica_quad->mask_uv_scale.ToString()); | |
6229 | |
6230 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
6231 host_impl_->DidDrawAllLayers(frame); | |
6232 } | |
6233 | |
6234 // Move the child to (-50, 0) instead. Now the mask should be moved to still | |
6235 // cover the layer being replicated. | |
6236 content_child_layer->SetPosition(gfx::Point(-50, 0)); | |
6237 { | |
6238 LayerTreeHostImpl::FrameData frame; | |
6239 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
6240 | |
6241 ASSERT_EQ(1u, frame.render_passes.size()); | |
6242 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size()); | |
6243 | |
6244 // The surface is 100x50 with its origin at (-50, 0). | |
6245 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
6246 frame.render_passes[0]->quad_list.front()->material); | |
6247 const RenderPassDrawQuad* render_pass_quad = | |
6248 RenderPassDrawQuad::MaterialCast( | |
6249 frame.render_passes[0]->quad_list.front()); | |
6250 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(), | |
6251 render_pass_quad->rect.ToString()); | |
6252 | |
6253 // The mask covers the owning layer only. | |
6254 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
6255 frame.render_passes[0]->quad_list.ElementAt(1)->material); | |
6256 const RenderPassDrawQuad* replica_quad = RenderPassDrawQuad::MaterialCast( | |
6257 frame.render_passes[0]->quad_list.ElementAt(1)); | |
6258 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(), | |
6259 replica_quad->rect.ToString()); | |
6260 EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(), | |
6261 replica_quad->MaskUVRect().ToString()); | |
6262 EXPECT_EQ(gfx::Vector2dF(2.f, 1.f).ToString(), | |
6263 replica_quad->mask_uv_scale.ToString()); | |
6264 | |
6265 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
6266 host_impl_->DidDrawAllLayers(frame); | |
6267 } | |
6268 } | |
6269 | |
6270 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) { | |
6271 // The masked layer has bounds 50x50, but it has a child that causes | |
6272 // the surface bounds to be larger. It also has a parent that clips the | |
6273 // masked layer and its surface. | |
6274 | |
6275 scoped_ptr<LayerImpl> scoped_root = | |
6276 LayerImpl::Create(host_impl_->active_tree(), 1); | |
6277 LayerImpl* root = scoped_root.get(); | |
6278 root->SetHasRenderSurface(true); | |
6279 | |
6280 host_impl_->active_tree()->SetRootLayer(scoped_root.Pass()); | |
6281 | |
6282 scoped_ptr<LayerImpl> scoped_clipping_layer = | |
6283 LayerImpl::Create(host_impl_->active_tree(), 2); | |
6284 LayerImpl* clipping_layer = scoped_clipping_layer.get(); | |
6285 root->AddChild(scoped_clipping_layer.Pass()); | |
6286 | |
6287 scoped_ptr<LayerImpl> scoped_content_layer = | |
6288 LayerImpl::Create(host_impl_->active_tree(), 3); | |
6289 LayerImpl* content_layer = scoped_content_layer.get(); | |
6290 clipping_layer->AddChild(scoped_content_layer.Pass()); | |
6291 | |
6292 scoped_ptr<LayerImpl> scoped_content_child_layer = | |
6293 LayerImpl::Create(host_impl_->active_tree(), 4); | |
6294 LayerImpl* content_child_layer = scoped_content_child_layer.get(); | |
6295 content_layer->AddChild(scoped_content_child_layer.Pass()); | |
6296 | |
6297 scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer = | |
6298 FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6); | |
6299 FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get(); | |
6300 content_layer->SetMaskLayer(scoped_mask_layer.Pass()); | |
6301 content_layer->SetHasRenderSurface(true); | |
6302 | |
6303 gfx::Size root_size(100, 100); | |
6304 root->SetBounds(root_size); | |
6305 root->SetContentBounds(root_size); | |
6306 root->SetPosition(gfx::PointF()); | |
6307 | |
6308 gfx::Rect clipping_rect(20, 10, 10, 20); | |
6309 clipping_layer->SetBounds(clipping_rect.size()); | |
6310 clipping_layer->SetContentBounds(clipping_rect.size()); | |
6311 clipping_layer->SetPosition(clipping_rect.origin()); | |
6312 clipping_layer->SetMasksToBounds(true); | |
6313 | |
6314 gfx::Size layer_size(50, 50); | |
6315 content_layer->SetBounds(layer_size); | |
6316 content_layer->SetContentBounds(layer_size); | |
6317 content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin()); | |
6318 content_layer->SetDrawsContent(true); | |
6319 | |
6320 gfx::Size child_size(50, 50); | |
6321 content_child_layer->SetBounds(child_size); | |
6322 content_child_layer->SetContentBounds(child_size); | |
6323 content_child_layer->SetPosition(gfx::Point(50, 0)); | |
6324 content_child_layer->SetDrawsContent(true); | |
6325 | |
6326 gfx::Size mask_size(100, 100); | |
6327 mask_layer->SetBounds(mask_size); | |
6328 mask_layer->SetContentBounds(mask_size); | |
6329 mask_layer->SetPosition(gfx::PointF()); | |
6330 mask_layer->SetDrawsContent(true); | |
6331 | |
6332 float device_scale_factor = 1.f; | |
6333 host_impl_->SetViewportSize(root_size); | |
6334 host_impl_->SetDeviceScaleFactor(device_scale_factor); | |
6335 { | |
6336 LayerTreeHostImpl::FrameData frame; | |
6337 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
6338 | |
6339 ASSERT_EQ(1u, frame.render_passes.size()); | |
6340 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size()); | |
6341 | |
6342 // The surface is clipped to 10x20. | |
6343 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
6344 frame.render_passes[0]->quad_list.front()->material); | |
6345 const RenderPassDrawQuad* render_pass_quad = | |
6346 RenderPassDrawQuad::MaterialCast( | |
6347 frame.render_passes[0]->quad_list.front()); | |
6348 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(), | |
6349 render_pass_quad->rect.ToString()); | |
6350 // The masked layer is 50x50, but the surface size is 10x20. So the texture | |
6351 // coords in the mask are scaled by 10/50 and 20/50. | |
6352 // The surface is clipped to (20,10) so the mask texture coords are offset | |
6353 // by 20/50 and 10/50 | |
6354 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) | |
6355 .ToString(), | |
6356 render_pass_quad->MaskUVRect().ToString()); | |
6357 EXPECT_EQ(gfx::Vector2dF(10.f / 50.f, 20.f / 50.f).ToString(), | |
6358 render_pass_quad->mask_uv_scale.ToString()); | |
6359 | |
6360 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
6361 host_impl_->DidDrawAllLayers(frame); | |
6362 } | |
6363 } | |
6364 | |
6365 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer { | |
6366 public: | |
6367 using GLRenderer::ShouldAntialiasQuad; | |
6368 }; | |
6369 | |
6370 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) { | |
6371 // Due to precision issues (especially on Android), sometimes far | |
6372 // away quads can end up thinking they need AA. | |
6373 float device_scale_factor = 4.f / 3.f; | |
6374 host_impl_->SetDeviceScaleFactor(device_scale_factor); | |
6375 gfx::Size root_size(2000, 1000); | |
6376 gfx::Size device_viewport_size = | |
6377 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor)); | |
6378 host_impl_->SetViewportSize(device_viewport_size); | |
6379 | |
6380 host_impl_->CreatePendingTree(); | |
6381 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f, | |
6382 16.f); | |
6383 | |
6384 scoped_ptr<LayerImpl> scoped_root = | |
6385 LayerImpl::Create(host_impl_->pending_tree(), 1); | |
6386 LayerImpl* root = scoped_root.get(); | |
6387 root->SetHasRenderSurface(true); | |
6388 | |
6389 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass()); | |
6390 | |
6391 scoped_ptr<LayerImpl> scoped_scrolling_layer = | |
6392 LayerImpl::Create(host_impl_->pending_tree(), 2); | |
6393 LayerImpl* scrolling_layer = scoped_scrolling_layer.get(); | |
6394 root->AddChild(scoped_scrolling_layer.Pass()); | |
6395 | |
6396 gfx::Size content_layer_bounds(100000, 100); | |
6397 gfx::Size pile_tile_size(3000, 3000); | |
6398 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile( | |
6399 pile_tile_size, content_layer_bounds)); | |
6400 | |
6401 scoped_ptr<FakePictureLayerImpl> scoped_content_layer = | |
6402 FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(), | |
6403 3, pile); | |
6404 LayerImpl* content_layer = scoped_content_layer.get(); | |
6405 scrolling_layer->AddChild(scoped_content_layer.Pass()); | |
6406 content_layer->SetBounds(content_layer_bounds); | |
6407 content_layer->SetDrawsContent(true); | |
6408 | |
6409 root->SetBounds(root_size); | |
6410 | |
6411 gfx::ScrollOffset scroll_offset(100000, 0); | |
6412 scrolling_layer->SetScrollClipLayer(root->id()); | |
6413 scrolling_layer->PushScrollOffsetFromMainThread(scroll_offset); | |
6414 | |
6415 host_impl_->ActivateSyncTree(); | |
6416 | |
6417 bool update_lcd_text = false; | |
6418 host_impl_->active_tree()->UpdateDrawProperties(update_lcd_text); | |
6419 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size()); | |
6420 | |
6421 LayerTreeHostImpl::FrameData frame; | |
6422 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
6423 | |
6424 ASSERT_EQ(1u, frame.render_passes.size()); | |
6425 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size()); | |
6426 const DrawQuad* quad = frame.render_passes[0]->quad_list.front(); | |
6427 | |
6428 bool antialiased = | |
6429 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad( | |
6430 quad->quadTransform(), quad, false); | |
6431 EXPECT_FALSE(antialiased); | |
6432 | |
6433 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
6434 host_impl_->DidDrawAllLayers(frame); | |
6435 } | |
6436 | |
6437 | |
6438 class CompositorFrameMetadataTest : public LayerTreeHostImplTest { | |
6439 public: | |
6440 CompositorFrameMetadataTest() | |
6441 : swap_buffers_complete_(0) {} | |
6442 | |
6443 void DidSwapBuffersCompleteOnImplThread() override { | |
6444 swap_buffers_complete_++; | |
6445 } | |
6446 | |
6447 int swap_buffers_complete_; | |
6448 }; | |
6449 | |
6450 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) { | |
6451 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1)); | |
6452 { | |
6453 LayerTreeHostImpl::FrameData frame; | |
6454 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
6455 host_impl_->DrawLayers(&frame, base::TimeTicks()); | |
6456 host_impl_->DidDrawAllLayers(frame); | |
6457 } | |
6458 CompositorFrameAck ack; | |
6459 host_impl_->ReclaimResources(&ack); | |
6460 host_impl_->DidSwapBuffersComplete(); | |
6461 EXPECT_EQ(swap_buffers_complete_, 1); | |
6462 } | |
6463 | |
6464 class CountingSoftwareDevice : public SoftwareOutputDevice { | |
6465 public: | |
6466 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {} | |
6467 | |
6468 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override { | |
6469 ++frames_began_; | |
6470 return SoftwareOutputDevice::BeginPaint(damage_rect); | |
6471 } | |
6472 void EndPaint(SoftwareFrameData* frame_data) override { | |
6473 ++frames_ended_; | |
6474 SoftwareOutputDevice::EndPaint(frame_data); | |
6475 } | |
6476 | |
6477 int frames_began_, frames_ended_; | |
6478 }; | |
6479 | |
6480 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) { | |
6481 // No main thread evictions in resourceless software mode. | |
6482 set_reduce_memory_result(false); | |
6483 CountingSoftwareDevice* software_device = new CountingSoftwareDevice(); | |
6484 bool delegated_rendering = false; | |
6485 FakeOutputSurface* output_surface = | |
6486 FakeOutputSurface::CreateDeferredGL( | |
6487 scoped_ptr<SoftwareOutputDevice>(software_device), | |
6488 delegated_rendering).release(); | |
6489 EXPECT_TRUE(CreateHostImpl(DefaultSettings(), | |
6490 scoped_ptr<OutputSurface>(output_surface))); | |
6491 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
6492 | |
6493 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
6494 | |
6495 const gfx::Transform external_transform; | |
6496 const gfx::Rect external_viewport; | |
6497 const gfx::Rect external_clip; | |
6498 const bool resourceless_software_draw = true; | |
6499 host_impl_->SetExternalDrawConstraints(external_transform, | |
6500 external_viewport, | |
6501 external_clip, | |
6502 external_viewport, | |
6503 external_transform, | |
6504 resourceless_software_draw); | |
6505 | |
6506 EXPECT_EQ(0, software_device->frames_began_); | |
6507 EXPECT_EQ(0, software_device->frames_ended_); | |
6508 | |
6509 DrawFrame(); | |
6510 | |
6511 EXPECT_EQ(1, software_device->frames_began_); | |
6512 EXPECT_EQ(1, software_device->frames_ended_); | |
6513 | |
6514 // Call another API method that is likely to hit nullptr in this mode. | |
6515 scoped_refptr<base::trace_event::TracedValue> state = | |
6516 make_scoped_refptr(new base::trace_event::TracedValue()); | |
6517 host_impl_->ActivationStateAsValueInto(state.get()); | |
6518 } | |
6519 | |
6520 TEST_F(LayerTreeHostImplTest, | |
6521 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) { | |
6522 set_reduce_memory_result(false); | |
6523 bool delegated_rendering = false; | |
6524 FakeOutputSurface* output_surface = | |
6525 FakeOutputSurface::CreateDeferredGL( | |
6526 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()), | |
6527 delegated_rendering).release(); | |
6528 EXPECT_TRUE(CreateHostImpl(DefaultSettings(), | |
6529 scoped_ptr<OutputSurface>(output_surface))); | |
6530 | |
6531 const gfx::Transform external_transform; | |
6532 const gfx::Rect external_viewport; | |
6533 const gfx::Rect external_clip; | |
6534 const bool resourceless_software_draw = true; | |
6535 host_impl_->SetExternalDrawConstraints(external_transform, | |
6536 external_viewport, | |
6537 external_clip, | |
6538 external_viewport, | |
6539 external_transform, | |
6540 resourceless_software_draw); | |
6541 | |
6542 // SolidColorLayerImpl will be drawn. | |
6543 scoped_ptr<SolidColorLayerImpl> root_layer = | |
6544 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1); | |
6545 | |
6546 LayerTreeHostImpl::FrameData frame; | |
6547 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
6548 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
6549 host_impl_->DidDrawAllLayers(frame); | |
6550 | |
6551 EXPECT_EQ(1u, frame.will_draw_layers.size()); | |
6552 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]); | |
6553 } | |
6554 | |
6555 class LayerTreeHostImplTestDeferredInitialize : public LayerTreeHostImplTest { | |
6556 protected: | |
6557 void SetUp() override { | |
6558 LayerTreeHostImplTest::SetUp(); | |
6559 | |
6560 set_reduce_memory_result(false); | |
6561 | |
6562 bool delegated_rendering = false; | |
6563 scoped_ptr<FakeOutputSurface> output_surface( | |
6564 FakeOutputSurface::CreateDeferredGL( | |
6565 scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice()), | |
6566 delegated_rendering)); | |
6567 output_surface_ = output_surface.get(); | |
6568 | |
6569 EXPECT_TRUE(CreateHostImpl(DefaultSettings(), output_surface.Pass())); | |
6570 | |
6571 scoped_ptr<SolidColorLayerImpl> root_layer = | |
6572 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1); | |
6573 SetupRootLayerImpl(root_layer.Pass()); | |
6574 | |
6575 onscreen_context_provider_ = TestContextProvider::Create(); | |
6576 } | |
6577 | |
6578 void UpdateRendererCapabilitiesOnImplThread() override { | |
6579 did_update_renderer_capabilities_ = true; | |
6580 } | |
6581 | |
6582 FakeOutputSurface* output_surface_; | |
6583 scoped_refptr<TestContextProvider> onscreen_context_provider_; | |
6584 bool did_update_renderer_capabilities_; | |
6585 }; | |
6586 | |
6587 | |
6588 TEST_F(LayerTreeHostImplTestDeferredInitialize, Success) { | |
6589 // Software draw. | |
6590 DrawFrame(); | |
6591 | |
6592 EXPECT_FALSE(host_impl_->output_surface()->context_provider()); | |
6593 | |
6594 // DeferredInitialize and hardware draw. | |
6595 did_update_renderer_capabilities_ = false; | |
6596 EXPECT_TRUE(output_surface_->InitializeAndSetContext3d( | |
6597 onscreen_context_provider_, nullptr)); | |
6598 EXPECT_EQ(onscreen_context_provider_.get(), | |
6599 host_impl_->output_surface()->context_provider()); | |
6600 EXPECT_TRUE(did_update_renderer_capabilities_); | |
6601 | |
6602 // Defer intialized GL draw. | |
6603 DrawFrame(); | |
6604 | |
6605 // Revert back to software. | |
6606 did_update_renderer_capabilities_ = false; | |
6607 output_surface_->ReleaseGL(); | |
6608 EXPECT_FALSE(host_impl_->output_surface()->context_provider()); | |
6609 EXPECT_TRUE(did_update_renderer_capabilities_); | |
6610 | |
6611 // Software draw again. | |
6612 DrawFrame(); | |
6613 } | |
6614 | |
6615 TEST_F(LayerTreeHostImplTestDeferredInitialize, Fails) { | |
6616 // Software draw. | |
6617 DrawFrame(); | |
6618 | |
6619 // Fail initialization of the onscreen context before the OutputSurface binds | |
6620 // it to the thread. | |
6621 onscreen_context_provider_->UnboundTestContext3d()->set_context_lost(true); | |
6622 | |
6623 EXPECT_FALSE(host_impl_->output_surface()->context_provider()); | |
6624 | |
6625 // DeferredInitialize fails. | |
6626 did_update_renderer_capabilities_ = false; | |
6627 EXPECT_FALSE(output_surface_->InitializeAndSetContext3d( | |
6628 onscreen_context_provider_, nullptr)); | |
6629 EXPECT_FALSE(host_impl_->output_surface()->context_provider()); | |
6630 EXPECT_FALSE(did_update_renderer_capabilities_); | |
6631 | |
6632 // Software draw again. | |
6633 DrawFrame(); | |
6634 } | |
6635 | |
6636 // Checks that we have a non-0 default allocation if we pass a context that | |
6637 // doesn't support memory management extensions. | |
6638 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) { | |
6639 LayerTreeSettings settings; | |
6640 host_impl_ = LayerTreeHostImpl::Create( | |
6641 settings, this, &proxy_, &stats_instrumentation_, | |
6642 shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), | |
6643 task_graph_runner_.get(), 0); | |
6644 | |
6645 scoped_ptr<OutputSurface> output_surface( | |
6646 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create())); | |
6647 host_impl_->InitializeRenderer(output_surface.Pass()); | |
6648 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes()); | |
6649 } | |
6650 | |
6651 TEST_F(LayerTreeHostImplTest, MemoryPolicy) { | |
6652 ManagedMemoryPolicy policy1( | |
6653 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000); | |
6654 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue( | |
6655 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING); | |
6656 int allow_nice_to_have_cutoff_value = | |
6657 ManagedMemoryPolicy::PriorityCutoffToValue( | |
6658 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE); | |
6659 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue( | |
6660 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING); | |
6661 | |
6662 // GPU rasterization should be disabled by default on the tree(s) | |
6663 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization()); | |
6664 EXPECT_TRUE(host_impl_->pending_tree() == NULL); | |
6665 | |
6666 host_impl_->SetVisible(true); | |
6667 host_impl_->SetMemoryPolicy(policy1); | |
6668 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_); | |
6669 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_); | |
6670 | |
6671 host_impl_->SetVisible(false); | |
6672 EXPECT_EQ(0u, current_limit_bytes_); | |
6673 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_); | |
6674 | |
6675 host_impl_->SetVisible(true); | |
6676 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_); | |
6677 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_); | |
6678 | |
6679 // Now enable GPU rasterization and test if we get nice to have cutoff, | |
6680 // when visible. | |
6681 LayerTreeSettings settings; | |
6682 settings.gpu_rasterization_enabled = true; | |
6683 host_impl_ = LayerTreeHostImpl::Create( | |
6684 settings, this, &proxy_, &stats_instrumentation_, NULL, NULL, NULL, 0); | |
6685 host_impl_->SetUseGpuRasterization(true); | |
6686 host_impl_->SetVisible(true); | |
6687 host_impl_->SetMemoryPolicy(policy1); | |
6688 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_); | |
6689 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_); | |
6690 | |
6691 host_impl_->SetVisible(false); | |
6692 EXPECT_EQ(0u, current_limit_bytes_); | |
6693 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_); | |
6694 } | |
6695 | |
6696 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) { | |
6697 ASSERT_TRUE(host_impl_->active_tree()); | |
6698 | |
6699 // RequiresHighResToDraw is set when new output surface is used. | |
6700 EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); | |
6701 | |
6702 host_impl_->ResetRequiresHighResToDraw(); | |
6703 | |
6704 host_impl_->SetVisible(false); | |
6705 EXPECT_FALSE(host_impl_->RequiresHighResToDraw()); | |
6706 host_impl_->SetVisible(true); | |
6707 EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); | |
6708 host_impl_->SetVisible(false); | |
6709 EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); | |
6710 | |
6711 host_impl_->ResetRequiresHighResToDraw(); | |
6712 | |
6713 EXPECT_FALSE(host_impl_->RequiresHighResToDraw()); | |
6714 host_impl_->SetVisible(true); | |
6715 EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); | |
6716 } | |
6717 | |
6718 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) { | |
6719 ASSERT_TRUE(host_impl_->active_tree()); | |
6720 EXPECT_FALSE(host_impl_->use_gpu_rasterization()); | |
6721 | |
6722 // RequiresHighResToDraw is set when new output surface is used. | |
6723 EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); | |
6724 | |
6725 host_impl_->ResetRequiresHighResToDraw(); | |
6726 | |
6727 host_impl_->SetUseGpuRasterization(false); | |
6728 EXPECT_FALSE(host_impl_->RequiresHighResToDraw()); | |
6729 host_impl_->SetUseGpuRasterization(true); | |
6730 EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); | |
6731 host_impl_->SetUseGpuRasterization(false); | |
6732 EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); | |
6733 | |
6734 host_impl_->ResetRequiresHighResToDraw(); | |
6735 | |
6736 EXPECT_FALSE(host_impl_->RequiresHighResToDraw()); | |
6737 host_impl_->SetUseGpuRasterization(true); | |
6738 EXPECT_TRUE(host_impl_->RequiresHighResToDraw()); | |
6739 } | |
6740 | |
6741 class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest { | |
6742 public: | |
6743 void SetUp() override { | |
6744 LayerTreeSettings settings; | |
6745 settings.impl_side_painting = true; | |
6746 | |
6747 fake_host_impl_ = new FakeLayerTreeHostImpl(settings, &proxy_, | |
6748 shared_bitmap_manager_.get(), | |
6749 task_graph_runner_.get()); | |
6750 host_impl_.reset(fake_host_impl_); | |
6751 host_impl_->InitializeRenderer(CreateOutputSurface()); | |
6752 host_impl_->SetViewportSize(gfx::Size(10, 10)); | |
6753 } | |
6754 | |
6755 FakeLayerTreeHostImpl* fake_host_impl_; | |
6756 }; | |
6757 | |
6758 TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) { | |
6759 fake_host_impl_->DidModifyTilePriorities(); | |
6760 EXPECT_TRUE(fake_host_impl_->prepare_tiles_needed()); | |
6761 fake_host_impl_->SetVisible(false); | |
6762 EXPECT_FALSE(fake_host_impl_->prepare_tiles_needed()); | |
6763 } | |
6764 | |
6765 TEST_F(LayerTreeHostImplTest, UIResourceManagement) { | |
6766 scoped_ptr<TestWebGraphicsContext3D> context = | |
6767 TestWebGraphicsContext3D::Create(); | |
6768 TestWebGraphicsContext3D* context3d = context.get(); | |
6769 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d(); | |
6770 CreateHostImpl(DefaultSettings(), output_surface.Pass()); | |
6771 | |
6772 EXPECT_EQ(0u, context3d->NumTextures()); | |
6773 | |
6774 UIResourceId ui_resource_id = 1; | |
6775 bool is_opaque = false; | |
6776 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque); | |
6777 host_impl_->CreateUIResource(ui_resource_id, bitmap); | |
6778 EXPECT_EQ(1u, context3d->NumTextures()); | |
6779 ResourceProvider::ResourceId id1 = | |
6780 host_impl_->ResourceIdForUIResource(ui_resource_id); | |
6781 EXPECT_NE(0u, id1); | |
6782 | |
6783 // Multiple requests with the same id is allowed. The previous texture is | |
6784 // deleted. | |
6785 host_impl_->CreateUIResource(ui_resource_id, bitmap); | |
6786 EXPECT_EQ(1u, context3d->NumTextures()); | |
6787 ResourceProvider::ResourceId id2 = | |
6788 host_impl_->ResourceIdForUIResource(ui_resource_id); | |
6789 EXPECT_NE(0u, id2); | |
6790 EXPECT_NE(id1, id2); | |
6791 | |
6792 // Deleting invalid UIResourceId is allowed and does not change state. | |
6793 host_impl_->DeleteUIResource(-1); | |
6794 EXPECT_EQ(1u, context3d->NumTextures()); | |
6795 | |
6796 // Should return zero for invalid UIResourceId. Number of textures should | |
6797 // not change. | |
6798 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1)); | |
6799 EXPECT_EQ(1u, context3d->NumTextures()); | |
6800 | |
6801 host_impl_->DeleteUIResource(ui_resource_id); | |
6802 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id)); | |
6803 EXPECT_EQ(0u, context3d->NumTextures()); | |
6804 | |
6805 // Should not change state for multiple deletion on one UIResourceId | |
6806 host_impl_->DeleteUIResource(ui_resource_id); | |
6807 EXPECT_EQ(0u, context3d->NumTextures()); | |
6808 } | |
6809 | |
6810 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) { | |
6811 scoped_ptr<TestWebGraphicsContext3D> context = | |
6812 TestWebGraphicsContext3D::Create(); | |
6813 TestWebGraphicsContext3D* context3d = context.get(); | |
6814 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d()); | |
6815 | |
6816 EXPECT_EQ(0u, context3d->NumTextures()); | |
6817 | |
6818 gfx::Size size(4, 4); | |
6819 // SkImageInfo has no support for ETC1. The |info| below contains the right | |
6820 // total pixel size for the bitmap but not the right height and width. The | |
6821 // correct width/height are passed directly to UIResourceBitmap. | |
6822 SkImageInfo info = | |
6823 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType); | |
6824 skia::RefPtr<SkPixelRef> pixel_ref = | |
6825 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0)); | |
6826 pixel_ref->setImmutable(); | |
6827 UIResourceBitmap bitmap(pixel_ref, size); | |
6828 UIResourceId ui_resource_id = 1; | |
6829 host_impl_->CreateUIResource(ui_resource_id, bitmap); | |
6830 EXPECT_EQ(1u, context3d->NumTextures()); | |
6831 ResourceProvider::ResourceId id1 = | |
6832 host_impl_->ResourceIdForUIResource(ui_resource_id); | |
6833 EXPECT_NE(0u, id1); | |
6834 } | |
6835 | |
6836 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) { | |
6837 } | |
6838 | |
6839 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) { | |
6840 scoped_refptr<TestContextProvider> context_provider = | |
6841 TestContextProvider::Create(); | |
6842 | |
6843 CreateHostImpl(DefaultSettings(), | |
6844 FakeOutputSurface::Create3d(context_provider)); | |
6845 | |
6846 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1)); | |
6847 | |
6848 ScopedPtrVector<CopyOutputRequest> requests; | |
6849 requests.push_back(CopyOutputRequest::CreateRequest( | |
6850 base::Bind(&ShutdownReleasesContext_Callback))); | |
6851 | |
6852 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests); | |
6853 | |
6854 LayerTreeHostImpl::FrameData frame; | |
6855 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
6856 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
6857 host_impl_->DidDrawAllLayers(frame); | |
6858 | |
6859 // The CopyOutputResult's callback has a ref on the ContextProvider and a | |
6860 // texture in a texture mailbox. | |
6861 EXPECT_FALSE(context_provider->HasOneRef()); | |
6862 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures()); | |
6863 | |
6864 host_impl_ = nullptr; | |
6865 | |
6866 // The CopyOutputResult's callback was cancelled, the CopyOutputResult | |
6867 // released, and the texture deleted. | |
6868 EXPECT_TRUE(context_provider->HasOneRef()); | |
6869 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures()); | |
6870 } | |
6871 | |
6872 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) { | |
6873 // When flinging via touch, only the child should scroll (we should not | |
6874 // bubble). | |
6875 gfx::Size surface_size(10, 10); | |
6876 gfx::Size content_size(20, 20); | |
6877 scoped_ptr<LayerImpl> root_clip = | |
6878 LayerImpl::Create(host_impl_->active_tree(), 3); | |
6879 root_clip->SetHasRenderSurface(true); | |
6880 | |
6881 scoped_ptr<LayerImpl> root = | |
6882 CreateScrollableLayer(1, content_size, root_clip.get()); | |
6883 root->SetIsContainerForFixedPositionLayers(true); | |
6884 scoped_ptr<LayerImpl> child = | |
6885 CreateScrollableLayer(2, content_size, root_clip.get()); | |
6886 | |
6887 root->AddChild(child.Pass()); | |
6888 int root_id = root->id(); | |
6889 root_clip->AddChild(root.Pass()); | |
6890 | |
6891 host_impl_->SetViewportSize(surface_size); | |
6892 host_impl_->active_tree()->SetRootLayer(root_clip.Pass()); | |
6893 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1, | |
6894 Layer::INVALID_ID); | |
6895 host_impl_->active_tree()->DidBecomeActive(); | |
6896 DrawFrame(); | |
6897 { | |
6898 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
6899 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
6900 | |
6901 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); | |
6902 | |
6903 gfx::Vector2d scroll_delta(0, 100); | |
6904 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
6905 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
6906 | |
6907 host_impl_->ScrollEnd(); | |
6908 | |
6909 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
6910 host_impl_->ProcessScrollDeltas(); | |
6911 | |
6912 // Only the child should have scrolled. | |
6913 ASSERT_EQ(1u, scroll_info->scrolls.size()); | |
6914 ExpectNone(*scroll_info.get(), root_id); | |
6915 } | |
6916 } | |
6917 | |
6918 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) { | |
6919 // Scroll a child layer beyond its maximum scroll range and make sure the | |
6920 // the scroll doesn't bubble up to the parent layer. | |
6921 gfx::Size surface_size(10, 10); | |
6922 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1); | |
6923 root->SetHasRenderSurface(true); | |
6924 scoped_ptr<LayerImpl> root_scrolling = | |
6925 CreateScrollableLayer(2, surface_size, root.get()); | |
6926 | |
6927 scoped_ptr<LayerImpl> grand_child = | |
6928 CreateScrollableLayer(4, surface_size, root.get()); | |
6929 grand_child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2)); | |
6930 | |
6931 scoped_ptr<LayerImpl> child = | |
6932 CreateScrollableLayer(3, surface_size, root.get()); | |
6933 child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4)); | |
6934 child->AddChild(grand_child.Pass()); | |
6935 | |
6936 root_scrolling->AddChild(child.Pass()); | |
6937 root->AddChild(root_scrolling.Pass()); | |
6938 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
6939 host_impl_->active_tree()->DidBecomeActive(); | |
6940 host_impl_->SetViewportSize(surface_size); | |
6941 DrawFrame(); | |
6942 { | |
6943 scoped_ptr<ScrollAndScaleSet> scroll_info; | |
6944 LayerImpl* child = | |
6945 host_impl_->active_tree()->root_layer()->children()[0]->children()[0]; | |
6946 LayerImpl* grand_child = child->children()[0]; | |
6947 | |
6948 gfx::Vector2d scroll_delta(0, -2); | |
6949 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
6950 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
6951 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll); | |
6952 | |
6953 // The grand child should have scrolled up to its limit. | |
6954 scroll_info = host_impl_->ProcessScrollDeltas(); | |
6955 ASSERT_EQ(1u, scroll_info->scrolls.size()); | |
6956 ExpectContains(*scroll_info, grand_child->id(), scroll_delta); | |
6957 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child); | |
6958 | |
6959 // The child should have received the bubbled delta, but the locked | |
6960 // scrolling layer should remain set as the grand child. | |
6961 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll); | |
6962 scroll_info = host_impl_->ProcessScrollDeltas(); | |
6963 ASSERT_EQ(2u, scroll_info->scrolls.size()); | |
6964 ExpectContains(*scroll_info, grand_child->id(), scroll_delta); | |
6965 ExpectContains(*scroll_info, child->id(), scroll_delta); | |
6966 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child); | |
6967 | |
6968 // The first |ScrollBy| after the fling should re-lock the scrolling | |
6969 // layer to the first layer that scrolled, which is the child. | |
6970 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); | |
6971 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll); | |
6972 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child); | |
6973 | |
6974 // The child should have scrolled up to its limit. | |
6975 scroll_info = host_impl_->ProcessScrollDeltas(); | |
6976 ASSERT_EQ(2u, scroll_info->scrolls.size()); | |
6977 ExpectContains(*scroll_info, grand_child->id(), scroll_delta); | |
6978 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta); | |
6979 | |
6980 // As the locked layer is at it's limit, no further scrolling can occur. | |
6981 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll); | |
6982 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child); | |
6983 host_impl_->ScrollEnd(); | |
6984 } | |
6985 } | |
6986 | |
6987 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) { | |
6988 // When flinging via wheel, the root should eventually scroll (we should | |
6989 // bubble). | |
6990 gfx::Size surface_size(10, 10); | |
6991 gfx::Size content_size(20, 20); | |
6992 scoped_ptr<LayerImpl> root_clip = | |
6993 LayerImpl::Create(host_impl_->active_tree(), 3); | |
6994 root_clip->SetHasRenderSurface(true); | |
6995 scoped_ptr<LayerImpl> root_scroll = | |
6996 CreateScrollableLayer(1, content_size, root_clip.get()); | |
6997 int root_scroll_id = root_scroll->id(); | |
6998 scoped_ptr<LayerImpl> child = | |
6999 CreateScrollableLayer(2, content_size, root_clip.get()); | |
7000 | |
7001 root_scroll->AddChild(child.Pass()); | |
7002 root_clip->AddChild(root_scroll.Pass()); | |
7003 | |
7004 host_impl_->SetViewportSize(surface_size); | |
7005 host_impl_->active_tree()->SetRootLayer(root_clip.Pass()); | |
7006 host_impl_->active_tree()->DidBecomeActive(); | |
7007 DrawFrame(); | |
7008 { | |
7009 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7010 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
7011 | |
7012 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); | |
7013 | |
7014 gfx::Vector2d scroll_delta(0, 100); | |
7015 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
7016 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
7017 | |
7018 host_impl_->ScrollEnd(); | |
7019 | |
7020 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
7021 host_impl_->ProcessScrollDeltas(); | |
7022 | |
7023 // The root should have scrolled. | |
7024 ASSERT_EQ(2u, scroll_info->scrolls.size()); | |
7025 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10)); | |
7026 } | |
7027 } | |
7028 | |
7029 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) { | |
7030 // If we ray cast a scroller that is not on the first layer's ancestor chain, | |
7031 // we should return SCROLL_UNKNOWN. | |
7032 gfx::Size content_size(100, 100); | |
7033 SetupScrollAndContentsLayers(content_size); | |
7034 | |
7035 int scroll_layer_id = 2; | |
7036 LayerImpl* scroll_layer = | |
7037 host_impl_->active_tree()->LayerById(scroll_layer_id); | |
7038 scroll_layer->SetDrawsContent(true); | |
7039 | |
7040 int page_scale_layer_id = 5; | |
7041 LayerImpl* page_scale_layer = | |
7042 host_impl_->active_tree()->LayerById(page_scale_layer_id); | |
7043 | |
7044 int occluder_layer_id = 6; | |
7045 scoped_ptr<LayerImpl> occluder_layer = | |
7046 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id); | |
7047 occluder_layer->SetDrawsContent(true); | |
7048 occluder_layer->SetBounds(content_size); | |
7049 occluder_layer->SetContentBounds(content_size); | |
7050 occluder_layer->SetPosition(gfx::PointF()); | |
7051 | |
7052 // The parent of the occluder is *above* the scroller. | |
7053 page_scale_layer->AddChild(occluder_layer.Pass()); | |
7054 | |
7055 DrawFrame(); | |
7056 | |
7057 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN, | |
7058 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
7059 } | |
7060 | |
7061 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) { | |
7062 // If we ray cast a scroller this is on the first layer's ancestor chain, but | |
7063 // is not the first scroller we encounter when walking up from the layer, we | |
7064 // should also return SCROLL_UNKNOWN. | |
7065 gfx::Size content_size(100, 100); | |
7066 SetupScrollAndContentsLayers(content_size); | |
7067 | |
7068 int scroll_layer_id = 2; | |
7069 LayerImpl* scroll_layer = | |
7070 host_impl_->active_tree()->LayerById(scroll_layer_id); | |
7071 scroll_layer->SetDrawsContent(true); | |
7072 | |
7073 int occluder_layer_id = 6; | |
7074 scoped_ptr<LayerImpl> occluder_layer = | |
7075 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id); | |
7076 occluder_layer->SetDrawsContent(true); | |
7077 occluder_layer->SetBounds(content_size); | |
7078 occluder_layer->SetContentBounds(content_size); | |
7079 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f)); | |
7080 | |
7081 int child_scroll_clip_layer_id = 7; | |
7082 scoped_ptr<LayerImpl> child_scroll_clip = | |
7083 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id); | |
7084 | |
7085 int child_scroll_layer_id = 8; | |
7086 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer( | |
7087 child_scroll_layer_id, content_size, child_scroll_clip.get()); | |
7088 | |
7089 child_scroll->SetPosition(gfx::PointF(10.f, 10.f)); | |
7090 | |
7091 child_scroll->AddChild(occluder_layer.Pass()); | |
7092 scroll_layer->AddChild(child_scroll.Pass()); | |
7093 | |
7094 DrawFrame(); | |
7095 | |
7096 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN, | |
7097 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
7098 } | |
7099 | |
7100 TEST_F(LayerTreeHostImplTest, NotScrollInvisibleScroller) { | |
7101 gfx::Size content_size(100, 100); | |
7102 SetupScrollAndContentsLayers(content_size); | |
7103 | |
7104 LayerImpl* root = host_impl_->active_tree()->LayerById(1); | |
7105 | |
7106 int scroll_layer_id = 2; | |
7107 LayerImpl* scroll_layer = | |
7108 host_impl_->active_tree()->LayerById(scroll_layer_id); | |
7109 | |
7110 int child_scroll_layer_id = 7; | |
7111 scoped_ptr<LayerImpl> child_scroll = | |
7112 CreateScrollableLayer(child_scroll_layer_id, content_size, root); | |
7113 child_scroll->SetDrawsContent(false); | |
7114 | |
7115 scroll_layer->AddChild(child_scroll.Pass()); | |
7116 | |
7117 DrawFrame(); | |
7118 | |
7119 // We should not have scrolled |child_scroll| even though we technically "hit" | |
7120 // it. The reason for this is that if the scrolling the scroll would not move | |
7121 // any layer that is a drawn RSLL member, then we can ignore the hit. | |
7122 // | |
7123 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and | |
7124 // started scrolling the inner viewport. | |
7125 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7126 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
7127 | |
7128 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id()); | |
7129 } | |
7130 | |
7131 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) { | |
7132 gfx::Size content_size(100, 100); | |
7133 SetupScrollAndContentsLayers(content_size); | |
7134 | |
7135 LayerImpl* root = host_impl_->active_tree()->LayerById(1); | |
7136 LayerImpl* root_scroll_layer = host_impl_->active_tree()->LayerById(2); | |
7137 | |
7138 scoped_ptr<LayerImpl> invisible_scroll_layer = | |
7139 CreateScrollableLayer(7, content_size, root); | |
7140 invisible_scroll_layer->SetDrawsContent(false); | |
7141 | |
7142 scoped_ptr<LayerImpl> child_layer = | |
7143 LayerImpl::Create(host_impl_->active_tree(), 8); | |
7144 child_layer->SetDrawsContent(false); | |
7145 | |
7146 scoped_ptr<LayerImpl> grand_child_layer = | |
7147 LayerImpl::Create(host_impl_->active_tree(), 9); | |
7148 grand_child_layer->SetDrawsContent(true); | |
7149 grand_child_layer->SetBounds(content_size); | |
7150 grand_child_layer->SetContentBounds(content_size); | |
7151 // Move the grand child so it's not hit by our test point. | |
7152 grand_child_layer->SetPosition(gfx::PointF(10.f, 10.f)); | |
7153 | |
7154 child_layer->AddChild(grand_child_layer.Pass()); | |
7155 invisible_scroll_layer->AddChild(child_layer.Pass()); | |
7156 root_scroll_layer->AddChild(invisible_scroll_layer.Pass()); | |
7157 | |
7158 DrawFrame(); | |
7159 | |
7160 // We should have scrolled |invisible_scroll_layer| as it was hit and it has | |
7161 // a descendant which is a drawn RSLL member. | |
7162 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7163 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
7164 | |
7165 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id()); | |
7166 } | |
7167 | |
7168 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) { | |
7169 // This test case is very similar to the one above with one key difference: | |
7170 // the invisible scroller has a scroll child that is indeed draw contents. | |
7171 // If we attempt to initiate a gesture scroll off of the visible scroll child | |
7172 // we should still start the scroll child. | |
7173 gfx::Size content_size(100, 100); | |
7174 SetupScrollAndContentsLayers(content_size); | |
7175 | |
7176 LayerImpl* root = host_impl_->active_tree()->LayerById(1); | |
7177 | |
7178 int scroll_layer_id = 2; | |
7179 LayerImpl* scroll_layer = | |
7180 host_impl_->active_tree()->LayerById(scroll_layer_id); | |
7181 | |
7182 int scroll_child_id = 6; | |
7183 scoped_ptr<LayerImpl> scroll_child = | |
7184 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id); | |
7185 scroll_child->SetDrawsContent(true); | |
7186 scroll_child->SetBounds(content_size); | |
7187 scroll_child->SetContentBounds(content_size); | |
7188 // Move the scroll child so it's not hit by our test point. | |
7189 scroll_child->SetPosition(gfx::PointF(10.f, 10.f)); | |
7190 | |
7191 int invisible_scroll_layer_id = 7; | |
7192 scoped_ptr<LayerImpl> invisible_scroll = | |
7193 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root); | |
7194 invisible_scroll->SetDrawsContent(false); | |
7195 | |
7196 int container_id = 8; | |
7197 scoped_ptr<LayerImpl> container = | |
7198 LayerImpl::Create(host_impl_->active_tree(), container_id); | |
7199 | |
7200 scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>); | |
7201 scroll_children->insert(scroll_child.get()); | |
7202 invisible_scroll->SetScrollChildren(scroll_children.release()); | |
7203 | |
7204 scroll_child->SetScrollParent(invisible_scroll.get()); | |
7205 | |
7206 container->AddChild(invisible_scroll.Pass()); | |
7207 container->AddChild(scroll_child.Pass()); | |
7208 | |
7209 scroll_layer->AddChild(container.Pass()); | |
7210 | |
7211 DrawFrame(); | |
7212 | |
7213 // We should have scrolled |child_scroll| even though it is invisible. | |
7214 // The reason for this is that if the scrolling the scroll would move a layer | |
7215 // that is a drawn RSLL member, then we should accept this hit. | |
7216 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7217 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
7218 | |
7219 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id()); | |
7220 } | |
7221 | |
7222 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed | |
7223 // to CompositorFrameMetadata after SwapBuffers(); | |
7224 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) { | |
7225 scoped_ptr<SolidColorLayerImpl> root = | |
7226 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1); | |
7227 root->SetPosition(gfx::PointF()); | |
7228 root->SetBounds(gfx::Size(10, 10)); | |
7229 root->SetContentBounds(gfx::Size(10, 10)); | |
7230 root->SetDrawsContent(true); | |
7231 root->SetHasRenderSurface(true); | |
7232 | |
7233 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
7234 | |
7235 FakeOutputSurface* fake_output_surface = | |
7236 static_cast<FakeOutputSurface*>(host_impl_->output_surface()); | |
7237 | |
7238 const std::vector<ui::LatencyInfo>& metadata_latency_before = | |
7239 fake_output_surface->last_sent_frame().metadata.latency_info; | |
7240 EXPECT_TRUE(metadata_latency_before.empty()); | |
7241 | |
7242 ui::LatencyInfo latency_info; | |
7243 latency_info.AddLatencyNumber( | |
7244 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0); | |
7245 scoped_ptr<SwapPromise> swap_promise( | |
7246 new LatencyInfoSwapPromise(latency_info)); | |
7247 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass()); | |
7248 host_impl_->SetNeedsRedraw(); | |
7249 | |
7250 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize()); | |
7251 LayerTreeHostImpl::FrameData frame; | |
7252 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
7253 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
7254 host_impl_->DidDrawAllLayers(frame); | |
7255 EXPECT_TRUE(host_impl_->SwapBuffers(frame)); | |
7256 | |
7257 const std::vector<ui::LatencyInfo>& metadata_latency_after = | |
7258 fake_output_surface->last_sent_frame().metadata.latency_info; | |
7259 EXPECT_EQ(1u, metadata_latency_after.size()); | |
7260 EXPECT_TRUE(metadata_latency_after[0].FindLatency( | |
7261 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL)); | |
7262 } | |
7263 | |
7264 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) { | |
7265 int root_layer_id = 1; | |
7266 scoped_ptr<SolidColorLayerImpl> root = | |
7267 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id); | |
7268 root->SetPosition(gfx::PointF()); | |
7269 root->SetBounds(gfx::Size(10, 10)); | |
7270 root->SetContentBounds(gfx::Size(10, 10)); | |
7271 root->SetDrawsContent(true); | |
7272 root->SetHasRenderSurface(true); | |
7273 | |
7274 host_impl_->active_tree()->SetRootLayer(root.Pass()); | |
7275 | |
7276 // Ensure the default frame selection bounds are empty. | |
7277 FakeOutputSurface* fake_output_surface = | |
7278 static_cast<FakeOutputSurface*>(host_impl_->output_surface()); | |
7279 const ViewportSelectionBound& selection_start_before = | |
7280 fake_output_surface->last_sent_frame().metadata.selection_start; | |
7281 const ViewportSelectionBound& selection_end_before = | |
7282 fake_output_surface->last_sent_frame().metadata.selection_end; | |
7283 EXPECT_EQ(ViewportSelectionBound(), selection_start_before); | |
7284 EXPECT_EQ(ViewportSelectionBound(), selection_end_before); | |
7285 | |
7286 // Plumb the layer-local selection bounds. | |
7287 gfx::PointF selection_top(5, 0); | |
7288 gfx::PointF selection_bottom(5, 5); | |
7289 LayerSelectionBound start, end; | |
7290 start.type = SELECTION_BOUND_CENTER; | |
7291 start.layer_id = root_layer_id; | |
7292 start.edge_bottom = selection_bottom; | |
7293 start.edge_top = selection_top; | |
7294 end = start; | |
7295 host_impl_->active_tree()->RegisterSelection(start, end); | |
7296 | |
7297 // Trigger a draw-swap sequence. | |
7298 host_impl_->SetNeedsRedraw(); | |
7299 | |
7300 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize()); | |
7301 LayerTreeHostImpl::FrameData frame; | |
7302 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); | |
7303 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); | |
7304 host_impl_->DidDrawAllLayers(frame); | |
7305 EXPECT_TRUE(host_impl_->SwapBuffers(frame)); | |
7306 | |
7307 // Ensure the selection bounds have propagated to the frame metadata. | |
7308 const ViewportSelectionBound& selection_start_after = | |
7309 fake_output_surface->last_sent_frame().metadata.selection_start; | |
7310 const ViewportSelectionBound& selection_end_after = | |
7311 fake_output_surface->last_sent_frame().metadata.selection_end; | |
7312 EXPECT_EQ(start.type, selection_start_after.type); | |
7313 EXPECT_EQ(end.type, selection_end_after.type); | |
7314 EXPECT_EQ(selection_bottom, selection_start_after.edge_bottom); | |
7315 EXPECT_EQ(selection_top, selection_start_after.edge_top); | |
7316 EXPECT_TRUE(selection_start_after.visible); | |
7317 EXPECT_TRUE(selection_start_after.visible); | |
7318 } | |
7319 | |
7320 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor { | |
7321 public: | |
7322 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host, | |
7323 LayerTreeHostImpl* layer_tree_host_impl, | |
7324 int* set_needs_commit_count, | |
7325 int* set_needs_redraw_count, | |
7326 int* forward_to_main_count) | |
7327 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl), | |
7328 set_needs_commit_count_(set_needs_commit_count), | |
7329 set_needs_redraw_count_(set_needs_redraw_count), | |
7330 forward_to_main_count_(forward_to_main_count) {} | |
7331 | |
7332 ~SimpleSwapPromiseMonitor() override {} | |
7333 | |
7334 void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; } | |
7335 | |
7336 void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; } | |
7337 | |
7338 void OnForwardScrollUpdateToMainThreadOnImpl() override { | |
7339 (*forward_to_main_count_)++; | |
7340 } | |
7341 | |
7342 private: | |
7343 int* set_needs_commit_count_; | |
7344 int* set_needs_redraw_count_; | |
7345 int* forward_to_main_count_; | |
7346 }; | |
7347 | |
7348 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) { | |
7349 int set_needs_commit_count = 0; | |
7350 int set_needs_redraw_count = 0; | |
7351 int forward_to_main_count = 0; | |
7352 | |
7353 { | |
7354 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( | |
7355 new SimpleSwapPromiseMonitor(NULL, | |
7356 host_impl_.get(), | |
7357 &set_needs_commit_count, | |
7358 &set_needs_redraw_count, | |
7359 &forward_to_main_count)); | |
7360 host_impl_->SetNeedsRedraw(); | |
7361 EXPECT_EQ(0, set_needs_commit_count); | |
7362 EXPECT_EQ(1, set_needs_redraw_count); | |
7363 EXPECT_EQ(0, forward_to_main_count); | |
7364 } | |
7365 | |
7366 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being | |
7367 // monitored. | |
7368 host_impl_->SetNeedsRedraw(); | |
7369 EXPECT_EQ(0, set_needs_commit_count); | |
7370 EXPECT_EQ(1, set_needs_redraw_count); | |
7371 EXPECT_EQ(0, forward_to_main_count); | |
7372 | |
7373 { | |
7374 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( | |
7375 new SimpleSwapPromiseMonitor(NULL, | |
7376 host_impl_.get(), | |
7377 &set_needs_commit_count, | |
7378 &set_needs_redraw_count, | |
7379 &forward_to_main_count)); | |
7380 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10)); | |
7381 EXPECT_EQ(0, set_needs_commit_count); | |
7382 EXPECT_EQ(2, set_needs_redraw_count); | |
7383 EXPECT_EQ(0, forward_to_main_count); | |
7384 } | |
7385 | |
7386 { | |
7387 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( | |
7388 new SimpleSwapPromiseMonitor(NULL, | |
7389 host_impl_.get(), | |
7390 &set_needs_commit_count, | |
7391 &set_needs_redraw_count, | |
7392 &forward_to_main_count)); | |
7393 // Empty damage rect won't signal the monitor. | |
7394 host_impl_->SetNeedsRedrawRect(gfx::Rect()); | |
7395 EXPECT_EQ(0, set_needs_commit_count); | |
7396 EXPECT_EQ(2, set_needs_redraw_count); | |
7397 EXPECT_EQ(0, forward_to_main_count); | |
7398 } | |
7399 | |
7400 { | |
7401 set_needs_commit_count = 0; | |
7402 set_needs_redraw_count = 0; | |
7403 forward_to_main_count = 0; | |
7404 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( | |
7405 new SimpleSwapPromiseMonitor(NULL, | |
7406 host_impl_.get(), | |
7407 &set_needs_commit_count, | |
7408 &set_needs_redraw_count, | |
7409 &forward_to_main_count)); | |
7410 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
7411 | |
7412 // Scrolling normally should not trigger any forwarding. | |
7413 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7414 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
7415 EXPECT_TRUE( | |
7416 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll); | |
7417 host_impl_->ScrollEnd(); | |
7418 | |
7419 EXPECT_EQ(0, set_needs_commit_count); | |
7420 EXPECT_EQ(1, set_needs_redraw_count); | |
7421 EXPECT_EQ(0, forward_to_main_count); | |
7422 | |
7423 // Scrolling with a scroll handler should defer the swap to the main | |
7424 // thread. | |
7425 scroll_layer->SetHaveScrollEventHandlers(true); | |
7426 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7427 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
7428 EXPECT_TRUE( | |
7429 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll); | |
7430 host_impl_->ScrollEnd(); | |
7431 | |
7432 EXPECT_EQ(0, set_needs_commit_count); | |
7433 EXPECT_EQ(2, set_needs_redraw_count); | |
7434 EXPECT_EQ(1, forward_to_main_count); | |
7435 } | |
7436 } | |
7437 | |
7438 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest { | |
7439 public: | |
7440 void SetUp() override { | |
7441 LayerTreeSettings settings = DefaultSettings(); | |
7442 CreateHostImpl(settings, CreateOutputSurface()); | |
7443 host_impl_->active_tree()->set_top_controls_height(top_controls_height_); | |
7444 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_); | |
7445 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f); | |
7446 } | |
7447 | |
7448 protected: | |
7449 static const int top_controls_height_; | |
7450 }; | |
7451 | |
7452 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50; | |
7453 | |
7454 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) { | |
7455 SetupScrollAndContentsLayers(gfx::Size(100, 100)) | |
7456 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10)); | |
7457 host_impl_->Animate(base::TimeTicks()); | |
7458 EXPECT_FALSE(did_request_redraw_); | |
7459 } | |
7460 | |
7461 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsHeightIsCommitted) { | |
7462 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
7463 EXPECT_FALSE(did_request_redraw_); | |
7464 host_impl_->CreatePendingTree(); | |
7465 host_impl_->sync_tree()->set_top_controls_height(100); | |
7466 host_impl_->ActivateSyncTree(); | |
7467 EXPECT_EQ(100, host_impl_->top_controls_manager()->TopControlsHeight()); | |
7468 } | |
7469 | |
7470 TEST_F(LayerTreeHostImplWithTopControlsTest, | |
7471 TopControlsStayFullyVisibleOnHeightChange) { | |
7472 SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
7473 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7474 | |
7475 host_impl_->CreatePendingTree(); | |
7476 host_impl_->sync_tree()->set_top_controls_height(0); | |
7477 host_impl_->ActivateSyncTree(); | |
7478 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7479 | |
7480 host_impl_->CreatePendingTree(); | |
7481 host_impl_->sync_tree()->set_top_controls_height(50); | |
7482 host_impl_->ActivateSyncTree(); | |
7483 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7484 } | |
7485 | |
7486 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) { | |
7487 SetupScrollAndContentsLayers(gfx::Size(100, 100)) | |
7488 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10)); | |
7489 host_impl_->DidChangeTopControlsPosition(); | |
7490 EXPECT_TRUE(did_request_animate_); | |
7491 EXPECT_TRUE(did_request_redraw_); | |
7492 } | |
7493 | |
7494 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) { | |
7495 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200)); | |
7496 host_impl_->SetViewportSize(gfx::Size(100, 100)); | |
7497 host_impl_->top_controls_manager()->UpdateTopControlsState( | |
7498 BOTH, SHOWN, false); | |
7499 DrawFrame(); | |
7500 | |
7501 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7502 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
7503 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7504 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
7505 scroll_layer->CurrentScrollOffset().ToString()); | |
7506 | |
7507 // Scroll just the top controls and verify that the scroll succeeds. | |
7508 const float residue = 10; | |
7509 float offset = top_controls_height_ - residue; | |
7510 EXPECT_TRUE( | |
7511 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); | |
7512 EXPECT_FLOAT_EQ(-offset, | |
7513 host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7514 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
7515 scroll_layer->CurrentScrollOffset().ToString()); | |
7516 | |
7517 // Scroll across the boundary | |
7518 const float content_scroll = 20; | |
7519 offset = residue + content_scroll; | |
7520 EXPECT_TRUE( | |
7521 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); | |
7522 EXPECT_EQ(-top_controls_height_, | |
7523 host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7524 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(), | |
7525 scroll_layer->CurrentScrollOffset().ToString()); | |
7526 | |
7527 // Now scroll back to the top of the content | |
7528 offset = -content_scroll; | |
7529 EXPECT_TRUE( | |
7530 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); | |
7531 EXPECT_EQ(-top_controls_height_, | |
7532 host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7533 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
7534 scroll_layer->CurrentScrollOffset().ToString()); | |
7535 | |
7536 // And scroll the top controls completely into view | |
7537 offset = -top_controls_height_; | |
7538 EXPECT_TRUE( | |
7539 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); | |
7540 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7541 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
7542 scroll_layer->CurrentScrollOffset().ToString()); | |
7543 | |
7544 // And attempt to scroll past the end | |
7545 EXPECT_FALSE( | |
7546 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); | |
7547 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7548 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
7549 scroll_layer->CurrentScrollOffset().ToString()); | |
7550 | |
7551 host_impl_->ScrollEnd(); | |
7552 } | |
7553 | |
7554 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) { | |
7555 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200)); | |
7556 host_impl_->SetViewportSize(gfx::Size(100, 200)); | |
7557 host_impl_->top_controls_manager()->UpdateTopControlsState( | |
7558 BOTH, SHOWN, false); | |
7559 DrawFrame(); | |
7560 | |
7561 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7562 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
7563 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7564 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
7565 scroll_layer->CurrentScrollOffset().ToString()); | |
7566 | |
7567 // Scroll the top controls partially. | |
7568 const float residue = 35; | |
7569 float offset = top_controls_height_ - residue; | |
7570 EXPECT_TRUE( | |
7571 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); | |
7572 EXPECT_FLOAT_EQ(-offset, | |
7573 host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7574 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
7575 scroll_layer->CurrentScrollOffset().ToString()); | |
7576 | |
7577 did_request_redraw_ = false; | |
7578 did_request_animate_ = false; | |
7579 did_request_commit_ = false; | |
7580 | |
7581 // End the scroll while the controls are still offset from their limit. | |
7582 host_impl_->ScrollEnd(); | |
7583 ASSERT_TRUE(host_impl_->top_controls_manager()->animation()); | |
7584 EXPECT_TRUE(did_request_animate_); | |
7585 EXPECT_TRUE(did_request_redraw_); | |
7586 EXPECT_FALSE(did_request_commit_); | |
7587 | |
7588 // The top controls should properly animate until finished, despite the scroll | |
7589 // offset being at the origin. | |
7590 base::TimeTicks animation_time = gfx::FrameTime::Now(); | |
7591 while (did_request_animate_) { | |
7592 did_request_redraw_ = false; | |
7593 did_request_animate_ = false; | |
7594 did_request_commit_ = false; | |
7595 | |
7596 float old_offset = | |
7597 host_impl_->top_controls_manager()->ControlsTopOffset(); | |
7598 | |
7599 animation_time += base::TimeDelta::FromMilliseconds(5); | |
7600 host_impl_->Animate(animation_time); | |
7601 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
7602 scroll_layer->CurrentScrollOffset().ToString()); | |
7603 | |
7604 float new_offset = | |
7605 host_impl_->top_controls_manager()->ControlsTopOffset(); | |
7606 | |
7607 // No commit is needed as the controls are animating the content offset, | |
7608 // not the scroll offset. | |
7609 EXPECT_FALSE(did_request_commit_); | |
7610 | |
7611 if (new_offset != old_offset) | |
7612 EXPECT_TRUE(did_request_redraw_); | |
7613 | |
7614 if (new_offset != 0) { | |
7615 EXPECT_TRUE(host_impl_->top_controls_manager()->animation()); | |
7616 EXPECT_TRUE(did_request_animate_); | |
7617 } | |
7618 } | |
7619 EXPECT_FALSE(host_impl_->top_controls_manager()->animation()); | |
7620 } | |
7621 | |
7622 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) { | |
7623 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200)); | |
7624 host_impl_->SetViewportSize(gfx::Size(100, 100)); | |
7625 host_impl_->top_controls_manager()->UpdateTopControlsState( | |
7626 BOTH, SHOWN, false); | |
7627 float initial_scroll_offset = 50; | |
7628 scroll_layer->PushScrollOffsetFromMainThread( | |
7629 gfx::ScrollOffset(0, initial_scroll_offset)); | |
7630 DrawFrame(); | |
7631 | |
7632 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7633 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
7634 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7635 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(), | |
7636 scroll_layer->CurrentScrollOffset().ToString()); | |
7637 | |
7638 // Scroll the top controls partially. | |
7639 const float residue = 15; | |
7640 float offset = top_controls_height_ - residue; | |
7641 EXPECT_TRUE( | |
7642 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); | |
7643 EXPECT_FLOAT_EQ(-offset, | |
7644 host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7645 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(), | |
7646 scroll_layer->CurrentScrollOffset().ToString()); | |
7647 | |
7648 did_request_redraw_ = false; | |
7649 did_request_animate_ = false; | |
7650 did_request_commit_ = false; | |
7651 | |
7652 // End the scroll while the controls are still offset from the limit. | |
7653 host_impl_->ScrollEnd(); | |
7654 ASSERT_TRUE(host_impl_->top_controls_manager()->animation()); | |
7655 EXPECT_TRUE(did_request_animate_); | |
7656 EXPECT_TRUE(did_request_redraw_); | |
7657 EXPECT_FALSE(did_request_commit_); | |
7658 | |
7659 // Animate the top controls to the limit. | |
7660 base::TimeTicks animation_time = gfx::FrameTime::Now(); | |
7661 while (did_request_animate_) { | |
7662 did_request_redraw_ = false; | |
7663 did_request_animate_ = false; | |
7664 did_request_commit_ = false; | |
7665 | |
7666 float old_offset = | |
7667 host_impl_->top_controls_manager()->ControlsTopOffset(); | |
7668 | |
7669 animation_time += base::TimeDelta::FromMilliseconds(5); | |
7670 host_impl_->Animate(animation_time); | |
7671 | |
7672 float new_offset = | |
7673 host_impl_->top_controls_manager()->ControlsTopOffset(); | |
7674 | |
7675 if (new_offset != old_offset) { | |
7676 EXPECT_TRUE(did_request_redraw_); | |
7677 EXPECT_TRUE(did_request_commit_); | |
7678 } | |
7679 } | |
7680 EXPECT_FALSE(host_impl_->top_controls_manager()->animation()); | |
7681 EXPECT_EQ(-top_controls_height_, | |
7682 host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7683 } | |
7684 | |
7685 TEST_F(LayerTreeHostImplWithTopControlsTest, | |
7686 TopControlsAnimationAfterMainThreadFlingStopped) { | |
7687 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200)); | |
7688 host_impl_->SetViewportSize(gfx::Size(100, 100)); | |
7689 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN, | |
7690 false); | |
7691 float initial_scroll_offset = 50; | |
7692 scroll_layer->PushScrollOffsetFromMainThread( | |
7693 gfx::ScrollOffset(0, initial_scroll_offset)); | |
7694 DrawFrame(); | |
7695 | |
7696 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7697 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
7698 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7699 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(), | |
7700 scroll_layer->CurrentScrollOffset().ToString()); | |
7701 | |
7702 // Scroll the top controls partially. | |
7703 const float residue = 15; | |
7704 float offset = top_controls_height_ - residue; | |
7705 EXPECT_TRUE( | |
7706 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); | |
7707 EXPECT_FLOAT_EQ(-offset, | |
7708 host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7709 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(), | |
7710 scroll_layer->CurrentScrollOffset().ToString()); | |
7711 | |
7712 did_request_redraw_ = false; | |
7713 did_request_animate_ = false; | |
7714 did_request_commit_ = false; | |
7715 | |
7716 // End the fling while the controls are still offset from the limit. | |
7717 host_impl_->MainThreadHasStoppedFlinging(); | |
7718 ASSERT_TRUE(host_impl_->top_controls_manager()->animation()); | |
7719 EXPECT_TRUE(did_request_animate_); | |
7720 EXPECT_TRUE(did_request_redraw_); | |
7721 EXPECT_FALSE(did_request_commit_); | |
7722 | |
7723 // Animate the top controls to the limit. | |
7724 base::TimeTicks animation_time = gfx::FrameTime::Now(); | |
7725 while (did_request_animate_) { | |
7726 did_request_redraw_ = false; | |
7727 did_request_animate_ = false; | |
7728 did_request_commit_ = false; | |
7729 | |
7730 float old_offset = host_impl_->top_controls_manager()->ControlsTopOffset(); | |
7731 | |
7732 animation_time += base::TimeDelta::FromMilliseconds(5); | |
7733 host_impl_->Animate(animation_time); | |
7734 | |
7735 float new_offset = host_impl_->top_controls_manager()->ControlsTopOffset(); | |
7736 | |
7737 if (new_offset != old_offset) { | |
7738 EXPECT_TRUE(did_request_redraw_); | |
7739 EXPECT_TRUE(did_request_commit_); | |
7740 } | |
7741 } | |
7742 EXPECT_FALSE(host_impl_->top_controls_manager()->animation()); | |
7743 EXPECT_EQ(-top_controls_height_, | |
7744 host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7745 } | |
7746 | |
7747 TEST_F(LayerTreeHostImplWithTopControlsTest, | |
7748 TopControlsScrollDeltaInOverScroll) { | |
7749 // test varifies that the overscroll delta should not have accumulated in | |
7750 // the top controls if we do a hide and show without releasing finger. | |
7751 | |
7752 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200)); | |
7753 host_impl_->SetViewportSize(gfx::Size(100, 100)); | |
7754 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN, | |
7755 false); | |
7756 DrawFrame(); | |
7757 | |
7758 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7759 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
7760 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7761 | |
7762 float offset = 50; | |
7763 EXPECT_TRUE( | |
7764 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); | |
7765 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7766 EXPECT_EQ(gfx::Vector2dF().ToString(), | |
7767 scroll_layer->CurrentScrollOffset().ToString()); | |
7768 | |
7769 EXPECT_TRUE( | |
7770 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); | |
7771 EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(), | |
7772 scroll_layer->CurrentScrollOffset().ToString()); | |
7773 | |
7774 EXPECT_TRUE( | |
7775 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); | |
7776 | |
7777 // Should have fully scrolled | |
7778 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer->MaxScrollOffset().y()).ToString(), | |
7779 scroll_layer->CurrentScrollOffset().ToString()); | |
7780 | |
7781 float overscrollamount = 10; | |
7782 | |
7783 // Overscroll the content | |
7784 EXPECT_FALSE( | |
7785 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount)) | |
7786 .did_scroll); | |
7787 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(), | |
7788 scroll_layer->CurrentScrollOffset().ToString()); | |
7789 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount).ToString(), | |
7790 host_impl_->accumulated_root_overscroll().ToString()); | |
7791 | |
7792 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset)) | |
7793 .did_scroll); | |
7794 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(), | |
7795 scroll_layer->CurrentScrollOffset().ToString()); | |
7796 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7797 | |
7798 EXPECT_TRUE( | |
7799 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset)).did_scroll); | |
7800 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(), | |
7801 scroll_layer->CurrentScrollOffset().ToString()); | |
7802 | |
7803 // Top controls should be fully visible | |
7804 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset()); | |
7805 | |
7806 host_impl_->ScrollEnd(); | |
7807 } | |
7808 | |
7809 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { | |
7810 public: | |
7811 void SetupVirtualViewportLayers(const gfx::Size& content_size, | |
7812 const gfx::Size& outer_viewport, | |
7813 const gfx::Size& inner_viewport) { | |
7814 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); | |
7815 const int kOuterViewportClipLayerId = 6; | |
7816 const int kOuterViewportScrollLayerId = 7; | |
7817 const int kInnerViewportScrollLayerId = 2; | |
7818 const int kInnerViewportClipLayerId = 4; | |
7819 const int kPageScaleLayerId = 5; | |
7820 | |
7821 scoped_ptr<LayerImpl> inner_scroll = | |
7822 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId); | |
7823 inner_scroll->SetIsContainerForFixedPositionLayers(true); | |
7824 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset()); | |
7825 | |
7826 scoped_ptr<LayerImpl> inner_clip = | |
7827 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId); | |
7828 inner_clip->SetBounds(inner_viewport); | |
7829 | |
7830 scoped_ptr<LayerImpl> page_scale = | |
7831 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId); | |
7832 | |
7833 inner_scroll->SetScrollClipLayer(inner_clip->id()); | |
7834 inner_scroll->SetBounds(outer_viewport); | |
7835 inner_scroll->SetContentBounds(outer_viewport); | |
7836 inner_scroll->SetPosition(gfx::PointF()); | |
7837 | |
7838 scoped_ptr<LayerImpl> outer_clip = | |
7839 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId); | |
7840 outer_clip->SetBounds(outer_viewport); | |
7841 outer_clip->SetIsContainerForFixedPositionLayers(true); | |
7842 | |
7843 scoped_ptr<LayerImpl> outer_scroll = | |
7844 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId); | |
7845 outer_scroll->SetScrollClipLayer(outer_clip->id()); | |
7846 outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset()); | |
7847 outer_scroll->SetBounds(content_size); | |
7848 outer_scroll->SetContentBounds(content_size); | |
7849 outer_scroll->SetPosition(gfx::PointF()); | |
7850 | |
7851 scoped_ptr<LayerImpl> contents = | |
7852 LayerImpl::Create(layer_tree_impl, 8); | |
7853 contents->SetDrawsContent(true); | |
7854 contents->SetBounds(content_size); | |
7855 contents->SetContentBounds(content_size); | |
7856 contents->SetPosition(gfx::PointF()); | |
7857 | |
7858 outer_scroll->AddChild(contents.Pass()); | |
7859 outer_clip->AddChild(outer_scroll.Pass()); | |
7860 inner_scroll->AddChild(outer_clip.Pass()); | |
7861 page_scale->AddChild(inner_scroll.Pass()); | |
7862 inner_clip->AddChild(page_scale.Pass()); | |
7863 | |
7864 inner_clip->SetHasRenderSurface(true); | |
7865 layer_tree_impl->SetRootLayer(inner_clip.Pass()); | |
7866 layer_tree_impl->SetViewportLayersFromIds( | |
7867 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId, | |
7868 kOuterViewportScrollLayerId); | |
7869 | |
7870 host_impl_->active_tree()->DidBecomeActive(); | |
7871 } | |
7872 }; | |
7873 | |
7874 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) { | |
7875 gfx::Size content_size = gfx::Size(100, 160); | |
7876 gfx::Size outer_viewport = gfx::Size(50, 80); | |
7877 gfx::Size inner_viewport = gfx::Size(25, 40); | |
7878 | |
7879 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport); | |
7880 | |
7881 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer(); | |
7882 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer(); | |
7883 DrawFrame(); | |
7884 { | |
7885 gfx::Vector2dF inner_expected; | |
7886 gfx::Vector2dF outer_expected; | |
7887 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset()); | |
7888 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset()); | |
7889 | |
7890 // Make sure the fling goes to the outer viewport first | |
7891 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7892 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
7893 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); | |
7894 | |
7895 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height()); | |
7896 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
7897 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y()); | |
7898 | |
7899 host_impl_->ScrollEnd(); | |
7900 | |
7901 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset()); | |
7902 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset()); | |
7903 | |
7904 // Fling past the outer viewport boundry, make sure inner viewport scrolls. | |
7905 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7906 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
7907 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); | |
7908 | |
7909 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
7910 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y()); | |
7911 | |
7912 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
7913 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y()); | |
7914 | |
7915 host_impl_->ScrollEnd(); | |
7916 | |
7917 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset()); | |
7918 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset()); | |
7919 } | |
7920 } | |
7921 | |
7922 TEST_F(LayerTreeHostImplVirtualViewportTest, | |
7923 DiagonalScrollBubblesPerfectlyToInner) { | |
7924 gfx::Size content_size = gfx::Size(100, 160); | |
7925 gfx::Size outer_viewport = gfx::Size(50, 80); | |
7926 gfx::Size inner_viewport = gfx::Size(25, 40); | |
7927 | |
7928 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport); | |
7929 | |
7930 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer(); | |
7931 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer(); | |
7932 DrawFrame(); | |
7933 { | |
7934 gfx::Vector2dF inner_expected; | |
7935 gfx::Vector2dF outer_expected; | |
7936 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset()); | |
7937 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset()); | |
7938 | |
7939 // Make sure the scroll goes to the outer viewport first. | |
7940 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7941 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
7942 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); | |
7943 | |
7944 // Scroll near the edge of the outer viewport. | |
7945 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height()); | |
7946 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
7947 outer_expected += scroll_delta; | |
7948 | |
7949 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset()); | |
7950 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset()); | |
7951 | |
7952 // Now diagonal scroll across the outer viewport boundary in a single event. | |
7953 // The entirety of the scroll should be consumed, as bubbling between inner | |
7954 // and outer viewport layers is perfect. | |
7955 host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2)); | |
7956 outer_expected += scroll_delta; | |
7957 inner_expected += scroll_delta; | |
7958 host_impl_->ScrollEnd(); | |
7959 | |
7960 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset()); | |
7961 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset()); | |
7962 } | |
7963 } | |
7964 | |
7965 TEST_F(LayerTreeHostImplVirtualViewportTest, | |
7966 TouchFlingCanLockToViewportLayerAfterBubbling) { | |
7967 gfx::Size content_size = gfx::Size(100, 160); | |
7968 gfx::Size outer_viewport = gfx::Size(50, 80); | |
7969 gfx::Size inner_viewport = gfx::Size(25, 40); | |
7970 | |
7971 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport); | |
7972 | |
7973 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer(); | |
7974 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer(); | |
7975 | |
7976 scoped_ptr<LayerImpl> child = | |
7977 CreateScrollableLayer(10, outer_viewport, outer_scroll); | |
7978 LayerImpl* child_scroll = child.get(); | |
7979 outer_scroll->children()[0]->AddChild(child.Pass()); | |
7980 | |
7981 DrawFrame(); | |
7982 { | |
7983 scoped_ptr<ScrollAndScaleSet> scroll_info; | |
7984 | |
7985 gfx::Vector2d scroll_delta(0, inner_viewport.height()); | |
7986 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
7987 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE)); | |
7988 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll); | |
7989 | |
7990 // The child should have scrolled up to its limit. | |
7991 scroll_info = host_impl_->ProcessScrollDeltas(); | |
7992 ASSERT_EQ(1u, scroll_info->scrolls.size()); | |
7993 ExpectContains(*scroll_info, child_scroll->id(), scroll_delta); | |
7994 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll); | |
7995 | |
7996 // The first |ScrollBy| after the fling should re-lock the scrolling | |
7997 // layer to the first layer that scrolled, the inner viewport scroll layer. | |
7998 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin()); | |
7999 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll); | |
8000 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll); | |
8001 | |
8002 // The inner viewport should have scrolled up to its limit. | |
8003 scroll_info = host_impl_->ProcessScrollDeltas(); | |
8004 ASSERT_EQ(2u, scroll_info->scrolls.size()); | |
8005 ExpectContains(*scroll_info, child_scroll->id(), scroll_delta); | |
8006 ExpectContains(*scroll_info, inner_scroll->id(), scroll_delta); | |
8007 | |
8008 // As the locked layer is at its limit, no further scrolling can occur. | |
8009 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll); | |
8010 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll); | |
8011 host_impl_->ScrollEnd(); | |
8012 } | |
8013 } | |
8014 | |
8015 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest { | |
8016 public: | |
8017 void SetUp() override { | |
8018 LayerTreeSettings settings = DefaultSettings(); | |
8019 settings.max_memory_for_prepaint_percentage = 50; | |
8020 CreateHostImpl(settings, CreateOutputSurface()); | |
8021 } | |
8022 }; | |
8023 | |
8024 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) { | |
8025 // Set up a memory policy and percentages which could cause | |
8026 // 32-bit integer overflows. | |
8027 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB | |
8028 | |
8029 // Verify implicit limits are calculated correctly with no overflows | |
8030 host_impl_->SetMemoryPolicy(mem_policy); | |
8031 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes, | |
8032 300u * 1024u * 1024u); | |
8033 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes, | |
8034 150u * 1024u * 1024u); | |
8035 } | |
8036 | |
8037 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) { | |
8038 const gfx::Size layer_size(100, 100); | |
8039 gfx::Transform external_transform; | |
8040 const gfx::Rect external_viewport(layer_size); | |
8041 const gfx::Rect external_clip(layer_size); | |
8042 const bool resourceless_software_draw = false; | |
8043 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size); | |
8044 | |
8045 host_impl_->SetExternalDrawConstraints(external_transform, | |
8046 external_viewport, | |
8047 external_clip, | |
8048 external_viewport, | |
8049 external_transform, | |
8050 resourceless_software_draw); | |
8051 DrawFrame(); | |
8052 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
8053 external_transform, layer->draw_properties().target_space_transform); | |
8054 | |
8055 external_transform.Translate(20, 20); | |
8056 host_impl_->SetExternalDrawConstraints(external_transform, | |
8057 external_viewport, | |
8058 external_clip, | |
8059 external_viewport, | |
8060 external_transform, | |
8061 resourceless_software_draw); | |
8062 DrawFrame(); | |
8063 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
8064 external_transform, layer->draw_properties().target_space_transform); | |
8065 } | |
8066 | |
8067 TEST_F(LayerTreeHostImplTest, ScrollAnimated) { | |
8068 SetupScrollAndContentsLayers(gfx::Size(100, 200)); | |
8069 DrawFrame(); | |
8070 | |
8071 base::TimeTicks start_time = | |
8072 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100); | |
8073 | |
8074 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
8075 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50))); | |
8076 | |
8077 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer(); | |
8078 | |
8079 host_impl_->Animate(start_time); | |
8080 host_impl_->UpdateAnimationState(true); | |
8081 | |
8082 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset()); | |
8083 | |
8084 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50)); | |
8085 host_impl_->UpdateAnimationState(true); | |
8086 | |
8087 float y = scrolling_layer->CurrentScrollOffset().y(); | |
8088 EXPECT_TRUE(y > 1 && y < 49); | |
8089 | |
8090 // Update target. | |
8091 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
8092 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50))); | |
8093 | |
8094 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200)); | |
8095 host_impl_->UpdateAnimationState(true); | |
8096 | |
8097 y = scrolling_layer->CurrentScrollOffset().y(); | |
8098 EXPECT_TRUE(y > 50 && y < 100); | |
8099 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer()); | |
8100 | |
8101 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250)); | |
8102 host_impl_->UpdateAnimationState(true); | |
8103 | |
8104 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100), | |
8105 scrolling_layer->CurrentScrollOffset()); | |
8106 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer()); | |
8107 } | |
8108 | |
8109 TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairs) { | |
8110 host_impl_->CreatePendingTree(); | |
8111 | |
8112 scoped_ptr<PictureLayerImpl> layer = | |
8113 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 10); | |
8114 layer->SetBounds(gfx::Size(10, 10)); | |
8115 scoped_ptr<FakePictureLayerImpl> nondraw_layer = | |
8116 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 12); | |
8117 nondraw_layer->SetBounds(gfx::Size(10, 10)); | |
8118 | |
8119 scoped_refptr<RasterSource> pile(FakePicturePileImpl::CreateEmptyPile( | |
8120 gfx::Size(10, 10), gfx::Size(10, 10))); | |
8121 Region empty_invalidation; | |
8122 const PictureLayerTilingSet* null_tiling_set = nullptr; | |
8123 layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size()); | |
8124 layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set); | |
8125 nondraw_layer->set_gpu_raster_max_texture_size( | |
8126 host_impl_->device_viewport_size()); | |
8127 nondraw_layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set); | |
8128 | |
8129 layer->AddChild(nondraw_layer.Pass()); | |
8130 host_impl_->pending_tree()->SetRootLayer(layer.Pass()); | |
8131 | |
8132 LayerTreeImpl* pending_tree = host_impl_->pending_tree(); | |
8133 LayerImpl* pending_layer = pending_tree->root_layer(); | |
8134 FakePictureLayerImpl* pending_nondraw_layer = | |
8135 static_cast<FakePictureLayerImpl*>(pending_layer->children()[0]); | |
8136 | |
8137 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false); | |
8138 | |
8139 std::vector<PictureLayerImpl::Pair> layer_pairs; | |
8140 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true); | |
8141 EXPECT_EQ(1u, layer_pairs.size()); | |
8142 EXPECT_EQ(pending_layer, layer_pairs[0].pending); | |
8143 EXPECT_EQ(nullptr, layer_pairs[0].active); | |
8144 | |
8145 host_impl_->ActivateSyncTree(); | |
8146 | |
8147 LayerTreeImpl* active_tree = host_impl_->active_tree(); | |
8148 LayerImpl* active_layer = active_tree->root_layer(); | |
8149 FakePictureLayerImpl* active_nondraw_layer = | |
8150 static_cast<FakePictureLayerImpl*>(active_layer->children()[0]); | |
8151 EXPECT_NE(active_tree, pending_tree); | |
8152 EXPECT_NE(active_layer, pending_layer); | |
8153 EXPECT_NE(active_nondraw_layer, pending_nondraw_layer); | |
8154 EXPECT_NE(nullptr, active_tree); | |
8155 EXPECT_NE(nullptr, active_layer); | |
8156 EXPECT_NE(nullptr, active_nondraw_layer); | |
8157 | |
8158 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false); | |
8159 | |
8160 host_impl_->CreatePendingTree(); | |
8161 | |
8162 layer_pairs.clear(); | |
8163 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true); | |
8164 EXPECT_EQ(1u, layer_pairs.size()); | |
8165 EXPECT_EQ(active_layer, layer_pairs[0].active); | |
8166 EXPECT_EQ(pending_layer, layer_pairs[0].pending); | |
8167 | |
8168 // Activate, the active layer has no twin now. | |
8169 host_impl_->ActivateSyncTree(); | |
8170 | |
8171 layer_pairs.clear(); | |
8172 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true); | |
8173 EXPECT_EQ(1u, layer_pairs.size()); | |
8174 EXPECT_EQ(active_layer, layer_pairs[0].active); | |
8175 EXPECT_EQ(nullptr, layer_pairs[0].pending); | |
8176 | |
8177 // Create another layer in the pending tree that's not in the active tree. We | |
8178 // should get two pairs. | |
8179 host_impl_->CreatePendingTree(); | |
8180 host_impl_->pending_tree()->root_layer()->AddChild( | |
8181 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11)); | |
8182 | |
8183 LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[1]; | |
8184 | |
8185 layer_pairs.clear(); | |
8186 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true); | |
8187 EXPECT_EQ(2u, layer_pairs.size()); | |
8188 // The pair ordering is flaky, so make it consistent. | |
8189 if (layer_pairs[0].active != active_layer) | |
8190 std::swap(layer_pairs[0], layer_pairs[1]); | |
8191 EXPECT_EQ(active_layer, layer_pairs[0].active); | |
8192 EXPECT_EQ(pending_layer, layer_pairs[0].pending); | |
8193 EXPECT_EQ(new_pending_layer, layer_pairs[1].pending); | |
8194 EXPECT_EQ(nullptr, layer_pairs[1].active); | |
8195 | |
8196 host_impl_->pending_tree()->root_layer()->RemoveChild(new_pending_layer); | |
8197 | |
8198 // Have the pending layer be part of the RSLL now. It should appear in the | |
8199 // list without an active twin. | |
8200 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true); | |
8201 | |
8202 layer_pairs.clear(); | |
8203 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true); | |
8204 EXPECT_EQ(2u, layer_pairs.size()); | |
8205 // The pair ordering is flaky, so make it consistent. | |
8206 if (layer_pairs[0].active != active_layer) | |
8207 std::swap(layer_pairs[0], layer_pairs[1]); | |
8208 EXPECT_EQ(active_layer, layer_pairs[0].active); | |
8209 EXPECT_EQ(pending_layer, layer_pairs[0].pending); | |
8210 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending); | |
8211 EXPECT_EQ(nullptr, layer_pairs[1].active); | |
8212 | |
8213 // Have the active layer be part of the RSLL now instead. It should appear in | |
8214 // the list without a pending twin. | |
8215 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false); | |
8216 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true); | |
8217 | |
8218 layer_pairs.clear(); | |
8219 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true); | |
8220 EXPECT_EQ(2u, layer_pairs.size()); | |
8221 // The pair ordering is flaky, so make it consistent. | |
8222 if (layer_pairs[0].active != active_layer) | |
8223 std::swap(layer_pairs[0], layer_pairs[1]); | |
8224 EXPECT_EQ(active_layer, layer_pairs[0].active); | |
8225 EXPECT_EQ(pending_layer, layer_pairs[0].pending); | |
8226 EXPECT_EQ(nullptr, layer_pairs[1].pending); | |
8227 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active); | |
8228 } | |
8229 | |
8230 TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairsWithNonRSLLMembers) { | |
8231 host_impl_->CreatePendingTree(); | |
8232 | |
8233 scoped_ptr<PictureLayerImpl> layer = | |
8234 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 10); | |
8235 layer->SetBounds(gfx::Size(10, 10)); | |
8236 scoped_ptr<FakePictureLayerImpl> nondraw_layer = | |
8237 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 12); | |
8238 nondraw_layer->SetBounds(gfx::Size(10, 10)); | |
8239 | |
8240 scoped_refptr<RasterSource> pile(FakePicturePileImpl::CreateEmptyPile( | |
8241 gfx::Size(10, 10), gfx::Size(10, 10))); | |
8242 Region empty_invalidation; | |
8243 const PictureLayerTilingSet* null_tiling_set = nullptr; | |
8244 layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size()); | |
8245 layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set); | |
8246 nondraw_layer->set_gpu_raster_max_texture_size( | |
8247 host_impl_->device_viewport_size()); | |
8248 nondraw_layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set); | |
8249 | |
8250 layer->AddChild(nondraw_layer.Pass()); | |
8251 host_impl_->pending_tree()->SetRootLayer(layer.Pass()); | |
8252 | |
8253 LayerTreeImpl* pending_tree = host_impl_->pending_tree(); | |
8254 LayerImpl* pending_layer = pending_tree->root_layer(); | |
8255 FakePictureLayerImpl* pending_nondraw_layer = | |
8256 static_cast<FakePictureLayerImpl*>(pending_layer->children()[0]); | |
8257 | |
8258 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false); | |
8259 | |
8260 std::vector<PictureLayerImpl::Pair> layer_pairs; | |
8261 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false); | |
8262 EXPECT_EQ(2u, layer_pairs.size()); | |
8263 // The pair ordering is flaky, so make it consistent. | |
8264 if (layer_pairs[0].pending != pending_layer) | |
8265 std::swap(layer_pairs[0], layer_pairs[1]); | |
8266 EXPECT_EQ(pending_layer, layer_pairs[0].pending); | |
8267 EXPECT_EQ(nullptr, layer_pairs[0].active); | |
8268 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending); | |
8269 EXPECT_EQ(nullptr, layer_pairs[1].active); | |
8270 | |
8271 host_impl_->ActivateSyncTree(); | |
8272 | |
8273 LayerTreeImpl* active_tree = host_impl_->active_tree(); | |
8274 LayerImpl* active_layer = active_tree->root_layer(); | |
8275 FakePictureLayerImpl* active_nondraw_layer = | |
8276 static_cast<FakePictureLayerImpl*>(active_layer->children()[0]); | |
8277 EXPECT_NE(active_tree, pending_tree); | |
8278 EXPECT_NE(active_layer, pending_layer); | |
8279 EXPECT_NE(active_nondraw_layer, pending_nondraw_layer); | |
8280 EXPECT_NE(nullptr, active_tree); | |
8281 EXPECT_NE(nullptr, active_layer); | |
8282 EXPECT_NE(nullptr, active_nondraw_layer); | |
8283 | |
8284 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false); | |
8285 | |
8286 host_impl_->CreatePendingTree(); | |
8287 | |
8288 layer_pairs.clear(); | |
8289 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false); | |
8290 EXPECT_EQ(2u, layer_pairs.size()); | |
8291 // The pair ordering is flaky, so make it consistent. | |
8292 if (layer_pairs[0].active != active_layer) | |
8293 std::swap(layer_pairs[0], layer_pairs[1]); | |
8294 EXPECT_EQ(active_layer, layer_pairs[0].active); | |
8295 EXPECT_EQ(pending_layer, layer_pairs[0].pending); | |
8296 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending); | |
8297 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active); | |
8298 | |
8299 // Activate, the active layer has no twin now. | |
8300 host_impl_->ActivateSyncTree(); | |
8301 | |
8302 layer_pairs.clear(); | |
8303 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false); | |
8304 EXPECT_EQ(2u, layer_pairs.size()); | |
8305 // The pair ordering is flaky, so make it consistent. | |
8306 if (layer_pairs[0].active != active_layer) | |
8307 std::swap(layer_pairs[0], layer_pairs[1]); | |
8308 EXPECT_EQ(active_layer, layer_pairs[0].active); | |
8309 EXPECT_EQ(nullptr, layer_pairs[0].pending); | |
8310 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active); | |
8311 EXPECT_EQ(nullptr, layer_pairs[1].pending); | |
8312 | |
8313 // Create another layer in the pending tree that's not in the active tree. We | |
8314 // should get three pairs including the nondraw layers. | |
8315 host_impl_->CreatePendingTree(); | |
8316 host_impl_->pending_tree()->root_layer()->AddChild( | |
8317 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11)); | |
8318 | |
8319 LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[1]; | |
8320 | |
8321 layer_pairs.clear(); | |
8322 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false); | |
8323 EXPECT_EQ(3u, layer_pairs.size()); | |
8324 // The pair ordering is flaky, so make it consistent. | |
8325 if (layer_pairs[0].active != active_layer) | |
8326 std::swap(layer_pairs[0], layer_pairs[1]); | |
8327 if (layer_pairs[0].active != active_layer) | |
8328 std::swap(layer_pairs[0], layer_pairs[2]); | |
8329 if (layer_pairs[1].pending != new_pending_layer) | |
8330 std::swap(layer_pairs[1], layer_pairs[2]); | |
8331 EXPECT_EQ(active_layer, layer_pairs[0].active); | |
8332 EXPECT_EQ(pending_layer, layer_pairs[0].pending); | |
8333 EXPECT_EQ(new_pending_layer, layer_pairs[1].pending); | |
8334 EXPECT_EQ(nullptr, layer_pairs[1].active); | |
8335 EXPECT_EQ(active_nondraw_layer, layer_pairs[2].active); | |
8336 EXPECT_EQ(pending_nondraw_layer, layer_pairs[2].pending); | |
8337 | |
8338 host_impl_->pending_tree()->root_layer()->RemoveChild(new_pending_layer); | |
8339 | |
8340 // Have the pending layer be part of the RSLL now. It should appear in the | |
8341 // list, as should its active twin since we don't request only layers with | |
8342 // valid draw properties. | |
8343 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true); | |
8344 | |
8345 layer_pairs.clear(); | |
8346 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false); | |
8347 EXPECT_EQ(2u, layer_pairs.size()); | |
8348 // The pair ordering is flaky, so make it consistent. | |
8349 if (layer_pairs[0].active != active_layer) | |
8350 std::swap(layer_pairs[0], layer_pairs[1]); | |
8351 EXPECT_EQ(active_layer, layer_pairs[0].active); | |
8352 EXPECT_EQ(pending_layer, layer_pairs[0].pending); | |
8353 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending); | |
8354 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active); | |
8355 | |
8356 // Have the active layer be part of the RSLL now instead. It should appear in | |
8357 // the list, as should its pending twin since we don't request only layers | |
8358 // with valid draw properties. | |
8359 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false); | |
8360 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true); | |
8361 | |
8362 layer_pairs.clear(); | |
8363 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false); | |
8364 EXPECT_EQ(2u, layer_pairs.size()); | |
8365 // The pair ordering is flaky, so make it consistent. | |
8366 if (layer_pairs[0].active != active_layer) | |
8367 std::swap(layer_pairs[0], layer_pairs[1]); | |
8368 EXPECT_EQ(active_layer, layer_pairs[0].active); | |
8369 EXPECT_EQ(pending_layer, layer_pairs[0].pending); | |
8370 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active); | |
8371 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending); | |
8372 } | |
8373 | |
8374 TEST_F(LayerTreeHostImplTest, DidBecomeActive) { | |
8375 host_impl_->CreatePendingTree(); | |
8376 host_impl_->ActivateSyncTree(); | |
8377 host_impl_->CreatePendingTree(); | |
8378 | |
8379 LayerTreeImpl* pending_tree = host_impl_->pending_tree(); | |
8380 | |
8381 scoped_ptr<FakePictureLayerImpl> pending_layer = | |
8382 FakePictureLayerImpl::Create(pending_tree, 10); | |
8383 FakePictureLayerImpl* raw_pending_layer = pending_layer.get(); | |
8384 pending_tree->SetRootLayer(pending_layer.Pass()); | |
8385 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer()); | |
8386 | |
8387 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count()); | |
8388 pending_tree->DidBecomeActive(); | |
8389 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count()); | |
8390 | |
8391 scoped_ptr<FakePictureLayerImpl> mask_layer = | |
8392 FakePictureLayerImpl::Create(pending_tree, 11); | |
8393 FakePictureLayerImpl* raw_mask_layer = mask_layer.get(); | |
8394 raw_pending_layer->SetMaskLayer(mask_layer.Pass()); | |
8395 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer()); | |
8396 | |
8397 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count()); | |
8398 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count()); | |
8399 pending_tree->DidBecomeActive(); | |
8400 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count()); | |
8401 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count()); | |
8402 | |
8403 scoped_ptr<FakePictureLayerImpl> replica_layer = | |
8404 FakePictureLayerImpl::Create(pending_tree, 12); | |
8405 scoped_ptr<FakePictureLayerImpl> replica_mask_layer = | |
8406 FakePictureLayerImpl::Create(pending_tree, 13); | |
8407 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get(); | |
8408 replica_layer->SetMaskLayer(replica_mask_layer.Pass()); | |
8409 raw_pending_layer->SetReplicaLayer(replica_layer.Pass()); | |
8410 ASSERT_EQ(raw_replica_mask_layer, | |
8411 raw_pending_layer->replica_layer()->mask_layer()); | |
8412 | |
8413 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count()); | |
8414 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count()); | |
8415 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count()); | |
8416 pending_tree->DidBecomeActive(); | |
8417 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count()); | |
8418 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count()); | |
8419 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count()); | |
8420 } | |
8421 | |
8422 TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) { | |
8423 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); | |
8424 host_impl_->SetViewportSize(gfx::Size(50, 50)); | |
8425 DrawFrame(); | |
8426 | |
8427 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer()); | |
8428 | |
8429 float min_page_scale = 1.f, max_page_scale = 4.f; | |
8430 float page_scale_factor = 1.f; | |
8431 | |
8432 // The scroll deltas should have the page scale factor applied. | |
8433 { | |
8434 host_impl_->active_tree()->PushPageScaleFromMainThread( | |
8435 page_scale_factor, min_page_scale, max_page_scale); | |
8436 host_impl_->SetPageScaleOnActiveTree(page_scale_factor); | |
8437 scroll_layer->SetScrollDelta(gfx::Vector2d()); | |
8438 | |
8439 float page_scale_delta = 2.f; | |
8440 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE); | |
8441 host_impl_->PinchGestureBegin(); | |
8442 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point()); | |
8443 host_impl_->PinchGestureEnd(); | |
8444 host_impl_->ScrollEnd(); | |
8445 | |
8446 gfx::Vector2dF scroll_delta(0, 5); | |
8447 EXPECT_EQ(InputHandler::SCROLL_STARTED, | |
8448 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); | |
8449 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset()); | |
8450 | |
8451 host_impl_->ScrollBy(gfx::Point(), scroll_delta); | |
8452 host_impl_->ScrollEnd(); | |
8453 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5), | |
8454 scroll_layer->CurrentScrollOffset()); | |
8455 } | |
8456 } | |
8457 | |
8458 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest { | |
8459 public: | |
8460 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {} | |
8461 void DidLoseOutputSurfaceOnImplThread() override { num_lost_surfaces_++; } | |
8462 | |
8463 protected: | |
8464 int num_lost_surfaces_; | |
8465 }; | |
8466 | |
8467 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) { | |
8468 // Really we just need at least one client notification each time | |
8469 // we go from having a valid output surface to not having a valid output | |
8470 // surface. | |
8471 EXPECT_EQ(0, num_lost_surfaces_); | |
8472 host_impl_->DidLoseOutputSurface(); | |
8473 EXPECT_EQ(1, num_lost_surfaces_); | |
8474 host_impl_->DidLoseOutputSurface(); | |
8475 EXPECT_LE(1, num_lost_surfaces_); | |
8476 } | |
8477 | |
8478 } // namespace | |
8479 } // namespace cc | |
OLD | NEW |