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

Unified Diff: cc/trees/draw_property_utils.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/draw_property_utils.cc
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6e99a3a175e8685a009a71f305595b93225bcf71
--- /dev/null
+++ b/cc/trees/draw_property_utils.cc
@@ -0,0 +1,192 @@
+// 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/draw_property_utils.h"
+
+#include <vector>
+
+#include "cc/base/math_util.h"
+#include "cc/layers/layer.h"
+#include "cc/trees/property_tree.h"
+#include "cc/trees/property_tree_builder.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+
+namespace cc {
+
+namespace {
+
+void CalculateVisibleRects(
+ const std::vector<Layer*>& layers_that_need_visible_rects,
+ const ClipTree& clip_tree,
+ const TransformTree& transform_tree) {
+ for (size_t i = 0; i < layers_that_need_visible_rects.size(); ++i) {
+ Layer* layer = layers_that_need_visible_rects[i];
+
+ // TODO(ajuma): Compute content_scale rather than using it. Note that for
enne (OOO) 2014/12/10 23:45:59 I do wonder if we could punt on this until impl-si
enne (OOO) 2014/12/10 23:45:59 I do wonder if we could punt on this until impl-si
Ian Vollick 2014/12/12 03:01:47 sgtm! I've added another comment saying that once
+ // PictureLayer and PictureImageLayers, content_bounds == bounds and
+ // content_scale_x == content_scale_y == 1.0.
+ gfx::Size layer_content_bounds = layer->content_bounds();
+ float contents_scale_x = layer->contents_scale_x();
+ float contents_scale_y = layer->contents_scale_y();
+ const bool has_clip = layer->clip_tree_index() > 0;
+ if (has_clip && layer->has_render_target()) {
+ const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
+ const TransformNode* clip_transform_node =
+ transform_tree.Node(clip_node->data.transform_id);
+ const TransformNode* transform_node =
+ transform_tree.Node(layer->transform_tree_index());
+ const TransformNode* target_node =
+ transform_tree.Node(layer->render_target()->transform_tree_index());
+
+ gfx::Transform clip_to_target;
+ gfx::Transform content_to_target;
+ gfx::Transform target_to_content;
+
+ target_to_content.Scale(contents_scale_x, contents_scale_y);
+ target_to_content.Translate(-layer->offset_to_transform_parent().x(),
+ -layer->offset_to_transform_parent().y());
+
+ bool success = ComputeTransform(transform_tree, clip_transform_node->id,
+ target_node->id, &clip_to_target) &&
+ ComputeTransform(transform_tree, transform_node->id,
+ target_node->id, &content_to_target) &&
+ ComputeTransform(transform_tree, target_node->id,
+ transform_node->id, &target_to_content);
+
+ if (!success)
enne (OOO) 2014/12/10 23:45:59 What happens if this doesn't succeed? When does th
Ian Vollick 2014/12/12 03:01:47 If this doesn't succeed it means that an ancestor
enne (OOO) 2014/12/12 19:05:49 Could this just be a DCHECK instead?
Ian Vollick 2014/12/15 21:45:17 Done.
+ continue;
+
+ content_to_target.Translate(layer->offset_to_transform_parent().x(),
+ layer->offset_to_transform_parent().y());
+ content_to_target.Scale(1.0 / contents_scale_x, 1.0 / contents_scale_y);
+
+ gfx::Rect layer_content_rect = gfx::Rect(layer_content_bounds);
+ gfx::RectF layer_content_bounds_in_target_space =
+ MathUtil::MapClippedRect(content_to_target, layer_content_rect);
+ gfx::RectF clip_rect_in_target_space;
+ if (target_node->id > clip_node->id) {
+ clip_rect_in_target_space = MathUtil::ProjectClippedRect(
+ clip_to_target, clip_node->data.combined_clip);
+ } else {
+ clip_rect_in_target_space = MathUtil::MapClippedRect(
+ clip_to_target, clip_node->data.combined_clip);
+ }
+
+ clip_rect_in_target_space.Intersect(layer_content_bounds_in_target_space);
+
+ gfx::Rect visible_rect =
+ gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
+ target_to_content, clip_rect_in_target_space));
+
+ visible_rect.Intersect(gfx::Rect(layer_content_bounds));
+
+ layer->set_debug_visible_rect(visible_rect);
+ } else {
+ layer->set_debug_visible_rect(gfx::Rect(layer_content_bounds));
+ }
+ }
+}
+
+void FindLayersThatNeedVisibleRects(Layer* layer,
+ std::vector<Layer*>* layers_to_update) {
+ if (layer->NeedsVisibleRectUpdated())
+ layers_to_update->push_back(layer);
+
+ for (size_t i = 0; i < layer->children().size(); ++i) {
+ FindLayersThatNeedVisibleRects(layer->children()[i].get(),
+ layers_to_update);
+ }
+}
+
+} // namespace
+
+void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) {
+ for (int i = 0; i < static_cast<int>(clip_tree->size()); ++i) {
+ ClipNode* clip_node = clip_tree->Node(i);
+
+ // Only descendants of a real clipping layer (i.e., not 0) may have their
+ // clip adjusted due to intersecting with an ancestor clip.
+ const bool is_clipped = clip_node->parent_id > 0;
+ if (!is_clipped) {
+ clip_node->data.combined_clip = clip_node->data.clip;
+ continue;
+ }
+
+ ClipNode* parent_clip_node = clip_tree->parent(clip_node);
+ const TransformNode* parent_transform_node =
+ transform_tree.Node(parent_clip_node->data.transform_id);
+ const TransformNode* transform_node =
+ transform_tree.Node(clip_node->data.transform_id);
+
+ // Clips must be combined in target space. We cannot, for example, combine
+ // clips in the space of the child clip. The reason is non-affine
+ // transforms. Say we have the following tree T->A->B->C, and B clips C, but
+ // draw into target T. It may be the case that A applies a perspective
+ // transform, and B and C are at different z positions. When projected into
+ // target space, the relative sizes and positions of B and C can shift.
+ // Since it's the relationship in target space that matters, that's where we
+ // must combine clips.
+ gfx::Transform parent_to_target;
+ gfx::Transform clip_to_target;
+ gfx::Transform target_to_clip;
+
+ bool success =
+ ComputeTransform(transform_tree, parent_transform_node->id,
+ clip_node->data.target_id, &parent_to_target) &&
+ ComputeTransform(transform_tree, transform_node->id,
+ clip_node->data.target_id, &clip_to_target) &&
+ ComputeTransform(transform_tree, clip_node->data.target_id,
+ transform_node->id, &target_to_clip);
+
+ if (!success)
enne (OOO) 2014/12/10 23:45:59 What happens if this doesn't succeed?
Ian Vollick 2014/12/12 03:01:47 Added a comment with an explanation.
+ continue;
+
+ // In order to intersect with as small a rect as possible, we do a
+ // preliminary clip in target space so that when we project back, there's
+ // less likelihood of intersecting the view plane.
+ gfx::RectF inherited_clip_in_target_space = MathUtil::MapClippedRect(
+ parent_to_target, parent_clip_node->data.combined_clip);
+
+ gfx::RectF clip_in_target_space =
+ MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip);
+
+ gfx::RectF intersected_in_target_space = gfx::IntersectRects(
+ inherited_clip_in_target_space, clip_in_target_space);
+
+ clip_node->data.combined_clip = MathUtil::ProjectClippedRect(
+ target_to_clip, intersected_in_target_space);
+
+ clip_node->data.combined_clip.Intersect(clip_node->data.clip);
+ }
+}
+
+void ComputeTransforms(TransformTree* transform_tree) {
+ for (int i = 0; i < static_cast<int>(transform_tree->size()); ++i)
+ UpdateScreenSpaceTransform(transform_tree, i);
+}
+
+void ComputeVisibleRectsUsingPropertyTrees(
+ 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) {
+ std::vector<Layer*> layers_to_update;
+ FindLayersThatNeedVisibleRects(root_layer, &layers_to_update);
+
+ if (!layers_to_update.empty()) {
+ PropertyTreeBuilder::BuildPropertyTrees(
+ root_layer, page_scale_layer, page_scale_factor, device_scale_factor,
+ viewport, device_transform, transform_tree, clip_tree);
+
+ ComputeTransforms(transform_tree);
+ ComputeClips(clip_tree, *transform_tree);
+ CalculateVisibleRects(layers_to_update, *clip_tree, *transform_tree);
+ }
+}
+
+} // namespace cc

Powered by Google App Engine
This is Rietveld 408576698