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

Unified Diff: cc/trees/draw_property_utils.cc

Issue 2067783002: cc: Calculate visible rect inside non root copy request (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@rectF
Patch Set: edit comment to be more explicit 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 | cc/trees/layer_tree_host_common_unittest.cc » ('j') | 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 6881a25cc1a3f323a0bbaaf55f6f9a04dcad94a5..0e4294638f654d26d5e8942cc5558ef197f9347c 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -92,6 +92,120 @@ bool ComputeClipRectInTargetSpace(const LayerType* layer,
return true;
}
+struct ConditionalClip {
+ bool is_clipped;
+ gfx::RectF clip_rect;
+};
+
+static ConditionalClip ComputeRectInTargetSpace(
+ gfx::RectF rect,
+ const TransformTree& transform_tree,
+ int current_transform_id,
+ int target_transform_id) {
+ gfx::Transform current_to_target;
+ if (!transform_tree.ComputeTransformWithDestinationSublayerScale(
+ current_transform_id, target_transform_id, &current_to_target))
+ // If transform is not invertible, cannot apply clip.
+ return ConditionalClip{false, gfx::RectF()};
+ if (current_transform_id > target_transform_id)
+ return ConditionalClip{true, // is_clipped.
+ MathUtil::MapClippedRect(current_to_target, rect)};
+
+ return ConditionalClip{true, // is_clipped.
+ MathUtil::ProjectClippedRect(current_to_target, rect)};
+}
+
+static ConditionalClip ComputeCurrentClip(const ClipNode* clip_node,
+ const TransformTree& transform_tree,
+ int target_transform_id) {
+ if (clip_node->data.transform_id != target_transform_id)
+ return ComputeRectInTargetSpace(clip_node->data.clip, transform_tree,
+ clip_node->data.transform_id,
+ target_transform_id);
+
+ gfx::RectF current_clip = clip_node->data.clip;
+ gfx::Vector2dF sublayer_scale =
+ transform_tree.Node(target_transform_id)->data.sublayer_scale;
+ if (sublayer_scale.x() > 0 && sublayer_scale.y() > 0)
+ current_clip.Scale(sublayer_scale.x(), sublayer_scale.y());
+ return ConditionalClip{true /* is_clipped */, current_clip};
+}
+
+static ConditionalClip ComputeAccumulatedClip(
+ const ClipTree& clip_tree,
+ int local_clip_id,
+ const EffectTree& effect_tree,
+ int target_id,
+ const TransformTree& transform_tree) {
+ const ClipNode* clip_node = clip_tree.Node(local_clip_id);
+ const EffectNode* target_node = effect_tree.Node(target_id);
+ int target_transform_id = target_node->data.transform_id;
+ bool is_clipped = false;
+
+ // Collect all the clips that need to be accumulated.
+ std::stack<const ClipNode*> parent_chain;
+
+ // If target is not direct ancestor of clip, this will find least common
+ // ancestor between the target and the clip.
+ while (target_node->id >= 0 && clip_node->id >= 0) {
+ while (target_node->data.clip_id > clip_node->id ||
+ target_node->data.has_unclipped_descendants) {
+ target_node = effect_tree.Node(target_node->data.target_id);
+ }
+ if (target_node->data.clip_id == clip_node->id)
+ break;
+ while (target_node->data.clip_id < clip_node->id) {
+ parent_chain.push(clip_node);
+ clip_node = clip_tree.parent(clip_node);
+ }
+ if (target_node->data.clip_id == clip_node->id) {
+ // Target is responsible for applying this clip_node (id equals to
+ // target_node's clip id), no need to accumulate this as part of clip
+ // rect.
+ clip_node = parent_chain.top();
+ parent_chain.pop();
+ break;
+ }
+ }
+
+ // TODO(weiliangc): If we don't create clip for render surface, we don't need
+ // to check applies_local_clip.
+ while (!clip_node->data.applies_local_clip && parent_chain.size() > 0) {
+ clip_node = parent_chain.top();
+ parent_chain.pop();
+ }
+
+ if (!clip_node->data.applies_local_clip)
+ // No clip node applying clip in between.
+ return ConditionalClip{false, gfx::RectF()};
+
+ ConditionalClip current_clip =
+ ComputeCurrentClip(clip_node, transform_tree, target_transform_id);
+ is_clipped = current_clip.is_clipped;
+ gfx::RectF accumulated_clip = current_clip.clip_rect;
+
+ while (parent_chain.size() > 0) {
+ clip_node = parent_chain.top();
+ parent_chain.pop();
+ if (!clip_node->data.applies_local_clip) {
+ continue;
+ }
+ ConditionalClip current_clip =
+ ComputeCurrentClip(clip_node, transform_tree, target_transform_id);
+
+ // If transform is not invertible, no clip will be applied.
+ if (!current_clip.is_clipped)
+ return ConditionalClip{false, gfx::RectF()};
+
+ is_clipped = true;
+ accumulated_clip =
+ gfx::IntersectRects(accumulated_clip, current_clip.clip_rect);
+ }
+
+ return ConditionalClip{
+ is_clipped, accumulated_clip.IsEmpty() ? gfx::RectF() : accumulated_clip};
+}
+
template <typename LayerType>
void CalculateClipRects(
const typename LayerType::LayerListType& visible_layer_list,
@@ -184,11 +298,36 @@ void CalculateVisibleRects(
for (auto& layer : visible_layer_list) {
gfx::Size layer_bounds = layer->bounds();
- 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));
+ int effect_ancestor_with_copy_request =
+ effect_tree.ClosestAncestorWithCopyRequest(layer->effect_tree_index());
+ if (effect_ancestor_with_copy_request > 1) {
+ // Non root copy request.
+ ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip(
+ clip_tree, layer->clip_tree_index(), effect_tree,
+ effect_ancestor_with_copy_request, transform_tree);
+ if (!accumulated_clip_rect.is_clipped) {
+ layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
+ continue;
+ }
+
+ gfx::RectF accumulated_clip_in_copy_request_space =
+ accumulated_clip_rect.clip_rect;
+
+ const EffectNode* copy_request_effect_node =
+ effect_tree.Node(effect_ancestor_with_copy_request);
+ ConditionalClip clip_in_layer_space = ComputeRectInTargetSpace(
+ accumulated_clip_in_copy_request_space, transform_tree,
+ copy_request_effect_node->data.transform_id,
+ layer->transform_tree_index());
+ if (clip_in_layer_space.is_clipped) {
+ gfx::RectF clip_rect = clip_in_layer_space.clip_rect;
+ clip_rect.Offset(-layer->offset_to_transform_parent());
+ gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_rect);
+ visible_rect.Intersect(gfx::Rect(layer_bounds));
+ layer->set_visible_layer_rect(visible_rect);
+ } else {
+ layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
+ }
continue;
}
@@ -678,94 +817,6 @@ void ComputeEffects(EffectTree* effect_tree) {
effect_tree->set_needs_update(false);
}
-static gfx::RectF ComputeCurrentClip(const ClipNode* clip_node,
- const TransformTree& transform_tree,
- int target_transform_id) {
- if (clip_node->data.transform_id != target_transform_id) {
- gfx::Transform current_to_target;
- if (!transform_tree.ComputeTransformWithDestinationSublayerScale(
- clip_node->data.transform_id, target_transform_id,
- &current_to_target))
- return gfx::RectF();
- if (clip_node->data.transform_id > target_transform_id)
- return MathUtil::MapClippedRect(current_to_target, clip_node->data.clip);
- else
- return MathUtil::ProjectClippedRect(current_to_target,
- clip_node->data.clip);
- } else {
- gfx::RectF current_clip = clip_node->data.clip;
- gfx::Vector2dF sublayer_scale =
- transform_tree.Node(target_transform_id)->data.sublayer_scale;
- if (sublayer_scale.x() > 0 && sublayer_scale.y() > 0) {
- current_clip.Scale(sublayer_scale.x(), sublayer_scale.y());
- }
- return current_clip;
- }
-}
-
-static gfx::RectF ComputeAccumulatedClip(const ClipTree& clip_tree,
- int local_clip_id,
- const EffectTree& effect_tree,
- int target_id,
- const TransformTree& transform_tree) {
- const ClipNode* clip_node = clip_tree.Node(local_clip_id);
- const EffectNode* target_node = effect_tree.Node(target_id);
- int target_transform_id = target_node->data.transform_id;
-
- // Collect all the clips that need to be accumulated.
- std::stack<const ClipNode*> parent_chain;
-
- // If target is not direct ancestor of clip, this will find least common
- // ancestor between the target and the clip.
- while (target_node->id >= 0 && clip_node->id >= 0) {
- while (target_node->data.clip_id > clip_node->id ||
- target_node->data.has_unclipped_descendants) {
- target_node = effect_tree.Node(target_node->data.target_id);
- }
- if (target_node->data.clip_id == clip_node->id)
- break;
- while (target_node->data.clip_id < clip_node->id) {
- parent_chain.push(clip_node);
- clip_node = clip_tree.parent(clip_node);
- }
- if (target_node->data.clip_id == clip_node->id) {
- clip_node = parent_chain.top();
- parent_chain.pop();
- break;
- }
- }
-
- // TODO(weiliangc): If we don't create clip for render surface, we don't need
- // to check applies_local_clip.
- while (!clip_node->data.applies_local_clip && parent_chain.size() > 0) {
- clip_node = parent_chain.top();
- parent_chain.pop();
- }
-
- if (!clip_node->data.applies_local_clip)
- return gfx::RectF();
-
- gfx::RectF accumulated_clip =
- ComputeCurrentClip(clip_node, transform_tree, target_transform_id);
-
- while (parent_chain.size() > 0) {
- clip_node = parent_chain.top();
- parent_chain.pop();
- if (!clip_node->data.applies_local_clip) {
- continue;
- }
- gfx::RectF current_clip =
- ComputeCurrentClip(clip_node, transform_tree, target_transform_id);
-
- if (current_clip.IsEmpty())
- return gfx::RectF();
-
- accumulated_clip = gfx::IntersectRects(accumulated_clip, current_clip);
- }
-
- return accumulated_clip.IsEmpty() ? gfx::RectF() : accumulated_clip;
-}
-
static void ComputeClipsWithEffectTree(PropertyTrees* property_trees) {
EffectTree* effect_tree = &property_trees->effect_tree;
const ClipTree* clip_tree = &property_trees->clip_tree;
@@ -784,9 +835,10 @@ static void ComputeClipsWithEffectTree(PropertyTrees* property_trees) {
EffectNode* effect_node = effect_tree->Node(i);
const EffectNode* target_node =
effect_tree->Node(effect_node->data.target_id);
- gfx::RectF accumulated_clip =
+ ConditionalClip accumulated_clip_rect =
ComputeAccumulatedClip(*clip_tree, effect_node->data.clip_id,
*effect_tree, target_node->id, *transform_tree);
+ gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect;
const RenderSurfaceImpl* render_surface = effect_node->data.render_surface;
if (render_surface && render_surface->is_clipped()) {
DCHECK(gfx::ToEnclosingRect(accumulated_clip) ==
@@ -815,10 +867,12 @@ static void ComputeLayerClipRect(const PropertyTrees* property_trees,
target_node = effect_tree->Node(1);
}
- gfx::RectF accumulated_clip =
+ ConditionalClip accumulated_clip_rect =
ComputeAccumulatedClip(*clip_tree, layer->clip_tree_index(), *effect_tree,
target_node->id, *transform_tree);
+ gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect;
+
if ((!property_trees->non_root_surfaces_enabled &&
clip_tree->Node(layer->clip_tree_index())
->data.layers_are_clipped_when_surfaces_disabled) ||
« no previous file with comments | « no previous file | cc/trees/layer_tree_host_common_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698