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

Unified Diff: cc/trees/draw_property_utils.cc

Issue 1800923002: cc: Directly use property trees to calculate clip rect (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add setting to only calculate and verify in cc_unittest Created 4 years, 9 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
Index: cc/trees/draw_property_utils.cc
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index d31fb067ea8273269f0c0d71aee57a0c4f8e69b9..2d6577bdcb28ee94c08c63356b47410db2d04302 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);
@@ -454,22 +453,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) {
@@ -486,7 +490,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
@@ -651,6 +656,145 @@ 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;
+ 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) {
+ DCHECK(accumulated_clip == clip_node->data.clip_in_target_space);
ajuma 2016/03/19 00:29:41 The original patch also had logic to compare the e
weiliangc 2016/05/11 23:08:08 Added the logic back. Now the verification on rend
+ }
+ 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 ||
ajuma 2016/03/19 00:29:41 Since this is currently only called when non_root_
weiliangc 2016/05/11 23:08:08 Added computation and verification for resourceles
+ clip_tree->Node(layer->clip_tree_index())->data.layers_are_clipped) {
+ DCHECK(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,
@@ -736,6 +880,15 @@ void ComputeVisibleRects(Layer* root_layer,
&visible_layer_list);
}
+void VerifyClipTreeCalculations(const LayerImplList& layer_list,
+ PropertyTrees* property_trees) {
+ if (property_trees->non_root_surfaces_enabled) {
ajuma 2016/03/19 00:29:41 Just to make sure I understand, the reason this do
weiliangc 2016/05/11 23:08:08 Yes. I have added a hack to the computation (aka e
+ ComputeClipsWithEffectTree(property_trees);
+ for (auto layer : layer_list)
+ ComputeLayerClipRect(property_trees, layer);
+ }
+}
+
void ComputeVisibleRects(LayerImpl* root_layer,
PropertyTrees* property_trees,
bool can_render_to_separate_surface,
@@ -802,6 +955,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)
ajuma 2016/03/19 00:29:41 Since we now have this DCHECK, the 'if' below can
weiliangc 2016/05/11 23:08:08 Done.
+ << "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)

Powered by Google App Engine
This is Rietveld 408576698