cc: Avoid duplicate work when computing draw properties using property trees

This adds a ComputeLayerDrawPropertiesUsingPropertyTrees function and a
ComputeSurfaceDrawPropertiesUsingPropertyTrees function that compute
these properties together, avoiding re-computing values that are needed
by the computation of more than one property.

BUG=497817
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel

Review URL: https://codereview.chromium.org/1310283002

Cr-Commit-Position: refs/heads/master@{#347400}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index ec382c9..004a1b8 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -164,6 +164,8 @@
     "layers/picture_layer_impl.cc",
     "layers/picture_layer_impl.h",
     "layers/render_pass_sink.h",
+    "layers/render_surface_draw_properties.cc",
+    "layers/render_surface_draw_properties.h",
     "layers/render_surface_impl.cc",
     "layers/render_surface_impl.h",
     "layers/scrollbar_layer_impl_base.cc",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index fb5916e..5c1ffbb 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -221,6 +221,8 @@
         'layers/picture_layer_impl.cc',
         'layers/picture_layer_impl.h',
         'layers/render_pass_sink.h',
+        'layers/render_surface_draw_properties.cc',
+        'layers/render_surface_draw_properties.h',
         'layers/render_surface_impl.cc',
         'layers/render_surface_impl.h',
         'layers/scrollbar_layer_impl_base.cc',
diff --git a/cc/layers/render_surface_draw_properties.cc b/cc/layers/render_surface_draw_properties.cc
new file mode 100644
index 0000000..22131fd
--- /dev/null
+++ b/cc/layers/render_surface_draw_properties.cc
@@ -0,0 +1,14 @@
+// Copyright 2015 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/layers/render_surface_draw_properties.h"
+
+namespace cc {
+
+RenderSurfaceDrawProperties::RenderSurfaceDrawProperties()
+    : draw_opacity(0.f), is_clipped(false) {}
+
+RenderSurfaceDrawProperties::~RenderSurfaceDrawProperties() {}
+
+}  // namespace cc
diff --git a/cc/layers/render_surface_draw_properties.h b/cc/layers/render_surface_draw_properties.h
new file mode 100644
index 0000000..f648909a
--- /dev/null
+++ b/cc/layers/render_surface_draw_properties.h
@@ -0,0 +1,45 @@
+// Copyright 2015 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.
+
+#ifndef CC_LAYERS_RENDER_SURFACE_DRAW_PROPERTIES_H_
+#define CC_LAYERS_RENDER_SURFACE_DRAW_PROPERTIES_H_
+
+#include "cc/base/cc_export.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/transform.h"
+
+namespace cc {
+
+// Container for properties that render surfaces need to compute before they can
+// be drawn.
+struct CC_EXPORT RenderSurfaceDrawProperties {
+  RenderSurfaceDrawProperties();
+  ~RenderSurfaceDrawProperties();
+
+  float draw_opacity;
+
+  // Transforms from the surface's own space to the space of its target surface.
+  gfx::Transform draw_transform;
+
+  // Transforms from the surface's own space to the viewport.
+  gfx::Transform screen_space_transform;
+
+  // If the surface has a replica, these transform from the replica's space to
+  // the space of the target surface and the viewport.
+  gfx::Transform replica_draw_transform;
+  gfx::Transform replica_screen_space_transform;
+
+  // This is in the surface's own space.
+  gfx::Rect content_rect;
+
+  // This is in the space of the surface's target surface.
+  gfx::Rect clip_rect;
+
+  // True if the surface needs to be clipped by clip_rect.
+  bool is_clipped;
+};
+
+}  // namespace cc
+
+#endif  // CC_LAYERS_RENDER_SURFACE_DRAW_PROPERTIES_H_
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index a000ec6..a3fa4b5b 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -7,8 +7,10 @@
 #include <vector>
 
 #include "cc/base/math_util.h"
+#include "cc/layers/draw_properties.h"
 #include "cc/layers/layer.h"
 #include "cc/layers/layer_impl.h"
+#include "cc/layers/render_surface_draw_properties.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/property_tree.h"
 #include "cc/trees/property_tree_builder.h"
@@ -630,9 +632,7 @@
 template <typename LayerType>
 gfx::Transform DrawTransformFromPropertyTreesInternal(
     const LayerType* layer,
-    const TransformTree& tree) {
-  const TransformNode* node = tree.Node(layer->transform_tree_index());
-
+    const TransformNode* node) {
   gfx::Transform xform;
   const bool owns_non_root_surface =
       layer->parent() && layer->has_render_surface();
@@ -653,17 +653,18 @@
 
 gfx::Transform DrawTransformFromPropertyTrees(const Layer* layer,
                                               const TransformTree& tree) {
-  return DrawTransformFromPropertyTreesInternal(layer, tree);
+  return DrawTransformFromPropertyTreesInternal(
+      layer, tree.Node(layer->transform_tree_index()));
 }
 
 gfx::Transform DrawTransformFromPropertyTrees(const LayerImpl* layer,
                                               const TransformTree& tree) {
-  return DrawTransformFromPropertyTreesInternal(layer, tree);
+  return DrawTransformFromPropertyTreesInternal(
+      layer, tree.Node(layer->transform_tree_index()));
 }
 
-gfx::Transform DrawTransformOfRenderSurfaceFromPropertyTrees(
-    const RenderSurfaceImpl* render_surface,
-    const TransformTree& tree) {
+gfx::Transform SurfaceDrawTransform(const RenderSurfaceImpl* render_surface,
+                                    const TransformTree& tree) {
   const TransformNode* node = tree.Node(render_surface->TransformTreeIndex());
   gfx::Transform render_surface_transform;
   // The draw transform of root render surface is identity tranform.
@@ -681,28 +682,24 @@
   return render_surface_transform;
 }
 
-bool RenderSurfaceIsClippedFromPropertyTrees(
-    const RenderSurfaceImpl* render_surface,
-    const ClipTree& tree) {
-  const ClipNode* node = tree.Node(render_surface->ClipTreeIndex());
+bool SurfaceIsClipped(const RenderSurfaceImpl* render_surface,
+                      const ClipNode* clip_node) {
   // If the render surface's owning layer doesn't form a clip node, it is not
   // clipped.
-  if (render_surface->OwningLayerId() != node->owner_id)
+  if (render_surface->OwningLayerId() != clip_node->owner_id)
     return false;
-  return node->data.render_surface_is_clipped;
+  return clip_node->data.render_surface_is_clipped;
 }
 
-gfx::Rect ClipRectOfRenderSurfaceFromPropertyTrees(
-    const RenderSurfaceImpl* render_surface,
-    const ClipTree& clip_tree) {
-  if (!RenderSurfaceIsClippedFromPropertyTrees(render_surface, clip_tree))
+gfx::Rect SurfaceClipRect(const RenderSurfaceImpl* render_surface,
+                          const ClipNode* parent_clip_node,
+                          bool is_clipped) {
+  if (!is_clipped)
     return gfx::Rect();
-  const ClipNode* clip_node = clip_tree.Node(render_surface->ClipTreeIndex());
-  const ClipNode* parent_clip_node = clip_tree.parent(clip_node);
   return gfx::ToEnclosingRect(parent_clip_node->data.clip_in_target_space);
 }
 
-gfx::Transform ScreenSpaceTransformOfRenderSurfaceFromPropertyTrees(
+gfx::Transform SurfaceScreenSpaceTransform(
     const RenderSurfaceImpl* render_surface,
     const TransformTree& tree) {
   const TransformNode* node = tree.Node(render_surface->TransformTreeIndex());
@@ -721,74 +718,31 @@
 template <typename LayerType>
 gfx::Transform ScreenSpaceTransformFromPropertyTreesInternal(
     LayerType* layer,
-    const TransformTree& tree) {
+    const TransformNode* node) {
   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();
-  }
+  gfx::Transform ssxform = node->data.to_screen;
+  xform.ConcatTransform(ssxform);
+  if (layer->should_flatten_transform_from_property_tree())
+    xform.FlattenTo2d();
   return xform;
 }
 
 gfx::Transform ScreenSpaceTransformFromPropertyTrees(
     const Layer* layer,
     const TransformTree& tree) {
-  return ScreenSpaceTransformFromPropertyTreesInternal(layer, tree);
+  return ScreenSpaceTransformFromPropertyTreesInternal(
+      layer, tree.Node(layer->transform_tree_index()));
 }
 
 gfx::Transform ScreenSpaceTransformFromPropertyTrees(
     const LayerImpl* layer,
     const TransformTree& tree) {
-  return ScreenSpaceTransformFromPropertyTreesInternal(layer, tree);
+  return ScreenSpaceTransformFromPropertyTreesInternal(
+      layer, tree.Node(layer->transform_tree_index()));
 }
 
-template <typename LayerType>
-bool ScreenSpaceTransformIsAnimatingFromPropertyTreesInternal(
-    LayerType* layer,
-    const TransformTree& tree) {
-  return tree.Node(layer->transform_tree_index())->data.to_screen_is_animated;
-}
-
-bool ScreenSpaceTransformIsAnimatingFromPropertyTrees(
-    const Layer* layer,
-    const TransformTree& tree) {
-  return ScreenSpaceTransformIsAnimatingFromPropertyTreesInternal(layer, tree);
-}
-
-bool ScreenSpaceTransformIsAnimatingFromPropertyTrees(
-    const LayerImpl* layer,
-    const TransformTree& tree) {
-  return ScreenSpaceTransformIsAnimatingFromPropertyTreesInternal(layer, tree);
-}
-
-float MaximumAnimationTargetScaleFromPropertyTrees(const LayerImpl* layer,
-                                                   const TransformTree& tree) {
-  if (!layer->layer_tree_impl()
-           ->settings()
-           .layer_transforms_should_scale_layer_contents)
-    return 0.f;
-
-  return tree.Node(layer->transform_tree_index())
-      ->data.combined_maximum_animation_target_scale;
-}
-
-float StartingAnimationScaleFromPropertyTrees(const LayerImpl* layer,
-                                              const TransformTree& tree) {
-  if (!layer->layer_tree_impl()
-           ->settings()
-           .layer_transforms_should_scale_layer_contents)
-    return 0.f;
-
-  return tree.Node(layer->transform_tree_index())
-      ->data.combined_starting_animation_scale;
-}
-
-float DrawOpacityFromPropertyTrees(const LayerImpl* layer,
-                                   const EffectTree& tree) {
+float LayerDrawOpacity(const LayerImpl* layer, const EffectTree& tree) {
   if (!layer->render_target())
     return 0.f;
 
@@ -806,9 +760,8 @@
   return draw_opacity;
 }
 
-float DrawOpacityOfRenderSurfaceFromPropertyTrees(
-    RenderSurfaceImpl* render_surface,
-    const EffectTree& tree) {
+float SurfaceDrawOpacity(RenderSurfaceImpl* render_surface,
+                         const EffectTree& tree) {
   const EffectNode* node = tree.Node(render_surface->EffectTreeIndex());
   float target_opacity_tree_index = render_surface->TargetEffectTreeIndex();
   if (target_opacity_tree_index < 0)
@@ -822,25 +775,20 @@
   return draw_opacity;
 }
 
-bool CanUseLcdTextFromPropertyTrees(const LayerImpl* layer,
-                                    bool layers_always_allowed_lcd_text,
-                                    bool can_use_lcd_text,
-                                    PropertyTrees* property_trees) {
+bool LayerCanUseLcdText(const LayerImpl* layer,
+                        bool layers_always_allowed_lcd_text,
+                        bool can_use_lcd_text,
+                        const TransformNode* transform_node,
+                        const EffectNode* effect_node) {
   if (layers_always_allowed_lcd_text)
     return true;
   if (!can_use_lcd_text)
     return false;
   if (!layer->contents_opaque())
     return false;
-  DCHECK(!property_trees->transform_tree.needs_update());
-  DCHECK(!property_trees->effect_tree.needs_update());
 
-  const EffectNode* opacity_node =
-      property_trees->effect_tree.Node(layer->effect_tree_index());
-  if (opacity_node->data.screen_space_opacity != 1.f)
+  if (effect_node->data.screen_space_opacity != 1.f)
     return false;
-  const TransformNode* transform_node =
-      property_trees->transform_tree.Node(layer->transform_tree_index());
   if (!transform_node->data.node_and_ancestors_have_only_integer_translation)
     return false;
   if (static_cast<int>(layer->offset_to_transform_parent().x()) !=
@@ -852,43 +800,14 @@
   return true;
 }
 
-gfx::Rect DrawableContentRectOfSurfaceFromPropertyTrees(
-    const RenderSurfaceImpl* render_surface,
-    const TransformTree& transform_tree) {
-  gfx::Rect drawable_content_rect =
-      gfx::ToEnclosingRect(MathUtil::MapClippedRect(
-          DrawTransformOfRenderSurfaceFromPropertyTrees(render_surface,
-                                                        transform_tree),
-          render_surface->content_rect_from_property_trees()));
-  if (render_surface->HasReplica()) {
-    drawable_content_rect.Union(gfx::ToEnclosingRect(MathUtil::MapClippedRect(
-        DrawTransformOfRenderSurfaceReplicaFromPropertyTrees(render_surface,
-                                                             transform_tree),
-        render_surface->content_rect_from_property_trees())));
-  }
-  return drawable_content_rect;
-}
-
-gfx::Rect DrawableContentRectFromPropertyTrees(
+gfx::Rect LayerDrawableContentRect(
     const LayerImpl* layer,
-    const TransformTree& transform_tree) {
-  gfx::Rect drawable_content_rect = MathUtil::MapEnclosingClippedRect(
-      DrawTransformFromPropertyTrees(layer, transform_tree),
-      gfx::Rect(layer->bounds()));
-  if (layer->is_clipped()) {
-    drawable_content_rect.Intersect(
-        layer->clip_rect_in_target_space_from_property_trees());
-  }
-  return drawable_content_rect;
-}
-
-gfx::Rect ClipRectFromPropertyTrees(const LayerImpl* layer,
-                                    const TransformTree& transform_tree) {
+    const gfx::Rect& layer_bounds_in_target_space,
+    const gfx::Rect& clip_rect) {
   if (layer->is_clipped())
-    return layer->clip_rect_in_target_space_from_property_trees();
-  return MathUtil::MapEnclosingClippedRect(
-      DrawTransformFromPropertyTrees(layer, transform_tree),
-      gfx::Rect(layer->bounds()));
+    return IntersectRects(layer_bounds_in_target_space, clip_rect);
+
+  return layer_bounds_in_target_space;
 }
 
 gfx::Transform ReplicaToSurfaceTransform(
@@ -918,23 +837,89 @@
   return replica_to_surface;
 }
 
-gfx::Transform DrawTransformOfRenderSurfaceReplicaFromPropertyTrees(
-    const RenderSurfaceImpl* render_surface,
-    const TransformTree& tree) {
-  if (!render_surface->HasReplica())
-    return gfx::Transform();
-  return DrawTransformOfRenderSurfaceFromPropertyTrees(render_surface, tree) *
-         ReplicaToSurfaceTransform(render_surface, tree);
+gfx::Rect LayerClipRect(const LayerImpl* layer,
+                        const gfx::Rect& layer_bounds_in_target_space) {
+  if (layer->is_clipped())
+    return layer->clip_rect_in_target_space_from_property_trees();
+
+  return layer_bounds_in_target_space;
 }
 
-gfx::Transform ScreenSpaceTransformOfRenderSurfaceReplicaFromPropertyTrees(
-    const RenderSurfaceImpl* render_surface,
-    const TransformTree& tree) {
-  if (!render_surface->HasReplica())
-    return gfx::Transform();
-  return ScreenSpaceTransformOfRenderSurfaceFromPropertyTrees(render_surface,
-                                                              tree) *
-         ReplicaToSurfaceTransform(render_surface, tree);
+void ComputeLayerDrawPropertiesUsingPropertyTrees(
+    const LayerImpl* layer,
+    const PropertyTrees* property_trees,
+    bool layers_always_allowed_lcd_text,
+    bool can_use_lcd_text,
+    DrawProperties* draw_properties) {
+  draw_properties->visible_layer_rect =
+      layer->visible_rect_from_property_trees();
+
+  const TransformNode* transform_node =
+      property_trees->transform_tree.Node(layer->transform_tree_index());
+  const EffectNode* effect_node =
+      property_trees->effect_tree.Node(layer->effect_tree_index());
+
+  draw_properties->target_space_transform =
+      DrawTransformFromPropertyTreesInternal(layer, transform_node);
+  draw_properties->screen_space_transform =
+      ScreenSpaceTransformFromPropertyTreesInternal(layer, transform_node);
+  draw_properties->screen_space_transform_is_animating =
+      transform_node->data.to_screen_is_animated;
+  if (layer->layer_tree_impl()
+          ->settings()
+          .layer_transforms_should_scale_layer_contents) {
+    draw_properties->maximum_animation_contents_scale =
+        transform_node->data.combined_maximum_animation_target_scale;
+    draw_properties->starting_animation_contents_scale =
+        transform_node->data.combined_starting_animation_scale;
+  } else {
+    draw_properties->maximum_animation_contents_scale = 0.f;
+    draw_properties->starting_animation_contents_scale = 0.f;
+  }
+
+  draw_properties->opacity =
+      LayerDrawOpacity(layer, property_trees->effect_tree);
+  draw_properties->can_use_lcd_text =
+      LayerCanUseLcdText(layer, layers_always_allowed_lcd_text,
+                         can_use_lcd_text, transform_node, effect_node);
+
+  gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect(
+      draw_properties->target_space_transform, gfx::Rect(layer->bounds()));
+  draw_properties->clip_rect = LayerClipRect(layer, bounds_in_target_space);
+  draw_properties->drawable_content_rect = LayerDrawableContentRect(
+      layer, bounds_in_target_space, draw_properties->clip_rect);
+}
+
+void ComputeSurfaceDrawPropertiesUsingPropertyTrees(
+    RenderSurfaceImpl* render_surface,
+    const PropertyTrees* property_trees,
+    RenderSurfaceDrawProperties* draw_properties) {
+  const ClipNode* clip_node =
+      property_trees->clip_tree.Node(render_surface->ClipTreeIndex());
+
+  draw_properties->is_clipped = SurfaceIsClipped(render_surface, clip_node);
+  draw_properties->draw_opacity =
+      SurfaceDrawOpacity(render_surface, property_trees->effect_tree);
+  draw_properties->draw_transform =
+      SurfaceDrawTransform(render_surface, property_trees->transform_tree);
+  draw_properties->screen_space_transform = SurfaceScreenSpaceTransform(
+      render_surface, property_trees->transform_tree);
+
+  if (render_surface->HasReplica()) {
+    gfx::Transform replica_to_surface = ReplicaToSurfaceTransform(
+        render_surface, property_trees->transform_tree);
+    draw_properties->replica_draw_transform =
+        draw_properties->draw_transform * replica_to_surface;
+    draw_properties->replica_screen_space_transform =
+        draw_properties->screen_space_transform * replica_to_surface;
+  } else {
+    draw_properties->replica_draw_transform.MakeIdentity();
+    draw_properties->replica_screen_space_transform.MakeIdentity();
+  }
+
+  draw_properties->clip_rect = SurfaceClipRect(
+      render_surface, property_trees->clip_tree.parent(clip_node),
+      draw_properties->is_clipped);
 }
 
 }  // namespace cc
diff --git a/cc/trees/draw_property_utils.h b/cc/trees/draw_property_utils.h
index 889a9a8..1291e0f 100644
--- a/cc/trees/draw_property_utils.h
+++ b/cc/trees/draw_property_utils.h
@@ -16,8 +16,10 @@
 namespace cc {
 
 class ClipTree;
+struct DrawProperties;
 class Layer;
 class LayerImpl;
+struct RenderSurfaceDrawProperties;
 class RenderSurfaceImpl;
 class EffectTree;
 class TransformTree;
@@ -74,25 +76,21 @@
                                       PropertyTrees* property_trees,
                                       LayerImplList* update_layer_list);
 
+void CC_EXPORT ComputeLayerDrawPropertiesUsingPropertyTrees(
+    const LayerImpl* layer,
+    const PropertyTrees* property_trees,
+    bool layers_always_allowed_lcd_text,
+    bool can_use_lcd_text,
+    DrawProperties* draw_properties);
+
+void CC_EXPORT ComputeSurfaceDrawPropertiesUsingPropertyTrees(
+    RenderSurfaceImpl* render_surface,
+    const PropertyTrees* property_trees,
+    RenderSurfaceDrawProperties* draw_properties);
+
 gfx::Transform CC_EXPORT
 DrawTransformFromPropertyTrees(const Layer* layer, const TransformTree& tree);
 
-gfx::Transform CC_EXPORT DrawTransformOfRenderSurfaceFromPropertyTrees(
-    const RenderSurfaceImpl* render_Surface,
-    const TransformTree& tree);
-
-bool CC_EXPORT
-RenderSurfaceIsClippedFromPropertyTrees(const RenderSurfaceImpl* render_surface,
-                                        const ClipTree& tree);
-
-gfx::Rect CC_EXPORT ClipRectOfRenderSurfaceFromPropertyTrees(
-    const RenderSurfaceImpl* render_surface,
-    const ClipTree& clip_tree);
-
-gfx::Transform CC_EXPORT ScreenSpaceTransformOfRenderSurfaceFromPropertyTrees(
-    const RenderSurfaceImpl* render_surface,
-    const TransformTree& tree);
-
 gfx::Transform CC_EXPORT
 DrawTransformFromPropertyTrees(const LayerImpl* layer,
                                const TransformTree& tree);
@@ -105,56 +103,6 @@
 ScreenSpaceTransformFromPropertyTrees(const LayerImpl* layer,
                                       const TransformTree& tree);
 
-bool CC_EXPORT
-ScreenSpaceTransformIsAnimatingFromPropertyTrees(const Layer* layer,
-                                                 const TransformTree& tree);
-
-bool CC_EXPORT
-ScreenSpaceTransformIsAnimatingFromPropertyTrees(const LayerImpl* layer,
-                                                 const TransformTree& tree);
-
-float CC_EXPORT
-MaximumAnimationTargetScaleFromPropertyTrees(const LayerImpl* layer,
-                                             const TransformTree& tree);
-
-float CC_EXPORT
-StartingAnimationScaleFromPropertyTrees(const LayerImpl* layer,
-                                        const TransformTree& tree);
-
-float CC_EXPORT DrawOpacityFromPropertyTrees(const LayerImpl* layer,
-                                             const EffectTree& tree);
-
-float CC_EXPORT
-DrawOpacityOfRenderSurfaceFromPropertyTrees(RenderSurfaceImpl* render_surface,
-                                            const EffectTree& tree);
-
-bool CC_EXPORT
-CanUseLcdTextFromPropertyTrees(const LayerImpl* layer,
-                               bool layers_always_allowed_lcd_text,
-                               bool can_use_lcd_text,
-                               PropertyTrees* property_trees);
-
-gfx::Rect CC_EXPORT DrawableContentRectOfSurfaceFromPropertyTrees(
-    const RenderSurfaceImpl* render_surface,
-    const TransformTree& transform_tree);
-
-gfx::Rect CC_EXPORT
-DrawableContentRectFromPropertyTrees(const LayerImpl* layer,
-                                     const TransformTree& transform_tree);
-
-gfx::Rect CC_EXPORT
-ClipRectFromPropertyTrees(const LayerImpl* layer,
-                          const TransformTree& transform_tree);
-
-gfx::Transform CC_EXPORT DrawTransformOfRenderSurfaceReplicaFromPropertyTrees(
-    const RenderSurfaceImpl* render_surface,
-    const TransformTree& tree);
-
-gfx::Transform CC_EXPORT
-ScreenSpaceTransformOfRenderSurfaceReplicaFromPropertyTrees(
-    const RenderSurfaceImpl* render_surface,
-    const TransformTree& tree);
-
 }  // namespace cc
 
 #endif  // CC_TREES_DRAW_PROPERTY_UTILS_H_
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index 8b55bbc..2ac9ef42 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -12,6 +12,7 @@
 #include "cc/layers/layer.h"
 #include "cc/layers/layer_impl.h"
 #include "cc/layers/layer_iterator.h"
+#include "cc/layers/render_surface_draw_properties.h"
 #include "cc/layers/render_surface_impl.h"
 #include "cc/trees/draw_property_utils.h"
 #include "cc/trees/layer_tree_host.h"
@@ -2268,146 +2269,105 @@
 
 void VerifyPropertyTreeValuesForSurface(RenderSurfaceImpl* render_surface,
                                         PropertyTrees* property_trees) {
-  const bool render_surface_draw_transforms_match =
-      ApproximatelyEqual(render_surface->draw_transform(),
-                         DrawTransformOfRenderSurfaceFromPropertyTrees(
-                             render_surface, property_trees->transform_tree));
+  RenderSurfaceDrawProperties draw_properties;
+  ComputeSurfaceDrawPropertiesUsingPropertyTrees(render_surface, property_trees,
+                                                 &draw_properties);
+
+  // content_rect has to be computed recursively, so is computed separately from
+  // other draw properties.
+  draw_properties.content_rect =
+      render_surface->content_rect_from_property_trees();
+
+  const bool render_surface_draw_transforms_match = ApproximatelyEqual(
+      render_surface->draw_transform(), draw_properties.draw_transform);
   CHECK(render_surface_draw_transforms_match)
       << "expected: " << render_surface->draw_transform().ToString()
-      << " actual: "
-      << DrawTransformOfRenderSurfaceFromPropertyTrees(
-             render_surface, property_trees->transform_tree)
-             .ToString();
+      << " actual: " << draw_properties.draw_transform.ToString();
 
   const bool render_surface_screen_space_transform_match =
       ApproximatelyEqual(render_surface->screen_space_transform(),
-                         ScreenSpaceTransformOfRenderSurfaceFromPropertyTrees(
-                             render_surface, property_trees->transform_tree));
+                         draw_properties.screen_space_transform);
   CHECK(render_surface_screen_space_transform_match)
       << "expected: " << render_surface->screen_space_transform().ToString()
-      << " actual: "
-      << ScreenSpaceTransformOfRenderSurfaceFromPropertyTrees(
-             render_surface, property_trees->transform_tree)
-             .ToString();
+      << " actual: " << draw_properties.screen_space_transform.ToString();
 
   const bool render_surface_replica_draw_transforms_match =
       ApproximatelyEqual(render_surface->replica_draw_transform(),
-                         DrawTransformOfRenderSurfaceReplicaFromPropertyTrees(
-                             render_surface, property_trees->transform_tree));
+                         draw_properties.replica_draw_transform);
   CHECK(render_surface_replica_draw_transforms_match)
       << "expected: " << render_surface->replica_draw_transform().ToString()
-      << " actual: "
-      << DrawTransformOfRenderSurfaceReplicaFromPropertyTrees(
-             render_surface, property_trees->transform_tree)
-             .ToString();
+      << " actual: " << draw_properties.replica_draw_transform.ToString();
 
   const bool render_surface_replica_screen_space_transforms_match =
-      ApproximatelyEqual(
-          render_surface->replica_screen_space_transform(),
-          ScreenSpaceTransformOfRenderSurfaceReplicaFromPropertyTrees(
-              render_surface, property_trees->transform_tree));
+      ApproximatelyEqual(render_surface->replica_screen_space_transform(),
+                         draw_properties.replica_screen_space_transform);
   CHECK(render_surface_replica_screen_space_transforms_match)
       << "expected: "
       << render_surface->replica_screen_space_transform().ToString()
       << " actual: "
-      << ScreenSpaceTransformOfRenderSurfaceReplicaFromPropertyTrees(
-             render_surface, property_trees->transform_tree)
-             .ToString();
+      << draw_properties.replica_screen_space_transform.ToString();
 
-  CHECK_EQ(render_surface->is_clipped(),
-           RenderSurfaceIsClippedFromPropertyTrees(render_surface,
-                                                   property_trees->clip_tree));
+  CHECK_EQ(render_surface->is_clipped(), draw_properties.is_clipped);
 
-  const bool render_surface_clip_rects_match =
-      ApproximatelyEqual(render_surface->clip_rect(),
-                         ClipRectOfRenderSurfaceFromPropertyTrees(
-                             render_surface, property_trees->clip_tree));
+  const bool render_surface_clip_rects_match = ApproximatelyEqual(
+      render_surface->clip_rect(), draw_properties.clip_rect);
   CHECK(render_surface_clip_rects_match)
-      << "expected: " << render_surface->clip_rect().ToString() << " actual: "
-      << ClipRectOfRenderSurfaceFromPropertyTrees(render_surface,
-                                                  property_trees->clip_tree)
-             .ToString();
+      << "expected: " << render_surface->clip_rect().ToString()
+      << " actual: " << draw_properties.clip_rect.ToString();
 
-  const bool render_surface_content_rects_match =
-      ApproximatelyEqual(render_surface->content_rect(),
-                         render_surface->content_rect_from_property_trees());
+  CHECK_EQ(render_surface->draw_opacity(), draw_properties.draw_opacity);
+
+  const bool render_surface_content_rects_match = ApproximatelyEqual(
+      render_surface->content_rect(), draw_properties.content_rect);
   CHECK(render_surface_content_rects_match)
       << "expected: " << render_surface->content_rect().ToString()
-      << " actual: "
-      << render_surface->content_rect_from_property_trees().ToString();
-
-  CHECK_EQ(render_surface->draw_opacity(),
-           DrawOpacityOfRenderSurfaceFromPropertyTrees(
-               render_surface, property_trees->effect_tree));
+      << " actual: " << draw_properties.content_rect.ToString();
 }
 
 void VerifyPropertyTreeValuesForLayer(LayerImpl* current_layer,
                                       PropertyTrees* property_trees,
                                       bool layers_always_allowed_lcd_text,
                                       bool can_use_lcd_text) {
-  const bool visible_rects_match =
-      ApproximatelyEqual(current_layer->visible_layer_rect(),
-                         current_layer->visible_rect_from_property_trees());
+  DrawProperties draw_properties;
+  ComputeLayerDrawPropertiesUsingPropertyTrees(
+      current_layer, property_trees, layers_always_allowed_lcd_text,
+      can_use_lcd_text, &draw_properties);
+
+  const bool visible_rects_match = ApproximatelyEqual(
+      current_layer->visible_layer_rect(), draw_properties.visible_layer_rect);
   CHECK(visible_rects_match)
       << "expected: " << current_layer->visible_layer_rect().ToString()
-      << " actual: "
-      << current_layer->visible_rect_from_property_trees().ToString();
+      << " actual: " << draw_properties.visible_layer_rect.ToString();
 
-  const bool draw_transforms_match =
-      ApproximatelyEqual(current_layer->draw_transform(),
-                         DrawTransformFromPropertyTrees(
-                             current_layer, property_trees->transform_tree));
+  const bool draw_transforms_match = ApproximatelyEqual(
+      current_layer->draw_transform(), draw_properties.target_space_transform);
   CHECK(draw_transforms_match)
       << "expected: " << current_layer->draw_transform().ToString()
-      << " actual: "
-      << DrawTransformFromPropertyTrees(
-             current_layer, property_trees->transform_tree).ToString();
+      << " actual: " << draw_properties.target_space_transform.ToString();
 
-  const bool draw_opacities_match =
-      current_layer->draw_opacity() ==
-      DrawOpacityFromPropertyTrees(current_layer, property_trees->effect_tree);
-  CHECK(draw_opacities_match)
-      << "expected: " << current_layer->draw_opacity()
-      << " actual: " << DrawOpacityFromPropertyTrees(
-                            current_layer, property_trees->effect_tree);
-
-  const bool can_use_lcd_text_match =
-      CanUseLcdTextFromPropertyTrees(
-          current_layer, layers_always_allowed_lcd_text, can_use_lcd_text,
-          property_trees) == current_layer->can_use_lcd_text();
-  CHECK(can_use_lcd_text_match);
-
+  CHECK_EQ(current_layer->draw_opacity(), draw_properties.opacity);
+  CHECK_EQ(current_layer->can_use_lcd_text(), draw_properties.can_use_lcd_text);
   CHECK_EQ(current_layer->screen_space_transform_is_animating(),
-           ScreenSpaceTransformIsAnimatingFromPropertyTrees(
-               current_layer, property_trees->transform_tree));
+           draw_properties.screen_space_transform_is_animating);
 
   const bool drawable_content_rects_match =
       ApproximatelyEqual(current_layer->drawable_content_rect(),
-                         DrawableContentRectFromPropertyTrees(
-                             current_layer, property_trees->transform_tree));
+                         draw_properties.drawable_content_rect);
   CHECK(drawable_content_rects_match)
       << "expected: " << current_layer->drawable_content_rect().ToString()
-      << " actual: "
-      << DrawableContentRectFromPropertyTrees(current_layer,
-                                              property_trees->transform_tree)
-             .ToString();
+      << " actual: " << draw_properties.drawable_content_rect.ToString();
 
-  const bool clip_rects_match = ApproximatelyEqual(
-      current_layer->clip_rect(),
-      ClipRectFromPropertyTrees(current_layer, property_trees->transform_tree));
+  const bool clip_rects_match =
+      ApproximatelyEqual(current_layer->clip_rect(), draw_properties.clip_rect);
   CHECK(clip_rects_match) << "expected: "
                           << current_layer->clip_rect().ToString()
                           << " actual: "
-                          << ClipRectFromPropertyTrees(
-                                 current_layer, property_trees->transform_tree)
-                                 .ToString();
+                          << draw_properties.clip_rect.ToString();
 
   CHECK_EQ(current_layer->draw_properties().maximum_animation_contents_scale,
-           MaximumAnimationTargetScaleFromPropertyTrees(
-               current_layer, property_trees->transform_tree));
+           draw_properties.maximum_animation_contents_scale);
   CHECK_EQ(current_layer->draw_properties().starting_animation_contents_scale,
-           StartingAnimationScaleFromPropertyTrees(
-               current_layer, property_trees->transform_tree));
+           draw_properties.starting_animation_contents_scale);
 }
 
 void VerifyPropertyTreeValues(
@@ -2582,10 +2542,9 @@
         // If the owning layer of a render surface draws content, the content
         // rect of the render surface is initialized to the drawable content
         // rect of the layer.
-        gfx::Rect content_rect =
-            layer->DrawsContent() ? DrawableContentRectFromPropertyTrees(
-                                        layer, property_trees->transform_tree)
-                                  : gfx::Rect();
+        gfx::Rect content_rect = layer->DrawsContent()
+                                     ? layer->drawable_content_rect()
+                                     : gfx::Rect();
         layer->render_surface()->SetAccumulatedContentRect(content_rect);
       }
     } else if (!layer_should_be_skipped &&
@@ -2594,8 +2553,7 @@
       // content rect of the render surface it is drawing into.
       gfx::Rect surface_content_rect =
           layer->render_target()->render_surface()->accumulated_content_rect();
-      surface_content_rect.Union(DrawableContentRectFromPropertyTrees(
-          layer, property_trees->transform_tree));
+      surface_content_rect.Union(layer->drawable_content_rect());
       layer->render_target()->render_surface()->SetAccumulatedContentRect(
           surface_content_rect);
     }
@@ -2634,9 +2592,7 @@
 
   if (verify_property_trees && render_to_separate_surface &&
       !IsRootLayer(layer)) {
-    if (!layer->replica_layer() &&
-        RenderSurfaceIsClippedFromPropertyTrees(layer->render_surface(),
-                                                property_trees->clip_tree)) {
+    if (!layer->replica_layer() && layer->render_surface()->is_clipped()) {
       // Here, we clip the render surface's content rect with its clip rect.
       // As the clip rect of render surface is in the surface's target space,
       // we first map the content rect into the target space, intersect it with
@@ -2646,11 +2602,8 @@
 
       if (!surface_content_rect.IsEmpty()) {
         gfx::Rect surface_clip_rect = LayerTreeHostCommon::CalculateVisibleRect(
-            ClipRectOfRenderSurfaceFromPropertyTrees(layer->render_surface(),
-                                                     property_trees->clip_tree),
-            surface_content_rect,
-            DrawTransformOfRenderSurfaceFromPropertyTrees(
-                layer->render_surface(), property_trees->transform_tree));
+            layer->render_surface()->clip_rect(), surface_content_rect,
+            layer->render_surface()->draw_transform());
         surface_content_rect.Intersect(surface_clip_rect);
         layer->render_surface()->SetAccumulatedContentRect(
             surface_content_rect);
@@ -2665,8 +2618,8 @@
                                           ->render_target()
                                           ->render_surface()
                                           ->accumulated_content_rect();
-      surface_target_rect.Union(DrawableContentRectOfSurfaceFromPropertyTrees(
-          layer->render_surface(), property_trees->transform_tree));
+      surface_target_rect.Union(
+          gfx::ToEnclosedRect(layer->render_surface()->DrawableContentRect()));
       layer->parent()
           ->render_target()
           ->render_surface()