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

Unified Diff: cc/trees/property_tree_builder.cc

Issue 687873004: Introduce Property Trees (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@wip-awoloszyn2
Patch Set: . Created 6 years 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/property_tree_builder.cc
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b1517063bdf973346fc6be331b39656a7d02003e
--- /dev/null
+++ b/cc/trees/property_tree_builder.cc
@@ -0,0 +1,306 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/property_tree_builder.h"
+
+#include <map>
+#include <set>
+
+#include "cc/base/math_util.h"
+#include "cc/layers/layer.h"
+#include "cc/trees/layer_tree_host.h"
+#include "ui/gfx/point_f.h"
+
+namespace cc {
+
+class LayerTreeHost;
+
+namespace {
+
+struct DataForRecursion {
+ TransformTree* transform_tree;
+ ClipTree* clip_tree;
+ Layer* transform_tree_parent;
+ Layer* transform_fixed_parent;
+ Layer* render_target;
+ int clip_tree_parent;
+ gfx::Vector2dF offset_to_transform_tree_parent;
+ gfx::Vector2dF offset_to_transform_fixed_parent;
+ const Layer* page_scale_layer;
+ float page_scale_factor;
+ float device_scale_factor;
+};
+
+static Layer* GetTransformParent(const DataForRecursion& data, Layer* layer) {
+ return layer->position_constraint().is_fixed_position()
+ ? data.transform_fixed_parent
+ : data.transform_tree_parent;
+}
+
+static ClipNode* GetClipParent(const DataForRecursion& data, Layer* layer) {
+ const bool inherits_clip = !layer->parent() || !layer->clip_parent();
+ const int id = inherits_clip ? data.clip_tree_parent
+ : layer->clip_parent()->clip_tree_index();
+ return data.clip_tree->Node(id);
+}
+
+static bool RequiresClipNode(Layer* layer,
+ bool axis_aligned_with_respect_to_parent) {
+ const bool render_surface_applies_non_axis_aligned_clip =
+ layer->render_surface() && !axis_aligned_with_respect_to_parent &&
+ layer->is_clipped();
+ const bool render_surface_may_grow_due_to_clip_children =
+ layer->render_surface() && layer->num_unclipped_descendants() > 0;
+
+ return !layer->parent() || layer->masks_to_bounds() || layer->mask_layer() ||
+ render_surface_applies_non_axis_aligned_clip ||
+ render_surface_may_grow_due_to_clip_children;
+}
+
+void AddClipNodeIfNeeded(const DataForRecursion& data_from_ancestor,
+ Layer* layer,
+ DataForRecursion* data_for_children) {
+ ClipNode* parent = GetClipParent(data_from_ancestor, layer);
+ int parent_id = parent->id;
+
+ const bool axis_aligned_with_respect_to_parent = Are2DAxisAligned(
+ *data_from_ancestor.transform_tree, layer->transform_tree_index(),
+ parent->data.transform_id);
+
+ // TODO(vollick): once Andrew refactors the surface determinations out of
enne (OOO) 2014/12/10 23:45:59 What's the status on this work?
Ian Vollick 2014/12/12 03:01:47 Andrew's got a patch up for review. Ball's in Dana
+ // CDP, the the layer->render_surface() check will be invalid.
+ const bool has_unclipped_surface =
+ layer->render_surface() &&
+ layer->render_surface()->clip_rect().IsEmpty() &&
+ layer->num_unclipped_descendants() == 0;
+
+ if (has_unclipped_surface)
+ parent_id = 0;
+
+ if (!RequiresClipNode(layer, axis_aligned_with_respect_to_parent)) {
+ // Unclipped surfaces reset the clip rect.
+ data_for_children->clip_tree_parent = parent_id;
+ } else if (layer->parent()) {
+ // Note the root clip gets handled elsewhere.
+ Layer* transform_parent = GetTransformParent(*data_for_children, layer);
+ ClipNode node;
+ node.data.clip = gfx::RectF(
+ gfx::PointF() + layer->offset_to_transform_parent(), layer->bounds());
+ node.data.transform_id = transform_parent->transform_tree_index();
+ node.data.target_id =
+ data_from_ancestor.render_target->transform_tree_index();
+
+ data_for_children->clip_tree_parent =
+ data_for_children->clip_tree->Insert(node, parent_id);
+ }
+
+ layer->set_clip_tree_index(
+ has_unclipped_surface ? 0 : data_for_children->clip_tree_parent);
+
+ // TODO(awoloszyn): Right now when we hit a node with a replica, we reset the
+ // clip for all children since we may need to draw. We need to figure out a
+ // better way, since we will need both the clipped and unclipped versions.
+}
+
+void AddTransformNodeIfNeeded(const DataForRecursion& data_from_ancestor,
+ Layer* layer,
+ DataForRecursion* data_for_children) {
+ const bool is_root = !layer->parent();
+ const bool is_page_scale_application_layer =
+ layer->parent() && layer->parent() == data_from_ancestor.page_scale_layer;
+ const bool is_scrollable = layer->scrollable();
+ const bool is_fixed = layer->position_constraint().is_fixed_position();
+
+ const bool has_significant_transform =
+ !layer->transform().IsIdentityOr2DTranslation();
+
+ const bool has_animated_transform =
+ layer->layer_animation_controller()->IsAnimatingProperty(
+ Animation::Transform);
+
+ const bool has_transform_origin = layer->transform_origin() != gfx::Point3F();
+
+ const bool has_surface = layer->render_surface();
+
+ const bool flattening_change = layer->parent() &&
+ layer->should_flatten_transform() &&
+ !layer->parent()->should_flatten_transform();
+
+ bool requires_node = is_root || is_scrollable || is_fixed ||
+ has_significant_transform || has_animated_transform ||
+ is_page_scale_application_layer || flattening_change ||
+ has_transform_origin || has_surface;
+
+ Layer* transform_parent = GetTransformParent(data_from_ancestor, layer);
+
+ // May be non-zero if layer is fixed or has a scroll parent.
+ gfx::Vector2dF parent_offset;
+ if (transform_parent) {
+ // TODO(vollick): This is to mimic bugs in current CDP. Need to log a bug
enne (OOO) 2014/12/10 23:45:59 !!!
Ian Vollick 2014/12/12 03:01:47 Yeah :( I've logged the bug and referenced it in t
+ // about this and reference it here.
+ if (!is_fixed)
+ parent_offset = transform_parent->offset_to_transform_parent();
+
+ gfx::Transform to_parent;
+ Layer* source = data_from_ancestor.transform_tree_parent;
+ if (layer->scroll_parent()) {
+ source = layer->parent();
+ parent_offset += layer->parent()->offset_to_transform_parent();
+ }
+
+ ComputeTransform(*data_from_ancestor.transform_tree,
+ source->transform_tree_index(),
+ transform_parent->transform_tree_index(), &to_parent);
+
+ parent_offset += to_parent.To2dTranslation();
+ }
+
+ if (layer->IsContainerForFixedPositionLayers() || is_root)
+ data_for_children->transform_fixed_parent = layer;
+ data_for_children->transform_tree_parent = layer;
+
+ if (!requires_node) {
+ gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() +
+ layer->transform().To2dTranslation();
+ layer->set_offset_to_transform_parent(parent_offset + local_offset);
+ layer->set_transform_tree_index(transform_parent->transform_tree_index());
+ return;
+ }
+
+ if (!is_root) {
+ data_for_children->transform_tree->Insert(
+ TransformNode(), transform_parent->transform_tree_index());
+ }
+
+ TransformNode* node = data_for_children->transform_tree->back();
+
+ node->data.flattens = layer->should_flatten_transform();
+ node->data.target_id =
+ data_from_ancestor.render_target->transform_tree_index();
+
+ gfx::Transform transform;
+ float device_and_page_scale_factors = 1.0f;
+ if (is_root)
+ device_and_page_scale_factors = data_from_ancestor.device_scale_factor;
+ if (is_page_scale_application_layer)
+ device_and_page_scale_factors *= data_from_ancestor.page_scale_factor;
+
+ transform.Scale(device_and_page_scale_factors, device_and_page_scale_factors);
+
+ // NB: We've accounted for the scroll offset here but we haven't taken into
+ // account snapping to screen space pixels (since we haven't computed any
+ // screen space transforms). For the purposes of computing rects we need to
+ // record, this should be fine (the visible rects we compute may be slightly
+ // different than what we'd compute with snapping, but since we significantly
+ // expand the visible rect when determining what to record, the slight
+ // difference should be inconsequential).
+ gfx::Vector2dF position = layer->position().OffsetFromOrigin();
+ if (!layer->scroll_parent()) {
+ position -= gfx::Vector2dF(layer->TotalScrollOffset().x(),
+ layer->TotalScrollOffset().y());
+ }
+
+ position += parent_offset;
+
+ transform.Translate3d(position.x() + layer->transform_origin().x(),
+ position.y() + layer->transform_origin().y(),
+ layer->transform_origin().z());
+ transform.PreconcatTransform(layer->transform());
+ transform.Translate3d(-layer->transform_origin().x(),
+ -layer->transform_origin().y(),
+ -layer->transform_origin().z());
+
+ node->data.to_parent = transform;
+ node->data.is_invertible = transform.GetInverse(&node->data.from_parent);
+
+ UpdateScreenSpaceTransform(data_from_ancestor.transform_tree, node->id);
+
+ layer->set_offset_to_transform_parent(gfx::Vector2dF());
+ layer->set_transform_tree_index(node->id);
+}
+
+void BuildPropertyTreesInternal(Layer* layer,
+ const DataForRecursion& data_from_parent) {
+ DataForRecursion data_for_children(data_from_parent);
+ if (layer->render_surface())
+ data_for_children.render_target = layer;
+
+ AddTransformNodeIfNeeded(data_from_parent, layer, &data_for_children);
+ AddClipNodeIfNeeded(data_from_parent, layer, &data_for_children);
+
+ for (size_t i = 0; i < layer->children().size(); ++i) {
+ if (!layer->children()[i]->scroll_parent())
+ BuildPropertyTreesInternal(layer->children()[i].get(), data_for_children);
+ }
+
+ if (layer->scroll_children()) {
+ for (Layer* scroll_child : *layer->scroll_children()) {
+ BuildPropertyTreesInternal(scroll_child, data_for_children);
+ }
+ }
+
+ if (layer->has_replica())
+ BuildPropertyTreesInternal(layer->replica_layer(), data_for_children);
+}
+
+} // namespace
+
+void PropertyTreeBuilder::BuildPropertyTrees(
+ Layer* root_layer,
+ const Layer* page_scale_layer,
+ float page_scale_factor,
+ float device_scale_factor,
+ const gfx::Rect& viewport,
+ const gfx::Transform& device_transform,
+ TransformTree* transform_tree,
+ ClipTree* clip_tree) {
+ DataForRecursion data_for_recursion;
+ data_for_recursion.transform_tree = transform_tree;
+ data_for_recursion.clip_tree = clip_tree;
+ data_for_recursion.transform_tree_parent = nullptr;
+ data_for_recursion.transform_fixed_parent = nullptr;
+ data_for_recursion.render_target = root_layer;
+ data_for_recursion.clip_tree_parent = 0;
+ data_for_recursion.page_scale_layer = page_scale_layer;
+ data_for_recursion.page_scale_factor = page_scale_factor;
+ data_for_recursion.device_scale_factor = device_scale_factor;
+
+ int transform_root_id = 0;
+ int clip_root_id = 0;
+
+ // We only need to clip the root if we have a non-empty viewport. The root of
enne (OOO) 2014/12/10 23:46:00 When is the viewport empty?
Ian Vollick 2014/12/12 03:01:47 This happens in unit tests and the assumption ther
enne (OOO) 2014/12/12 19:05:49 Can you leave a comment saying that empty viewport
Ian Vollick 2014/12/15 21:45:17 This is now unnecessary due to hush's patch. Remov
+ // the clip tree does not clip, so we need to add another node in this case.
+ if (!viewport.IsEmpty()) {
+ data_for_recursion.clip_tree_parent = clip_tree->Insert(ClipNode(), 0);
+ clip_root_id = data_for_recursion.clip_tree_parent;
+ }
+
+ BuildPropertyTreesInternal(root_layer, data_for_recursion);
+
+ TransformNode* transform_root = transform_tree->Node(transform_root_id);
+ ClipNode* clip_root = clip_tree->Node(clip_root_id);
+
+ gfx::Transform combined_transform =
+ device_transform * transform_root->data.to_parent;
enne (OOO) 2014/12/10 23:45:59 Is this ever not identity? Doesn't the transform r
Ian Vollick 2014/12/12 03:01:47 The dsf (and device transform) are applied to the
Ian Vollick 2014/12/15 21:45:17 I've added an extra "super root" to the transform
+
+ transform_root->data.set_to_parent(combined_transform);
+ gfx::RectF transformed_viewport = viewport;
+
+ if (!combined_transform.IsIdentity()) {
+ gfx::Transform inverse_transform;
+ if (!combined_transform.GetInverse(&inverse_transform)) {
+ // If we have an univertible transform, then we clip off the entire
+ // subtree.
+ transformed_viewport = gfx::RectF();
+ } else {
+ transformed_viewport =
+ MathUtil::ProjectClippedRect(inverse_transform, viewport);
+ }
+ }
+
+ clip_root->data.clip = transformed_viewport;
enne (OOO) 2014/12/10 23:46:00 Why do you need to inverse transform the viewport
Ian Vollick 2014/12/12 03:01:47 To get to screen space (where this clip is applied
enne (OOO) 2014/12/12 19:05:49 Hmm. Maybe I just figured that this function woul
Ian Vollick 2014/12/15 21:45:17 Now that we have the super root, we don't need to
+ clip_root->data.transform_id = transform_root->id;
+}
+
+} // namespace cc

Powered by Google App Engine
This is Rietveld 408576698