| 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 |