Chromium Code Reviews| 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..923bf90589fd38582dd81a4648d9e2928104da9a 100644 |
| --- a/cc/trees/draw_property_utils.cc |
| +++ b/cc/trees/draw_property_utils.cc |
| @@ -92,6 +92,113 @@ bool ComputeClipRectInTargetSpace(const LayerType* layer, |
| return true; |
| } |
| +struct ClipRect { |
| + bool is_clipped; |
| + gfx::RectF clip_rect; |
| +}; |
| + |
| +static ClipRect 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, ¤t_to_target)) |
| + return ClipRect{false, gfx::RectF()}; |
|
ajuma
2016/06/14 15:09:53
To make the bools here and below more readable (th
weiliangc
2016/06/15 12:27:57
Renamed ClipRect to ConditionalClip, and add comme
|
| + if (current_transform_id > target_transform_id) |
| + return ClipRect{true, MathUtil::MapClippedRect(current_to_target, rect)}; |
| + else |
|
ajuma
2016/06/14 15:09:53
Nit: no need for 'else' after return
weiliangc
2016/06/15 12:27:57
Done.
|
| + return ClipRect{true, |
| + MathUtil::ProjectClippedRect(current_to_target, rect)}; |
| +} |
| + |
| +static ClipRect 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); |
| + } else { |
|
ajuma
2016/06/14 15:09:53
Here too, no need to use 'else' here since there's
weiliangc
2016/06/15 12:27:57
Done.
|
| + 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 ClipRect{true, current_clip}; |
| + } |
| +} |
| + |
| +static ClipRect 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) { |
| + 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 ClipRect{false, gfx::RectF()}; |
| + |
| + ClipRect 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; |
| + } |
| + ClipRect current_clip = |
| + ComputeCurrentClip(clip_node, transform_tree, target_transform_id); |
| + |
| + if (!current_clip.is_clipped) |
| + return ClipRect{false, gfx::RectF()}; |
| + |
| + is_clipped |= current_clip.is_clipped; |
| + accumulated_clip = |
| + gfx::IntersectRects(accumulated_clip, current_clip.clip_rect); |
| + } |
| + |
| + return ClipRect{is_clipped, |
| + accumulated_clip.IsEmpty() ? gfx::RectF() : accumulated_clip}; |
| +} |
| + |
| template <typename LayerType> |
| void CalculateClipRects( |
| const typename LayerType::LayerListType& visible_layer_list, |
| @@ -184,11 +291,35 @@ 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. |
| + ClipRect 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); |
| + ClipRect 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) { |
|
ajuma
2016/06/14 15:09:53
Since accumulated_clip_rect.is_clipped is true her
weiliangc
2016/06/15 12:27:57
Yes I think so.
|
| + 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 +809,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, |
| - ¤t_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 +827,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 = |
| + ClipRect 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 +859,12 @@ static void ComputeLayerClipRect(const PropertyTrees* property_trees, |
| target_node = effect_tree->Node(1); |
| } |
| - gfx::RectF accumulated_clip = |
| + ClipRect 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) || |