Index: cc/trees/draw_property_utils.cc |
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc |
index 6f7e8cbcd63920ac9a5b387d93be96a02af5fecb..ff37f73ffbbeaadbd28760b4a4d9297e24a9d7a0 100644 |
--- a/cc/trees/draw_property_utils.cc |
+++ b/cc/trees/draw_property_utils.cc |
@@ -224,9 +224,12 @@ static ConditionalClip ComputeAccumulatedClip(PropertyTrees* property_trees, |
std::stack<const ClipNode*, std::vector<const ClipNode*>> parent_chain; |
// If target is not direct ancestor of clip, this will find least common |
- // ancestor between the target and the clip. |
+ // ancestor between the target and the clip. Or, if the target has a |
+ // contributing layer that escapes clip, this will find the nearest ancestor |
+ // that doesn't. |
while (target_node->clip_id > clip_node->id || |
- target_node->has_unclipped_descendants) { |
+ effect_tree.GetRenderSurface(target_node->id) |
+ ->has_contributing_layer_that_escapes_clip()) { |
target_node = effect_tree.Node(target_node->target_id); |
} |
@@ -318,6 +321,36 @@ static bool HasSingularTransform(int transform_tree_index, |
return !node->is_invertible || !node->ancestors_are_invertible; |
} |
+static int LowestCommonAncestor(int clip_id_1, |
+ int clip_id_2, |
+ const ClipTree* clip_tree) { |
+ const ClipNode* clip_node_1 = clip_tree->Node(clip_id_1); |
+ const ClipNode* clip_node_2 = clip_tree->Node(clip_id_2); |
+ while (clip_node_1->id != clip_node_2->id) { |
+ if (clip_node_1->id < clip_node_2->id) |
+ clip_node_2 = clip_tree->parent(clip_node_2); |
+ else |
+ clip_node_1 = clip_tree->parent(clip_node_1); |
+ } |
+ return clip_node_1->id; |
+} |
+ |
+static void SetHasContributingLayerThatEscapesClip(int lca_clip_id, |
+ int target_effect_id, |
+ EffectTree* effect_tree) { |
+ const EffectNode* effect_node = effect_tree->Node(target_effect_id); |
+ // Find all ancestor targets starting from effect_node who are clipped by |
+ // a descendant of lowest ancestor clip and set their |
+ // has_contributing_layer_that_escapes_clip to true. |
+ while (effect_node->clip_id > lca_clip_id) { |
+ RenderSurfaceImpl* render_surface = |
+ effect_tree->GetRenderSurface(effect_node->id); |
+ DCHECK(render_surface); |
+ render_surface->set_has_contributing_layer_that_escapes_clip(true); |
+ effect_node = effect_tree->Node(effect_node->target_id); |
+ } |
+} |
+ |
template <typename LayerType> |
static int TransformTreeIndexForBackfaceVisibility(LayerType* layer, |
const TransformTree& tree) { |
@@ -512,6 +545,30 @@ static gfx::Rect LayerDrawableContentRect( |
return layer_bounds_in_target_space; |
} |
+static void SetSurfaceIsClipped(const ClipTree& clip_tree, |
+ RenderSurfaceImpl* render_surface) { |
+ bool is_clipped; |
+ if (render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId) { |
+ // Root render surface is always clipped. |
+ is_clipped = true; |
+ } else if (render_surface->has_contributing_layer_that_escapes_clip()) { |
+ // We cannot clip a surface that has a contribuitng layer which escapes the |
+ // clip. |
+ is_clipped = false; |
+ } else if (render_surface->ClipTreeIndex() == |
+ render_surface->render_target()->ClipTreeIndex()) { |
+ // There is no clip between between the render surface and its target, so |
+ // the surface need not be clipped. |
+ is_clipped = false; |
weiliangc
2017/03/30 19:02:17
I also think it's ok to clip here too. It will jus
jaydasika
2017/04/03 19:06:31
Acknowledged. Will do in a follow-up.
|
+ } else { |
+ // If the clips between the render surface and its target only expand the |
+ // clips and do not apply any new clip, we need not clip the render surface. |
+ const ClipNode* clip_node = clip_tree.Node(render_surface->ClipTreeIndex()); |
+ is_clipped = clip_node->clip_type != ClipNode::ClipType::EXPANDS_CLIP; |
weiliangc
2017/03/30 19:02:17
I think even with expansion this should still be i
jaydasika
2017/04/03 19:06:31
For this to happen, we need the other change (that
weiliangc
2017/04/04 20:56:38
Yeah sounds good to have a follow up.
|
+ } |
+ render_surface->SetIsClipped(is_clipped); |
+} |
+ |
static void SetSurfaceDrawOpacity(const EffectTree& tree, |
RenderSurfaceImpl* render_surface) { |
// Draw opacity of a surface is the product of opacities between the surface |
@@ -926,13 +983,23 @@ void ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, |
transform_node->to_screen_is_potentially_animated; |
} |
- // Compute draw opacities |
+ // Compute effects and determine if render surfaces have contributing layers |
+ // that escape clip. |
for (LayerImpl* layer : *layer_list) { |
layer->draw_properties().opacity = |
LayerDrawOpacity(layer, property_trees->effect_tree); |
+ RenderSurfaceImpl* render_target = layer->render_target(); |
+ int lca_clip_id = LowestCommonAncestor(layer->clip_tree_index(), |
+ render_target->ClipTreeIndex(), |
+ &property_trees->clip_tree); |
+ if (lca_clip_id != render_target->ClipTreeIndex()) { |
+ SetHasContributingLayerThatEscapesClip(lca_clip_id, |
+ render_target->EffectTreeIndex(), |
+ &property_trees->effect_tree); |
+ } |
} |
- // Compute clips and viisble rects |
+ // Compute clips and visible rects |
for (LayerImpl* layer : *layer_list) { |
ConditionalClip clip = LayerClipRect(property_trees, layer); |
// is_clipped should be set before visible rect computation as it is used |
@@ -967,19 +1034,7 @@ void ComputeMaskDrawProperties(LayerImpl* mask_layer, |
void ComputeSurfaceDrawProperties(PropertyTrees* property_trees, |
RenderSurfaceImpl* render_surface, |
const bool use_layer_lists) { |
- const EffectNode* effect_node = |
- property_trees->effect_tree.Node(render_surface->EffectTreeIndex()); |
- if (use_layer_lists) { |
- // TODO(crbug.com/702010) : Calculate surface's is_clipped value outside |
- // cc property tree building. This is a temporary hack to make SPv2 layout |
- // tests pass. |
- bool is_clipped = effect_node->id == EffectTree::kContentsRootNodeId || |
- (render_surface->render_target()->ClipTreeIndex() != |
- render_surface->ClipTreeIndex()); |
- render_surface->SetIsClipped(is_clipped); |
- } else { |
- render_surface->SetIsClipped(effect_node->surface_is_clipped); |
- } |
+ SetSurfaceIsClipped(property_trees->clip_tree, render_surface); |
SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface); |
SetSurfaceDrawTransform(property_trees, render_surface); |
render_surface->SetScreenSpaceTransform( |