| 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 a9828a715908959d43b45f56b3db11f329d21524..9feae1721f493bf00b0b60c0dc05a9146a58c5a5 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,
|
| @@ -430,10 +436,21 @@ static inline bool TransformToScreenIsKnown(Layer* layer) {
|
| return !layer->screen_space_transform_is_animating();
|
| }
|
|
|
| +static inline bool LayerDrawOpacityIsZero(Layer* layer) {
|
| + return !layer->draw_opacity() && !layer->draw_opacity_is_animating();
|
| +}
|
| +
|
| +static inline bool LayerDrawOpacityIsZero(LayerImpl* layer) {
|
| + return !layer->draw_opacity();
|
| +}
|
| +
|
| template <typename LayerType>
|
| static bool LayerShouldBeSkipped(LayerType* layer,
|
| - bool layer_is_visible) {
|
| + bool layer_is_visible,
|
| + bool layer_has_zero_opacity) {
|
| // Layers can be skipped if any of these conditions are met.
|
| + // - an ancestor node has zero opacity, and there are no event handlers in
|
| + // the subtree rooted at |layer|.
|
| // - is not visible due to it or one of its ancestors being hidden.
|
| // - has empty bounds
|
| // - the layer is not double-sided, but its back face is visible.
|
| @@ -446,8 +463,14 @@ static bool LayerShouldBeSkipped(LayerType* layer,
|
| // - the visible_content_rect is empty
|
| //
|
| // Note, if the layer should not have been drawn due to being fully
|
| - // transparent, we would have skipped the entire subtree and never made it
|
| - // into this function, so it is safe to omit this check here.
|
| + // transparent, then we do not skip the entire subtree only if there is an
|
| + // event handler in the subtree. So if the layer is fully transparent, then
|
| + // skip the layer if its subtree doesn't have any event handler.
|
| +
|
| + if (layer_has_zero_opacity &&
|
| + !layer->draw_properties().layer_or_descendant_has_event_handler) {
|
| + return true;
|
| + }
|
|
|
| if (!layer_is_visible)
|
| return true;
|
| @@ -469,18 +492,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 (LayerDrawOpacityIsZero(layer))
|
| return true;
|
|
|
| return false;
|
| }
|
|
|
| static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
|
| - bool layer_is_visible) {
|
| + bool layer_is_visible,
|
| + bool *layer_has_zero_opacity) {
|
| + if (*layer_has_zero_opacity &&
|
| + !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)
|
| @@ -496,15 +528,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)
|
| + *layer_has_zero_opacity = 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* layer_has_zero_opacity) {
|
| + if (*layer_has_zero_opacity &&
|
| + !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)
|
| @@ -520,9 +567,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)
|
| + *layer_has_zero_opacity = true;
|
| + return false;
|
| + }
|
| +
|
| + return skip_if_no_event_handler;
|
| }
|
|
|
| // Called on each layer that could be drawn after all information from
|
| @@ -1031,15 +1088,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;
|
| }
|
| @@ -1090,12 +1151,17 @@ 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 =
|
| recursive_data->num_unclipped_descendants;
|
| 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) {
|
| @@ -1151,6 +1217,8 @@ struct DataForRecursion {
|
| bool in_subtree_of_page_scale_application_layer;
|
| bool subtree_can_use_lcd_text;
|
| bool subtree_is_visible_from_ancestor;
|
| +
|
| + bool layer_has_zero_opacity;
|
| };
|
|
|
| template <typename LayerType>
|
| @@ -1420,12 +1488,17 @@ static void CalculateDrawPropertiesInternal(
|
| if (layer->HasCopyRequest())
|
| layer_is_visible = true;
|
|
|
| + bool layer_has_zero_opacity =
|
| + data_from_ancestor.layer_has_zero_opacity;
|
| // The root layer cannot skip CalcDrawProperties.
|
| - if (!IsRootLayer(layer) && SubtreeShouldBeSkipped(layer, layer_is_visible)) {
|
| + if (!IsRootLayer(layer) &&
|
| + SubtreeShouldBeSkipped(layer, layer_is_visible,
|
| + &layer_has_zero_opacity)) {
|
| if (layer->render_surface())
|
| layer->ClearRenderSurface();
|
| return;
|
| }
|
| + data_for_children.layer_has_zero_opacity = layer_has_zero_opacity;
|
|
|
| // We need to circumvent the normal recursive flow of information for clip
|
| // children (they don't inherit their direct ancestor's clip information).
|
| @@ -1843,7 +1916,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.layer_has_zero_opacity))
|
| descendants.push_back(layer);
|
|
|
| if (!layer->children().empty()) {
|
| @@ -2147,6 +2221,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.layer_has_zero_opacity = false;
|
|
|
| PreCalculateMetaInformationRecursiveData recursive_data;
|
| PreCalculateMetaInformation(inputs->root_layer, &recursive_data);
|
| @@ -2206,6 +2281,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.layer_has_zero_opacity = false;
|
|
|
| PreCalculateMetaInformationRecursiveData recursive_data;
|
| PreCalculateMetaInformation(inputs->root_layer, &recursive_data);
|
|
|