OLD | NEW |
1 // Copyright 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/trees/layer_tree_host_impl.h" | 5 #include "cc/trees/layer_tree_host_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <map> | 9 #include <map> |
10 | 10 |
(...skipping 21 matching lines...) Expand all Loading... |
32 #include "cc/input/page_scale_animation.h" | 32 #include "cc/input/page_scale_animation.h" |
33 #include "cc/input/scroll_elasticity_helper.h" | 33 #include "cc/input/scroll_elasticity_helper.h" |
34 #include "cc/input/top_controls_manager.h" | 34 #include "cc/input/top_controls_manager.h" |
35 #include "cc/layers/append_quads_data.h" | 35 #include "cc/layers/append_quads_data.h" |
36 #include "cc/layers/heads_up_display_layer_impl.h" | 36 #include "cc/layers/heads_up_display_layer_impl.h" |
37 #include "cc/layers/layer_impl.h" | 37 #include "cc/layers/layer_impl.h" |
38 #include "cc/layers/layer_iterator.h" | 38 #include "cc/layers/layer_iterator.h" |
39 #include "cc/layers/painted_scrollbar_layer_impl.h" | 39 #include "cc/layers/painted_scrollbar_layer_impl.h" |
40 #include "cc/layers/render_surface_impl.h" | 40 #include "cc/layers/render_surface_impl.h" |
41 #include "cc/layers/scrollbar_layer_impl_base.h" | 41 #include "cc/layers/scrollbar_layer_impl_base.h" |
| 42 #include "cc/layers/viewport.h" |
42 #include "cc/output/compositor_frame_metadata.h" | 43 #include "cc/output/compositor_frame_metadata.h" |
43 #include "cc/output/copy_output_request.h" | 44 #include "cc/output/copy_output_request.h" |
44 #include "cc/output/delegating_renderer.h" | 45 #include "cc/output/delegating_renderer.h" |
45 #include "cc/output/gl_renderer.h" | 46 #include "cc/output/gl_renderer.h" |
46 #include "cc/output/software_renderer.h" | 47 #include "cc/output/software_renderer.h" |
47 #include "cc/quads/render_pass_draw_quad.h" | 48 #include "cc/quads/render_pass_draw_quad.h" |
48 #include "cc/quads/shared_quad_state.h" | 49 #include "cc/quads/shared_quad_state.h" |
49 #include "cc/quads/solid_color_draw_quad.h" | 50 #include "cc/quads/solid_color_draw_quad.h" |
50 #include "cc/quads/texture_draw_quad.h" | 51 #include "cc/quads/texture_draw_quad.h" |
51 #include "cc/resources/bitmap_tile_task_worker_pool.h" | 52 #include "cc/resources/bitmap_tile_task_worker_pool.h" |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 animation_registrar_->set_supports_scroll_animations( | 234 animation_registrar_->set_supports_scroll_animations( |
234 proxy_->SupportsImplScrolling()); | 235 proxy_->SupportsImplScrolling()); |
235 | 236 |
236 SetDebugState(settings.initial_debug_state); | 237 SetDebugState(settings.initial_debug_state); |
237 | 238 |
238 // LTHI always has an active tree. | 239 // LTHI always has an active tree. |
239 active_tree_ = | 240 active_tree_ = |
240 LayerTreeImpl::create(this, new SyncedProperty<ScaleGroup>(), | 241 LayerTreeImpl::create(this, new SyncedProperty<ScaleGroup>(), |
241 new SyncedTopControls, new SyncedElasticOverscroll); | 242 new SyncedTopControls, new SyncedElasticOverscroll); |
242 | 243 |
| 244 viewport_ = Viewport::Create(this); |
| 245 |
243 TRACE_EVENT_OBJECT_CREATED_WITH_ID( | 246 TRACE_EVENT_OBJECT_CREATED_WITH_ID( |
244 TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerTreeHostImpl", id_); | 247 TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerTreeHostImpl", id_); |
245 | 248 |
246 top_controls_manager_ = | 249 top_controls_manager_ = |
247 TopControlsManager::Create(this, | 250 TopControlsManager::Create(this, |
248 settings.top_controls_show_threshold, | 251 settings.top_controls_show_threshold, |
249 settings.top_controls_hide_threshold); | 252 settings.top_controls_hide_threshold); |
250 } | 253 } |
251 | 254 |
252 LayerTreeHostImpl::~LayerTreeHostImpl() { | 255 LayerTreeHostImpl::~LayerTreeHostImpl() { |
(...skipping 2217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2470 SetNeedsAnimate(); | 2473 SetNeedsAnimate(); |
2471 return SCROLL_STARTED; | 2474 return SCROLL_STARTED; |
2472 } | 2475 } |
2473 } | 2476 } |
2474 ScrollEnd(); | 2477 ScrollEnd(); |
2475 return scroll_status; | 2478 return scroll_status; |
2476 } | 2479 } |
2477 | 2480 |
2478 gfx::Vector2dF LayerTreeHostImpl::ScrollLayerWithViewportSpaceDelta( | 2481 gfx::Vector2dF LayerTreeHostImpl::ScrollLayerWithViewportSpaceDelta( |
2479 LayerImpl* layer_impl, | 2482 LayerImpl* layer_impl, |
2480 float scale_from_viewport_to_screen_space, | |
2481 const gfx::PointF& viewport_point, | 2483 const gfx::PointF& viewport_point, |
2482 const gfx::Vector2dF& viewport_delta) { | 2484 const gfx::Vector2dF& viewport_delta) { |
2483 // Layers with non-invertible screen space transforms should not have passed | 2485 // Layers with non-invertible screen space transforms should not have passed |
2484 // the scroll hit test in the first place. | 2486 // the scroll hit test in the first place. |
2485 DCHECK(layer_impl->screen_space_transform().IsInvertible()); | 2487 DCHECK(layer_impl->screen_space_transform().IsInvertible()); |
2486 gfx::Transform inverse_screen_space_transform( | 2488 gfx::Transform inverse_screen_space_transform( |
2487 gfx::Transform::kSkipInitialization); | 2489 gfx::Transform::kSkipInitialization); |
2488 bool did_invert = layer_impl->screen_space_transform().GetInverse( | 2490 bool did_invert = layer_impl->screen_space_transform().GetInverse( |
2489 &inverse_screen_space_transform); | 2491 &inverse_screen_space_transform); |
2490 // TODO(shawnsingh): With the advent of impl-side crolling for non-root | 2492 // TODO(shawnsingh): With the advent of impl-side crolling for non-root |
2491 // layers, we may need to explicitly handle uninvertible transforms here. | 2493 // layers, we may need to explicitly handle uninvertible transforms here. |
2492 DCHECK(did_invert); | 2494 DCHECK(did_invert); |
2493 | 2495 |
| 2496 float scale_from_viewport_to_screen_space = device_scale_factor_; |
2494 gfx::PointF screen_space_point = | 2497 gfx::PointF screen_space_point = |
2495 gfx::ScalePoint(viewport_point, scale_from_viewport_to_screen_space); | 2498 gfx::ScalePoint(viewport_point, scale_from_viewport_to_screen_space); |
2496 | 2499 |
2497 gfx::Vector2dF screen_space_delta = viewport_delta; | 2500 gfx::Vector2dF screen_space_delta = viewport_delta; |
2498 screen_space_delta.Scale(scale_from_viewport_to_screen_space); | 2501 screen_space_delta.Scale(scale_from_viewport_to_screen_space); |
2499 | 2502 |
2500 // First project the scroll start and end points to local layer space to find | 2503 // First project the scroll start and end points to local layer space to find |
2501 // the scroll delta in layer coordinates. | 2504 // the scroll delta in layer coordinates. |
2502 bool start_clipped, end_clipped; | 2505 bool start_clipped, end_clipped; |
2503 gfx::PointF screen_space_end_point = screen_space_point + screen_space_delta; | 2506 gfx::PointF screen_space_end_point = screen_space_point + screen_space_delta; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2558 float page_scale_factor) { | 2561 float page_scale_factor) { |
2559 gfx::ScrollOffset previous_offset = layer_impl->CurrentScrollOffset(); | 2562 gfx::ScrollOffset previous_offset = layer_impl->CurrentScrollOffset(); |
2560 gfx::Vector2dF delta = local_delta; | 2563 gfx::Vector2dF delta = local_delta; |
2561 delta.Scale(1.f / page_scale_factor); | 2564 delta.Scale(1.f / page_scale_factor); |
2562 layer_impl->ScrollBy(delta); | 2565 layer_impl->ScrollBy(delta); |
2563 gfx::ScrollOffset scrolled = | 2566 gfx::ScrollOffset scrolled = |
2564 layer_impl->CurrentScrollOffset() - previous_offset; | 2567 layer_impl->CurrentScrollOffset() - previous_offset; |
2565 return gfx::Vector2dF(scrolled.x(), scrolled.y()); | 2568 return gfx::Vector2dF(scrolled.x(), scrolled.y()); |
2566 } | 2569 } |
2567 | 2570 |
2568 bool LayerTreeHostImpl::ShouldTopControlsConsumeScroll( | 2571 gfx::Vector2dF LayerTreeHostImpl::ScrollLayer(LayerImpl* layer_impl, |
2569 const gfx::Vector2dF& scroll_delta) const { | 2572 const gfx::Vector2dF& delta, |
2570 DCHECK(CurrentlyScrollingLayer()); | 2573 const gfx::Point& viewport_point, |
| 2574 bool is_wheel_scroll) { |
| 2575 // Gesture events need to be transformed from viewport coordinates to |
| 2576 // local layer coordinates so that the scrolling contents exactly follow |
| 2577 // the user's finger. In contrast, wheel events represent a fixed amount |
| 2578 // of scrolling so we can just apply them directly, but the page scale |
| 2579 // factor is applied to the scroll delta. |
| 2580 if (is_wheel_scroll) { |
| 2581 float scale_factor = active_tree()->current_page_scale_factor(); |
| 2582 return ScrollLayerWithLocalDelta(layer_impl, |
| 2583 delta, |
| 2584 scale_factor); |
| 2585 } |
2571 | 2586 |
2572 // Always consume if it's in the direction to show the top controls. | 2587 return ScrollLayerWithViewportSpaceDelta(layer_impl, |
2573 if (scroll_delta.y() < 0) | 2588 viewport_point, |
2574 return true; | 2589 delta); |
2575 | |
2576 if (active_tree()->TotalScrollOffset().y() < | |
2577 active_tree()->TotalMaxScrollOffset().y()) | |
2578 return true; | |
2579 | |
2580 return false; | |
2581 } | 2590 } |
2582 | 2591 |
2583 InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( | 2592 InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( |
2584 const gfx::Point& viewport_point, | 2593 const gfx::Point& viewport_point, |
2585 const gfx::Vector2dF& scroll_delta) { | 2594 const gfx::Vector2dF& scroll_delta) { |
2586 TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy"); | 2595 TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy"); |
2587 if (!CurrentlyScrollingLayer()) | 2596 if (!CurrentlyScrollingLayer()) |
2588 return InputHandlerScrollResult(); | 2597 return InputHandlerScrollResult(); |
2589 | 2598 |
2590 gfx::Vector2dF pending_delta = scroll_delta; | 2599 gfx::Vector2dF pending_delta = scroll_delta; |
2591 gfx::Vector2dF unused_root_delta; | 2600 gfx::Vector2dF unused_root_delta; |
2592 bool did_scroll_x = false; | 2601 bool did_scroll_x = false; |
2593 bool did_scroll_y = false; | 2602 bool did_scroll_y = false; |
2594 bool did_scroll_top_controls = false; | 2603 bool did_scroll_top_controls = false; |
2595 | 2604 |
2596 bool consume_by_top_controls = ShouldTopControlsConsumeScroll(scroll_delta); | 2605 for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); |
2597 | |
2598 // There's an edge case where the outer viewport isn't scrollable when the | |
2599 // scroll starts, however, as the top controls show the outer viewport becomes | |
2600 // scrollable. Therefore, always try scrolling the outer viewport before the | |
2601 // inner. | |
2602 // TODO(bokan): Move the top controls logic out of the loop since the scroll | |
2603 // that causes the outer viewport to become scrollable will still be applied | |
2604 // to the inner viewport. | |
2605 LayerImpl* start_layer = CurrentlyScrollingLayer(); | |
2606 if (start_layer == InnerViewportScrollLayer() && OuterViewportScrollLayer()) | |
2607 start_layer = OuterViewportScrollLayer(); | |
2608 | |
2609 for (LayerImpl* layer_impl = start_layer; | |
2610 layer_impl; | 2606 layer_impl; |
2611 layer_impl = layer_impl->parent()) { | 2607 layer_impl = layer_impl->parent()) { |
2612 if (!layer_impl->scrollable()) | 2608 // Skip the outer viewport scroll layer so that we try to scroll the |
| 2609 // viewport only once. i.e. The inner viewport layer represents the |
| 2610 // viewport. |
| 2611 if (!layer_impl->scrollable() || layer_impl == OuterViewportScrollLayer()) |
2613 continue; | 2612 continue; |
2614 | 2613 |
2615 if (layer_impl == InnerViewportScrollLayer() || | 2614 gfx::Vector2dF applied_delta; |
2616 layer_impl == OuterViewportScrollLayer()) { | 2615 if (layer_impl == InnerViewportScrollLayer()) { |
2617 if (consume_by_top_controls) { | 2616 Viewport::ScrollResult result = viewport()->ScrollBy(pending_delta, |
2618 gfx::Vector2dF excess_delta = | 2617 viewport_point, |
2619 top_controls_manager_->ScrollBy(pending_delta); | 2618 wheel_scrolling_); |
2620 gfx::Vector2dF applied_delta = pending_delta - excess_delta; | 2619 applied_delta = result.applied_delta; |
2621 pending_delta = excess_delta; | 2620 unused_root_delta = result.unused_scroll_delta; |
2622 // Force updating of vertical adjust values if needed. | 2621 did_scroll_top_controls = result.top_controls_applied_delta.y() != 0; |
2623 if (applied_delta.y() != 0) | 2622 } else { |
2624 did_scroll_top_controls = true; | 2623 applied_delta = ScrollLayer(layer_impl, |
2625 } | 2624 pending_delta, |
2626 // Track root layer deltas for reporting overscroll. | 2625 viewport_point, |
2627 if (layer_impl == InnerViewportScrollLayer()) | 2626 wheel_scrolling_); |
2628 unused_root_delta = pending_delta; | |
2629 } | 2627 } |
2630 | 2628 |
2631 gfx::Vector2dF applied_delta; | 2629 // If the layer wasn't able to move, try the next one in the hierarchy. |
2632 // Gesture events need to be transformed from viewport coordinates to local | |
2633 // layer coordinates so that the scrolling contents exactly follow the | |
2634 // user's finger. In contrast, wheel events represent a fixed amount of | |
2635 // scrolling so we can just apply them directly, but the page scale factor | |
2636 // is applied to the scroll delta. | |
2637 if (!wheel_scrolling_) { | |
2638 float scale_from_viewport_to_screen_space = device_scale_factor_; | |
2639 applied_delta = | |
2640 ScrollLayerWithViewportSpaceDelta(layer_impl, | |
2641 scale_from_viewport_to_screen_space, | |
2642 viewport_point, pending_delta); | |
2643 } else { | |
2644 applied_delta = ScrollLayerWithLocalDelta( | |
2645 layer_impl, pending_delta, active_tree_->current_page_scale_factor()); | |
2646 } | |
2647 | |
2648 const float kEpsilon = 0.1f; | 2630 const float kEpsilon = 0.1f; |
2649 if (layer_impl == InnerViewportScrollLayer()) { | |
2650 unused_root_delta.Subtract(applied_delta); | |
2651 if (std::abs(unused_root_delta.x()) < kEpsilon) | |
2652 unused_root_delta.set_x(0.0f); | |
2653 if (std::abs(unused_root_delta.y()) < kEpsilon) | |
2654 unused_root_delta.set_y(0.0f); | |
2655 // Disable overscroll on axes which is impossible to scroll. | |
2656 if (settings_.report_overscroll_only_for_scrollable_axes) { | |
2657 if (std::abs(active_tree_->TotalMaxScrollOffset().x()) <= kEpsilon || | |
2658 !layer_impl->user_scrollable_horizontal()) | |
2659 unused_root_delta.set_x(0.0f); | |
2660 if (std::abs(active_tree_->TotalMaxScrollOffset().y()) <= kEpsilon || | |
2661 !layer_impl->user_scrollable_vertical()) | |
2662 unused_root_delta.set_y(0.0f); | |
2663 } | |
2664 } | |
2665 | |
2666 // Scrolls should bubble perfectly between the outer and inner viewports. | |
2667 bool allow_unrestricted_bubbling_for_current_layer = | |
2668 layer_impl == OuterViewportScrollLayer(); | |
2669 bool allow_bubbling_for_current_layer = | |
2670 allow_unrestricted_bubbling_for_current_layer || should_bubble_scrolls_; | |
2671 | |
2672 // If the layer wasn't able to move, try the next one in the hierarchy. | |
2673 bool did_move_layer_x = std::abs(applied_delta.x()) > kEpsilon; | 2631 bool did_move_layer_x = std::abs(applied_delta.x()) > kEpsilon; |
2674 bool did_move_layer_y = std::abs(applied_delta.y()) > kEpsilon; | 2632 bool did_move_layer_y = std::abs(applied_delta.y()) > kEpsilon; |
2675 did_scroll_x |= did_move_layer_x; | 2633 did_scroll_x |= did_move_layer_x; |
2676 did_scroll_y |= did_move_layer_y; | 2634 did_scroll_y |= did_move_layer_y; |
2677 if (!did_move_layer_x && !did_move_layer_y) { | 2635 |
2678 if (allow_bubbling_for_current_layer || !did_lock_scrolling_layer_) | 2636 if (did_move_layer_x || did_move_layer_y) { |
2679 continue; | 2637 did_lock_scrolling_layer_ = true; |
2680 else | 2638 |
| 2639 // When scrolls are allowed to bubble, it's important that the original |
| 2640 // scrolling layer be preserved. This ensures that, after a scroll |
| 2641 // bubbles, the user can reverse scroll directions and immediately resume |
| 2642 // scrolling the original layer that scrolled. |
| 2643 if (!should_bubble_scrolls_) { |
| 2644 active_tree_->SetCurrentlyScrollingLayer(layer_impl); |
2681 break; | 2645 break; |
2682 } | 2646 } |
2683 | 2647 |
2684 did_lock_scrolling_layer_ = true; | |
2685 | |
2686 // When scrolls are allowed to bubble, it's important that the original | |
2687 // scrolling layer be preserved. This ensures that, after a scroll bubbles, | |
2688 // the user can reverse scroll directions and immediately resume scrolling | |
2689 // the original layer that scrolled. | |
2690 if (!should_bubble_scrolls_) | |
2691 active_tree_->SetCurrentlyScrollingLayer(layer_impl); | |
2692 | |
2693 if (!allow_bubbling_for_current_layer) | |
2694 break; | |
2695 | |
2696 if (allow_unrestricted_bubbling_for_current_layer) { | |
2697 pending_delta -= applied_delta; | |
2698 } else { | |
2699 // If the applied delta is within 45 degrees of the input delta, bail out | 2648 // If the applied delta is within 45 degrees of the input delta, bail out |
2700 // to make it easier to scroll just one layer in one direction without | 2649 // to make it easier to scroll just one layer in one direction without |
2701 // affecting any of its parents. | 2650 // affecting any of its parents. |
2702 float angle_threshold = 45; | 2651 float angle_threshold = 45; |
2703 if (MathUtil::SmallestAngleBetweenVectors(applied_delta, pending_delta) < | 2652 if (MathUtil::SmallestAngleBetweenVectors(applied_delta, pending_delta) < |
2704 angle_threshold) { | 2653 angle_threshold) |
2705 pending_delta = gfx::Vector2dF(); | |
2706 break; | 2654 break; |
2707 } | |
2708 | 2655 |
2709 // Allow further movement only on an axis perpendicular to the direction | 2656 // Allow further movement only on an axis perpendicular to the direction |
2710 // in which the layer moved. | 2657 // in which the layer moved. |
2711 gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x()); | 2658 gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x()); |
2712 pending_delta = | 2659 pending_delta = |
2713 MathUtil::ProjectVector(pending_delta, perpendicular_axis); | 2660 MathUtil::ProjectVector(pending_delta, perpendicular_axis); |
| 2661 |
| 2662 if (gfx::ToRoundedVector2d(pending_delta).IsZero()) |
| 2663 break; |
2714 } | 2664 } |
2715 | 2665 |
2716 if (gfx::ToRoundedVector2d(pending_delta).IsZero()) | 2666 if (!should_bubble_scrolls_ && did_lock_scrolling_layer_) |
2717 break; | 2667 break; |
2718 } | 2668 } |
2719 | 2669 |
2720 bool did_scroll_content = did_scroll_x || did_scroll_y; | 2670 bool did_scroll_content = did_scroll_x || did_scroll_y; |
2721 if (did_scroll_content) { | 2671 if (did_scroll_content) { |
2722 // If we are scrolling with an active scroll handler, forward latency | 2672 // If we are scrolling with an active scroll handler, forward latency |
2723 // tracking information to the main thread so the delay introduced by the | 2673 // tracking information to the main thread so the delay introduced by the |
2724 // handler is accounted for. | 2674 // handler is accounted for. |
2725 if (scroll_affects_scroll_handler()) | 2675 if (scroll_affects_scroll_handler()) |
2726 NotifySwapPromiseMonitorsOfForwardingToMainThread(); | 2676 NotifySwapPromiseMonitorsOfForwardingToMainThread(); |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3464 new_target.SetToMin(layer_impl->MaxScrollOffset()); | 3414 new_target.SetToMin(layer_impl->MaxScrollOffset()); |
3465 | 3415 |
3466 curve->UpdateTarget( | 3416 curve->UpdateTarget( |
3467 animation->TrimTimeToCurrentIteration(CurrentBeginFrameArgs().frame_time) | 3417 animation->TrimTimeToCurrentIteration(CurrentBeginFrameArgs().frame_time) |
3468 .InSecondsF(), | 3418 .InSecondsF(), |
3469 new_target); | 3419 new_target); |
3470 | 3420 |
3471 return true; | 3421 return true; |
3472 } | 3422 } |
3473 } // namespace cc | 3423 } // namespace cc |
OLD | NEW |