Index: cc/trees/draw_property_utils.cc |
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc |
index 0e25f0687715978be833548261978ecd61da2438..9295d1aa5e4dddd588321c3edd2a9927a8a905a1 100644 |
--- a/cc/trees/draw_property_utils.cc |
+++ b/cc/trees/draw_property_utils.cc |
@@ -8,6 +8,7 @@ |
#include "cc/base/math_util.h" |
#include "cc/layers/layer.h" |
+#include "cc/layers/layer_impl.h" |
#include "cc/trees/property_tree.h" |
#include "cc/trees/property_tree_builder.h" |
#include "ui/gfx/geometry/rect_conversions.h" |
@@ -16,12 +17,13 @@ namespace cc { |
namespace { |
+template <typename LayerType> |
void CalculateVisibleRects( |
- const std::vector<Layer*>& layers_that_need_visible_rects, |
+ const std::vector<LayerType*>& 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]; |
+ LayerType* layer = layers_that_need_visible_rects[i]; |
// TODO(ajuma): Compute content_scale rather than using it. Note that for |
// PictureLayer and PictureImageLayers, content_bounds == bounds and |
@@ -134,36 +136,43 @@ void CalculateVisibleRects( |
} |
} |
-static bool IsRootLayerOfNewRenderingContext(Layer* layer) { |
+template <typename LayerType> |
+static bool IsRootLayerOfNewRenderingContext(LayerType* layer) { |
if (layer->parent()) |
return !layer->parent()->Is3dSorted() && layer->Is3dSorted(); |
return layer->Is3dSorted(); |
} |
-static inline bool LayerIsInExisting3DRenderingContext(Layer* layer) { |
+template <typename LayerType> |
+static inline bool LayerIsInExisting3DRenderingContext(LayerType* layer) { |
return layer->Is3dSorted() && layer->parent() && |
layer->parent()->Is3dSorted(); |
} |
-static bool TransformToScreenIsKnown(Layer* layer, const TransformTree& tree) { |
+template <typename LayerType> |
+static bool TransformToScreenIsKnown(LayerType* layer, |
+ const TransformTree& tree) { |
const TransformNode* node = tree.Node(layer->transform_tree_index()); |
return !node->data.to_screen_is_animated; |
} |
-static bool IsLayerBackFaceExposed(Layer* layer, const TransformTree& tree) { |
+template <typename LayerType> |
+static bool IsLayerBackFaceExposed(LayerType* layer, |
+ const TransformTree& tree) { |
if (!TransformToScreenIsKnown(layer, tree)) |
return false; |
if (LayerIsInExisting3DRenderingContext(layer)) |
- return layer->draw_transform_from_property_trees(tree).IsBackFaceVisible(); |
+ return DrawTransformFromPropertyTrees(layer, tree).IsBackFaceVisible(); |
return layer->transform().IsBackFaceVisible(); |
} |
-static bool IsSurfaceBackFaceExposed(Layer* layer, |
+template <typename LayerType> |
+static bool IsSurfaceBackFaceExposed(LayerType* layer, |
const TransformTree& tree) { |
if (!TransformToScreenIsKnown(layer, tree)) |
return false; |
if (LayerIsInExisting3DRenderingContext(layer)) |
- return layer->draw_transform_from_property_trees(tree).IsBackFaceVisible(); |
+ return DrawTransformFromPropertyTrees(layer, tree).IsBackFaceVisible(); |
if (IsRootLayerOfNewRenderingContext(layer)) |
return layer->transform().IsBackFaceVisible(); |
@@ -174,13 +183,15 @@ static bool IsSurfaceBackFaceExposed(Layer* layer, |
return false; |
} |
-static bool HasSingularTransform(Layer* layer, const TransformTree& tree) { |
+template <typename LayerType> |
+static bool HasSingularTransform(LayerType* layer, const TransformTree& tree) { |
const TransformNode* node = tree.Node(layer->transform_tree_index()); |
return !node->data.is_invertible || !node->data.ancestors_are_invertible; |
} |
-static bool IsBackFaceInvisible(Layer* layer, const TransformTree& tree) { |
- Layer* backface_test_layer = layer; |
+template <typename LayerType> |
+static bool IsBackFaceInvisible(LayerType* layer, const TransformTree& tree) { |
+ LayerType* backface_test_layer = layer; |
if (layer->use_parent_backface_visibility()) { |
DCHECK(layer->parent()); |
DCHECK(!layer->parent()->use_parent_backface_visibility()); |
@@ -190,25 +201,36 @@ static bool IsBackFaceInvisible(Layer* layer, const TransformTree& tree) { |
IsLayerBackFaceExposed(backface_test_layer, tree); |
} |
-static bool IsAnimatingTransformToScreen(Layer* layer, |
+template <typename LayerType> |
+static bool IsAnimatingTransformToScreen(LayerType* layer, |
const TransformTree& tree) { |
const TransformNode* node = tree.Node(layer->transform_tree_index()); |
return node->data.to_screen_is_animated; |
} |
-static bool IsInvisibleDueToTransform(Layer* layer, const TransformTree& tree) { |
+template <typename LayerType> |
+static bool IsInvisibleDueToTransform(LayerType* layer, |
+ const TransformTree& tree) { |
if (IsAnimatingTransformToScreen(layer, tree)) |
return false; |
return HasSingularTransform(layer, tree) || IsBackFaceInvisible(layer, tree); |
} |
-void FindLayersThatNeedVisibleRects(Layer* layer, |
+bool LayerIsInvisible(const Layer* layer) { |
+ return !layer->opacity() && !layer->OpacityIsAnimating() && |
+ !layer->OpacityCanAnimateOnImplThread(); |
+} |
+ |
+bool LayerIsInvisible(const LayerImpl* layer) { |
+ return !layer->opacity() && !layer->OpacityIsAnimating(); |
+} |
+ |
+template <typename LayerType> |
+void FindLayersThatNeedVisibleRects(LayerType* layer, |
const TransformTree& tree, |
bool subtree_is_visible_from_ancestor, |
- std::vector<Layer*>* layers_to_update) { |
- const bool layer_is_invisible = |
- (!layer->opacity() && !layer->OpacityIsAnimating() && |
- !layer->OpacityCanAnimateOnImplThread()); |
+ std::vector<LayerType*>* layers_to_update) { |
+ const bool layer_is_invisible = LayerIsInvisible(layer); |
const bool layer_is_backfacing = |
(layer->has_render_surface() && !layer->double_sided() && |
IsSurfaceBackFaceExposed(layer, tree)); |
@@ -228,9 +250,7 @@ void FindLayersThatNeedVisibleRects(Layer* layer, |
} |
for (size_t i = 0; i < layer->children().size(); ++i) { |
- FindLayersThatNeedVisibleRects(layer->children()[i].get(), |
- tree, |
- layer_is_drawn, |
+ FindLayersThatNeedVisibleRects(layer->child_at(i), tree, layer_is_drawn, |
layers_to_update); |
} |
} |
@@ -326,7 +346,23 @@ void ComputeTransforms(TransformTree* transform_tree) { |
transform_tree->UpdateTransforms(i); |
} |
-void ComputeVisibleRectsUsingPropertyTrees( |
+template <typename LayerType> |
+void ComputeVisibleRectsUsingPropertyTreesInternal( |
+ LayerType* root_layer, |
+ PropertyTrees* property_trees) { |
+ ComputeTransforms(&property_trees->transform_tree); |
+ ComputeClips(&property_trees->clip_tree, property_trees->transform_tree); |
+ |
+ std::vector<LayerType*> layers_to_update; |
+ const bool subtree_is_visible_from_ancestor = true; |
+ FindLayersThatNeedVisibleRects(root_layer, property_trees->transform_tree, |
+ subtree_is_visible_from_ancestor, |
+ &layers_to_update); |
+ CalculateVisibleRects(layers_to_update, property_trees->clip_tree, |
+ property_trees->transform_tree); |
+} |
+ |
+void BuildPropertyTreesAndComputeVisibleRects( |
Layer* root_layer, |
const Layer* page_scale_layer, |
float page_scale_factor, |
@@ -337,16 +373,145 @@ void ComputeVisibleRectsUsingPropertyTrees( |
PropertyTreeBuilder::BuildPropertyTrees( |
root_layer, page_scale_layer, page_scale_factor, device_scale_factor, |
viewport, device_transform, property_trees); |
- ComputeTransforms(&property_trees->transform_tree); |
- ComputeClips(&property_trees->clip_tree, property_trees->transform_tree); |
+ ComputeVisibleRectsUsingPropertyTrees(root_layer, property_trees); |
+} |
- std::vector<Layer*> layers_to_update; |
- const bool subtree_is_visible_from_ancestor = true; |
- FindLayersThatNeedVisibleRects(root_layer, property_trees->transform_tree, |
- subtree_is_visible_from_ancestor, |
- &layers_to_update); |
- CalculateVisibleRects(layers_to_update, property_trees->clip_tree, |
- property_trees->transform_tree); |
+void BuildPropertyTreesAndComputeVisibleRects( |
+ LayerImpl* root_layer, |
+ const LayerImpl* page_scale_layer, |
+ float page_scale_factor, |
+ float device_scale_factor, |
+ const gfx::Rect& viewport, |
+ const gfx::Transform& device_transform, |
+ PropertyTrees* property_trees) { |
+ PropertyTreeBuilder::BuildPropertyTrees( |
+ root_layer, page_scale_layer, page_scale_factor, device_scale_factor, |
+ viewport, device_transform, property_trees); |
+ ComputeVisibleRectsUsingPropertyTrees(root_layer, property_trees); |
+} |
+ |
+void ComputeVisibleRectsUsingPropertyTrees(Layer* root_layer, |
+ PropertyTrees* property_trees) { |
+ ComputeVisibleRectsUsingPropertyTreesInternal(root_layer, property_trees); |
+} |
+ |
+void ComputeVisibleRectsUsingPropertyTrees(LayerImpl* root_layer, |
+ PropertyTrees* property_trees) { |
+ ComputeVisibleRectsUsingPropertyTreesInternal(root_layer, property_trees); |
+} |
+ |
+template <typename LayerType> |
+gfx::Transform DrawTransformFromPropertyTreesInternal( |
+ const LayerType* layer, |
+ const TransformTree& tree) { |
+ const TransformNode* node = tree.Node(layer->transform_tree_index()); |
+ // TODO(vollick): ultimately we'll need to find this information (whether or |
+ // not we establish a render surface) somewhere other than the layer. |
+ const TransformNode* target_node = |
+ layer->render_surface() ? node : tree.Node(node->data.content_target_id); |
+ |
+ gfx::Transform xform; |
+ const bool owns_non_root_surface = layer->parent() && layer->render_surface(); |
+ if (!owns_non_root_surface) { |
+ // If you're not the root, or you don't own a surface, you need to apply |
+ // your local offset. |
+ xform = node->data.to_target; |
+ if (layer->should_flatten_transform_from_property_tree()) |
+ xform.FlattenTo2d(); |
+ xform.Translate(layer->offset_to_transform_parent().x(), |
+ layer->offset_to_transform_parent().y()); |
+ // A fixed-position layer does not necessarily have the same render target |
+ // as its transform node. In particular, its transform node may be an |
+ // ancestor of its render target's transform node. For example, given layer |
+ // tree R->S->F, suppose F is fixed and S owns a render surface (e.g., say S |
+ // has opacity 0.9 and both S and F draw content). Then F's transform node |
+ // is the root node, so the target space transform from that node is defined |
+ // with respect to the root render surface. But F will render to S's |
+ // surface, so must apply a change of basis transform to the target space |
+ // transform from its transform node. |
+ if (layer->position_constraint().is_fixed_position()) { |
+ gfx::Transform tree_target_to_render_target; |
+ tree.ComputeTransform(node->data.content_target_id, |
+ layer->render_target()->transform_tree_index(), |
+ &tree_target_to_render_target); |
+ xform.ConcatTransform(tree_target_to_render_target); |
+ } |
+ } else { |
+ // Surfaces need to apply their sublayer scale. |
+ xform.Scale(target_node->data.sublayer_scale.x(), |
+ target_node->data.sublayer_scale.y()); |
+ } |
+ xform.Scale(1.0 / layer->contents_scale_x(), 1.0 / layer->contents_scale_y()); |
+ return xform; |
+} |
+ |
+gfx::Transform DrawTransformFromPropertyTrees(const Layer* layer, |
+ const TransformTree& tree) { |
+ return DrawTransformFromPropertyTreesInternal(layer, tree); |
+} |
+ |
+gfx::Transform DrawTransformFromPropertyTrees(const LayerImpl* layer, |
+ const TransformTree& tree) { |
+ return DrawTransformFromPropertyTreesInternal(layer, tree); |
+} |
+ |
+template <typename LayerType> |
+gfx::Transform ScreenSpaceTransformFromPropertyTreesInternal( |
+ LayerType* layer, |
+ const TransformTree& tree) { |
+ gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(), |
+ layer->offset_to_transform_parent().y()); |
+ if (layer->transform_tree_index() >= 0) { |
+ gfx::Transform ssxform = |
+ tree.Node(layer->transform_tree_index())->data.to_screen; |
+ xform.ConcatTransform(ssxform); |
+ if (layer->should_flatten_transform_from_property_tree()) |
+ xform.FlattenTo2d(); |
+ } |
+ xform.Scale(1.0 / layer->contents_scale_x(), 1.0 / layer->contents_scale_y()); |
+ return xform; |
+} |
+ |
+gfx::Transform ScreenSpaceTransformFromPropertyTrees( |
+ const Layer* layer, |
+ const TransformTree& tree) { |
+ return ScreenSpaceTransformFromPropertyTreesInternal(layer, tree); |
+} |
+ |
+gfx::Transform ScreenSpaceTransformFromPropertyTrees( |
+ const LayerImpl* layer, |
+ const TransformTree& tree) { |
+ return ScreenSpaceTransformFromPropertyTreesInternal(layer, tree); |
+} |
+ |
+template <typename LayerType> |
+float DrawOpacityFromPropertyTreesInternal(LayerType layer, |
+ const OpacityTree& tree) { |
+ if (!layer->render_target()) |
+ return 0.f; |
+ |
+ const OpacityNode* target_node = |
+ tree.Node(layer->render_target()->opacity_tree_index()); |
+ const OpacityNode* node = tree.Node(layer->opacity_tree_index()); |
+ if (node == target_node) |
+ return 1.f; |
+ |
+ float draw_opacity = 1.f; |
+ while (node != target_node) { |
+ draw_opacity *= node->data; |
+ node = tree.parent(node); |
+ } |
+ return draw_opacity; |
+} |
+ |
+float DrawOpacityFromPropertyTrees(const Layer* layer, |
+ const OpacityTree& tree) { |
+ return DrawOpacityFromPropertyTreesInternal(layer, tree); |
+} |
+ |
+float DrawOpacityFromPropertyTrees(const LayerImpl* layer, |
+ const OpacityTree& tree) { |
+ return DrawOpacityFromPropertyTreesInternal(layer, tree); |
} |
} // namespace cc |