return false;
}
+template <typename LayerType>
+static bool HasInvertibleOrAnimatedTransform(LayerType* layer) {
+ return layer->transform_is_invertible() || layer->TransformIsAnimating();
+}
+
static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
bool layer_is_drawn) {
+ // If the layer transform is not invertible, it should not be drawn.
+ // TODO(ajuma): Correctly process subtrees with singular transform for the
+ // case where we may animate to a non-singular transform and wish to
+ // pre-raster.
+ if (!HasInvertibleOrAnimatedTransform(layer))
+ 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)
}
static inline bool SubtreeShouldBeSkipped(Layer* layer, bool layer_is_drawn) {
+ // If the layer transform is not invertible, it should not be drawn.
+ if (!layer->transform_is_invertible() && !layer->TransformIsAnimating())
+ 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)
}
template <typename LayerType>
-static inline void CalculateContentsScale(LayerType* layer,
- float contents_scale,
- float device_scale_factor,
- float page_scale_factor,
- bool animating_transform_to_screen) {
+static inline void CalculateContentsScale(
+ LayerType* layer,
+ float contents_scale,
+ float device_scale_factor,
+ float page_scale_factor,
+ float maximum_animation_contents_scale,
+ bool animating_transform_to_screen) {
layer->CalculateContentsScale(contents_scale,
device_scale_factor,
page_scale_factor,
+ maximum_animation_contents_scale,
animating_transform_to_screen,
&layer->draw_properties().contents_scale_x,
&layer->draw_properties().contents_scale_y,
contents_scale,
device_scale_factor,
page_scale_factor,
+ maximum_animation_contents_scale,
animating_transform_to_screen,
&mask_layer->draw_properties().contents_scale_x,
&mask_layer->draw_properties().contents_scale_y,
contents_scale,
device_scale_factor,
page_scale_factor,
+ maximum_animation_contents_scale,
animating_transform_to_screen,
&replica_mask_layer->draw_properties().contents_scale_x,
&replica_mask_layer->draw_properties().contents_scale_y,
float ideal_contents_scale,
float device_scale_factor,
float page_scale_factor,
+ float maximum_animation_contents_scale,
bool animating_transform_to_screen) {
CalculateContentsScale(layer,
ideal_contents_scale,
device_scale_factor,
page_scale_factor,
+ maximum_animation_contents_scale,
animating_transform_to_screen);
}
float ideal_contents_scale,
float device_scale_factor,
float page_scale_factor,
+ float maximum_animation_contents_scale,
bool animating_transform_to_screen) {
if (can_adjust_raster_scale) {
float ideal_raster_scale =
contents_scale,
device_scale_factor,
page_scale_factor,
+ maximum_animation_contents_scale,
animating_transform_to_screen);
if (layer->content_bounds() != old_content_bounds ||
layer->SetNeedsPushProperties();
}
-static inline RenderSurface* CreateOrReuseRenderSurface(Layer* layer) {
- // The render surface should always be new on the main thread, as the
- // RenderSurfaceLayerList should be a new empty list when given to
- // CalculateDrawProperties.
- DCHECK(!layer->render_surface());
- layer->CreateRenderSurface();
- return layer->render_surface();
+static inline void CalculateAnimationContentsScale(
+ Layer* layer,
+ bool ancestor_is_animating_scale,
+ float ancestor_maximum_animation_contents_scale,
+ const gfx::Transform& parent_transform,
+ const gfx::Transform& combined_transform,
+ bool* combined_is_animating_scale,
+ float* combined_maximum_animation_contents_scale) {
+ *combined_is_animating_scale = false;
+ *combined_maximum_animation_contents_scale = 0.f;
+}
+
+static inline void CalculateAnimationContentsScale(
+ LayerImpl* layer,
+ bool ancestor_is_animating_scale,
+ float ancestor_maximum_animation_contents_scale,
+ const gfx::Transform& ancestor_transform,
+ const gfx::Transform& combined_transform,
+ bool* combined_is_animating_scale,
+ float* combined_maximum_animation_contents_scale) {
+ if (ancestor_is_animating_scale &&
+ ancestor_maximum_animation_contents_scale == 0.f) {
+ // We've already failed to compute a maximum animated scale at an
+ // ancestor, so we'll continue to fail.
+ *combined_maximum_animation_contents_scale = 0.f;
+ *combined_is_animating_scale = true;
+ return;
+ }
+
+ if (!combined_transform.IsScaleOrTranslation()) {
+ // Computing maximum animated scale in the presence of
+ // non-scale/translation transforms isn't supported.
+ *combined_maximum_animation_contents_scale = 0.f;
+ *combined_is_animating_scale = true;
+ return;
+ }
+
+ // We currently only support computing maximum scale for combinations of
+ // scales and translations. We treat all non-translations as potentially
+ // affecting scale. Animations that include non-translation/scale components
+ // will cause the computation of MaximumScale below to fail.
+ bool layer_is_animating_scale =
+ !layer->layer_animation_controller()->HasOnlyTranslationTransforms();
+
+ if (!layer_is_animating_scale && !ancestor_is_animating_scale) {
+ *combined_maximum_animation_contents_scale = 0.f;
+ *combined_is_animating_scale = false;
+ return;
+ }
+
+ // We don't attempt to accumulate animation scale from multiple nodes,
+ // because of the risk of significant overestimation. For example, one node
+ // may be increasing scale from 1 to 10 at the same time as a descendant is
+ // decreasing scale from 10 to 1. Naively combining these scales would produce
+ // a scale of 100.
+ if (layer_is_animating_scale && ancestor_is_animating_scale) {
+ *combined_maximum_animation_contents_scale = 0.f;
+ *combined_is_animating_scale = true;
+ return;
+ }
+
+ // At this point, we know either the layer or an ancestor, but not both,
+ // is animating scale.
+ *combined_is_animating_scale = true;
+ if (!layer_is_animating_scale) {
+ gfx::Vector2dF layer_transform_scales =
+ MathUtil::ComputeTransform2dScaleComponents(layer->transform(), 0.f);
+ *combined_maximum_animation_contents_scale =
+ ancestor_maximum_animation_contents_scale *
+ std::max(layer_transform_scales.x(), layer_transform_scales.y());
+ return;
+ }
+
+ float layer_maximum_animated_scale = 0.f;
+ if (!layer->layer_animation_controller()->MaximumScale(
+ &layer_maximum_animated_scale)) {
+ *combined_maximum_animation_contents_scale = 0.f;
+ return;
+ }
+ gfx::Vector2dF ancestor_transform_scales =
+ MathUtil::ComputeTransform2dScaleComponents(ancestor_transform, 0.f);
+ *combined_maximum_animation_contents_scale =
+ layer_maximum_animated_scale *
+ std::max(ancestor_transform_scales.x(), ancestor_transform_scales.y());
}
-static inline RenderSurfaceImpl* CreateOrReuseRenderSurface(LayerImpl* layer) {
+template <typename LayerType>
+static inline typename LayerType::RenderSurfaceType* CreateOrReuseRenderSurface(
+ LayerType* layer) {
if (!layer->render_surface()) {
layer->CreateRenderSurface();
return layer->render_surface();
return layer->render_surface();
}
+template <typename LayerTypePtr>
+static inline void MarkLayerWithRenderSurfaceLayerListId(
+ LayerTypePtr layer,
+ int current_render_surface_layer_list_id) {
+ layer->draw_properties().last_drawn_render_surface_layer_list_id =
+ current_render_surface_layer_list_id;
+}
+
+template <typename LayerTypePtr>
+static inline void MarkMasksWithRenderSurfaceLayerListId(
+ LayerTypePtr layer,
+ int current_render_surface_layer_list_id) {
+ if (layer->mask_layer()) {
+ MarkLayerWithRenderSurfaceLayerListId(layer->mask_layer(),
+ current_render_surface_layer_list_id);
+ }
+ if (layer->replica_layer() && layer->replica_layer()->mask_layer()) {
+ MarkLayerWithRenderSurfaceLayerListId(layer->replica_layer()->mask_layer(),
+ current_render_surface_layer_list_id);
+ }
+}
+
+template <typename LayerListType>
+static inline void MarkLayerListWithRenderSurfaceLayerListId(
+ LayerListType* layer_list,
+ int current_render_surface_layer_list_id) {
+ for (typename LayerListType::iterator it = layer_list->begin();
+ it != layer_list->end();
+ ++it) {
+ MarkLayerWithRenderSurfaceLayerListId(*it,
+ current_render_surface_layer_list_id);
+ MarkMasksWithRenderSurfaceLayerListId(*it,
+ current_render_surface_layer_list_id);
+ }
+}
+
template <typename LayerType>
static inline void RemoveSurfaceForEarlyExit(
LayerType* layer_to_remove,
// things to crash. So here we proactively remove any additional
// layers from the end of the list.
while (render_surface_layer_list->back() != layer_to_remove) {
- render_surface_layer_list->back()->ClearRenderSurface();
+ MarkLayerListWithRenderSurfaceLayerListId(
+ &render_surface_layer_list->back()->render_surface()->layer_list(), 0);
+ MarkLayerWithRenderSurfaceLayerListId(render_surface_layer_list->back(), 0);
+
+ render_surface_layer_list->back()->ClearRenderSurfaceLayerList();
render_surface_layer_list->pop_back();
}
DCHECK_EQ(render_surface_layer_list->back(), layer_to_remove);
+ MarkLayerListWithRenderSurfaceLayerListId(
+ &layer_to_remove->render_surface()->layer_list(), 0);
+ MarkLayerWithRenderSurfaceLayerListId(layer_to_remove, 0);
render_surface_layer_list->pop_back();
- layer_to_remove->ClearRenderSurface();
+ layer_to_remove->ClearRenderSurfaceLayerList();
}
struct PreCalculateMetaInformationRecursiveData {
bool has_delegated_content = layer->HasDelegatedContent();
int num_descendants_that_draw_content = 0;
+ layer->draw_properties().sorted_for_recursion = false;
+ layer->draw_properties().has_child_with_a_scroll_parent = false;
+
+ if (!HasInvertibleOrAnimatedTransform(layer)) {
+ // Layers with singular transforms should not be drawn, the whole subtree
+ // can be skipped.
+ return;
+ }
+
if (has_delegated_content) {
// Layers with delegated content need to be treated as if they have as
// many children as the number of layers they own delegated quads for.
num_descendants_that_draw_content = 1000;
}
- layer->draw_properties().sorted_for_recursion = false;
- layer->draw_properties().has_child_with_a_scroll_parent = false;
-
if (layer->clip_parent())
recursive_data->num_unclipped_descendants++;
for (size_t i = 0; i < layer->children().size(); ++i) {
LayerType* child_layer =
- LayerTreeHostCommon::get_child_as_raw_ptr(layer->children(), i);
+ LayerTreeHostCommon::get_layer_as_raw_ptr(layer->children(), i);
PreCalculateMetaInformationRecursiveData data_for_child;
PreCalculateMetaInformation(child_layer, &data_for_child);
// passed down the recursion to the children that actually use it.
gfx::Rect clip_rect_of_target_surface_in_target_space;
+ // The maximum amount by which this layer will be scaled during the lifetime
+ // of currently running animations.
+ float maximum_animation_contents_scale;
+
+ bool ancestor_is_animating_scale;
bool ancestor_clips_subtree;
typename LayerType::RenderSurfaceType*
nearest_occlusion_immune_ancestor_surface;
bool order_changed = false;
for (size_t i = 0; i < parent.children().size(); ++i) {
LayerType* current =
- LayerTreeHostCommon::get_child_as_raw_ptr(parent.children(), i);
+ LayerTreeHostCommon::get_layer_as_raw_ptr(parent.children(), i);
if (current->draw_properties().sorted_for_recursion) {
order_changed = true;
*count = layer->draw_properties().num_render_surfaces_added;
}
-template <typename LayerType,
- typename GetIndexAndCountType>
+// We need to extract a list from the the two flavors of RenderSurfaceListType
+// for use in the sorting function below.
+static LayerList* GetLayerListForSorting(RenderSurfaceLayerList* rsll) {
+ return &rsll->AsLayerList();
+}
+
+static LayerImplList* GetLayerListForSorting(LayerImplList* layer_list) {
+ return layer_list;
+}
+
+template <typename LayerType, typename GetIndexAndCountType>
static void SortLayerListContributions(
const LayerType& parent,
- typename LayerType::RenderSurfaceListType* unsorted,
+ typename LayerType::LayerListType* unsorted,
size_t start_index_for_all_contributions,
GetIndexAndCountType get_index_and_count) {
-
typename LayerType::LayerListType buffer;
for (size_t i = 0; i < parent.children().size(); ++i) {
LayerType* child =
- LayerTreeHostCommon::get_child_as_raw_ptr(parent.children(), i);
+ LayerTreeHostCommon::get_layer_as_raw_ptr(parent.children(), i);
size_t start_index = 0;
size_t count = 0;
const SubtreeGlobals<LayerType>& globals,
const DataForRecursion<LayerType>& data_from_ancestor,
typename LayerType::RenderSurfaceListType* render_surface_layer_list,
- typename LayerType::RenderSurfaceListType* layer_list,
- std::vector<AccumulatedSurfaceState<LayerType> >*
- accumulated_surface_state) {
+ typename LayerType::LayerListType* layer_list,
+ std::vector<AccumulatedSurfaceState<LayerType> >* accumulated_surface_state,
+ int current_render_surface_layer_list_id) {
// This function computes the new matrix transformations recursively for this
// layer and all its descendants. It also computes the appropriate render
// surfaces.
// The root layer cannot skip CalcDrawProperties.
if (!IsRootLayer(layer) && SubtreeShouldBeSkipped(layer, layer_is_drawn)) {
if (layer->render_surface())
- layer->ClearRenderSurface();
+ layer->ClearRenderSurfaceLayerList();
return;
}
ApplyPositionAdjustment(layer, data_from_ancestor.fixed_container,
data_from_ancestor.scroll_compensation_matrix, &combined_transform);
+ bool combined_is_animating_scale = false;
+ float combined_maximum_animation_contents_scale = 0.f;
+ if (globals.can_adjust_raster_scales) {
+ CalculateAnimationContentsScale(
+ layer,
+ data_from_ancestor.ancestor_is_animating_scale,
+ data_from_ancestor.maximum_animation_contents_scale,
+ data_from_ancestor.parent_matrix,
+ combined_transform,
+ &combined_is_animating_scale,
+ &combined_maximum_animation_contents_scale);
+ }
+ data_for_children.ancestor_is_animating_scale = combined_is_animating_scale;
+ data_for_children.maximum_animation_contents_scale =
+ combined_maximum_animation_contents_scale;
+
// Compute the 2d scale components of the transform hierarchy up to the target
// surface. From there, we can decide on a contents scale for the layer.
float layer_scale_factors = globals.device_scale_factor;
globals.can_adjust_raster_scales,
ideal_contents_scale,
globals.device_scale_factor,
- data_from_ancestor.in_subtree_of_page_scale_application_layer ?
- globals.page_scale_factor : 1.f,
+ data_from_ancestor.in_subtree_of_page_scale_application_layer
+ ? globals.page_scale_factor
+ : 1.f,
+ combined_maximum_animation_contents_scale,
animating_transform_to_screen);
// The draw_transform that gets computed below is effectively the layer's
// subtree
if (!layer->double_sided() && TransformToParentIsKnown(layer) &&
IsSurfaceBackFaceVisible(layer, combined_transform)) {
- layer->ClearRenderSurface();
+ layer->ClearRenderSurfaceLayerList();
return;
}
layer_draw_properties.clip_rect = rect_in_target_space;
}
- typename LayerType::RenderSurfaceListType& descendants =
+ typename LayerType::LayerListType& descendants =
(layer->render_surface() ? layer->render_surface()->layer_list()
: *layer_list);
// and should be included in the sorting process.
size_t sorting_start_index = descendants.size();
- if (!LayerShouldBeSkipped(layer, layer_is_drawn))
+ if (!LayerShouldBeSkipped(layer, layer_is_drawn)) {
+ MarkLayerWithRenderSurfaceLayerListId(layer,
+ current_render_surface_layer_list_id);
descendants.push_back(layer);
+ }
// Any layers that are appended after this point may need to be sorted if we
// visit the children out of order.
LayerType* child =
layer_draw_properties.has_child_with_a_scroll_parent
? sorted_children[i]
- : LayerTreeHostCommon::get_child_as_raw_ptr(layer->children(), i);
+ : LayerTreeHostCommon::get_layer_as_raw_ptr(layer->children(), i);
child->draw_properties().index_of_first_descendants_addition =
descendants.size();
child->draw_properties().index_of_first_render_surface_layer_list_addition =
render_surface_layer_list->size();
- CalculateDrawPropertiesInternal<LayerType>(child,
- globals,
- data_for_children,
- render_surface_layer_list,
- &descendants,
- accumulated_surface_state);
+ CalculateDrawPropertiesInternal<LayerType>(
+ child,
+ globals,
+ data_for_children,
+ render_surface_layer_list,
+ &descendants,
+ accumulated_surface_state,
+ current_render_surface_layer_list_id);
if (child->render_surface() &&
+ !child->render_surface()->layer_list().empty() &&
!child->render_surface()->content_rect().IsEmpty()) {
+ // This child will contribute its render surface, which means
+ // we need to mark just the mask layer (and replica mask layer)
+ // with the id.
+ MarkMasksWithRenderSurfaceLayerListId(
+ child, current_render_surface_layer_list_id);
descendants.push_back(child);
}
if (child_order_changed) {
SortLayerListContributions(
*layer,
- render_surface_layer_list,
+ GetLayerListForSorting(render_surface_layer_list),
render_surface_layer_list_child_sorting_start_index,
&GetNewRenderSurfacesStartIndexAndCount<LayerType>);
}
}
-void LayerTreeHostCommon::CalculateDrawProperties(
- CalcDrawPropsMainInputs* inputs) {
- DCHECK(inputs->root_layer);
- DCHECK(IsRootLayer(inputs->root_layer));
- DCHECK(inputs->render_surface_layer_list);
+template <typename LayerType, typename RenderSurfaceLayerListType>
+static void ProcessCalcDrawPropsInputs(
+ const LayerTreeHostCommon::CalcDrawPropsInputs<LayerType,
+ RenderSurfaceLayerListType>&
+ inputs,
+ SubtreeGlobals<LayerType>* globals,
+ DataForRecursion<LayerType>* data_for_recursion) {
+ DCHECK(inputs.root_layer);
+ DCHECK(IsRootLayer(inputs.root_layer));
+ DCHECK(inputs.render_surface_layer_list);
+
gfx::Transform identity_matrix;
- gfx::Transform scaled_device_transform = inputs->device_transform;
- scaled_device_transform.Scale(inputs->device_scale_factor,
- inputs->device_scale_factor);
- RenderSurfaceLayerList dummy_layer_list;
// The root layer's render_surface should receive the device viewport as the
// initial clip rect.
- gfx::Rect device_viewport_rect(inputs->device_viewport_size);
+ gfx::Rect device_viewport_rect(inputs.device_viewport_size);
+
+ gfx::Vector2dF device_transform_scale_components =
+ MathUtil::ComputeTransform2dScaleComponents(inputs.device_transform, 1.f);
+ // Not handling the rare case of different x and y device scale.
+ float device_transform_scale =
+ std::max(device_transform_scale_components.x(),
+ device_transform_scale_components.y());
+
+ gfx::Transform scaled_device_transform = inputs.device_transform;
+ scaled_device_transform.Scale(inputs.device_scale_factor,
+ inputs.device_scale_factor);
+
+ globals->layer_sorter = NULL;
+ globals->max_texture_size = inputs.max_texture_size;
+ globals->device_scale_factor =
+ inputs.device_scale_factor * device_transform_scale;
+ globals->page_scale_factor = inputs.page_scale_factor;
+ globals->page_scale_application_layer = inputs.page_scale_application_layer;
+ globals->can_render_to_separate_surface =
+ inputs.can_render_to_separate_surface;
+ globals->can_adjust_raster_scales = inputs.can_adjust_raster_scales;
+
+ data_for_recursion->parent_matrix = scaled_device_transform;
+ data_for_recursion->full_hierarchy_matrix = identity_matrix;
+ data_for_recursion->scroll_compensation_matrix = identity_matrix;
+ data_for_recursion->fixed_container = inputs.root_layer;
+ data_for_recursion->clip_rect_in_target_space = device_viewport_rect;
+ data_for_recursion->clip_rect_of_target_surface_in_target_space =
+ device_viewport_rect;
+ data_for_recursion->maximum_animation_contents_scale = 0.f;
+ data_for_recursion->ancestor_is_animating_scale = false;
+ data_for_recursion->ancestor_clips_subtree = true;
+ data_for_recursion->nearest_occlusion_immune_ancestor_surface = NULL;
+ 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;
+}
+void LayerTreeHostCommon::CalculateDrawProperties(
+ CalcDrawPropsMainInputs* inputs) {
+ LayerList dummy_layer_list;
SubtreeGlobals<Layer> globals;
- globals.layer_sorter = NULL;
- globals.max_texture_size = inputs->max_texture_size;
- globals.device_scale_factor = inputs->device_scale_factor;
- globals.page_scale_factor = inputs->page_scale_factor;
- globals.page_scale_application_layer = inputs->page_scale_application_layer;
- globals.can_render_to_separate_surface =
- inputs->can_render_to_separate_surface;
- globals.can_adjust_raster_scales = inputs->can_adjust_raster_scales;
-
DataForRecursion<Layer> data_for_recursion;
- data_for_recursion.parent_matrix = scaled_device_transform;
- data_for_recursion.full_hierarchy_matrix = identity_matrix;
- data_for_recursion.scroll_compensation_matrix = identity_matrix;
- data_for_recursion.fixed_container = inputs->root_layer;
- data_for_recursion.clip_rect_in_target_space = device_viewport_rect;
- data_for_recursion.clip_rect_of_target_surface_in_target_space =
- device_viewport_rect;
- data_for_recursion.ancestor_clips_subtree = true;
- data_for_recursion.nearest_occlusion_immune_ancestor_surface = NULL;
- 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;
+ ProcessCalcDrawPropsInputs(*inputs, &globals, &data_for_recursion);
PreCalculateMetaInformationRecursiveData recursive_data;
PreCalculateMetaInformation(inputs->root_layer, &recursive_data);
std::vector<AccumulatedSurfaceState<Layer> > accumulated_surface_state;
- CalculateDrawPropertiesInternal<Layer>(inputs->root_layer,
- globals,
- data_for_recursion,
- inputs->render_surface_layer_list,
- &dummy_layer_list,
- &accumulated_surface_state);
+ CalculateDrawPropertiesInternal<Layer>(
+ inputs->root_layer,
+ globals,
+ data_for_recursion,
+ inputs->render_surface_layer_list,
+ &dummy_layer_list,
+ &accumulated_surface_state,
+ inputs->current_render_surface_layer_list_id);
// The dummy layer list should not have been used.
DCHECK_EQ(0u, dummy_layer_list.size());
void LayerTreeHostCommon::CalculateDrawProperties(
CalcDrawPropsImplInputs* inputs) {
- DCHECK(inputs->root_layer);
- DCHECK(IsRootLayer(inputs->root_layer));
- DCHECK(inputs->render_surface_layer_list);
-
- gfx::Transform identity_matrix;
- gfx::Transform scaled_device_transform = inputs->device_transform;
- scaled_device_transform.Scale(inputs->device_scale_factor,
- inputs->device_scale_factor);
LayerImplList dummy_layer_list;
- LayerSorter layer_sorter;
-
- // The root layer's render_surface should receive the device viewport as the
- // initial clip rect.
- gfx::Rect device_viewport_rect(inputs->device_viewport_size);
-
SubtreeGlobals<LayerImpl> globals;
- globals.layer_sorter = &layer_sorter;
- globals.max_texture_size = inputs->max_texture_size;
- globals.device_scale_factor = inputs->device_scale_factor;
- globals.page_scale_factor = inputs->page_scale_factor;
- globals.page_scale_application_layer = inputs->page_scale_application_layer;
- globals.can_render_to_separate_surface =
- inputs->can_render_to_separate_surface;
- globals.can_adjust_raster_scales = inputs->can_adjust_raster_scales;
-
DataForRecursion<LayerImpl> data_for_recursion;
- data_for_recursion.parent_matrix = scaled_device_transform;
- data_for_recursion.full_hierarchy_matrix = identity_matrix;
- data_for_recursion.scroll_compensation_matrix = identity_matrix;
- data_for_recursion.fixed_container = inputs->root_layer;
- data_for_recursion.clip_rect_in_target_space = device_viewport_rect;
- data_for_recursion.clip_rect_of_target_surface_in_target_space =
- device_viewport_rect;
- data_for_recursion.ancestor_clips_subtree = true;
- data_for_recursion.nearest_occlusion_immune_ancestor_surface = NULL;
- 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;
+ ProcessCalcDrawPropsInputs(*inputs, &globals, &data_for_recursion);
+
+ LayerSorter layer_sorter;
+ globals.layer_sorter = &layer_sorter;
PreCalculateMetaInformationRecursiveData recursive_data;
PreCalculateMetaInformation(inputs->root_layer, &recursive_data);
std::vector<AccumulatedSurfaceState<LayerImpl> >
accumulated_surface_state;
- CalculateDrawPropertiesInternal<LayerImpl>(inputs->root_layer,
- globals,
- data_for_recursion,
- inputs->render_surface_layer_list,
- &dummy_layer_list,
- &accumulated_surface_state);
+ CalculateDrawPropertiesInternal<LayerImpl>(
+ inputs->root_layer,
+ globals,
+ data_for_recursion,
+ inputs->render_surface_layer_list,
+ &dummy_layer_list,
+ &accumulated_surface_state,
+ inputs->current_render_surface_layer_list_id);
// The dummy layer list should not have been used.
DCHECK_EQ(0u, dummy_layer_list.size());
return false;
}
+static bool PointHitsLayer(LayerImpl* layer,
+ const gfx::PointF& screen_space_point) {
+ gfx::RectF content_rect(layer->content_bounds());
+ if (!PointHitsRect(
+ screen_space_point, layer->screen_space_transform(), content_rect))
+ return false;
+
+ // At this point, we think the point does hit the layer, but we need to walk
+ // up the parents to ensure that the layer was not clipped in such a way
+ // that the hit point actually should not hit the layer.
+ if (PointIsClippedBySurfaceOrClipRect(screen_space_point, layer))
+ return false;
+
+ // Skip the HUD layer.
+ if (layer == layer->layer_tree_impl()->hud_layer())
+ return false;
+
+ return true;
+}
+
+LayerImpl* LayerTreeHostCommon::FindFirstScrollingLayerThatIsHitByPoint(
+ const gfx::PointF& screen_space_point,
+ const LayerImplList& render_surface_layer_list) {
+ typedef LayerIterator<LayerImpl> LayerIteratorType;
+ LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list);
+ for (LayerIteratorType it =
+ LayerIteratorType::Begin(&render_surface_layer_list);
+ it != end;
+ ++it) {
+ // We don't want to consider render_surfaces for hit testing.
+ if (!it.represents_itself())
+ continue;
+
+ LayerImpl* current_layer = (*it);
+ if (!PointHitsLayer(current_layer, screen_space_point))
+ continue;
+
+ if (current_layer->scrollable())
+ return current_layer;
+ }
+
+ return NULL;
+}
+
LayerImpl* LayerTreeHostCommon::FindLayerThatIsHitByPoint(
const gfx::PointF& screen_space_point,
const LayerImplList& render_surface_layer_list) {
continue;
LayerImpl* current_layer = (*it);
-
- gfx::RectF content_rect(current_layer->content_bounds());
- if (!PointHitsRect(screen_space_point,
- current_layer->screen_space_transform(),
- content_rect))
- continue;
-
- // At this point, we think the point does hit the layer, but we need to walk
- // up the parents to ensure that the layer was not clipped in such a way
- // that the hit point actually should not hit the layer.
- if (PointIsClippedBySurfaceOrClipRect(screen_space_point, current_layer))
- continue;
-
- // Skip the HUD layer.
- if (current_layer == current_layer->layer_tree_impl()->hud_layer())
+ if (!PointHitsLayer(current_layer, screen_space_point))
continue;
found_layer = current_layer;
LayerImpl* LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion(
const gfx::PointF& screen_space_point,
const LayerImplList& render_surface_layer_list) {
- // First find out which layer was hit from the saved list of visible layers
- // in the most recent frame.
- LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
- screen_space_point,
- render_surface_layer_list);
-
- // Walk up the hierarchy and look for a layer with a touch event handler
- // region that the given point hits.
- // This walk may not be necessary anymore: http://crbug.com/310817
- for (; layer_impl; layer_impl = layer_impl->parent()) {
+ typedef LayerIterator<LayerImpl> LayerIteratorType;
+ LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list);
+ for (LayerIteratorType it =
+ LayerIteratorType::Begin(&render_surface_layer_list);
+ it != end;
+ ++it) {
+ // We don't want to consider render_surfaces for hit testing.
+ if (!it.represents_itself())
+ continue;
+
+ LayerImpl* current_layer = (*it);
+ if (!PointHitsLayer(current_layer, screen_space_point))
+ continue;
+
if (LayerTreeHostCommon::LayerHasTouchEventHandlersAt(screen_space_point,
- layer_impl))
- break;
+ current_layer))
+ return current_layer;
+
+ // Note that we could stop searching if we hit a layer we know to be
+ // opaque to hit-testing, but knowing that reliably is tricky (eg. due to
+ // CSS pointer-events: none). Also blink has an optimization for the
+ // common case of an entire document having handlers where it doesn't
+ // report any rects for child layers (since it knows they can't exceed
+ // the document bounds).
}
- return layer_impl;
+ return NULL;
}
bool LayerTreeHostCommon::LayerHasTouchEventHandlersAt(