Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(621)

Unified Diff: cc/trees/draw_property_utils.cc

Issue 2008283003: cc: Separate computation of clip rect and visible rect to two functions (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address review comments Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/trees/draw_property_utils.cc
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index fef5d28d672cbc6909cf6eedcb8717d861e8d15a..e027c8ca9cc90a062579a5acdb3b25a1d2a937aa 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -58,106 +58,97 @@ static void ValidateRenderSurfaceForLayer(LayerImpl* layer) {
#endif
template <typename LayerType>
-void CalculateVisibleRects(
+bool ComputeClipRectInTargetSpace(const LayerType* layer,
+ const ClipNode* clip_node,
+ const TransformTree& transform_tree,
+ int target_node_id,
+ gfx::Rect* clip_rect_in_target_space) {
+ DCHECK(layer->clip_tree_index() == clip_node->id);
+ DCHECK(clip_node->data.target_id != target_node_id);
+
+ gfx::Transform clip_to_target;
+ if (clip_node->data.target_id > target_node_id) {
+ // In this case, layer has a scroll parent. We need to keep the scale
+ // at the layer's target but remove the scale at the scroll parent's
+ // target.
+ if (transform_tree.ComputeTransformWithDestinationSublayerScale(
+ clip_node->data.target_id, target_node_id, &clip_to_target)) {
+ const TransformNode* source_node =
+ transform_tree.Node(clip_node->data.target_id);
+ if (source_node->data.sublayer_scale.x() != 0.f &&
+ source_node->data.sublayer_scale.y() != 0.f)
+ clip_to_target.Scale(1.0f / source_node->data.sublayer_scale.x(),
+ 1.0f / source_node->data.sublayer_scale.y());
+ *clip_rect_in_target_space =
+ gfx::ToEnclosingRect(MathUtil::MapClippedRect(
+ clip_to_target, clip_node->data.clip_in_target_space));
+ } else {
+ return false;
+ }
+ } else {
+ if (transform_tree.ComputeTransform(clip_node->data.target_id,
+ target_node_id, &clip_to_target)) {
+ *clip_rect_in_target_space =
+ gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
+ clip_to_target, clip_node->data.clip_in_target_space));
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <typename LayerType>
+void CalculateClipRects(
const typename LayerType::LayerListType& visible_layer_list,
const ClipTree& clip_tree,
const TransformTree& transform_tree,
const EffectTree& effect_tree,
bool non_root_surfaces_enabled) {
for (auto& layer : visible_layer_list) {
- gfx::Size layer_bounds = layer->bounds();
const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
- const bool is_unclipped = clip_node->data.resets_clip &&
- !clip_node->data.applies_local_clip &&
- non_root_surfaces_enabled;
+ // The entire layer is visible if it has copy requests.
+ const EffectNode* effect_node =
+ effect_tree.Node(layer->effect_tree_index());
+ if (effect_node->data.has_copy_request &&
+ effect_node->owner_id == layer->id())
+ continue;
+
+ if (!non_root_surfaces_enabled) {
+ layer->set_clip_rect(
+ gfx::ToEnclosingRect(clip_node->data.clip_in_target_space));
+ continue;
+ }
+
// When both the layer and the target are unclipped, the entire layer
// content rect is visible.
const bool fully_visible = !clip_node->data.layers_are_clipped &&
- !clip_node->data.target_is_clipped &&
- non_root_surfaces_enabled;
- const TransformNode* transform_node =
- transform_tree.Node(layer->transform_tree_index());
- if (!is_unclipped && !fully_visible) {
- // The entire layer is visible if it has copy requests.
- const EffectNode* effect_node =
- effect_tree.Node(layer->effect_tree_index());
- if (effect_node->data.has_copy_request &&
- effect_node->owner_id == layer->id()) {
- layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
- continue;
- }
+ !clip_node->data.target_is_clipped;
- const TransformNode* target_node =
- non_root_surfaces_enabled
- ? transform_tree.Node(transform_node->data.content_target_id)
- : transform_tree.Node(0);
+ if (!fully_visible) {
+ const TransformNode* transform_node =
+ transform_tree.Node(layer->transform_tree_index());
+ int target_node_id = transform_node->data.content_target_id;
- // The clip node stores clip rect in its target space. If required,
- // this clip rect should be mapped to the current layer's target space.
- gfx::Rect clip_rect_in_target_space;
- gfx::Rect combined_clip_rect_in_target_space;
+ // The clip node stores clip rect in its target space.
+ gfx::Rect clip_rect_in_target_space =
+ gfx::ToEnclosingRect(clip_node->data.clip_in_target_space);
- // When we only have a root surface, the clip node and the layer must
- // necessarily have the same target (the root).
- if (clip_node->data.target_id != target_node->id &&
- non_root_surfaces_enabled) {
+ // If required, this clip rect should be mapped to the current layer's
+ // target space.
+ if (clip_node->data.target_id != target_node_id) {
// In this case, layer has a clip parent or scroll parent (or shares the
// target with an ancestor layer that has clip parent) and the clip
// parent's target is different from the layer's target. As the layer's
// target has unclippped descendants, it is unclippped.
- if (!clip_node->data.layers_are_clipped) {
- layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
+ if (!clip_node->data.layers_are_clipped)
continue;
- }
- bool success = true;
- gfx::Transform clip_to_target;
- if (clip_node->data.target_id > target_node->id) {
- // In this case, layer has a scroll parent. We need to keep the scale
- // at the layer's target but remove the scale at the scroll parent's
- // target.
- success = transform_tree.ComputeTransformWithDestinationSublayerScale(
- clip_node->data.target_id, target_node->id, &clip_to_target);
- const TransformNode* source_node =
- transform_tree.Node(clip_node->data.target_id);
- if (source_node->data.sublayer_scale.x() != 0.f &&
- source_node->data.sublayer_scale.y() != 0.f)
- clip_to_target.Scale(1.0f / source_node->data.sublayer_scale.x(),
- 1.0f / source_node->data.sublayer_scale.y());
- } else {
- success = transform_tree.ComputeTransform(
- clip_node->data.target_id, target_node->id, &clip_to_target);
- }
- if (!success) {
- // An animated singular transform may become non-singular during the
- // animation, so we still need to compute a visible rect. In this
- // situation, we treat the entire layer as visible.
- layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
+
+ // Compute the clip rect in target space and store it.
+ if (!ComputeClipRectInTargetSpace(layer, clip_node, transform_tree,
+ target_node_id,
+ &clip_rect_in_target_space))
continue;
- }
- // We use the clip node's clip_in_target_space (and not
- // combined_clip_in_target_space) here because we want to clip
- // with respect to clip parent's local clip and not its combined clip as
- // the combined clip has even the clip parent's target's clip baked into
- // it and as our target is different, we don't want to use it in our
- // visible rect computation.
- if (clip_node->data.target_id < target_node->id) {
- combined_clip_rect_in_target_space =
- gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
- clip_to_target, clip_node->data.clip_in_target_space));
- } else {
- combined_clip_rect_in_target_space =
- gfx::ToEnclosingRect(MathUtil::MapClippedRect(
- clip_to_target, clip_node->data.clip_in_target_space));
- }
- clip_rect_in_target_space = combined_clip_rect_in_target_space;
- } else {
- clip_rect_in_target_space =
- gfx::ToEnclosingRect(clip_node->data.clip_in_target_space);
- if (clip_node->data.target_is_clipped || !non_root_surfaces_enabled)
- combined_clip_rect_in_target_space = gfx::ToEnclosingRect(
- clip_node->data.combined_clip_in_target_space);
- else
- combined_clip_rect_in_target_space = clip_rect_in_target_space;
}
if (!clip_rect_in_target_space.IsEmpty()) {
@@ -165,68 +156,167 @@ void CalculateVisibleRects(
} else {
layer->set_clip_rect(gfx::Rect());
}
+ }
+ }
+}
- // The clip rect should be intersected with layer rect in target space.
- gfx::Transform content_to_target = non_root_surfaces_enabled
- ? transform_node->data.to_target
- : transform_node->data.to_screen;
+bool GetLayerClipRect(const scoped_refptr<Layer> layer,
+ const ClipNode* clip_node,
+ const TransformTree& transform_tree,
+ int target_node_id,
+ gfx::Rect* clip_rect_in_target_space) {
+ return ComputeClipRectInTargetSpace(layer.get(), clip_node, transform_tree,
+ target_node_id,
+ clip_rect_in_target_space);
+}
- content_to_target.Translate(layer->offset_to_transform_parent().x(),
- layer->offset_to_transform_parent().y());
- gfx::Rect layer_content_rect = gfx::Rect(layer_bounds);
- gfx::Rect layer_content_bounds_in_target_space =
- MathUtil::MapEnclosingClippedRect(content_to_target,
- layer_content_rect);
- combined_clip_rect_in_target_space.Intersect(
- layer_content_bounds_in_target_space);
- if (combined_clip_rect_in_target_space.IsEmpty()) {
- layer->set_visible_layer_rect(gfx::Rect());
- continue;
- }
+bool GetLayerClipRect(const LayerImpl* layer,
+ const ClipNode* clip_node,
+ const TransformTree& transform_tree,
+ int target_node_id,
+ gfx::Rect* clip_rect_in_target_space) {
+ // This is equivalent of calling ComputeClipRectInTargetSpace.
+ *clip_rect_in_target_space = layer->clip_rect();
+ return transform_tree.Node(target_node_id)->data.ancestors_are_invertible;
+}
- // If the layer is fully contained within the clip, treat it as fully
- // visible. Since clip_rect_in_target_space has already been intersected
- // with layer_content_bounds_in_target_space, the layer is fully contained
- // within the clip iff these rects are equal.
- if (combined_clip_rect_in_target_space ==
- layer_content_bounds_in_target_space) {
- layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
- continue;
- }
+template <typename LayerType>
+void CalculateVisibleRects(
+ const typename LayerType::LayerListType& visible_layer_list,
+ const ClipTree& clip_tree,
+ const TransformTree& transform_tree,
+ const EffectTree& effect_tree,
+ bool non_root_surfaces_enabled) {
+ for (auto& layer : visible_layer_list) {
+ gfx::Size layer_bounds = layer->bounds();
- gfx::Transform target_to_content;
- gfx::Transform target_to_layer;
- bool success = true;
+ const EffectNode* effect_node =
+ effect_tree.Node(layer->effect_tree_index());
+ if (effect_node->data.has_copy_request &&
+ effect_node->owner_id == layer->id()) {
+ layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
+ continue;
+ }
+
+ const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
+ const TransformNode* transform_node =
+ transform_tree.Node(layer->transform_tree_index());
+ if (!non_root_surfaces_enabled) {
+ // When we only have a root surface, the clip node and the layer must
+ // necessarily have the same target (the root).
if (transform_node->data.ancestors_are_invertible) {
- target_to_layer = non_root_surfaces_enabled
- ? transform_node->data.from_target
- : transform_node->data.from_screen;
+ gfx::Rect combined_clip_rect_in_target_space =
+ gfx::ToEnclosingRect(clip_node->data.combined_clip_in_target_space);
+ gfx::Transform target_to_content;
+ target_to_content.Translate(-layer->offset_to_transform_parent().x(),
+ -layer->offset_to_transform_parent().y());
+ target_to_content.PreconcatTransform(transform_node->data.from_screen);
+
+ gfx::Rect visible_rect = MathUtil::ProjectEnclosingClippedRect(
+ target_to_content, combined_clip_rect_in_target_space);
+ visible_rect.Intersect(gfx::Rect(layer_bounds));
+ layer->set_visible_layer_rect(visible_rect);
} else {
- success = transform_tree.ComputeTransformWithSourceSublayerScale(
- target_node->id, transform_node->id, &target_to_layer);
+ layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
+ }
+ continue;
+ }
+
+ // When both the layer and the target are unclipped, the entire layer
+ // content rect is visible.
+ const bool fully_visible = !clip_node->data.layers_are_clipped &&
+ !clip_node->data.target_is_clipped;
+
+ if (fully_visible) {
+ layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
+ continue;
+ }
+
+ int target_node_id = transform_node->data.content_target_id;
+
+ // The clip node stores clip rect in its target space. If required,
+ // this clip rect should be mapped to the current layer's target space.
+ gfx::Rect combined_clip_rect_in_target_space;
+
+ if (clip_node->data.target_id != target_node_id) {
+ // In this case, layer has a clip parent or scroll parent (or shares the
+ // target with an ancestor layer that has clip parent) and the clip
+ // parent's target is different from the layer's target. As the layer's
+ // target has unclippped descendants, it is unclippped.
+ if (!clip_node->data.layers_are_clipped) {
+ layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
+ continue;
}
- if (!success) {
+ // We use the clip node's clip_in_target_space (and not
+ // combined_clip_in_target_space) here because we want to clip
+ // with respect to clip parent's local clip and not its combined clip as
+ // the combined clip has even the clip parent's target's clip baked into
+ // it and as our target is different, we don't want to use it in our
+ // visible rect computation.
+ if (!GetLayerClipRect(layer, clip_node, transform_tree, target_node_id,
+ &combined_clip_rect_in_target_space)) {
+ layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
+ continue;
+ }
+ } else {
+ if (clip_node->data.target_is_clipped) {
+ combined_clip_rect_in_target_space =
+ gfx::ToEnclosingRect(clip_node->data.combined_clip_in_target_space);
+ } else {
+ combined_clip_rect_in_target_space =
+ gfx::ToEnclosingRect(clip_node->data.clip_in_target_space);
+ }
+ }
+
+ // The clip rect should be intersected with layer rect in target space.
+ gfx::Transform content_to_target = transform_node->data.to_target;
+ content_to_target.Translate(layer->offset_to_transform_parent().x(),
+ layer->offset_to_transform_parent().y());
+ gfx::Rect layer_content_rect = gfx::Rect(layer_bounds);
+ gfx::Rect layer_content_bounds_in_target_space =
+ MathUtil::MapEnclosingClippedRect(content_to_target,
+ layer_content_rect);
+ combined_clip_rect_in_target_space.Intersect(
+ layer_content_bounds_in_target_space);
+ if (combined_clip_rect_in_target_space.IsEmpty()) {
+ layer->set_visible_layer_rect(gfx::Rect());
+ continue;
+ }
+
+ // If the layer is fully contained within the clip, treat it as fully
+ // visible. Since clip_rect_in_target_space has already been intersected
+ // with layer_content_bounds_in_target_space, the layer is fully contained
+ // within the clip iff these rects are equal.
+ if (combined_clip_rect_in_target_space ==
+ layer_content_bounds_in_target_space) {
+ layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
+ continue;
+ }
+
+ gfx::Transform target_to_layer;
+ if (transform_node->data.ancestors_are_invertible) {
+ target_to_layer = transform_node->data.from_target;
+ } else {
+ if (!transform_tree.ComputeTransformWithSourceSublayerScale(
+ target_node_id, transform_node->id, &target_to_layer)) {
// An animated singular transform may become non-singular during the
// animation, so we still need to compute a visible rect. In this
// situation, we treat the entire layer as visible.
layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
continue;
}
-
- target_to_content.Translate(-layer->offset_to_transform_parent().x(),
- -layer->offset_to_transform_parent().y());
- target_to_content.PreconcatTransform(target_to_layer);
-
- gfx::Rect visible_rect = MathUtil::ProjectEnclosingClippedRect(
- target_to_content, combined_clip_rect_in_target_space);
-
- visible_rect.Intersect(gfx::Rect(layer_bounds));
-
- layer->set_visible_layer_rect(visible_rect);
- } else {
- layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
}
+
+ gfx::Transform target_to_content;
+ target_to_content.Translate(-layer->offset_to_transform_parent().x(),
+ -layer->offset_to_transform_parent().y());
+ target_to_content.PreconcatTransform(target_to_layer);
+
+ gfx::Rect visible_rect = MathUtil::ProjectEnclosingClippedRect(
+ target_to_content, combined_clip_rect_in_target_space);
+ visible_rect.Intersect(gfx::Rect(layer_bounds));
+ layer->set_visible_layer_rect(visible_rect);
}
}
@@ -770,6 +860,10 @@ static void ComputeVisibleRectsInternal(
FindLayersThatNeedUpdates(root_layer->layer_tree_impl(),
property_trees->transform_tree,
property_trees->effect_tree, visible_layer_list);
+ CalculateClipRects<LayerImpl>(*visible_layer_list, property_trees->clip_tree,
+ property_trees->transform_tree,
+ property_trees->effect_tree,
+ can_render_to_separate_surface);
CalculateVisibleRects<LayerImpl>(
*visible_layer_list, property_trees->clip_tree,
property_trees->transform_tree, property_trees->effect_tree,
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698