Chromium Code Reviews| Index: cc/trees/layer_tree_host_common.cc |
| diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc |
| index d483cc697bd76d44e0b7d9353dbb0974c6fdfc5d..b496ee5da9c1a65049bd8d9bb0807bd07de57cdc 100644 |
| --- a/cc/trees/layer_tree_host_common.cc |
| +++ b/cc/trees/layer_tree_host_common.cc |
| @@ -63,6 +63,12 @@ static gfx::Vector2dF GetEffectiveTotalScrollOffset(LayerType* layer) { |
| return offset; |
| } |
| +template <typename LayerType> |
| +static inline bool LayerCanAcceptInput(LayerType* layer) { |
| + return !layer->touch_event_handler_region().IsEmpty() || |
| + layer->have_wheel_event_handlers(); |
| +} |
| + |
| inline gfx::Rect CalculateVisibleRectWithCachedLayerRect( |
| gfx::Rect target_surface_rect, |
| gfx::Rect layer_bound_rect, |
| @@ -415,7 +421,16 @@ static inline bool TransformToScreenIsKnown(Layer* layer) { |
| template <typename LayerType> |
| static bool LayerShouldBeSkipped(LayerType* layer, |
| - bool layer_is_visible) { |
| + bool layer_is_visible, |
| + bool visit_for_event_handler_only) { |
|
danakj
2013/10/08 18:32:32
how about bool "layer_has_zero_opacity"? only is a
|
| + // If an ancestor node was going to be skipped, but wasn't only because it had |
| + // event handlers in the subtree, and there are not event handlers in the |
| + // subtree rooted at |layer|, then skip this layer. |
| + if (visit_for_event_handler_only && |
|
danakj
2013/10/08 18:32:32
Move this down below the big intro comment, and up
|
| + !layer->draw_properties().layer_or_descendant_has_event_handler) { |
| + return true; |
| + } |
| + |
| // Layers can be skipped if any of these conditions are met. |
| // - is not visible due to it or one of its ancestors being hidden. |
| // - has empty bounds |
| @@ -452,18 +467,27 @@ static bool LayerShouldBeSkipped(LayerType* layer, |
| IsLayerBackFaceVisible(backface_test_layer)) |
| return true; |
| - // The layer is visible to events. If it's subject to hit testing, then |
| - // we can't skip it. |
| - bool can_accept_input = !layer->touch_event_handler_region().IsEmpty() || |
| - layer->have_wheel_event_handlers(); |
| - if (!layer->DrawsContent() && !can_accept_input) |
| + // A layer cannot be skipped if it is subject to hit-testing. |
| + if (LayerCanAcceptInput(layer)) |
| + return false; |
| + |
| + if (!layer->DrawsContent()) |
| + return true; |
| + |
| + if (!layer->draw_opacity() && !layer->draw_opacity_is_animating()) |
|
danakj
2013/10/08 18:32:32
Animating only matters on the main thread. On the
|
| return true; |
| return false; |
| } |
| static inline bool SubtreeShouldBeSkipped(LayerImpl* layer, |
| - bool layer_is_visible) { |
| + bool layer_is_visible, |
| + bool *visit_for_event_handler_only) { |
| + if (*visit_for_event_handler_only && |
| + !layer->draw_properties().layer_or_descendant_has_event_handler) { |
| + return true; |
| + } |
| + |
| // When we need to do a readback/copy of a layer's output, we can not skip |
| // it or any of its ancestors. |
| if (layer->draw_properties().layer_or_descendant_has_copy_request) |
| @@ -479,15 +503,30 @@ static inline bool SubtreeShouldBeSkipped(LayerImpl* layer, |
| if (layer->layer_tree_impl()->IsPendingTree() && layer->OpacityIsAnimating()) |
| return false; |
| + bool skip_if_no_event_handler = !layer->opacity(); |
| + |
| + // If the layer (or any of its descendant) is subject to hit-testing, then the |
| + // subtree cannot be skipped. |
| + if (layer->draw_properties().layer_or_descendant_has_event_handler) { |
| + if (skip_if_no_event_handler) |
| + *visit_for_event_handler_only = true; |
| + return false; |
| + } |
| + |
| // The opacity of a layer always applies to its children (either implicitly |
| // via a render surface or explicitly if the parent preserves 3D), so the |
| // entire subtree can be skipped if this layer is fully transparent. |
| - // TODO(sad): Don't skip layers used for hit testing crbug.com/295295. |
| - return !layer->opacity(); |
| + return skip_if_no_event_handler; |
| } |
| static inline bool SubtreeShouldBeSkipped(Layer* layer, |
| - bool layer_is_visible) { |
| + bool layer_is_visible, |
| + bool* visit_for_event_handler_only) { |
| + if (*visit_for_event_handler_only && |
| + !layer->draw_properties().layer_or_descendant_has_event_handler) { |
| + return true; |
| + } |
| + |
| // When we need to do a readback/copy of a layer's output, we can not skip |
| // it or any of its ancestors. |
| if (layer->draw_properties().layer_or_descendant_has_copy_request) |
| @@ -503,9 +542,19 @@ static inline bool SubtreeShouldBeSkipped(Layer* layer, |
| // In particular, it should not cause the subtree to be skipped. |
| // Similarly, for layers that might animate opacity using an impl-only |
| // animation, their subtree should also not be skipped. |
| - // TODO(sad): Don't skip layers used for hit testing crbug.com/295295. |
| - return !layer->opacity() && !layer->OpacityIsAnimating() && |
| - !layer->OpacityCanAnimateOnImplThread(); |
| + bool skip_if_no_event_handler = |
| + !layer->opacity() && !layer->OpacityIsAnimating() && |
| + !layer->OpacityCanAnimateOnImplThread(); |
| + |
| + // If the layer (or any of its descendant) is subject to hit-testing, then the |
| + // subtree cannot be skipped. |
| + if (layer->draw_properties().layer_or_descendant_has_event_handler) { |
| + if (skip_if_no_event_handler) |
| + *visit_for_event_handler_only = true; |
| + return false; |
| + } |
| + |
| + return skip_if_no_event_handler; |
| } |
| // Called on each layer that could be drawn after all information from |
| @@ -1014,15 +1063,19 @@ static inline void RemoveSurfaceForEarlyExit( |
| struct PreCalculateMetaInformationRecursiveData { |
| bool layer_or_descendant_has_copy_request; |
| + bool layer_or_descendant_has_event_handler; |
| int num_unclipped_descendants; |
| PreCalculateMetaInformationRecursiveData() |
| : layer_or_descendant_has_copy_request(false), |
| + layer_or_descendant_has_event_handler(false), |
| num_unclipped_descendants(0) {} |
| void Merge(const PreCalculateMetaInformationRecursiveData& data) { |
| layer_or_descendant_has_copy_request |= |
| data.layer_or_descendant_has_copy_request; |
| + layer_or_descendant_has_event_handler |= |
| + data.layer_or_descendant_has_event_handler; |
| num_unclipped_descendants += |
| data.num_unclipped_descendants; |
| } |
| @@ -1084,6 +1137,9 @@ static void PreCalculateMetaInformation( |
| if (layer->HasCopyRequest()) |
| recursive_data->layer_or_descendant_has_copy_request = true; |
| + if (LayerCanAcceptInput(layer)) |
| + recursive_data->layer_or_descendant_has_event_handler = true; |
| + |
| layer->draw_properties().num_descendants_that_draw_content = |
| num_descendants_that_draw_content; |
| layer->draw_properties().num_unclipped_descendants = |
| @@ -1092,6 +1148,8 @@ static void PreCalculateMetaInformation( |
| descendants_can_clip_selves; |
| layer->draw_properties().layer_or_descendant_has_copy_request = |
| recursive_data->layer_or_descendant_has_copy_request; |
| + layer->draw_properties().layer_or_descendant_has_event_handler = |
| + recursive_data->layer_or_descendant_has_event_handler; |
| } |
| static void RoundTranslationComponents(gfx::Transform* transform) { |
| @@ -1147,6 +1205,8 @@ struct DataForRecursion { |
| bool in_subtree_of_page_scale_application_layer; |
| bool subtree_can_use_lcd_text; |
| bool subtree_is_visible_from_ancestor; |
| + |
| + bool visit_for_event_handler_only; |
| }; |
| // Recursively walks the layer tree starting at the given node and computes all |
| @@ -1306,12 +1366,17 @@ static void CalculateDrawPropertiesInternal( |
| if (layer->HasCopyRequest()) |
| layer_is_visible = true; |
| + bool visit_for_event_handler_only = |
| + data_from_ancestor.visit_for_event_handler_only; |
| // The root layer cannot skip CalcDrawProperties. |
| - if (!IsRootLayer(layer) && SubtreeShouldBeSkipped(layer, layer_is_visible)) { |
| + if (!IsRootLayer(layer) && |
| + SubtreeShouldBeSkipped(layer, layer_is_visible, |
| + &visit_for_event_handler_only)) { |
| if (layer->render_surface()) |
| layer->ClearRenderSurface(); |
| return; |
| } |
| + data_for_children.visit_for_event_handler_only = visit_for_event_handler_only; |
| // We need to circumvent the normal recursive flow of information for clip |
| // children (they don't inherit their direct ancestor's clip information). |
| @@ -1729,7 +1794,8 @@ static void CalculateDrawPropertiesInternal( |
| // and should be included in the sorting process. |
| size_t sorting_start_index = descendants.size(); |
| - if (!LayerShouldBeSkipped(layer, layer_is_visible)) |
| + if (!LayerShouldBeSkipped(layer, layer_is_visible, |
| + data_from_ancestor.visit_for_event_handler_only)) |
| descendants.push_back(layer); |
| if (!layer->children().empty()) { |
| @@ -1826,7 +1892,8 @@ static void CalculateDrawPropertiesInternal( |
| } |
| // Compute the layer's visible content rect (the rect is in content space). |
| - layer_draw_properties.visible_content_rect = CalculateVisibleContentRect( |
| + layer_draw_properties.visible_content_rect = |
|
danakj
2013/10/08 18:32:32
Leave this rect alone. If the layer has 0 opacity
|
| + visit_for_event_handler_only ? gfx::Rect() : CalculateVisibleContentRect( |
| layer, clip_rect_of_target_surface_in_target_space, rect_in_target_space); |
| // Compute the remaining properties for the render surface, if the layer has |
| @@ -1982,6 +2049,7 @@ void LayerTreeHostCommon::CalculateDrawProperties( |
| data_for_recursion.in_subtree_of_page_scale_application_layer = false; |
| data_for_recursion.subtree_can_use_lcd_text = inputs->can_use_lcd_text; |
| data_for_recursion.subtree_is_visible_from_ancestor = true; |
| + data_for_recursion.visit_for_event_handler_only = false; |
| PreCalculateMetaInformationRecursiveData recursive_data; |
| PreCalculateMetaInformation(inputs->root_layer, &recursive_data); |
| @@ -2041,6 +2109,7 @@ void LayerTreeHostCommon::CalculateDrawProperties( |
| data_for_recursion.in_subtree_of_page_scale_application_layer = false; |
| data_for_recursion.subtree_can_use_lcd_text = inputs->can_use_lcd_text; |
| data_for_recursion.subtree_is_visible_from_ancestor = true; |
| + data_for_recursion.visit_for_event_handler_only = false; |
| PreCalculateMetaInformationRecursiveData recursive_data; |
| PreCalculateMetaInformation(inputs->root_layer, &recursive_data); |