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 38492034fbcf2188876566de70cb80cc055b96ae..cf4bb68f178eb9d4438f0757931d0f9868c0c85c 100644 |
| --- a/cc/trees/draw_property_utils.cc |
| +++ b/cc/trees/draw_property_utils.cc |
| @@ -133,7 +133,6 @@ void CalculateVisibleRects(const std::vector<LayerType*>& visible_layer_list, |
| 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); |
| @@ -452,22 +451,27 @@ void FindLayersThatNeedUpdates( |
| template <typename LayerType> |
| void UpdateRenderSurfacesWithEffectTreeInternal(EffectTree* effect_tree, |
| - LayerType* layer) { |
| + LayerType* layer, |
| + int target_id) { |
| EffectNode* node = effect_tree->Node(layer->effect_tree_index()); |
| + if (node->owner_id == layer->id()) |
| + node->data.target_id = target_id; |
| - if (node->owner_id == layer->id() && node->data.has_render_surface) |
| + if (node->owner_id == layer->id() && node->data.has_render_surface) { |
| layer->SetHasRenderSurface(true); |
| - else |
| + target_id = node->id; |
| + } else { |
| layer->SetHasRenderSurface(false); |
| + } |
| for (size_t i = 0; i < layer->children().size(); ++i) { |
| - UpdateRenderSurfacesWithEffectTreeInternal<LayerType>(effect_tree, |
| - layer->child_at(i)); |
| + UpdateRenderSurfacesWithEffectTreeInternal<LayerType>( |
| + effect_tree, layer->child_at(i), target_id); |
| } |
| } |
| void UpdateRenderSurfacesWithEffectTree(EffectTree* effect_tree, Layer* layer) { |
| - UpdateRenderSurfacesWithEffectTreeInternal<Layer>(effect_tree, layer); |
| + UpdateRenderSurfacesWithEffectTreeInternal<Layer>(effect_tree, layer, 0); |
| } |
| void UpdateRenderSurfacesNonRootSurfacesDisabled(LayerImpl* layer) { |
| @@ -484,7 +488,8 @@ void UpdateRenderSurfacesWithEffectTree(EffectTree* effect_tree, |
| if (!non_root_surfaces_enabled) |
| UpdateRenderSurfacesNonRootSurfacesDisabled(layer); |
| else |
| - UpdateRenderSurfacesWithEffectTreeInternal<LayerImpl>(effect_tree, layer); |
| + UpdateRenderSurfacesWithEffectTreeInternal<LayerImpl>(effect_tree, layer, |
| + 0); |
| } |
| } // namespace |
| @@ -649,6 +654,147 @@ 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; |
| + } |
| + NOTREACHED(); |
| + return gfx::RectF(); |
| +} |
| + |
| +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; |
| + if (local_clip_id == target_node->data.clip_id) |
|
ajuma
2016/03/15 14:59:56
This confused me for a bit since it seemed like th
weiliangc
2016/03/15 15:29:36
This is a special case I started with, but is no l
|
| + return ComputeCurrentClip(clip_tree.Node(local_clip_id), transform_tree, |
| + target_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->id != 1 && !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 && clip_node->id != 1) |
| + 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 && clip_node->id != 1) { |
|
ajuma
2016/03/15 14:59:56
Do we still need this special handling for the vie
weiliangc
2016/03/15 15:29:36
No, I realized viewport clip always applies local
|
| + continue; |
| + } |
| + gfx::RectF current_clip = |
| + ComputeCurrentClip(clip_node, transform_tree, target_transform_id); |
| + accumulated_clip = gfx::IntersectRects(accumulated_clip, current_clip); |
| + } |
| + |
| + return accumulated_clip; |
| +} |
| + |
| +static void ComputeClipsWithEffectTree(PropertyTrees* property_trees) { |
| + EffectTree* effect_tree = &property_trees->effect_tree; |
| + const ClipTree* clip_tree = &property_trees->clip_tree; |
| + const TransformTree* transform_tree = &property_trees->transform_tree; |
| + EffectNode* root_effect_node = effect_tree->Node(1); |
| + root_effect_node->data.clip_rect = gfx::ToEnclosingRect( |
| + clip_tree->Node(root_effect_node->data.clip_id)->data.clip); |
| + for (int i = 2; i < static_cast<int>(effect_tree->size()); ++i) { |
| + EffectNode* effect_node = effect_tree->Node(i); |
| + const EffectNode* target_node = |
| + effect_tree->Node(effect_node->data.target_id); |
| + gfx::RectF accumulated_clip = |
| + ComputeAccumulatedClip(*clip_tree, effect_node->data.clip_id, |
| + *effect_tree, target_node->id, *transform_tree); |
| + |
| + const ClipNode* clip_node = clip_tree->Node(effect_node->data.clip_id); |
| + if (!clip_node->data.applies_local_clip && |
| + !effect_node->data.has_unclipped_descendants) { |
| + CHECK(accumulated_clip == clip_node->data.clip_in_target_space); |
| + } |
| + effect_node->data.clip_rect = gfx::ToEnclosingRect(accumulated_clip); |
| + } |
| +} |
| + |
| +static void ComputeLayerClipRect(const PropertyTrees* property_trees, |
| + const LayerImpl* layer) { |
| + const EffectTree* effect_tree = &property_trees->effect_tree; |
| + const ClipTree* clip_tree = &property_trees->clip_tree; |
| + const TransformTree* transform_tree = &property_trees->transform_tree; |
| + const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index()); |
| + const EffectNode* target_node = |
| + effect_node->data.has_render_surface |
| + ? effect_node |
| + : effect_tree->Node(effect_node->data.target_id); |
| + |
| + gfx::RectF accumulated_clip = |
| + ComputeAccumulatedClip(*clip_tree, layer->clip_tree_index(), *effect_tree, |
| + target_node->id, *transform_tree); |
| + if (!property_trees->non_root_surfaces_enabled || |
| + clip_tree->Node(layer->clip_tree_index())->data.layers_are_clipped) { |
| + CHECK(layer->clip_rect() == gfx::ToEnclosingRect(accumulated_clip)) |
| + << " layer: " << layer->id() << " clip id: " << layer->clip_tree_index() |
| + << " layer clip: " << layer->clip_rect().ToString() << " v.s. " |
| + << gfx::ToEnclosingRect(accumulated_clip).ToString() |
| + << " and clip node clip: " |
| + << gfx::ToEnclosingRect(clip_tree->Node(layer->clip_tree_index()) |
| + ->data.clip_in_target_space) |
| + .ToString(); |
| + } |
| +} |
| + |
| template <typename LayerType> |
| static void ComputeVisibleRectsInternal( |
| LayerType* root_layer, |
| @@ -742,10 +888,15 @@ void ComputeVisibleRects(LayerImpl* root_layer, |
| &property_trees->effect_tree, can_render_to_separate_surface, root_layer); |
| if (can_render_to_separate_surface) |
| ValidateRenderSurfaces(root_layer); |
| + if (can_render_to_separate_surface) |
| + ComputeClipsWithEffectTree(property_trees); |
| LayerImplList update_layer_list; |
| ComputeVisibleRectsInternal(root_layer, property_trees, |
| can_render_to_separate_surface, |
| &update_layer_list, visible_layer_list); |
| + if (can_render_to_separate_surface) |
| + for (auto layer : *visible_layer_list) |
| + ComputeLayerClipRect(property_trees, layer); |
| } |
| template <typename LayerType> |
| @@ -800,6 +951,8 @@ static void SetSurfaceDrawTransform(const TransformTree& tree, |
| static void SetSurfaceIsClipped(const ClipNode* clip_node, |
| RenderSurfaceImpl* render_surface) { |
| + DCHECK(render_surface->OwningLayerId() == clip_node->owner_id) |
| + << "we now create clip node for every render surface"; |
| // If the render surface's owning layer doesn't form a clip node, it is not |
| // clipped. |
| if (render_surface->OwningLayerId() != clip_node->owner_id) |
| @@ -1040,6 +1193,18 @@ void ComputeSurfaceDrawProperties(const PropertyTrees* property_trees, |
| SetSurfaceClipRect(property_trees->clip_tree.parent(clip_node), |
| property_trees->transform_tree, render_surface); |
| + |
| + if (!property_trees->non_root_surfaces_enabled) |
| + return; |
| + |
| + if (render_surface->is_clipped()) { |
| + const EffectNode* effect_node = |
| + property_trees->effect_tree.Node(render_surface->EffectTreeIndex()); |
| + DCHECK(effect_node->data.has_render_surface); |
| + CHECK(effect_node->data.clip_rect == render_surface->clip_rect()) |
| + << "effect tree's: " << effect_node->data.clip_rect.ToString() |
| + << " clip: " << render_surface->clip_rect().ToString(); |
| + } |
| } |
| template <typename LayerType> |