| Index: cc/trees/draw_property_utils.cc
|
| diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
|
| index 7a216f0e10445e920cfc9068653f7ef00efe7439..84b3e8f4bece627682b93d9fb8ac024bb609e746 100644
|
| --- a/cc/trees/draw_property_utils.cc
|
| +++ b/cc/trees/draw_property_utils.cc
|
| @@ -137,6 +137,29 @@ static ConditionalClip ComputeTargetRectInLocalSpace(
|
| MathUtil::ProjectClippedRect(target_to_local, rect)};
|
| }
|
|
|
| +static ConditionalClip ConvertRectBetweenSurfaceSpaces(
|
| + gfx::RectF rect,
|
| + const PropertyTrees* property_trees,
|
| + int source_transform_id,
|
| + int source_effect_id,
|
| + int dest_transform_id,
|
| + int dest_effect_id) {
|
| + gfx::Transform source_to_dest;
|
| + bool success = property_trees->GetToTarget(source_transform_id,
|
| + dest_effect_id, &source_to_dest);
|
| + if (!success)
|
| + return ConditionalClip{false, gfx::RectF()};
|
| + const EffectTree& effect_tree = property_trees->effect_tree;
|
| + const EffectNode* source_effect_node = effect_tree.Node(source_effect_id);
|
| + ConcatInverseSurfaceContentsScale(source_effect_node, &source_to_dest);
|
| + if (source_transform_id > dest_transform_id) {
|
| + return ConditionalClip{true, // is_clipped
|
| + MathUtil::MapClippedRect(source_to_dest, rect)};
|
| + }
|
| + return ConditionalClip{true, // is_clipped
|
| + MathUtil::ProjectClippedRect(source_to_dest, rect)};
|
| +}
|
| +
|
| static ConditionalClip ComputeLocalRectInTargetSpace(
|
| gfx::RectF rect,
|
| const PropertyTrees* property_trees,
|
| @@ -178,9 +201,71 @@ static ConditionalClip ComputeCurrentClip(const ClipNode* clip_node,
|
| return ConditionalClip{true /* is_clipped */, current_clip};
|
| }
|
|
|
| +static bool ApplyClipNodeToAccumulatedClip(const PropertyTrees* property_trees,
|
| + bool include_expanding_clips,
|
| + int target_id,
|
| + int target_transform_id,
|
| + const ClipNode* clip_node,
|
| + gfx::RectF* accumulated_clip) {
|
| + switch (clip_node->clip_type) {
|
| + case ClipNode::ClipType::APPLIES_LOCAL_CLIP: {
|
| + ConditionalClip current_clip = ComputeCurrentClip(
|
| + clip_node, property_trees, target_transform_id, target_id);
|
| +
|
| + // If transform is not invertible, no clip will be applied.
|
| + if (!current_clip.is_clipped)
|
| + return false;
|
| +
|
| + *accumulated_clip =
|
| + gfx::IntersectRects(*accumulated_clip, current_clip.clip_rect);
|
| + return true;
|
| + }
|
| + case ClipNode::ClipType::EXPANDS_CLIP: {
|
| + if (!include_expanding_clips)
|
| + return true;
|
| +
|
| + // Bring the accumulated clip to the space of the expanding effect.
|
| + const EffectNode* expanding_effect_node =
|
| + property_trees->effect_tree.Node(
|
| + clip_node->clip_expander->target_effect_id());
|
| + ConditionalClip accumulated_clip_in_expanding_space =
|
| + ConvertRectBetweenSurfaceSpaces(
|
| + *accumulated_clip, property_trees, target_transform_id, target_id,
|
| + expanding_effect_node->transform_id, expanding_effect_node->id);
|
| + // If transform is not invertible, no clip will be applied.
|
| + if (!accumulated_clip_in_expanding_space.is_clipped)
|
| + return false;
|
| +
|
| + // Do the expansion.
|
| + gfx::RectF expanded_clip_in_expanding_space =
|
| + gfx::RectF(clip_node->clip_expander->MapRectReverse(
|
| + gfx::ToEnclosingRect(
|
| + accumulated_clip_in_expanding_space.clip_rect),
|
| + property_trees));
|
| +
|
| + // Put the expanded clip back into the original target space.
|
| + ConditionalClip expanded_clip_in_target_space =
|
| + ConvertRectBetweenSurfaceSpaces(
|
| + expanded_clip_in_expanding_space, property_trees,
|
| + expanding_effect_node->transform_id, expanding_effect_node->id,
|
| + target_transform_id, target_id);
|
| + // If transform is not invertible, no clip will be applied.
|
| + if (!expanded_clip_in_target_space.is_clipped)
|
| + return false;
|
| + *accumulated_clip = expanded_clip_in_target_space.clip_rect;
|
| + return true;
|
| + }
|
| + case ClipNode::ClipType::NONE:
|
| + return true;
|
| + }
|
| + NOTREACHED();
|
| + return true;
|
| +}
|
| +
|
| static ConditionalClip ComputeAccumulatedClip(
|
| const PropertyTrees* property_trees,
|
| bool include_viewport_clip,
|
| + bool include_expanding_clips,
|
| int local_clip_id,
|
| int target_id) {
|
| DCHECK(!include_viewport_clip ||
|
| @@ -191,7 +276,6 @@ static ConditionalClip ComputeAccumulatedClip(
|
| 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->transform_id;
|
| - bool is_clipped = false;
|
|
|
| // Collect all the clips that need to be accumulated.
|
| std::stack<const ClipNode*> parent_chain;
|
| @@ -220,43 +304,42 @@ static ConditionalClip ComputeAccumulatedClip(
|
| parent_chain.pop();
|
| }
|
|
|
| - // TODO(weiliangc): If we don't create clip for render surface, we don't need
|
| - // to check applies_local_clip.
|
| + // Find the first clip in the chain that we need to apply.
|
| while (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP &&
|
| parent_chain.size() > 0) {
|
| clip_node = parent_chain.top();
|
| parent_chain.pop();
|
| }
|
|
|
| - if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP)
|
| + if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP) {
|
| // No clip node applying clip in between.
|
| return ConditionalClip{false, gfx::RectF()};
|
| + }
|
|
|
| ConditionalClip current_clip = ComputeCurrentClip(
|
| clip_node, property_trees, target_transform_id, target_id);
|
| - is_clipped = current_clip.is_clipped;
|
| +
|
| + // If transform is not invertible, no clip will be applied.
|
| + if (!current_clip.is_clipped)
|
| + return ConditionalClip{false, gfx::RectF()};
|
| gfx::RectF accumulated_clip = current_clip.clip_rect;
|
|
|
| while (parent_chain.size() > 0) {
|
| clip_node = parent_chain.top();
|
| parent_chain.pop();
|
| - if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP) {
|
| - continue;
|
| - }
|
| - ConditionalClip current_clip = ComputeCurrentClip(
|
| - clip_node, property_trees, target_transform_id, target_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);
|
| + bool success = ApplyClipNodeToAccumulatedClip(
|
| + property_trees, include_expanding_clips, target_id, target_transform_id,
|
| + clip_node, &accumulated_clip);
|
| +
|
| + // Failure to apply the clip means we encountered an uninvertible transform,
|
| + // so no clip will be applied.
|
| + if (!success)
|
| + return ConditionalClip{false /* is_clipped */, gfx::RectF()};
|
| }
|
|
|
| - return ConditionalClip{
|
| - is_clipped, accumulated_clip.IsEmpty() ? gfx::RectF() : accumulated_clip};
|
| + return ConditionalClip{true /* is_clipped */, accumulated_clip.IsEmpty()
|
| + ? gfx::RectF()
|
| + : accumulated_clip};
|
| }
|
|
|
| static gfx::RectF ComputeAccumulatedClipInRootSpaceForVisibleRect(
|
| @@ -264,8 +347,10 @@ static gfx::RectF ComputeAccumulatedClipInRootSpaceForVisibleRect(
|
| int local_clip_id) {
|
| const int root_effect_id = EffectTree::kContentsRootNodeId;
|
| bool include_viewport_clip = true;
|
| + bool include_expanding_clips = true;
|
| ConditionalClip accumulated_clip = ComputeAccumulatedClip(
|
| - property_trees, include_viewport_clip, local_clip_id, root_effect_id);
|
| + property_trees, include_viewport_clip, include_expanding_clips,
|
| + local_clip_id, root_effect_id);
|
| DCHECK(accumulated_clip.is_clipped);
|
| return accumulated_clip.clip_rect;
|
| }
|
| @@ -338,9 +423,10 @@ void CalculateVisibleRects(const LayerImplList& visible_layer_list,
|
| if (effect_ancestor_with_copy_request > 1) {
|
| // Non root copy request.
|
| bool include_viewport_clip = false;
|
| + bool include_expanding_clips = true;
|
| ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip(
|
| - property_trees, include_viewport_clip, layer->clip_tree_index(),
|
| - effect_ancestor_with_copy_request);
|
| + property_trees, include_viewport_clip, include_expanding_clips,
|
| + layer->clip_tree_index(), effect_ancestor_with_copy_request);
|
| if (!accumulated_clip_rect.is_clipped) {
|
| layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
|
| continue;
|
| @@ -792,6 +878,12 @@ void ComputeClips(PropertyTrees* property_trees,
|
| continue;
|
| parent_combined_clip_in_target_space = MathUtil::ProjectClippedRect(
|
| parent_to_current, parent_clip_node->combined_clip_in_target_space);
|
| + if (clip_node->clip_type == ClipNode::ClipType::EXPANDS_CLIP) {
|
| + parent_combined_clip_in_target_space =
|
| + gfx::RectF(clip_node->clip_expander->MapRectReverse(
|
| + gfx::ToEnclosingRect(parent_combined_clip_in_target_space),
|
| + property_trees));
|
| + }
|
| parent_clip_in_target_space = MathUtil::ProjectClippedRect(
|
| parent_to_current, parent_clip_node->clip_in_target_space);
|
| }
|
| @@ -930,9 +1022,10 @@ static void ComputeClipsWithEffectTree(PropertyTrees* property_trees) {
|
| EffectNode* effect_node = effect_tree->Node(i);
|
| const EffectNode* target_node = effect_tree->Node(effect_node->target_id);
|
| bool include_viewport_clip = false;
|
| - ConditionalClip accumulated_clip_rect =
|
| - ComputeAccumulatedClip(property_trees, include_viewport_clip,
|
| - effect_node->clip_id, target_node->id);
|
| + bool include_expanding_clips = false;
|
| + ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip(
|
| + property_trees, include_viewport_clip, include_expanding_clips,
|
| + effect_node->clip_id, target_node->id);
|
| gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect;
|
| const RenderSurfaceImpl* render_surface = effect_node->render_surface;
|
| if (render_surface && render_surface->is_clipped()) {
|
| @@ -963,9 +1056,10 @@ static void ComputeLayerClipRect(const PropertyTrees* property_trees,
|
| }
|
|
|
| bool include_viewport_clip = false;
|
| - ConditionalClip accumulated_clip_rect =
|
| - ComputeAccumulatedClip(property_trees, include_viewport_clip,
|
| - layer->clip_tree_index(), target_node->id);
|
| + bool include_expanding_clips = false;
|
| + ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip(
|
| + property_trees, include_viewport_clip, include_expanding_clips,
|
| + layer->clip_tree_index(), target_node->id);
|
|
|
| bool is_clipped_from_clip_tree =
|
| property_trees->non_root_surfaces_enabled
|
| @@ -1098,9 +1192,10 @@ gfx::Rect ComputeLayerVisibleRectDynamic(const PropertyTrees* property_trees,
|
| gfx::RectF accumulated_clip_in_root_space;
|
| if (non_root_copy_request) {
|
| bool include_viewport_clip = false;
|
| + bool include_expanding_clips = true;
|
| ConditionalClip accumulated_clip = ComputeAccumulatedClip(
|
| - property_trees, include_viewport_clip, layer->clip_tree_index(),
|
| - effect_ancestor_with_copy_request);
|
| + property_trees, include_viewport_clip, include_expanding_clips,
|
| + layer->clip_tree_index(), effect_ancestor_with_copy_request);
|
| if (!accumulated_clip.is_clipped)
|
| return layer_content_rect;
|
| accumulated_clip_in_root_space = accumulated_clip.clip_rect;
|
|
|