Detemplatize cc property nodes

Property nodes used to be instantiation of TreeNode<T> template with different
payload. There is little gain from it (deduplicate 500 bytes of code for 3
times), while made us to type "->data." a few hundred times.
Also this extra level of indirection adds invisible mental overheads.

This CL detemplatizes TreeNode<T> and flatten the payload to the node.
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel

Review-Url: https://codereview.chromium.org/2118993002
Cr-Commit-Position: refs/heads/master@{#404339}
diff --git a/cc/trees/clip_node.cc b/cc/trees/clip_node.cc
new file mode 100644
index 0000000..b5efb98f
--- /dev/null
+++ b/cc/trees/clip_node.cc
@@ -0,0 +1,111 @@
+// Copyright 2016 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 "base/trace_event/trace_event_argument.h"
+#include "cc/base/math_util.h"
+#include "cc/proto/gfx_conversions.h"
+#include "cc/proto/property_tree.pb.h"
+#include "cc/trees/clip_node.h"
+
+namespace cc {
+
+ClipNode::ClipNode()
+    : id(-1),
+      parent_id(-1),
+      owner_id(-1),
+      transform_id(-1),
+      target_id(-1),
+      applies_local_clip(true),
+      layer_clipping_uses_only_local_clip(false),
+      target_is_clipped(false),
+      layers_are_clipped(false),
+      layers_are_clipped_when_surfaces_disabled(false),
+      resets_clip(false) {}
+
+ClipNode::ClipNode(const ClipNode& other) = default;
+
+bool ClipNode::operator==(const ClipNode& other) const {
+  return id == other.id && parent_id == other.parent_id &&
+         owner_id == other.owner_id && clip == other.clip &&
+         combined_clip_in_target_space == other.combined_clip_in_target_space &&
+         clip_in_target_space == other.clip_in_target_space &&
+         transform_id == other.transform_id && target_id == other.target_id &&
+         applies_local_clip == other.applies_local_clip &&
+         layer_clipping_uses_only_local_clip ==
+             other.layer_clipping_uses_only_local_clip &&
+         target_is_clipped == other.target_is_clipped &&
+         layers_are_clipped == other.layers_are_clipped &&
+         layers_are_clipped_when_surfaces_disabled ==
+             other.layers_are_clipped_when_surfaces_disabled &&
+         resets_clip == other.resets_clip;
+}
+
+void ClipNode::ToProtobuf(proto::TreeNode* proto) const {
+  proto->set_id(id);
+  proto->set_parent_id(parent_id);
+  proto->set_owner_id(owner_id);
+
+  DCHECK(!proto->has_clip_node_data());
+  proto::ClipNodeData* data = proto->mutable_clip_node_data();
+
+  RectFToProto(clip, data->mutable_clip());
+  RectFToProto(combined_clip_in_target_space,
+               data->mutable_combined_clip_in_target_space());
+  RectFToProto(clip_in_target_space, data->mutable_clip_in_target_space());
+
+  data->set_transform_id(transform_id);
+  data->set_target_id(target_id);
+  data->set_applies_local_clip(applies_local_clip);
+  data->set_layer_clipping_uses_only_local_clip(
+      layer_clipping_uses_only_local_clip);
+  data->set_target_is_clipped(target_is_clipped);
+  data->set_layers_are_clipped(layers_are_clipped);
+  data->set_layers_are_clipped_when_surfaces_disabled(
+      layers_are_clipped_when_surfaces_disabled);
+  data->set_resets_clip(resets_clip);
+}
+
+void ClipNode::FromProtobuf(const proto::TreeNode& proto) {
+  id = proto.id();
+  parent_id = proto.parent_id();
+  owner_id = proto.owner_id();
+
+  DCHECK(proto.has_clip_node_data());
+  const proto::ClipNodeData& data = proto.clip_node_data();
+
+  clip = ProtoToRectF(data.clip());
+  combined_clip_in_target_space =
+      ProtoToRectF(data.combined_clip_in_target_space());
+  clip_in_target_space = ProtoToRectF(data.clip_in_target_space());
+
+  transform_id = data.transform_id();
+  target_id = data.target_id();
+  applies_local_clip = data.applies_local_clip();
+  layer_clipping_uses_only_local_clip =
+      data.layer_clipping_uses_only_local_clip();
+  target_is_clipped = data.target_is_clipped();
+  layers_are_clipped = data.layers_are_clipped();
+  layers_are_clipped_when_surfaces_disabled =
+      data.layers_are_clipped_when_surfaces_disabled();
+  resets_clip = data.resets_clip();
+}
+
+void ClipNode::AsValueInto(base::trace_event::TracedValue* value) const {
+  value->SetInteger("id", id);
+  value->SetInteger("parent_id", parent_id);
+  value->SetInteger("owner_id", owner_id);
+  MathUtil::AddToTracedValue("clip", clip, value);
+  value->SetInteger("transform_id", transform_id);
+  value->SetInteger("target_id", target_id);
+  value->SetBoolean("applies_local_clip", applies_local_clip);
+  value->SetBoolean("layer_clipping_uses_only_local_clip",
+                    layer_clipping_uses_only_local_clip);
+  value->SetBoolean("target_is_clipped", target_is_clipped);
+  value->SetBoolean("layers_are_clipped", layers_are_clipped);
+  value->SetBoolean("layers_are_clipped_when_surfaces_disabled",
+                    layers_are_clipped_when_surfaces_disabled);
+  value->SetBoolean("resets_clip", resets_clip);
+}
+
+}  // namespace cc
diff --git a/cc/trees/clip_node.h b/cc/trees/clip_node.h
new file mode 100644
index 0000000..289930b
--- /dev/null
+++ b/cc/trees/clip_node.h
@@ -0,0 +1,82 @@
+// Copyright 2016 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_TREES_CLIP_NODE_H_
+#define CC_TREES_CLIP_NODE_H_
+
+#include "cc/base/cc_export.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace base {
+namespace trace_event {
+class TracedValue;
+}  // namespace trace_event
+}  // namespace base
+
+namespace cc {
+
+namespace proto {
+class TreeNode;
+}  // namespace proto
+
+struct CC_EXPORT ClipNode {
+  ClipNode();
+  ClipNode(const ClipNode& other);
+
+  int id;
+  int parent_id;
+  int owner_id;
+
+  // The clip rect that this node contributes, expressed in the space of its
+  // transform node.
+  gfx::RectF clip;
+
+  // Clip nodes are uses for two reasons. First, they are used for determining
+  // which parts of each layer are visible. Second, they are used for
+  // determining whether a clip needs to be applied when drawing a layer, and if
+  // so, the rect that needs to be used. These can be different since not all
+  // clips need to be applied directly to each layer. For example, a layer is
+  // implicitly clipped by the bounds of its target render surface and by clips
+  // applied to this surface. |combined_clip_in_target_space| is used for
+  // computing visible rects, and |clip_in_target_space| is used for computing
+  // clips applied at draw time. Both rects are expressed in the space of the
+  // target transform node, and may include clips contributed by ancestors.
+  gfx::RectF combined_clip_in_target_space;
+  gfx::RectF clip_in_target_space;
+
+  // The id of the transform node that defines the clip node's local space.
+  int transform_id;
+
+  // The id of the transform node that defines the clip node's target space.
+  int target_id;
+
+  // Whether this node contributes a new clip (that is, whether |clip| needs to
+  // be applied), rather than only inheriting ancestor clips.
+  bool applies_local_clip : 1;
+
+  // When true, |clip_in_target_space| does not include clips from ancestor
+  // nodes.
+  bool layer_clipping_uses_only_local_clip : 1;
+
+  // True if target surface needs to be drawn with a clip applied.
+  bool target_is_clipped : 1;
+
+  // True if layers with this clip tree node need to be drawn with a clip
+  // applied.
+  bool layers_are_clipped : 1;
+  bool layers_are_clipped_when_surfaces_disabled : 1;
+
+  // Nodes that correspond to unclipped surfaces disregard ancestor clips.
+  bool resets_clip : 1;
+
+  bool operator==(const ClipNode& other) const;
+
+  void ToProtobuf(proto::TreeNode* proto) const;
+  void FromProtobuf(const proto::TreeNode& proto);
+  void AsValueInto(base::trace_event::TracedValue* value) const;
+};
+
+}  // namespace cc
+
+#endif  // CC_TREES_CLIP_NODE_H_
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index 877fee2e..612c9a9 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -12,10 +12,13 @@
 #include "cc/layers/draw_properties.h"
 #include "cc/layers/layer.h"
 #include "cc/layers/layer_impl.h"
+#include "cc/trees/clip_node.h"
+#include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/property_tree.h"
 #include "cc/trees/property_tree_builder.h"
+#include "cc/trees/transform_node.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
 namespace cc {
@@ -46,9 +49,9 @@
           layer->effect_tree_index());
   if (effect_node->owner_id != layer->id())
     return;
-  DCHECK_EQ(effect_node->data.mask_layer_id, -1) << "layer: " << layer->id();
-  DCHECK_EQ(effect_node->data.replica_layer_id, -1) << "layer: " << layer->id();
-  DCHECK(effect_node->data.background_filters.IsEmpty());
+  DCHECK_EQ(effect_node->mask_layer_id, -1) << "layer: " << layer->id();
+  DCHECK_EQ(effect_node->replica_layer_id, -1) << "layer: " << layer->id();
+  DCHECK(effect_node->background_filters.IsEmpty());
 }
 
 #endif
@@ -58,12 +61,11 @@
                                         gfx::Transform* transform) {
   const EffectNode* effect_node = effect_tree.Node(effect_node_id);
   const EffectNode* target_effect_node =
-      effect_node->data.has_render_surface
+      effect_node->has_render_surface
           ? effect_node
-          : effect_tree.Node(effect_node->data.target_id);
-  transform->matrix().postScale(target_effect_node->data.sublayer_scale.x(),
-                                target_effect_node->data.sublayer_scale.y(),
-                                1.f);
+          : effect_tree.Node(effect_node->target_id);
+  transform->matrix().postScale(target_effect_node->sublayer_scale.x(),
+                                target_effect_node->sublayer_scale.y(), 1.f);
 }
 
 #if DCHECK_IS_ON()
@@ -75,15 +77,15 @@
       transform_tree.Node(target_transform_id);
   const EffectNode* effect_node = effect_tree.Node(effect_node_id);
   const EffectNode* target_effect_node =
-      effect_node->data.has_render_surface
+      effect_node->has_render_surface
           ? effect_node
-          : effect_tree.Node(effect_node->data.target_id);
-  DCHECK(target_transform_node->data.sublayer_scale ==
-         target_effect_node->data.sublayer_scale)
+          : effect_tree.Node(effect_node->target_id);
+  DCHECK(target_transform_node->sublayer_scale ==
+         target_effect_node->sublayer_scale)
       << " sublayer scale from transform tree: "
-      << target_transform_node->data.sublayer_scale.ToString()
+      << target_transform_node->sublayer_scale.ToString()
       << " sublayer scale from effect tree: "
-      << target_effect_node->data.sublayer_scale.ToString();
+      << target_effect_node->sublayer_scale.ToString();
 }
 #endif
 
@@ -95,15 +97,15 @@
                                   int target_node_id,
                                   gfx::RectF* clip_rect_in_target_space) {
   DCHECK(layer->clip_tree_index() == clip_node->id);
-  DCHECK(clip_node->data.target_id != target_node_id);
+  DCHECK(clip_node->target_id != target_node_id);
 
   gfx::Transform clip_to_target;
-  if (clip_node->data.target_id > target_node_id) {
+  if (clip_node->target_id > target_node_id) {
     // In this case, layer has a scroll parent. We need to keep the scale
     // at the layer's target but remove the scale at the scroll parent's
     // target.
-    if (transform_tree.ComputeTransform(clip_node->data.target_id,
-                                        target_node_id, &clip_to_target)) {
+    if (transform_tree.ComputeTransform(clip_node->target_id, target_node_id,
+                                        &clip_to_target)) {
       // We don't have to apply sublayer scale when target is root.
       if (target_node_id != 0) {
         AddSublayerScaleToTransform(layer->effect_tree_index(), effect_tree,
@@ -115,21 +117,21 @@
       }
 
       const TransformNode* source_node =
-          transform_tree.Node(clip_node->data.target_id);
-      if (source_node->data.sublayer_scale.x() != 0.f &&
-          source_node->data.sublayer_scale.y() != 0.f)
-        clip_to_target.Scale(1.0f / source_node->data.sublayer_scale.x(),
-                             1.0f / source_node->data.sublayer_scale.y());
+          transform_tree.Node(clip_node->target_id);
+      if (source_node->sublayer_scale.x() != 0.f &&
+          source_node->sublayer_scale.y() != 0.f)
+        clip_to_target.Scale(1.0f / source_node->sublayer_scale.x(),
+                             1.0f / source_node->sublayer_scale.y());
       *clip_rect_in_target_space = MathUtil::MapClippedRect(
-          clip_to_target, clip_node->data.clip_in_target_space);
+          clip_to_target, clip_node->clip_in_target_space);
     } else {
       return false;
     }
   } else {
-    if (transform_tree.ComputeTransform(clip_node->data.target_id,
-                                        target_node_id, &clip_to_target)) {
+    if (transform_tree.ComputeTransform(clip_node->target_id, target_node_id,
+                                        &clip_to_target)) {
       *clip_rect_in_target_space = MathUtil::ProjectClippedRect(
-          clip_to_target, clip_node->data.clip_in_target_space);
+          clip_to_target, clip_node->clip_in_target_space);
     } else {
       return false;
     }
@@ -183,14 +185,14 @@
 static ConditionalClip ComputeCurrentClip(const ClipNode* clip_node,
                                           const TransformTree& transform_tree,
                                           int target_transform_id) {
-  if (clip_node->data.transform_id != target_transform_id)
-    return ComputeLocalRectInTargetSpace(clip_node->data.clip, transform_tree,
-                                         clip_node->data.transform_id,
+  if (clip_node->transform_id != target_transform_id)
+    return ComputeLocalRectInTargetSpace(clip_node->clip, transform_tree,
+                                         clip_node->transform_id,
                                          target_transform_id);
 
-  gfx::RectF current_clip = clip_node->data.clip;
+  gfx::RectF current_clip = clip_node->clip;
   gfx::Vector2dF sublayer_scale =
-      transform_tree.Node(target_transform_id)->data.sublayer_scale;
+      transform_tree.Node(target_transform_id)->sublayer_scale;
   if (sublayer_scale.x() > 0 && sublayer_scale.y() > 0)
     current_clip.Scale(sublayer_scale.x(), sublayer_scale.y());
   return ConditionalClip{true /* is_clipped */, current_clip};
@@ -204,7 +206,7 @@
     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;
+  int target_transform_id = target_node->transform_id;
   bool is_clipped = false;
 
   // Collect all the clips that need to be accumulated.
@@ -213,17 +215,17 @@
   // 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);
+    while (target_node->clip_id > clip_node->id ||
+           target_node->has_unclipped_descendants) {
+      target_node = effect_tree.Node(target_node->target_id);
     }
-    if (target_node->data.clip_id == clip_node->id)
+    if (target_node->clip_id == clip_node->id)
       break;
-    while (target_node->data.clip_id < clip_node->id) {
+    while (target_node->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) {
+    if (target_node->clip_id == clip_node->id) {
       // Target is responsible for applying this clip_node (id equals to
       // target_node's clip id), no need to accumulate this as part of clip
       // rect.
@@ -235,12 +237,12 @@
 
   // 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) {
+  while (!clip_node->applies_local_clip && parent_chain.size() > 0) {
     clip_node = parent_chain.top();
     parent_chain.pop();
   }
 
-  if (!clip_node->data.applies_local_clip)
+  if (!clip_node->applies_local_clip)
     // No clip node applying clip in between.
     return ConditionalClip{false, gfx::RectF()};
 
@@ -252,7 +254,7 @@
   while (parent_chain.size() > 0) {
     clip_node = parent_chain.top();
     parent_chain.pop();
-    if (!clip_node->data.applies_local_clip) {
+    if (!clip_node->applies_local_clip) {
       continue;
     }
     ConditionalClip current_clip =
@@ -282,14 +284,14 @@
     const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
     if (!non_root_surfaces_enabled) {
       layer->set_clip_rect(
-          gfx::ToEnclosingRect(clip_node->data.clip_in_target_space));
+          gfx::ToEnclosingRect(clip_node->clip_in_target_space));
       continue;
     }
 
     // When both the layer and the target are unclipped, the entire layer
     // content rect is visible.
-    const bool fully_visible = !clip_node->data.layers_are_clipped &&
-                               !clip_node->data.target_is_clipped;
+    const bool fully_visible =
+        !clip_node->layers_are_clipped && !clip_node->target_is_clipped;
 
     if (!fully_visible) {
       const TransformNode* transform_node =
@@ -297,17 +299,16 @@
       int target_node_id = transform_tree.ContentTargetId(transform_node->id);
 
       // The clip node stores clip rect in its target space.
-      gfx::RectF clip_rect_in_target_space =
-          clip_node->data.clip_in_target_space;
+      gfx::RectF clip_rect_in_target_space = clip_node->clip_in_target_space;
 
       // If required, this clip rect should be mapped to the current layer's
       // target space.
-      if (clip_node->data.target_id != target_node_id) {
+      if (clip_node->target_id != target_node_id) {
         // In this case, layer has a clip parent or scroll parent (or shares the
         // target with an ancestor layer that has clip parent) and the clip
         // parent's target is different from the layer's target. As the layer's
         // target has unclippped descendants, it is unclippped.
-        if (!clip_node->data.layers_are_clipped)
+        if (!clip_node->layers_are_clipped)
           continue;
 
         // Compute the clip rect in target space and store it.
@@ -345,7 +346,7 @@
                       gfx::RectF* clip_rect_in_target_space) {
   // This is equivalent of calling ComputeClipRectInTargetSpace.
   *clip_rect_in_target_space = gfx::RectF(layer->clip_rect());
-  return transform_tree.Node(target_node_id)->data.ancestors_are_invertible;
+  return transform_tree.Node(target_node_id)->ancestors_are_invertible;
 }
 
 template <typename LayerType>
@@ -377,7 +378,7 @@
           effect_tree.Node(effect_ancestor_with_copy_request);
       ConditionalClip clip_in_layer_space = ComputeTargetRectInLocalSpace(
           accumulated_clip_in_copy_request_space, transform_tree,
-          copy_request_effect_node->data.transform_id,
+          copy_request_effect_node->transform_id,
           layer->transform_tree_index());
 
       if (clip_in_layer_space.is_clipped) {
@@ -398,9 +399,9 @@
     if (!non_root_surfaces_enabled) {
       // When we only have a root surface, the clip node and the layer must
       // necessarily have the same target (the root).
-      if (transform_node->data.ancestors_are_invertible) {
+      if (transform_node->ancestors_are_invertible) {
         gfx::RectF combined_clip_rect_in_target_space =
-            clip_node->data.combined_clip_in_target_space;
+            clip_node->combined_clip_in_target_space;
         gfx::Transform target_to_content;
         target_to_content.Translate(-layer->offset_to_transform_parent().x(),
                                     -layer->offset_to_transform_parent().y());
@@ -420,8 +421,8 @@
 
     // When both the layer and the target are unclipped, the entire layer
     // content rect is visible.
-    const bool fully_visible = !clip_node->data.layers_are_clipped &&
-                               !clip_node->data.target_is_clipped;
+    const bool fully_visible =
+        !clip_node->layers_are_clipped && !clip_node->target_is_clipped;
 
     if (fully_visible) {
       layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
@@ -434,12 +435,12 @@
     // this clip rect should be mapped to the current layer's target space.
     gfx::RectF combined_clip_rect_in_target_space;
 
-    if (clip_node->data.target_id != target_node_id) {
+    if (clip_node->target_id != target_node_id) {
       // In this case, layer has a clip parent or scroll parent (or shares the
       // target with an ancestor layer that has clip parent) and the clip
       // parent's target is different from the layer's target. As the layer's
       // target has unclippped descendants, it is unclippped.
-      if (!clip_node->data.layers_are_clipped) {
+      if (!clip_node->layers_are_clipped) {
         layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
         continue;
       }
@@ -457,12 +458,11 @@
         continue;
       }
     } else {
-      if (clip_node->data.target_is_clipped) {
+      if (clip_node->target_is_clipped) {
         combined_clip_rect_in_target_space =
-            clip_node->data.combined_clip_in_target_space;
+            clip_node->combined_clip_in_target_space;
       } else {
-        combined_clip_rect_in_target_space =
-            clip_node->data.clip_in_target_space;
+        combined_clip_rect_in_target_space = clip_node->clip_in_target_space;
       }
     }
 
@@ -491,7 +491,7 @@
     }
 
     gfx::Transform target_to_layer;
-    if (transform_node->data.ancestors_are_invertible) {
+    if (transform_node->ancestors_are_invertible) {
       target_to_layer = transform_tree.FromTarget(transform_node->id);
     } else {
       if (!transform_tree.ComputeTransformWithSourceSublayerScale(
@@ -519,7 +519,7 @@
 static bool HasSingularTransform(int transform_tree_index,
                                  const TransformTree& tree) {
   const TransformNode* node = tree.Node(transform_tree_index);
-  return !node->data.is_invertible || !node->data.ancestors_are_invertible;
+  return !node->is_invertible || !node->ancestors_are_invertible;
 }
 
 template <typename LayerType>
@@ -537,7 +537,7 @@
                                    const TransformTree& tree) {
   const TransformNode* node = tree.Node(transform_tree_index);
   return layer->use_local_transform_for_backface_visibility()
-             ? node->data.local.IsBackFaceVisible()
+             ? node->local.IsBackFaceVisible()
              : tree.ToTarget(transform_tree_index).IsBackFaceVisible();
 }
 
@@ -545,7 +545,7 @@
                                             int transform_tree_index,
                                             const TransformTree& tree) {
   const TransformNode* node = tree.Node(transform_tree_index);
-  return !node->data.to_screen_is_potentially_animated;
+  return !node->to_screen_is_potentially_animated;
 }
 
 static inline bool TransformToScreenIsKnown(LayerImpl* layer,
@@ -602,7 +602,7 @@
                                std::vector<LayerImpl*>* visible_layer_list) {
   for (auto* layer_impl : *layer_tree_impl) {
     bool layer_is_drawn =
-        effect_tree.Node(layer_impl->effect_tree_index())->data.is_drawn;
+        effect_tree.Node(layer_impl->effect_tree_index())->is_drawn;
 
     if (!IsRootLayer(layer_impl) &&
         LayerShouldBeSkipped(layer_impl, layer_is_drawn, transform_tree,
@@ -624,7 +624,7 @@
 
   EffectNode* node = effect_tree->Node(layer->effect_tree_index());
 
-  if (node->owner_id == layer->id() && node->data.has_render_surface)
+  if (node->owner_id == layer->id() && node->has_render_surface)
     layer->SetHasRenderSurface(true);
   else
     layer->SetHasRenderSurface(false);
@@ -641,16 +641,15 @@
       transform_tree.Node(layer->transform_tree_index());
   const EffectNode* effect_node = effect_tree.Node(layer->effect_tree_index());
 
-  if (effect_node->data.has_render_surface &&
-      effect_node->data.num_copy_requests_in_subtree > 0)
+  if (effect_node->has_render_surface &&
+      effect_node->num_copy_requests_in_subtree > 0)
     return false;
   // If the layer transform is not invertible, it should be skipped.
   // TODO(ajuma): Correctly process subtrees with singular transform for the
   // case where we may animate to a non-singular transform and wish to
   // pre-raster.
-  return !transform_node->data.node_and_ancestors_are_animated_or_invertible ||
-         effect_node->data.hidden_by_backface_visibility ||
-         !effect_node->data.is_drawn;
+  return !transform_node->node_and_ancestors_are_animated_or_invertible ||
+         effect_node->hidden_by_backface_visibility || !effect_node->is_drawn;
 }
 
 bool LayerShouldBeSkipped(LayerImpl* layer,
@@ -675,7 +674,7 @@
                                LayerList* update_layer_list) {
   for (auto* layer : *layer_tree_host) {
     bool layer_is_drawn =
-        effect_tree.Node(layer->effect_tree_index())->data.is_drawn;
+        effect_tree.Node(layer->effect_tree_index())->is_drawn;
 
     if (!IsRootLayer(layer) &&
         LayerShouldBeSkipped(layer, layer_is_drawn, transform_tree,
@@ -713,18 +712,18 @@
     ClipNode* clip_node = clip_tree->Node(i);
 
     if (clip_node->id == 1) {
-      ResetIfHasNanCoordinate(&clip_node->data.clip);
-      clip_node->data.clip_in_target_space = clip_node->data.clip;
-      clip_node->data.combined_clip_in_target_space = clip_node->data.clip;
+      ResetIfHasNanCoordinate(&clip_node->clip);
+      clip_node->clip_in_target_space = clip_node->clip;
+      clip_node->combined_clip_in_target_space = clip_node->clip;
       continue;
     }
     const TransformNode* transform_node =
-        transform_tree.Node(clip_node->data.transform_id);
+        transform_tree.Node(clip_node->transform_id);
     ClipNode* parent_clip_node = clip_tree->parent(clip_node);
 
     gfx::Transform parent_to_current;
     const TransformNode* parent_target_transform_node =
-        transform_tree.Node(parent_clip_node->data.target_id);
+        transform_tree.Node(parent_clip_node->target_id);
     bool success = true;
 
     // Clips must be combined in target space. We cannot, for example, combine
@@ -738,110 +737,105 @@
     // target space. So, we need to get the ancestor clip rect in the current
     // clip node's target space.
     gfx::RectF parent_combined_clip_in_target_space =
-        parent_clip_node->data.combined_clip_in_target_space;
+        parent_clip_node->combined_clip_in_target_space;
     gfx::RectF parent_clip_in_target_space =
-        parent_clip_node->data.clip_in_target_space;
+        parent_clip_node->clip_in_target_space;
     if (parent_target_transform_node &&
-        parent_target_transform_node->id != clip_node->data.target_id &&
+        parent_target_transform_node->id != clip_node->target_id &&
         non_root_surfaces_enabled) {
       success &= transform_tree.ComputeTransformWithDestinationSublayerScale(
-          parent_target_transform_node->id, clip_node->data.target_id,
+          parent_target_transform_node->id, clip_node->target_id,
           &parent_to_current);
-      if (parent_target_transform_node->data.sublayer_scale.x() > 0 &&
-          parent_target_transform_node->data.sublayer_scale.y() > 0)
+      if (parent_target_transform_node->sublayer_scale.x() > 0 &&
+          parent_target_transform_node->sublayer_scale.y() > 0)
         parent_to_current.Scale(
-            1.f / parent_target_transform_node->data.sublayer_scale.x(),
-            1.f / parent_target_transform_node->data.sublayer_scale.y());
+            1.f / parent_target_transform_node->sublayer_scale.x(),
+            1.f / parent_target_transform_node->sublayer_scale.y());
       // If we can't compute a transform, it's because we had to use the inverse
       // of a singular transform. We won't draw in this case, so there's no need
       // to compute clips.
       if (!success)
         continue;
       parent_combined_clip_in_target_space = MathUtil::ProjectClippedRect(
-          parent_to_current,
-          parent_clip_node->data.combined_clip_in_target_space);
+          parent_to_current, parent_clip_node->combined_clip_in_target_space);
       parent_clip_in_target_space = MathUtil::ProjectClippedRect(
-          parent_to_current, parent_clip_node->data.clip_in_target_space);
+          parent_to_current, parent_clip_node->clip_in_target_space);
     }
     // Only nodes affected by ancestor clips will have their clip adjusted due
     // to intersecting with an ancestor clip. But, we still need to propagate
     // the combined clip to our children because if they are clipped, they may
     // need to clip using our parent clip and if we don't propagate it here,
     // it will be lost.
-    if (clip_node->data.resets_clip && non_root_surfaces_enabled) {
-      if (clip_node->data.applies_local_clip) {
-        clip_node->data.clip_in_target_space = MathUtil::MapClippedRect(
-            transform_tree.ToTarget(clip_node->data.transform_id),
-            clip_node->data.clip);
-        ResetIfHasNanCoordinate(&clip_node->data.clip_in_target_space);
-        clip_node->data.combined_clip_in_target_space =
-            gfx::IntersectRects(clip_node->data.clip_in_target_space,
+    if (clip_node->resets_clip && non_root_surfaces_enabled) {
+      if (clip_node->applies_local_clip) {
+        clip_node->clip_in_target_space = MathUtil::MapClippedRect(
+            transform_tree.ToTarget(clip_node->transform_id), clip_node->clip);
+        ResetIfHasNanCoordinate(&clip_node->clip_in_target_space);
+        clip_node->combined_clip_in_target_space =
+            gfx::IntersectRects(clip_node->clip_in_target_space,
                                 parent_combined_clip_in_target_space);
       } else {
-        DCHECK(!clip_node->data.target_is_clipped);
-        DCHECK(!clip_node->data.layers_are_clipped);
-        clip_node->data.combined_clip_in_target_space =
+        DCHECK(!clip_node->target_is_clipped);
+        DCHECK(!clip_node->layers_are_clipped);
+        clip_node->combined_clip_in_target_space =
             parent_combined_clip_in_target_space;
       }
-      ResetIfHasNanCoordinate(&clip_node->data.combined_clip_in_target_space);
+      ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space);
       continue;
     }
-    bool use_only_parent_clip = !clip_node->data.applies_local_clip;
+    bool use_only_parent_clip = !clip_node->applies_local_clip;
     if (use_only_parent_clip) {
-      clip_node->data.combined_clip_in_target_space =
+      clip_node->combined_clip_in_target_space =
           parent_combined_clip_in_target_space;
       if (!non_root_surfaces_enabled) {
-        clip_node->data.clip_in_target_space =
-            parent_clip_node->data.clip_in_target_space;
-      } else if (!clip_node->data.target_is_clipped) {
-        clip_node->data.clip_in_target_space = parent_clip_in_target_space;
+        clip_node->clip_in_target_space =
+            parent_clip_node->clip_in_target_space;
+      } else if (!clip_node->target_is_clipped) {
+        clip_node->clip_in_target_space = parent_clip_in_target_space;
       } else {
         // Render Surface applies clip and the owning layer itself applies
         // no clip. So, clip_in_target_space is not used and hence we can set
         // it to an empty rect.
-        clip_node->data.clip_in_target_space = gfx::RectF();
+        clip_node->clip_in_target_space = gfx::RectF();
       }
     } else {
       gfx::Transform source_to_target;
 
       if (!non_root_surfaces_enabled) {
-        source_to_target =
-            transform_tree.ToScreen(clip_node->data.transform_id);
+        source_to_target = transform_tree.ToScreen(clip_node->transform_id);
       } else if (transform_tree.ContentTargetId(transform_node->id) ==
-                 clip_node->data.target_id) {
-        source_to_target =
-            transform_tree.ToTarget(clip_node->data.transform_id);
+                 clip_node->target_id) {
+        source_to_target = transform_tree.ToTarget(clip_node->transform_id);
       } else {
         success = transform_tree.ComputeTransformWithDestinationSublayerScale(
-            transform_node->id, clip_node->data.target_id, &source_to_target);
+            transform_node->id, clip_node->target_id, &source_to_target);
         // source_to_target computation should be successful as target is an
         // ancestor of the transform node.
         DCHECK(success);
       }
 
       gfx::RectF source_clip_in_target_space =
-          MathUtil::MapClippedRect(source_to_target, clip_node->data.clip);
+          MathUtil::MapClippedRect(source_to_target, clip_node->clip);
 
       // With surfaces disabled, the only case where we use only the local clip
       // for layer clipping is the case where no non-viewport ancestor node
       // applies a local clip.
       bool layer_clipping_uses_only_local_clip =
           non_root_surfaces_enabled
-              ? clip_node->data.layer_clipping_uses_only_local_clip
-              : !parent_clip_node->data
-                     .layers_are_clipped_when_surfaces_disabled;
+              ? clip_node->layer_clipping_uses_only_local_clip
+              : !parent_clip_node->layers_are_clipped_when_surfaces_disabled;
       if (!layer_clipping_uses_only_local_clip) {
-        clip_node->data.clip_in_target_space = gfx::IntersectRects(
+        clip_node->clip_in_target_space = gfx::IntersectRects(
             parent_clip_in_target_space, source_clip_in_target_space);
       } else {
-        clip_node->data.clip_in_target_space = source_clip_in_target_space;
+        clip_node->clip_in_target_space = source_clip_in_target_space;
       }
 
-      clip_node->data.combined_clip_in_target_space = gfx::IntersectRects(
+      clip_node->combined_clip_in_target_space = gfx::IntersectRects(
           parent_combined_clip_in_target_space, source_clip_in_target_space);
     }
-    ResetIfHasNanCoordinate(&clip_node->data.clip_in_target_space);
-    ResetIfHasNanCoordinate(&clip_node->data.combined_clip_in_target_space);
+    ResetIfHasNanCoordinate(&clip_node->clip_in_target_space);
+    ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space);
   }
   clip_tree->set_needs_update(false);
 }
@@ -860,13 +854,13 @@
     EffectNode* node = effect_tree->Node(i);
     if (i == 1) {
       // Render target on the first effect node is root.
-      node->data.target_id = 0;
+      node->target_id = 0;
     } else if (!can_render_to_separate_surface) {
-      node->data.target_id = 1;
-    } else if (effect_tree->parent(node)->data.has_render_surface) {
-      node->data.target_id = node->parent_id;
+      node->target_id = 1;
+    } else if (effect_tree->parent(node)->has_render_surface) {
+      node->target_id = node->parent_id;
     } else {
-      node->data.target_id = effect_tree->parent(node)->data.target_id;
+      node->target_id = effect_tree->parent(node)->target_id;
     }
   }
 }
@@ -885,9 +879,9 @@
   const TransformTree* transform_tree = &property_trees->transform_tree;
   EffectNode* root_effect_node = effect_tree->Node(1);
   const RenderSurfaceImpl* root_render_surface =
-      root_effect_node->data.render_surface;
-  gfx::Rect root_clip = gfx::ToEnclosingRect(
-      clip_tree->Node(root_effect_node->data.clip_id)->data.clip);
+      root_effect_node->render_surface;
+  gfx::Rect root_clip =
+      gfx::ToEnclosingRect(clip_tree->Node(root_effect_node->clip_id)->clip);
   if (root_render_surface->is_clipped())
     DCHECK(root_clip == root_render_surface->clip_rect())
         << "clip on root render surface: "
@@ -895,13 +889,12 @@
         << " v.s. root effect node's clip: " << root_clip.ToString();
   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);
+    const EffectNode* target_node = effect_tree->Node(effect_node->target_id);
     ConditionalClip accumulated_clip_rect =
-        ComputeAccumulatedClip(*clip_tree, effect_node->data.clip_id,
-                               *effect_tree, target_node->id, *transform_tree);
+        ComputeAccumulatedClip(*clip_tree, effect_node->clip_id, *effect_tree,
+                               target_node->id, *transform_tree);
     gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect;
-    const RenderSurfaceImpl* render_surface = effect_node->data.render_surface;
+    const RenderSurfaceImpl* render_surface = effect_node->render_surface;
     if (render_surface && render_surface->is_clipped()) {
       DCHECK(gfx::ToEnclosingRect(accumulated_clip) ==
              render_surface->clip_rect())
@@ -920,9 +913,9 @@
   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->has_render_surface
           ? effect_node
-          : effect_tree->Node(effect_node->data.target_id);
+          : effect_tree->Node(effect_node->target_id);
   // TODO(weiliangc): When effect node has up to date render surface info on
   // compositor thread, no need to check for resourceless draw mode
   if (!property_trees->non_root_surfaces_enabled) {
@@ -937,15 +930,15 @@
 
   if ((!property_trees->non_root_surfaces_enabled &&
        clip_tree->Node(layer->clip_tree_index())
-           ->data.layers_are_clipped_when_surfaces_disabled) ||
-      clip_tree->Node(layer->clip_tree_index())->data.layers_are_clipped) {
+           ->layers_are_clipped_when_surfaces_disabled) ||
+      clip_tree->Node(layer->clip_tree_index())->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)
+        << gfx::ToEnclosingRect(
+               clip_tree->Node(layer->clip_tree_index())->clip_in_target_space)
                .ToString();
   }
 }
@@ -954,10 +947,10 @@
     const EffectTree& effect_tree,
     const int effect_tree_index) {
   const EffectNode* node = effect_tree.Node(effect_tree_index);
-  if (node->data.has_render_surface)
-    return node->data.transform_id;
-  node = effect_tree.Node(node->data.target_id);
-  return node->data.transform_id;
+  if (node->has_render_surface)
+    return node->transform_id;
+  node = effect_tree.Node(node->target_id);
+  return node->transform_id;
 }
 
 static void VerifyDrawTransformsMatch(LayerImpl* layer,
@@ -1099,7 +1092,7 @@
     EffectNode* node =
         property_trees->effect_tree.Node(layer->effect_tree_index());
     if (node->owner_id == layer->id())
-      node->data.render_surface = layer->render_surface();
+      node->render_surface = layer->render_surface();
 #if DCHECK_IS_ON()
     if (can_render_to_separate_surface)
       ValidateRenderSurfaceForLayer(layer);
@@ -1138,7 +1131,7 @@
                     layer->offset_to_transform_parent().y());
   } else {
     // Surfaces need to apply their sublayer scale.
-    xform.Scale(node->data.sublayer_scale.x(), node->data.sublayer_scale.y());
+    xform.Scale(node->sublayer_scale.x(), node->sublayer_scale.y());
   }
   return xform;
 }
@@ -1163,21 +1156,19 @@
                                   &render_surface_transform);
   // We don't have to apply sublayer scale when target is root.
   if (target_transform_node->id != 0) {
-    AddSublayerScaleToTransform(effect_node->data.target_id, effect_tree,
+    AddSublayerScaleToTransform(effect_node->target_id, effect_tree,
                                 &render_surface_transform);
 #if DCHECK_IS_ON()
-    VerifySublayerScalesMatch(effect_node->data.target_id,
-                              target_transform_node->id, effect_tree,
-                              transform_tree);
+    VerifySublayerScalesMatch(effect_node->target_id, target_transform_node->id,
+                              effect_tree, transform_tree);
 #endif
   }
 
-  DCHECK(transform_node->data.sublayer_scale ==
-         effect_node->data.sublayer_scale);
-  if (effect_node->data.sublayer_scale.x() != 0.0 &&
-      effect_node->data.sublayer_scale.y() != 0.0)
-    render_surface_transform.Scale(1.0 / effect_node->data.sublayer_scale.x(),
-                                   1.0 / effect_node->data.sublayer_scale.y());
+  DCHECK(transform_node->sublayer_scale == effect_node->sublayer_scale);
+  if (effect_node->sublayer_scale.x() != 0.0 &&
+      effect_node->sublayer_scale.y() != 0.0)
+    render_surface_transform.Scale(1.0 / effect_node->sublayer_scale.x(),
+                                   1.0 / effect_node->sublayer_scale.y());
   render_surface->SetDrawTransform(render_surface_transform);
 }
 
@@ -1186,7 +1177,7 @@
   DCHECK(render_surface->OwningLayerId() == clip_node->owner_id)
       << "we now create clip node for every render surface";
 
-  render_surface->SetIsClipped(clip_node->data.target_is_clipped);
+  render_surface->SetIsClipped(clip_node->target_is_clipped);
 }
 
 static void SetSurfaceClipRect(const ClipNode* parent_clip_node,
@@ -1200,9 +1191,9 @@
   const TransformNode* transform_node =
       transform_tree.Node(render_surface->TransformTreeIndex());
   if (transform_tree.TargetId(transform_node->id) ==
-      parent_clip_node->data.target_id) {
+      parent_clip_node->target_id) {
     render_surface->SetClipRect(
-        gfx::ToEnclosingRect(parent_clip_node->data.clip_in_target_space));
+        gfx::ToEnclosingRect(parent_clip_node->clip_in_target_space));
     return;
   }
 
@@ -1212,7 +1203,7 @@
   gfx::Transform clip_parent_target_to_target;
   const bool success =
       transform_tree.ComputeTransformWithDestinationSublayerScale(
-          parent_clip_node->data.target_id,
+          parent_clip_node->target_id,
           transform_tree.TargetId(transform_node->id),
           &clip_parent_target_to_target);
 
@@ -1221,11 +1212,10 @@
     return;
   }
 
-  DCHECK_LT(parent_clip_node->data.target_id,
+  DCHECK_LT(parent_clip_node->target_id,
             transform_tree.TargetId(transform_node->id));
   render_surface->SetClipRect(gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
-      clip_parent_target_to_target,
-      parent_clip_node->data.clip_in_target_space)));
+      clip_parent_target_to_target, parent_clip_node->clip_in_target_space)));
 }
 
 template <typename LayerType>
@@ -1274,7 +1264,7 @@
   // (included) and its target surface (excluded).
   const EffectNode* node = tree.Node(render_surface->EffectTreeIndex());
   float draw_opacity = tree.EffectiveOpacity(node);
-  for (node = tree.parent(node); node && !node->data.has_render_surface;
+  for (node = tree.parent(node); node && !node->has_render_surface;
        node = tree.parent(node)) {
     draw_opacity *= tree.EffectiveOpacity(node);
   }
@@ -1300,8 +1290,8 @@
   const LayerImpl* replica_layer = render_surface->ReplicaLayer();
   const TransformNode* surface_transform_node =
       tree.Node(render_surface->TransformTreeIndex());
-  replica_to_surface.Scale(surface_transform_node->data.sublayer_scale.x(),
-                           surface_transform_node->data.sublayer_scale.y());
+  replica_to_surface.Scale(surface_transform_node->sublayer_scale.x(),
+                           surface_transform_node->sublayer_scale.y());
   replica_to_surface.Translate(replica_layer->offset_to_transform_parent().x(),
                                replica_layer->offset_to_transform_parent().y());
   gfx::Transform replica_transform_node_to_surface;
@@ -1309,11 +1299,10 @@
                         render_surface->TransformTreeIndex(),
                         &replica_transform_node_to_surface);
   replica_to_surface.PreconcatTransform(replica_transform_node_to_surface);
-  if (surface_transform_node->data.sublayer_scale.x() != 0 &&
-      surface_transform_node->data.sublayer_scale.y() != 0) {
-    replica_to_surface.Scale(
-        1.0 / surface_transform_node->data.sublayer_scale.x(),
-        1.0 / surface_transform_node->data.sublayer_scale.y());
+  if (surface_transform_node->sublayer_scale.x() != 0 &&
+      surface_transform_node->sublayer_scale.y() != 0) {
+    replica_to_surface.Scale(1.0 / surface_transform_node->sublayer_scale.x(),
+                             1.0 / surface_transform_node->sublayer_scale.y());
   }
   return replica_to_surface;
 }
@@ -1335,15 +1324,15 @@
         layer->draw_properties().screen_space_transform;
   }
   layer->draw_properties().screen_space_transform_is_animating =
-      transform_node->data.to_screen_is_potentially_animated;
+      transform_node->to_screen_is_potentially_animated;
 
   layer->draw_properties().opacity =
       LayerDrawOpacity(layer, property_trees->effect_tree);
   if (property_trees->non_root_surfaces_enabled) {
-    layer->draw_properties().is_clipped = clip_node->data.layers_are_clipped;
+    layer->draw_properties().is_clipped = clip_node->layers_are_clipped;
   } else {
     layer->draw_properties().is_clipped =
-        clip_node->data.layers_are_clipped_when_surfaces_disabled;
+        clip_node->layers_are_clipped_when_surfaces_disabled;
   }
 
   gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect(
@@ -1427,15 +1416,14 @@
     // When the page scale layer is also the root layer, the node should also
     // store the combined scale factor and not just the page scale factor.
     float post_local_scale_factor = page_scale_factor * device_scale_factor;
-    node->data.post_local_scale_factor = post_local_scale_factor;
-    node->data.post_local = device_transform;
-    node->data.post_local.Scale(post_local_scale_factor,
-                                post_local_scale_factor);
+    node->post_local_scale_factor = post_local_scale_factor;
+    node->post_local = device_transform;
+    node->post_local.Scale(post_local_scale_factor, post_local_scale_factor);
   } else {
-    node->data.post_local_scale_factor = page_scale_factor;
-    node->data.update_post_local_transform(gfx::PointF(), gfx::Point3F());
+    node->post_local_scale_factor = page_scale_factor;
+    node->update_post_local_transform(gfx::PointF(), gfx::Point3F());
   }
-  node->data.needs_local_transform_update = true;
+  node->needs_local_transform_update = true;
   property_trees->transform_tree.set_needs_update(true);
 }
 
@@ -1471,11 +1459,11 @@
 
   TransformNode* node = property_trees->transform_tree.Node(
       overscroll_elasticity_layer->transform_tree_index());
-  if (node->data.scroll_offset == gfx::ScrollOffset(elastic_overscroll))
+  if (node->scroll_offset == gfx::ScrollOffset(elastic_overscroll))
     return;
 
-  node->data.scroll_offset = gfx::ScrollOffset(elastic_overscroll);
-  node->data.needs_local_transform_update = true;
+  node->scroll_offset = gfx::ScrollOffset(elastic_overscroll);
+  node->needs_local_transform_update = true;
   property_trees->transform_tree.set_needs_update(true);
 }
 
diff --git a/cc/trees/effect_node.cc b/cc/trees/effect_node.cc
new file mode 100644
index 0000000..c26ddd93
--- /dev/null
+++ b/cc/trees/effect_node.cc
@@ -0,0 +1,141 @@
+// Copyright 2016 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 "base/trace_event/trace_event_argument.h"
+#include "cc/proto/gfx_conversions.h"
+#include "cc/proto/property_tree.pb.h"
+#include "cc/trees/effect_node.h"
+
+namespace cc {
+
+EffectNode::EffectNode()
+    : id(-1),
+      parent_id(-1),
+      owner_id(-1),
+      opacity(1.f),
+      screen_space_opacity(1.f),
+      has_render_surface(false),
+      render_surface(nullptr),
+      has_copy_request(false),
+      hidden_by_backface_visibility(false),
+      double_sided(false),
+      is_drawn(true),
+      subtree_hidden(false),
+      has_potential_opacity_animation(false),
+      is_currently_animating_opacity(false),
+      effect_changed(false),
+      num_copy_requests_in_subtree(0),
+      has_unclipped_descendants(false),
+      transform_id(0),
+      clip_id(0),
+      target_id(0),
+      mask_layer_id(-1),
+      replica_layer_id(-1),
+      replica_mask_layer_id(-1) {}
+
+EffectNode::EffectNode(const EffectNode& other) = default;
+
+bool EffectNode::operator==(const EffectNode& other) const {
+  return id == other.id && parent_id == other.parent_id &&
+         owner_id == other.owner_id && opacity == other.opacity &&
+         screen_space_opacity == other.screen_space_opacity &&
+         has_render_surface == other.has_render_surface &&
+         has_copy_request == other.has_copy_request &&
+         background_filters == other.background_filters &&
+         sublayer_scale == other.sublayer_scale &&
+         hidden_by_backface_visibility == other.hidden_by_backface_visibility &&
+         double_sided == other.double_sided && is_drawn == other.is_drawn &&
+         subtree_hidden == other.subtree_hidden &&
+         has_potential_opacity_animation ==
+             other.has_potential_opacity_animation &&
+         is_currently_animating_opacity ==
+             other.is_currently_animating_opacity &&
+         effect_changed == other.effect_changed &&
+         num_copy_requests_in_subtree == other.num_copy_requests_in_subtree &&
+         transform_id == other.transform_id && clip_id == other.clip_id &&
+         target_id == other.target_id && mask_layer_id == other.mask_layer_id &&
+         replica_layer_id == other.replica_layer_id &&
+         replica_mask_layer_id == other.replica_mask_layer_id;
+}
+
+void EffectNode::ToProtobuf(proto::TreeNode* proto) const {
+  proto->set_id(id);
+  proto->set_parent_id(parent_id);
+  proto->set_owner_id(owner_id);
+
+  DCHECK(!proto->has_effect_node_data());
+  proto::EffectNodeData* data = proto->mutable_effect_node_data();
+  data->set_opacity(opacity);
+  data->set_screen_space_opacity(screen_space_opacity);
+  data->set_has_render_surface(has_render_surface);
+  data->set_has_copy_request(has_copy_request);
+  data->set_hidden_by_backface_visibility(hidden_by_backface_visibility);
+  data->set_double_sided(double_sided);
+  data->set_is_drawn(is_drawn);
+  data->set_subtree_hidden(subtree_hidden);
+  data->set_has_potential_opacity_animation(has_potential_opacity_animation);
+  data->set_is_currently_animating_opacity(is_currently_animating_opacity);
+  data->set_effect_changed(effect_changed);
+  data->set_num_copy_requests_in_subtree(num_copy_requests_in_subtree);
+  data->set_transform_id(transform_id);
+  data->set_clip_id(clip_id);
+  data->set_target_id(target_id);
+  data->set_mask_layer_id(mask_layer_id);
+  data->set_replica_layer_id(replica_layer_id);
+  data->set_replica_mask_layer_id(replica_mask_layer_id);
+  Vector2dFToProto(sublayer_scale, data->mutable_sublayer_scale());
+}
+
+void EffectNode::FromProtobuf(const proto::TreeNode& proto) {
+  id = proto.id();
+  parent_id = proto.parent_id();
+  owner_id = proto.owner_id();
+
+  DCHECK(proto.has_effect_node_data());
+  const proto::EffectNodeData& data = proto.effect_node_data();
+
+  opacity = data.opacity();
+  screen_space_opacity = data.screen_space_opacity();
+  has_render_surface = data.has_render_surface();
+  has_copy_request = data.has_copy_request();
+  hidden_by_backface_visibility = data.hidden_by_backface_visibility();
+  double_sided = data.double_sided();
+  is_drawn = data.is_drawn();
+  subtree_hidden = data.subtree_hidden();
+  has_potential_opacity_animation = data.has_potential_opacity_animation();
+  is_currently_animating_opacity = data.is_currently_animating_opacity();
+  effect_changed = data.effect_changed();
+  num_copy_requests_in_subtree = data.num_copy_requests_in_subtree();
+  transform_id = data.transform_id();
+  clip_id = data.clip_id();
+  target_id = data.target_id();
+  mask_layer_id = data.mask_layer_id();
+  replica_layer_id = data.replica_layer_id();
+  replica_mask_layer_id = data.replica_mask_layer_id();
+  sublayer_scale = ProtoToVector2dF(data.sublayer_scale());
+}
+
+void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const {
+  value->SetInteger("id", id);
+  value->SetInteger("parent_id", parent_id);
+  value->SetInteger("owner_id", owner_id);
+  value->SetDouble("opacity", opacity);
+  value->SetBoolean("has_render_surface", has_render_surface);
+  value->SetBoolean("has_copy_request", has_copy_request);
+  value->SetBoolean("double_sided", double_sided);
+  value->SetBoolean("is_drawn", is_drawn);
+  value->SetBoolean("has_potential_opacity_animation",
+                    has_potential_opacity_animation);
+  value->SetBoolean("effect_changed", effect_changed);
+  value->SetInteger("num_copy_requests_in_subtree",
+                    num_copy_requests_in_subtree);
+  value->SetInteger("transform_id", transform_id);
+  value->SetInteger("clip_id", clip_id);
+  value->SetInteger("target_id", target_id);
+  value->SetInteger("mask_layer_id", mask_layer_id);
+  value->SetInteger("replica_layer_id", replica_layer_id);
+  value->SetInteger("replica_mask_layer_id", replica_mask_layer_id);
+}
+
+}  // namespace cc
diff --git a/cc/trees/effect_node.h b/cc/trees/effect_node.h
new file mode 100644
index 0000000..1e3c73c
--- /dev/null
+++ b/cc/trees/effect_node.h
@@ -0,0 +1,73 @@
+// Copyright 2016 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_TREES_EFFECT_NODE_H_
+#define CC_TREES_EFFECT_NODE_H_
+
+#include "cc/base/cc_export.h"
+#include "cc/output/filter_operations.h"
+
+namespace base {
+namespace trace_event {
+class TracedValue;
+}  // namespace trace_event
+}  // namespace base
+
+namespace cc {
+
+class RenderSurfaceImpl;
+
+namespace proto {
+class TreeNode;
+}  // namespace proto
+
+struct CC_EXPORT EffectNode {
+  EffectNode();
+  EffectNode(const EffectNode& other);
+
+  int id;
+  int parent_id;
+  int owner_id;
+
+  float opacity;
+  float screen_space_opacity;
+
+  FilterOperations background_filters;
+
+  gfx::Vector2dF sublayer_scale;
+
+  bool has_render_surface;
+  RenderSurfaceImpl* render_surface;
+  bool has_copy_request;
+  bool hidden_by_backface_visibility;
+  bool double_sided;
+  bool is_drawn;
+  // TODO(jaydasika) : Delete this after implementation of
+  // SetHideLayerAndSubtree is cleaned up. (crbug.com/595843)
+  bool subtree_hidden;
+  bool has_potential_opacity_animation;
+  bool is_currently_animating_opacity;
+  // We need to track changes to effects on the compositor to compute damage
+  // rect.
+  bool effect_changed;
+  int num_copy_requests_in_subtree;
+  bool has_unclipped_descendants;
+  int transform_id;
+  int clip_id;
+  // Effect node id of which this effect contributes to.
+  int target_id;
+  int mask_layer_id;
+  int replica_layer_id;
+  int replica_mask_layer_id;
+
+  bool operator==(const EffectNode& other) const;
+
+  void ToProtobuf(proto::TreeNode* proto) const;
+  void FromProtobuf(const proto::TreeNode& proto);
+  void AsValueInto(base::trace_event::TracedValue* value) const;
+};
+
+}  // namespace cc
+
+#endif  // CC_TREES_EFFECT_NODE_H_
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index 98aa7f3..0263d55 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -18,9 +18,11 @@
 #include "cc/proto/begin_main_frame_and_commit_state.pb.h"
 #include "cc/proto/gfx_conversions.h"
 #include "cc/trees/draw_property_utils.h"
+#include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/property_tree_builder.h"
+#include "cc/trees/scroll_node.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
 #include "ui/gfx/transform.h"
@@ -219,11 +221,10 @@
     ScrollTree* scroll_tree) {
   for (LayerImpl* layer : *layer_list) {
     if (layer->is_drawn_render_surface_layer_list_member()) {
-      DCHECK_GT(scroll_tree->Node(layer->scroll_tree_index())
-                    ->data.num_drawn_descendants,
-                0);
-      scroll_tree->Node(layer->scroll_tree_index())
-          ->data.num_drawn_descendants--;
+      DCHECK_GT(
+          scroll_tree->Node(layer->scroll_tree_index())->num_drawn_descendants,
+          0);
+      scroll_tree->Node(layer->scroll_tree_index())->num_drawn_descendants--;
     }
     layer->set_is_drawn_render_surface_layer_list_member(false);
   }
@@ -303,14 +304,14 @@
                                                 ScrollTree* scroll_tree) {
   for (int i = static_cast<int>(scroll_tree->size()) - 1; i > 0; --i) {
     ScrollNode* node = scroll_tree->Node(i);
-    scroll_tree->parent(node)->data.num_drawn_descendants +=
-        node->data.num_drawn_descendants;
+    scroll_tree->parent(node)->num_drawn_descendants +=
+        node->num_drawn_descendants;
   }
   for (LayerImpl* layer : *layer_tree_impl) {
     bool scrolls_drawn_descendant = false;
     if (layer->scrollable()) {
       ScrollNode* node = scroll_tree->Node(layer->scroll_tree_index());
-      if (node->data.num_drawn_descendants > 0)
+      if (node->num_drawn_descendants > 0)
         scrolls_drawn_descendant = true;
     }
     layer->set_scrolls_drawn_descendant(scrolls_drawn_descendant);
@@ -324,7 +325,7 @@
     bool can_render_to_separate_surface) {
   ScrollTree* scroll_tree = &property_trees->scroll_tree;
   for (int i = 0; i < static_cast<int>(scroll_tree->size()); ++i)
-    scroll_tree->Node(i)->data.num_drawn_descendants = 0;
+    scroll_tree->Node(i)->num_drawn_descendants = 0;
 
   // Add all non-skipped surfaces to the initial render surface layer list. Add
   // all non-skipped layers to the layer list of their target surface, and
@@ -338,8 +339,7 @@
     layer->set_is_drawn_render_surface_layer_list_member(false);
 
     bool layer_is_drawn =
-        property_trees->effect_tree.Node(layer->effect_tree_index())
-            ->data.is_drawn;
+        property_trees->effect_tree.Node(layer->effect_tree_index())->is_drawn;
     bool is_root = layer_tree_impl->IsRootLayer(layer);
     bool skip_layer =
         !is_root && draw_property_utils::LayerShouldBeSkipped(
@@ -399,7 +399,7 @@
       continue;
 
     layer->set_is_drawn_render_surface_layer_list_member(true);
-    scroll_tree->Node(layer->scroll_tree_index())->data.num_drawn_descendants++;
+    scroll_tree->Node(layer->scroll_tree_index())->num_drawn_descendants++;
     layer->render_target()->layer_list().push_back(layer);
 
     // The layer contributes its drawable content rect to its render target.
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index 4f47e2ea..52386ed 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -40,10 +40,14 @@
 #include "cc/test/geometry_test_utils.h"
 #include "cc/test/layer_tree_host_common_test.h"
 #include "cc/test/test_task_graph_runner.h"
+#include "cc/trees/clip_node.h"
 #include "cc/trees/draw_property_utils.h"
+#include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/scroll_node.h"
 #include "cc/trees/single_thread_proxy.h"
 #include "cc/trees/task_runner_provider.h"
+#include "cc/trees/transform_node.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/effects/SkOffsetImageFilter.h"
@@ -189,7 +193,7 @@
   const int transform_tree_size = parent->layer_tree_impl()
                                       ->property_trees()
                                       ->transform_tree.next_available_id();
-  EXPECT_LT(node->data.transform_id, transform_tree_size);
+  EXPECT_LT(node->transform_id, transform_tree_size);
 }
 
 TEST_F(LayerTreeHostCommonTest, TransformsForSingleLayer) {
@@ -1373,7 +1377,7 @@
   EffectTree& effect_tree =
       parent->layer_tree_impl()->property_trees()->effect_tree;
   EffectNode* node = effect_tree.Node(render_surface1->effect_tree_index());
-  EXPECT_TRUE(node->data.is_drawn);
+  EXPECT_TRUE(node->is_drawn);
 
   // When parent is transparent, the layer should not be drawn.
   parent->OnOpacityAnimated(0.f);
@@ -1388,7 +1392,7 @@
   }
 
   node = effect_tree.Node(render_surface1->effect_tree_index());
-  EXPECT_FALSE(node->data.is_drawn);
+  EXPECT_FALSE(node->is_drawn);
   EXPECT_EQ(gfx::Rect(), render_surface1->visible_layer_rect());
 }
 
@@ -1707,9 +1711,6 @@
   EXPECT_TRUE(child->test_properties()->should_flatten_transform);
   EXPECT_FALSE(grand_child->test_properties()->should_flatten_transform);
 
-  gfx::Transform expected_child_draw_transform = identity_matrix;
-  gfx::Transform expected_grand_child_draw_transform = identity_matrix;
-
   gfx::Transform flattened_rotation_about_y = rotation_about_y_axis;
   flattened_rotation_about_y.FlattenTo2d();
 
@@ -3675,7 +3676,7 @@
   EXPECT_FALSE(root->layer_tree_impl()
                    ->property_trees()
                    ->transform_tree.Node(grand_child->transform_tree_index())
-                   ->data.ancestors_are_invertible);
+                   ->ancestors_are_invertible);
 
   // CalcDrawProps skips a subtree when a layer's screen space transform is
   // uninvertible
@@ -3748,7 +3749,7 @@
       host_impl.active_tree()
           ->property_trees()
           ->transform_tree.Node(grand_child_ptr->transform_tree_index())
-          ->data.ancestors_are_invertible);
+          ->ancestors_are_invertible);
 
   // Since |grand_child| has an uninvertible screen space transform, it is
   // skipped so
@@ -4993,7 +4994,7 @@
 
   gfx::Transform expected_duplicate_child_draw_transform =
       child->DrawTransform();
-  EXPECT_TRANSFORMATION_MATRIX_EQ(child->DrawTransform(),
+  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_duplicate_child_draw_transform,
                                   duplicate_child_non_owner->DrawTransform());
   EXPECT_TRANSFORMATION_MATRIX_EQ(
       child->ScreenSpaceTransform(),
@@ -5207,7 +5208,7 @@
   EffectTree& tree =
       root_layer->layer_tree_impl()->property_trees()->effect_tree;
   EffectNode* node = tree.Node(child_ptr->effect_tree_index());
-  EXPECT_FALSE(node->data.is_drawn);
+  EXPECT_FALSE(node->is_drawn);
 
   // A layer should be drawn and it should contribute to drawn surface when
   // it has animating opacity even if it has opacity 0.
@@ -5223,7 +5224,7 @@
   child_ptr = root_layer->layer_tree_impl()->LayerById(2);
   tree = root_layer->layer_tree_impl()->property_trees()->effect_tree;
   node = tree.Node(child_ptr->effect_tree_index());
-  EXPECT_TRUE(node->data.is_drawn);
+  EXPECT_TRUE(node->is_drawn);
   EXPECT_TRUE(tree.ContributesToDrawnSurface(child_ptr->effect_tree_index()));
 
   // But if the opacity of the layer remains 0 after activation, it should not
@@ -5239,7 +5240,7 @@
   ExecuteCalculateDrawProperties(active_root);
 
   node = active_effect_tree.Node(active_child->effect_tree_index());
-  EXPECT_FALSE(node->data.is_drawn);
+  EXPECT_FALSE(node->is_drawn);
   EXPECT_FALSE(active_effect_tree.ContributesToDrawnSurface(
       active_child->effect_tree_index()));
 }
@@ -5723,15 +5724,15 @@
   EffectTree& tree =
       root_layer->layer_tree_impl()->property_trees()->effect_tree;
   EffectNode* node = tree.Node(copy_grand_parent_layer->effect_tree_index());
-  EXPECT_FALSE(node->data.is_drawn);
+  EXPECT_FALSE(node->is_drawn);
   node = tree.Node(copy_parent_layer->effect_tree_index());
-  EXPECT_FALSE(node->data.is_drawn);
+  EXPECT_FALSE(node->is_drawn);
   node = tree.Node(copy_layer->effect_tree_index());
-  EXPECT_TRUE(node->data.is_drawn);
+  EXPECT_TRUE(node->is_drawn);
   node = tree.Node(copy_child_layer->effect_tree_index());
-  EXPECT_TRUE(node->data.is_drawn);
+  EXPECT_TRUE(node->is_drawn);
   node = tree.Node(copy_grand_child_layer->effect_tree_index());
-  EXPECT_FALSE(node->data.is_drawn);
+  EXPECT_FALSE(node->is_drawn);
 
   // Though copy_layer is drawn, it shouldn't contribute to drawn surface as its
   // actually hidden.
@@ -6650,24 +6651,24 @@
   const EffectTree& tree =
       root->layer_tree_impl()->property_trees()->effect_tree;
   EXPECT_TRUE(tree.Node(render_surface1->effect_tree_index())
-                  ->data.hidden_by_backface_visibility);
+                  ->hidden_by_backface_visibility);
   EXPECT_TRUE(tree.Node(render_surface2->effect_tree_index())
-                  ->data.hidden_by_backface_visibility);
+                  ->hidden_by_backface_visibility);
 
   back_facing->OnTransformAnimated(identity_transform);
   render_surface2->OnTransformAnimated(rotate_about_y);
   ExecuteCalculateDrawProperties(root);
   EXPECT_FALSE(tree.Node(render_surface1->effect_tree_index())
-                   ->data.hidden_by_backface_visibility);
+                   ->hidden_by_backface_visibility);
   EXPECT_TRUE(tree.Node(render_surface2->effect_tree_index())
-                  ->data.hidden_by_backface_visibility);
+                  ->hidden_by_backface_visibility);
 
   render_surface1->OnTransformAnimated(rotate_about_y);
   ExecuteCalculateDrawProperties(root);
   EXPECT_TRUE(tree.Node(render_surface1->effect_tree_index())
-                  ->data.hidden_by_backface_visibility);
+                  ->hidden_by_backface_visibility);
   EXPECT_TRUE(tree.Node(render_surface2->effect_tree_index())
-                  ->data.hidden_by_backface_visibility);
+                  ->hidden_by_backface_visibility);
 }
 
 TEST_F(LayerTreeHostCommonTest, ClippedByScrollParent) {
@@ -9332,7 +9333,7 @@
 
   ClipTree& clip_tree = root->layer_tree_impl()->property_trees()->clip_tree;
   ClipNode* clip_node = clip_tree.Node(render_surface->clip_tree_index());
-  EXPECT_FALSE(clip_node->data.applies_local_clip);
+  EXPECT_FALSE(clip_node->applies_local_clip);
   EXPECT_EQ(gfx::Rect(20, 20), test_layer->visible_layer_rect());
 }
 
@@ -9980,13 +9981,13 @@
   TransformTree& tree =
       root->layer_tree_impl()->property_trees()->transform_tree;
   TransformNode* node = tree.Node(render_surface1->transform_tree_index());
-  EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(2.f, 2.f));
+  EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(2.f, 2.f));
 
   node = tree.Node(between_targets->transform_tree_index());
-  EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(1.f, 1.f));
+  EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(1.f, 1.f));
 
   node = tree.Node(render_surface2->transform_tree_index());
-  EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(2.f, 2.f));
+  EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(2.f, 2.f));
 
   EXPECT_EQ(gfx::Rect(15, 15), test_layer->visible_layer_rect());
 }
@@ -10126,20 +10127,20 @@
 
   EffectTree& tree = root->layer_tree_host()->property_trees()->effect_tree;
   EffectNode* node = tree.Node(animated->effect_tree_index());
-  EXPECT_FALSE(node->data.is_currently_animating_opacity);
-  EXPECT_TRUE(node->data.has_potential_opacity_animation);
+  EXPECT_FALSE(node->is_currently_animating_opacity);
+  EXPECT_TRUE(node->has_potential_opacity_animation);
 
   animation_ptr->set_time_offset(base::TimeDelta::FromMilliseconds(0));
   root->layer_tree_host()->AnimateLayers(
       base::TimeTicks::FromInternalValue(std::numeric_limits<int64_t>::max()));
   node = tree.Node(animated->effect_tree_index());
-  EXPECT_TRUE(node->data.is_currently_animating_opacity);
-  EXPECT_TRUE(node->data.has_potential_opacity_animation);
+  EXPECT_TRUE(node->is_currently_animating_opacity);
+  EXPECT_TRUE(node->has_potential_opacity_animation);
 
   player->AbortAnimations(TargetProperty::OPACITY, false /*needs_completion*/);
   node = tree.Node(animated->effect_tree_index());
-  EXPECT_FALSE(node->data.is_currently_animating_opacity);
-  EXPECT_FALSE(node->data.has_potential_opacity_animation);
+  EXPECT_FALSE(node->is_currently_animating_opacity);
+  EXPECT_FALSE(node->has_potential_opacity_animation);
 }
 
 TEST_F(LayerTreeHostCommonTest, TransformAnimationsTrackingTest) {
@@ -10190,21 +10191,21 @@
   TransformTree& tree =
       root->layer_tree_host()->property_trees()->transform_tree;
   TransformNode* node = tree.Node(animated->transform_tree_index());
-  EXPECT_FALSE(node->data.is_currently_animating);
-  EXPECT_TRUE(node->data.has_potential_animation);
+  EXPECT_FALSE(node->is_currently_animating);
+  EXPECT_TRUE(node->has_potential_animation);
 
   animation_ptr->set_time_offset(base::TimeDelta::FromMilliseconds(0));
   root->layer_tree_host()->AnimateLayers(
       base::TimeTicks::FromInternalValue(std::numeric_limits<int64_t>::max()));
   node = tree.Node(animated->transform_tree_index());
-  EXPECT_TRUE(node->data.is_currently_animating);
-  EXPECT_TRUE(node->data.has_potential_animation);
+  EXPECT_TRUE(node->is_currently_animating);
+  EXPECT_TRUE(node->has_potential_animation);
 
   player->AbortAnimations(TargetProperty::TRANSFORM,
                           false /*needs_completion*/);
   node = tree.Node(animated->transform_tree_index());
-  EXPECT_FALSE(node->data.is_currently_animating);
-  EXPECT_FALSE(node->data.has_potential_animation);
+  EXPECT_FALSE(node->is_currently_animating);
+  EXPECT_FALSE(node->has_potential_animation);
 }
 
 TEST_F(LayerTreeHostCommonTest, SerializeScrollUpdateInfo) {
@@ -10341,82 +10342,81 @@
   property_tree_root->id = kRootPropertyTreeNodeId;
   property_tree_root->parent_id = kInvalidPropertyTreeNodeId;
   property_tree_root->owner_id = kInvalidPropertyTreeNodeId;
-  property_tree_root->data.scrollable = false;
-  property_tree_root->data.main_thread_scrolling_reasons =
+  property_tree_root->scrollable = false;
+  property_tree_root->main_thread_scrolling_reasons =
       MainThreadScrollingReason::kNotScrollingOnMain;
-  property_tree_root->data.contains_non_fast_scrollable_region = false;
-  property_tree_root->data.transform_id = kRootPropertyTreeNodeId;
+  property_tree_root->contains_non_fast_scrollable_region = false;
+  property_tree_root->transform_id = kRootPropertyTreeNodeId;
 
   // The node owned by root1
   ScrollNode scroll_root1;
   scroll_root1.id = 1;
   scroll_root1.owner_id = root1->id();
-  scroll_root1.data.user_scrollable_horizontal = true;
-  scroll_root1.data.user_scrollable_vertical = true;
-  scroll_root1.data.transform_id = root1->transform_tree_index();
+  scroll_root1.user_scrollable_horizontal = true;
+  scroll_root1.user_scrollable_vertical = true;
+  scroll_root1.transform_id = root1->transform_tree_index();
   expected_scroll_tree.Insert(scroll_root1, 0);
 
   // The node owned by parent2
   ScrollNode scroll_parent2;
   scroll_parent2.id = 2;
   scroll_parent2.owner_id = parent2->id();
-  scroll_parent2.data.scrollable = true;
-  scroll_parent2.data.main_thread_scrolling_reasons =
+  scroll_parent2.scrollable = true;
+  scroll_parent2.main_thread_scrolling_reasons =
       parent2->main_thread_scrolling_reasons();
-  scroll_parent2.data.scroll_clip_layer_bounds = root1->bounds();
-  scroll_parent2.data.bounds = parent2->bounds();
-  scroll_parent2.data.max_scroll_offset_affected_by_page_scale = true;
-  scroll_parent2.data.is_inner_viewport_scroll_layer = true;
-  scroll_parent2.data.user_scrollable_horizontal = true;
-  scroll_parent2.data.user_scrollable_vertical = true;
-  scroll_parent2.data.transform_id = parent2->transform_tree_index();
+  scroll_parent2.scroll_clip_layer_bounds = root1->bounds();
+  scroll_parent2.bounds = parent2->bounds();
+  scroll_parent2.max_scroll_offset_affected_by_page_scale = true;
+  scroll_parent2.is_inner_viewport_scroll_layer = true;
+  scroll_parent2.user_scrollable_horizontal = true;
+  scroll_parent2.user_scrollable_vertical = true;
+  scroll_parent2.transform_id = parent2->transform_tree_index();
   expected_scroll_tree.Insert(scroll_parent2, 1);
 
   // The node owned by child6
   ScrollNode scroll_child6;
   scroll_child6.id = 3;
   scroll_child6.owner_id = child6->id();
-  scroll_child6.data.main_thread_scrolling_reasons =
+  scroll_child6.main_thread_scrolling_reasons =
       child6->main_thread_scrolling_reasons();
-  scroll_child6.data.should_flatten = true;
-  scroll_child6.data.user_scrollable_horizontal = true;
-  scroll_child6.data.user_scrollable_vertical = true;
-  scroll_child6.data.transform_id = child6->transform_tree_index();
+  scroll_child6.should_flatten = true;
+  scroll_child6.user_scrollable_horizontal = true;
+  scroll_child6.user_scrollable_vertical = true;
+  scroll_child6.transform_id = child6->transform_tree_index();
   expected_scroll_tree.Insert(scroll_child6, 2);
 
   // The node owned by child7, child7 also owns a transform node
   ScrollNode scroll_child7;
   scroll_child7.id = 4;
   scroll_child7.owner_id = child7->id();
-  scroll_child7.data.scrollable = true;
-  scroll_child7.data.scroll_clip_layer_bounds = parent3->bounds();
-  scroll_child7.data.bounds = child7->bounds();
-  scroll_child7.data.user_scrollable_horizontal = true;
-  scroll_child7.data.user_scrollable_vertical = true;
-  scroll_child7.data.transform_id = child7->transform_tree_index();
+  scroll_child7.scrollable = true;
+  scroll_child7.scroll_clip_layer_bounds = parent3->bounds();
+  scroll_child7.bounds = child7->bounds();
+  scroll_child7.user_scrollable_horizontal = true;
+  scroll_child7.user_scrollable_vertical = true;
+  scroll_child7.transform_id = child7->transform_tree_index();
   expected_scroll_tree.Insert(scroll_child7, 1);
 
   // The node owned by grand_child11, grand_child11 also owns a transform node
   ScrollNode scroll_grand_child11;
   scroll_grand_child11.id = 5;
   scroll_grand_child11.owner_id = grand_child11->id();
-  scroll_grand_child11.data.scrollable = true;
-  scroll_grand_child11.data.user_scrollable_horizontal = true;
-  scroll_grand_child11.data.user_scrollable_vertical = true;
-  scroll_grand_child11.data.transform_id =
-      grand_child11->transform_tree_index();
+  scroll_grand_child11.scrollable = true;
+  scroll_grand_child11.user_scrollable_horizontal = true;
+  scroll_grand_child11.user_scrollable_vertical = true;
+  scroll_grand_child11.transform_id = grand_child11->transform_tree_index();
   expected_scroll_tree.Insert(scroll_grand_child11, 4);
 
   // The node owned by parent5
   ScrollNode scroll_parent5;
   scroll_parent5.id = 8;
   scroll_parent5.owner_id = parent5->id();
-  scroll_parent5.data.contains_non_fast_scrollable_region = true;
-  scroll_parent5.data.bounds = gfx::Size(10, 10);
-  scroll_parent5.data.should_flatten = true;
-  scroll_parent5.data.user_scrollable_horizontal = true;
-  scroll_parent5.data.user_scrollable_vertical = true;
-  scroll_parent5.data.transform_id = parent5->transform_tree_index();
+  scroll_parent5.contains_non_fast_scrollable_region = true;
+  scroll_parent5.bounds = gfx::Size(10, 10);
+  scroll_parent5.should_flatten = true;
+  scroll_parent5.user_scrollable_horizontal = true;
+  scroll_parent5.user_scrollable_vertical = true;
+  scroll_parent5.transform_id = parent5->transform_tree_index();
   expected_scroll_tree.Insert(scroll_parent5, 1);
 
   expected_scroll_tree.SetScrollOffset(parent2->id(), gfx::ScrollOffset(0, 0));
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 9f1b377..dd3c629 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -82,6 +82,7 @@
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/scroll_node.h"
 #include "cc/trees/single_thread_proxy.h"
 #include "cc/trees/tree_synchronizer.h"
 #include "gpu/GLES2/gl2extchromium.h"
@@ -2457,11 +2458,11 @@
   InputHandler::ScrollStatus scroll_status;
   scroll_status.main_thread_scrolling_reasons =
       MainThreadScrollingReason::kNotScrollingOnMain;
-  if (!!scroll_node->data.main_thread_scrolling_reasons) {
+  if (!!scroll_node->main_thread_scrolling_reasons) {
     TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
     scroll_status.thread = InputHandler::SCROLL_ON_MAIN_THREAD;
     scroll_status.main_thread_scrolling_reasons =
-        scroll_node->data.main_thread_scrolling_reasons;
+        scroll_node->main_thread_scrolling_reasons;
     return scroll_status;
   }
 
@@ -2475,7 +2476,7 @@
     return scroll_status;
   }
 
-  if (scroll_node->data.contains_non_fast_scrollable_region) {
+  if (scroll_node->contains_non_fast_scrollable_region) {
     bool clipped = false;
     gfx::Transform inverse_screen_space_transform(
         gfx::Transform::kSkipInitialization);
@@ -2501,7 +2502,7 @@
     }
   }
 
-  if (!scroll_node->data.scrollable) {
+  if (!scroll_node->scrollable) {
     TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable");
     scroll_status.thread = InputHandler::SCROLL_IGNORED;
     scroll_status.main_thread_scrolling_reasons =
@@ -2528,7 +2529,7 @@
 static bool IsMainThreadScrolling(const InputHandler::ScrollStatus& status,
                                   const ScrollNode* scroll_node) {
   if (status.thread == InputHandler::SCROLL_ON_MAIN_THREAD) {
-    if (!!scroll_node->data.main_thread_scrolling_reasons) {
+    if (!!scroll_node->main_thread_scrolling_reasons) {
       DCHECK(MainThreadScrollingReason::MainThreadCanSetScrollReasons(
           status.main_thread_scrolling_reasons));
     } else {
@@ -2612,7 +2613,7 @@
   ScrollNode* scroll_node = scroll_tree.Node(child->scroll_tree_index());
   for (; scroll_tree.parent(scroll_node);
        scroll_node = scroll_tree.parent(scroll_node)) {
-    if (scroll_node->data.scrollable)
+    if (scroll_node->scrollable)
       return scroll_node->owner_id == scroll_ancestor->id();
   }
   return false;
@@ -2762,9 +2763,9 @@
 
   gfx::Vector2dF adjusted_scroll(delta);
   adjusted_scroll.Scale(1.f / scale_factor);
-  if (!scroll_node->data.user_scrollable_horizontal)
+  if (!scroll_node->user_scrollable_horizontal)
     adjusted_scroll.set_x(0);
-  if (!scroll_node->data.user_scrollable_vertical)
+  if (!scroll_node->user_scrollable_vertical)
     adjusted_scroll.set_y(0);
 
   gfx::ScrollOffset old_offset =
@@ -2796,9 +2797,9 @@
       current_offset + gfx::ScrollOffset(delta), scroll_node);
   DCHECK_EQ(
       ElementId(active_tree()->LayerById(scroll_node->owner_id)->element_id()),
-      scroll_node->data.element_id);
+      scroll_node->element_id);
 
-  animation_host_->ImplOnlyScrollAnimationCreate(scroll_node->data.element_id,
+  animation_host_->ImplOnlyScrollAnimationCreate(scroll_node->element_id,
                                                  target_offset, current_offset);
 
   SetNeedsOneBeginImplFrame();
@@ -2816,9 +2817,9 @@
   ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode();
   if (scroll_node) {
     gfx::Vector2dF delta = scroll_delta;
-    if (!scroll_node->data.user_scrollable_horizontal)
+    if (!scroll_node->user_scrollable_horizontal)
       delta.set_x(0);
-    if (!scroll_node->data.user_scrollable_vertical)
+    if (!scroll_node->user_scrollable_vertical)
       delta.set_y(0);
 
     if (ScrollAnimationUpdateTarget(scroll_node, delta)) {
@@ -2848,11 +2849,11 @@
     if (scroll_node) {
       for (; scroll_tree.parent(scroll_node);
            scroll_node = scroll_tree.parent(scroll_node)) {
-        if (!scroll_node->data.scrollable ||
-            scroll_node->data.is_outer_viewport_scroll_layer)
+        if (!scroll_node->scrollable ||
+            scroll_node->is_outer_viewport_scroll_layer)
           continue;
 
-        if (scroll_node->data.is_inner_viewport_scroll_layer) {
+        if (scroll_node->is_inner_viewport_scroll_layer) {
           gfx::Vector2dF scrolled = viewport()->ScrollAnimated(pending_delta);
           // Viewport::ScrollAnimated returns pending_delta as long as it
           // starts an animation.
@@ -3002,7 +3003,7 @@
   // details.
   const float kEpsilon = 0.1f;
 
-  if (scroll_node->data.is_inner_viewport_scroll_layer) {
+  if (scroll_node->is_inner_viewport_scroll_layer) {
     bool affect_top_controls = !wheel_scrolling_;
     Viewport::ScrollResult result = viewport()->ScrollBy(
         delta, viewport_point, scroll_state->is_direct_manipulation(),
@@ -3023,7 +3024,7 @@
   bool scrolled = std::abs(applied_delta.x()) > kEpsilon;
   scrolled = scrolled || std::abs(applied_delta.y()) > kEpsilon;
 
-  if (scrolled && !scroll_node->data.is_inner_viewport_scroll_layer) {
+  if (scrolled && !scroll_node->is_inner_viewport_scroll_layer) {
     // If the applied delta is within 45 degrees of the input
     // delta, bail out to make it easier to scroll just one layer
     // in one direction without affecting any of its parents.
@@ -3061,8 +3062,8 @@
       // Skip the outer viewport scroll layer so that we try to scroll the
       // viewport only once. i.e. The inner viewport layer represents the
       // viewport.
-      if (!scroll_node->data.scrollable ||
-          scroll_node->data.is_outer_viewport_scroll_layer)
+      if (!scroll_node->scrollable ||
+          scroll_node->is_outer_viewport_scroll_layer)
         continue;
       current_scroll_chain.push_front(scroll_node);
     }
@@ -3162,8 +3163,8 @@
     for (; scroll_tree.parent(scroll_node);
          scroll_node = scroll_tree.parent(scroll_node)) {
       // The inner viewport layer represents the viewport.
-      if (!scroll_node->data.scrollable ||
-          scroll_node->data.is_outer_viewport_scroll_layer)
+      if (!scroll_node->scrollable ||
+          scroll_node->is_outer_viewport_scroll_layer)
         continue;
 
       float height =
@@ -3819,10 +3820,10 @@
     const gfx::Vector2dF& scroll_delta) {
   DCHECK_EQ(
       ElementId(active_tree()->LayerById(scroll_node->owner_id)->element_id()),
-      scroll_node->data.element_id);
+      scroll_node->element_id);
 
   return animation_host_->ImplOnlyScrollAnimationUpdateTarget(
-      scroll_node->data.element_id, scroll_delta,
+      scroll_node->element_id, scroll_delta,
       active_tree_->property_trees()->scroll_tree.MaxScrollOffset(
           scroll_node->id),
       CurrentBeginFrameArgs().frame_time);
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 6a24e4a..b3807cf 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -62,8 +62,10 @@
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/test/test_web_graphics_context_3d.h"
+#include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/single_thread_proxy.h"
+#include "cc/trees/transform_node.h"
 #include "media/base/media.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -2940,7 +2942,7 @@
         host_impl_->active_tree()->property_trees()->effect_tree.Node(
             active_scrollbar_layer->effect_tree_index());
     EXPECT_FLOAT_EQ(active_scrollbar_layer->Opacity(),
-                    active_tree_node->data.opacity);
+                    active_tree_node->opacity);
 
     host_impl_->ScrollbarAnimationControllerForId(scroll->id())
         ->DidMouseMoveNear(0);
@@ -2964,14 +2966,14 @@
     host_impl_->pending_tree()
         ->property_trees()
         ->always_use_active_tree_opacity_effect_ids.push_back(400);
-    EXPECT_FLOAT_EQ(1.f, active_tree_node->data.opacity);
+    EXPECT_FLOAT_EQ(1.f, active_tree_node->opacity);
     EXPECT_FLOAT_EQ(1.f, active_scrollbar_layer->Opacity());
-    EXPECT_FLOAT_EQ(0.f, pending_tree_node->data.opacity);
+    EXPECT_FLOAT_EQ(0.f, pending_tree_node->opacity);
     host_impl_->ActivateSyncTree();
     active_tree_node =
         host_impl_->active_tree()->property_trees()->effect_tree.Node(
             active_scrollbar_layer->effect_tree_index());
-    EXPECT_FLOAT_EQ(1.f, active_tree_node->data.opacity);
+    EXPECT_FLOAT_EQ(1.f, active_tree_node->opacity);
     EXPECT_FLOAT_EQ(1.f, active_scrollbar_layer->Opacity());
   }
 };
@@ -9854,7 +9856,7 @@
   TransformNode* node =
       host_impl_->active_tree()->property_trees()->transform_tree.Node(
           test_layer->transform_tree_index());
-  EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(1.f, 1.f));
+  EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(1.f, 1.f));
 
   gfx::Transform external_transform;
   external_transform.Translate(10, 10);
@@ -9870,7 +9872,7 @@
                      resourceless_software_draw);
   node = host_impl_->active_tree()->property_trees()->transform_tree.Node(
       test_layer->transform_tree_index());
-  EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(2.f, 2.f));
+  EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(2.f, 2.f));
 
   // Clear the external transform.
   external_transform = gfx::Transform();
@@ -9881,7 +9883,7 @@
                      resourceless_software_draw);
   node = host_impl_->active_tree()->property_trees()->transform_tree.Node(
       test_layer->transform_tree_index());
-  EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(1.f, 1.f));
+  EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(1.f, 1.f));
 }
 
 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
@@ -10897,27 +10899,27 @@
       host_impl_->active_tree()->property_trees()->transform_tree.Node(
           page_scale_layer->transform_tree_index());
   // SetPageScaleOnActiveTree also updates the factors in property trees.
-  EXPECT_EQ(active_tree_node->data.post_local_scale_factor, 2.f);
+  EXPECT_EQ(active_tree_node->post_local_scale_factor, 2.f);
   EXPECT_EQ(host_impl_->active_tree()->current_page_scale_factor(), 2.f);
 
   TransformNode* pending_tree_node =
       host_impl_->pending_tree()->property_trees()->transform_tree.Node(
           page_scale_layer->transform_tree_index());
-  EXPECT_EQ(pending_tree_node->data.post_local_scale_factor, 1.f);
+  EXPECT_EQ(pending_tree_node->post_local_scale_factor, 1.f);
   EXPECT_EQ(host_impl_->pending_tree()->current_page_scale_factor(), 2.f);
 
   host_impl_->pending_tree()->UpdateDrawProperties(false);
   pending_tree_node =
       host_impl_->pending_tree()->property_trees()->transform_tree.Node(
           page_scale_layer->transform_tree_index());
-  EXPECT_EQ(pending_tree_node->data.post_local_scale_factor, 2.f);
+  EXPECT_EQ(pending_tree_node->post_local_scale_factor, 2.f);
 
   host_impl_->ActivateSyncTree();
   host_impl_->active_tree()->UpdateDrawProperties(false);
   active_tree_node =
       host_impl_->active_tree()->property_trees()->transform_tree.Node(
           page_scale_layer->transform_tree_index());
-  EXPECT_EQ(active_tree_node->data.post_local_scale_factor, 2.f);
+  EXPECT_EQ(active_tree_node->post_local_scale_factor, 2.f);
 }
 
 TEST_F(LayerTreeHostImplTest, SubLayerScaleForNodeInSubtreeOfPageScaleLayer) {
@@ -10940,7 +10942,7 @@
   TransformNode* node =
       host_impl_->active_tree()->property_trees()->transform_tree.Node(
           in_subtree_of_page_scale_layer->transform_tree_index());
-  EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(1.f, 1.f));
+  EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(1.f, 1.f));
 
   host_impl_->active_tree()->SetPageScaleOnActiveTree(2.f);
 
@@ -10949,7 +10951,7 @@
   in_subtree_of_page_scale_layer = host_impl_->active_tree()->LayerById(100);
   node = host_impl_->active_tree()->property_trees()->transform_tree.Node(
       in_subtree_of_page_scale_layer->transform_tree_index());
-  EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(2.f, 2.f));
+  EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(2.f, 2.f));
 }
 
 TEST_F(LayerTreeHostImplTest, JitterTest) {
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 5530858f..3e298044 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -49,9 +49,11 @@
 #include "cc/test/layer_tree_test.h"
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_web_graphics_context_3d.h"
+#include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_host_impl.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/single_thread_proxy.h"
+#include "cc/trees/transform_node.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/khronos/GLES2/gl2.h"
@@ -979,11 +981,11 @@
     EffectNode* node = effect_tree.Node(root_->effect_tree_index());
     switch (layer_tree_host()->source_frame_number()) {
       case 1:
-        node->data.opacity = 0.5f;
-        node->data.is_currently_animating_opacity = true;
+        node->opacity = 0.5f;
+        node->is_currently_animating_opacity = true;
         break;
       case 2:
-        node->data.is_currently_animating_opacity = false;
+        node->is_currently_animating_opacity = false;
         break;
     }
   }
@@ -998,12 +1000,12 @@
         PostSetNeedsCommitToMainThread();
         break;
       case 1:
-        EXPECT_EQ(node->data.opacity, 0.75f);
+        EXPECT_EQ(node->opacity, 0.75f);
         impl->sync_tree()->root_layer_for_testing()->OnOpacityAnimated(0.75f);
         PostSetNeedsCommitToMainThread();
         break;
       case 2:
-        EXPECT_EQ(node->data.opacity, 0.5f);
+        EXPECT_EQ(node->opacity, 0.5f);
         EndTest();
         break;
     }
@@ -1035,14 +1037,14 @@
     rotate10.Rotate(10.f);
     switch (layer_tree_host()->source_frame_number()) {
       case 1:
-        node->data.local = rotate10;
-        node->data.is_currently_animating = true;
+        node->local = rotate10;
+        node->is_currently_animating = true;
         break;
       case 2:
-        node->data.is_currently_animating = true;
+        node->is_currently_animating = true;
         break;
       case 3:
-        node->data.is_currently_animating = false;
+        node->is_currently_animating = false;
         break;
     }
   }
@@ -1063,19 +1065,19 @@
         PostSetNeedsCommitToMainThread();
         break;
       case 1:
-        EXPECT_EQ(node->data.local, rotate20);
+        EXPECT_EQ(node->local, rotate20);
         impl->sync_tree()->root_layer_for_testing()->OnTransformAnimated(
             rotate20);
         PostSetNeedsCommitToMainThread();
         break;
       case 2:
-        EXPECT_EQ(node->data.local, rotate20);
+        EXPECT_EQ(node->local, rotate20);
         impl->sync_tree()->root_layer_for_testing()->OnTransformAnimated(
             rotate20);
         PostSetNeedsCommitToMainThread();
         break;
       case 3:
-        EXPECT_EQ(node->data.local, rotate10);
+        EXPECT_EQ(node->local, rotate10);
         EndTest();
     }
   }
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc
index 9d7ba1f..4d660a5 100644
--- a/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -25,6 +25,7 @@
 #include "cc/test/fake_picture_layer.h"
 #include "cc/test/layer_tree_test.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/transform_node.h"
 
 namespace cc {
 namespace {
@@ -1686,7 +1687,7 @@
     translate.Translate(5, 5);
     switch (host_impl->sync_tree()->source_frame_number()) {
       case 2:
-        EXPECT_TRANSFORMATION_MATRIX_EQ(node->data.local, translate);
+        EXPECT_TRANSFORMATION_MATRIX_EQ(node->local, translate);
         EndTest();
         break;
       default:
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index fecc96ca..759586a 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -23,6 +23,7 @@
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/scroll_node.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index d0e1b73..4d6ec707 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -33,12 +33,16 @@
 #include "cc/layers/render_surface_impl.h"
 #include "cc/layers/scrollbar_layer_impl_base.h"
 #include "cc/resources/ui_resource_request.h"
+#include "cc/trees/clip_node.h"
 #include "cc/trees/draw_property_utils.h"
+#include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/layer_tree_host_impl.h"
 #include "cc/trees/occlusion_tracker.h"
 #include "cc/trees/property_tree.h"
 #include "cc/trees/property_tree_builder.h"
+#include "cc/trees/scroll_node.h"
+#include "cc/trees/transform_node.h"
 #include "ui/gfx/geometry/box_f.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -158,13 +162,12 @@
 
   if (transform_id != -1) {
     TransformNode* node = transform_tree.Node(transform_id);
-    if (node->data.scroll_offset !=
-        scroll_tree.current_scroll_offset(layer_id)) {
-      node->data.scroll_offset = scroll_tree.current_scroll_offset(layer_id);
-      node->data.needs_local_transform_update = true;
+    if (node->scroll_offset != scroll_tree.current_scroll_offset(layer_id)) {
+      node->scroll_offset = scroll_tree.current_scroll_offset(layer_id);
+      node->needs_local_transform_update = true;
       transform_tree.set_needs_update(true);
     }
-    node->data.transform_changed = true;
+    node->transform_changed = true;
     property_trees()->changed = true;
     set_needs_update_draw_properties();
   }
@@ -357,8 +360,8 @@
     if (clip_node) {
       DCHECK_EQ(layer->id(), clip_node->owner_id);
       gfx::SizeF bounds = gfx::SizeF(layer->bounds());
-      if (clip_node->data.clip.size() != bounds) {
-        clip_node->data.clip.set_size(bounds);
+      if (clip_node->clip.size() != bounds) {
+        clip_node->clip.set_size(bounds);
         clip_tree->set_needs_update(true);
       }
     }
@@ -619,10 +622,10 @@
     if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, id)) {
       EffectNode* node = property_trees_.effect_tree.Node(
           property_trees_.effect_id_to_index_map[id]);
-      if (!node->data.is_currently_animating_opacity ||
-          node->data.opacity == layer_id_to_opacity.second)
+      if (!node->is_currently_animating_opacity ||
+          node->opacity == layer_id_to_opacity.second)
         continue;
-      node->data.opacity = layer_id_to_opacity.second;
+      node->opacity = layer_id_to_opacity.second;
       property_trees_.effect_tree.set_needs_update(true);
     }
   }
@@ -634,11 +637,11 @@
                                          id)) {
       TransformNode* node = property_trees_.transform_tree.Node(
           property_trees_.transform_id_to_index_map[id]);
-      if (!node->data.is_currently_animating ||
-          node->data.local == layer_id_to_transform.second)
+      if (!node->is_currently_animating ||
+          node->local == layer_id_to_transform.second)
         continue;
-      node->data.local = layer_id_to_transform.second;
-      node->data.needs_local_transform_update = true;
+      node->local = layer_id_to_transform.second;
+      node->needs_local_transform_update = true;
       property_trees_.transform_tree.set_needs_update(true);
     }
   }
@@ -1660,18 +1663,18 @@
   // We first check if the point is clipped by viewport.
   const ClipNode* clip_node = clip_tree.Node(1);
   gfx::Rect combined_clip_in_target_space =
-      gfx::ToEnclosingRect(clip_node->data.combined_clip_in_target_space);
+      gfx::ToEnclosingRect(clip_node->combined_clip_in_target_space);
   if (!PointHitsRect(screen_space_point, gfx::Transform(),
                      combined_clip_in_target_space, NULL))
     return true;
 
   for (const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
        clip_node->id > 1; clip_node = clip_tree.parent(clip_node)) {
-    if (clip_node->data.applies_local_clip) {
+    if (clip_node->applies_local_clip) {
       const TransformNode* transform_node =
-          transform_tree.Node(clip_node->data.target_id);
+          transform_tree.Node(clip_node->target_id);
       gfx::Rect combined_clip_in_target_space =
-          gfx::ToEnclosingRect(clip_node->data.combined_clip_in_target_space);
+          gfx::ToEnclosingRect(clip_node->combined_clip_in_target_space);
 
       const LayerImpl* target_layer =
           layer->layer_tree_impl()->LayerById(transform_node->owner_id);
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc
index a7997b8..7c190da 100644
--- a/cc/trees/layer_tree_impl_unittest.cc
+++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -14,6 +14,7 @@
 #include "cc/test/layer_tree_host_common_test.h"
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_task_graph_runner.h"
+#include "cc/trees/clip_node.h"
 #include "cc/trees/draw_property_utils.h"
 #include "cc/trees/layer_tree_host_impl.h"
 #include "ui/gfx/geometry/size_conversions.h"
@@ -447,7 +448,7 @@
 
   ClipTree& clip_tree = host_impl().active_tree()->property_trees()->clip_tree;
   ClipNode* clip_node = clip_tree.Node(result_layer->clip_tree_index());
-  EXPECT_NE(clip_node->data.transform_id, clip_node->data.target_id);
+  EXPECT_NE(clip_node->transform_id, clip_node->target_id);
 }
 
 TEST_F(LayerTreeImplTest, HitTestingSiblings) {
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index 1612ff521..62de5d7 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -10,60 +10,22 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event_argument.h"
-#include "cc/base/math_util.h"
-#include "cc/input/main_thread_scrolling_reason.h"
-#include "cc/input/scroll_state.h"
 #include "cc/layers/layer_impl.h"
 #include "cc/output/copy_output_request.h"
-#include "cc/proto/gfx_conversions.h"
 #include "cc/proto/property_tree.pb.h"
-#include "cc/proto/scroll_offset.pb.h"
 #include "cc/proto/synced_property_conversions.h"
-#include "cc/proto/transform.pb.h"
-#include "cc/proto/vector2df.pb.h"
+#include "cc/trees/clip_node.h"
+#include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/property_tree.h"
+#include "cc/trees/scroll_node.h"
+#include "cc/trees/transform_node.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
 
 namespace cc {
 
 template <typename T>
-bool TreeNode<T>::operator==(const TreeNode<T>& other) const {
-  return id == other.id && parent_id == other.parent_id &&
-         owner_id == other.owner_id && data == other.data;
-}
-
-template <typename T>
-void TreeNode<T>::ToProtobuf(proto::TreeNode* proto) const {
-  proto->set_id(id);
-  proto->set_parent_id(parent_id);
-  proto->set_owner_id(owner_id);
-  data.ToProtobuf(proto);
-}
-
-template <typename T>
-void TreeNode<T>::FromProtobuf(const proto::TreeNode& proto) {
-  id = proto.id();
-  parent_id = proto.parent_id();
-  owner_id = proto.owner_id();
-  data.FromProtobuf(proto);
-}
-
-template <typename T>
-void TreeNode<T>::AsValueInto(base::trace_event::TracedValue* value) const {
-  value->SetInteger("id", id);
-  value->SetInteger("parent_id", parent_id);
-  value->SetInteger("owner_id", owner_id);
-  data.AsValueInto(value);
-}
-
-template struct TreeNode<TransformNodeData>;
-template struct TreeNode<ClipNodeData>;
-template struct TreeNode<EffectNodeData>;
-template struct TreeNode<ScrollNodeData>;
-
-template <typename T>
 PropertyTree<T>::PropertyTree()
     : needs_update_(false) {
   nodes_.push_back(T());
@@ -71,9 +33,15 @@
   back()->parent_id = -1;
 }
 
+// Equivalent to
+// PropertyTree<T>::~PropertyTree() = default;
+// but due to a gcc bug the generated destructor will have wrong symbol
+// visibility in component build.
 template <typename T>
-PropertyTree<T>::~PropertyTree() {
-}
+PropertyTree<T>::~PropertyTree() {}
+
+template <typename T>
+PropertyTree<T>& PropertyTree<T>::operator=(const PropertyTree<T>&) = default;
 
 TransformTree::TransformTree()
     : source_to_parent_updates_allowed_(true),
@@ -83,8 +51,8 @@
   cached_data_.push_back(TransformCachedNodeData());
 }
 
-TransformTree::~TransformTree() {
-}
+TransformTree::~TransformTree() = default;
+TransformTree& TransformTree::operator=(const TransformTree&) = default;
 
 template <typename T>
 int PropertyTree<T>::Insert(const T& tree_node, int parent_id) {
@@ -156,545 +124,6 @@
 template class PropertyTree<EffectNode>;
 template class PropertyTree<ScrollNode>;
 
-TransformNodeData::TransformNodeData()
-    : source_node_id(-1),
-      sorting_context_id(0),
-      needs_local_transform_update(true),
-      node_and_ancestors_are_animated_or_invertible(true),
-      is_invertible(true),
-      ancestors_are_invertible(true),
-      has_potential_animation(false),
-      is_currently_animating(false),
-      to_screen_is_potentially_animated(false),
-      has_only_translation_animations(true),
-      flattens_inherited_transform(false),
-      node_and_ancestors_are_flat(true),
-      node_and_ancestors_have_only_integer_translation(true),
-      scrolls(false),
-      needs_sublayer_scale(false),
-      affected_by_inner_viewport_bounds_delta_x(false),
-      affected_by_inner_viewport_bounds_delta_y(false),
-      affected_by_outer_viewport_bounds_delta_x(false),
-      affected_by_outer_viewport_bounds_delta_y(false),
-      in_subtree_of_page_scale_layer(false),
-      transform_changed(false),
-      post_local_scale_factor(1.0f) {}
-
-TransformNodeData::TransformNodeData(const TransformNodeData& other) = default;
-
-TransformNodeData::~TransformNodeData() {
-}
-
-bool TransformNodeData::operator==(const TransformNodeData& other) const {
-  return pre_local == other.pre_local && local == other.local &&
-         post_local == other.post_local && to_parent == other.to_parent &&
-         source_node_id == other.source_node_id &&
-         sorting_context_id == other.sorting_context_id &&
-         needs_local_transform_update == other.needs_local_transform_update &&
-         node_and_ancestors_are_animated_or_invertible ==
-             other.node_and_ancestors_are_animated_or_invertible &&
-         is_invertible == other.is_invertible &&
-         ancestors_are_invertible == other.ancestors_are_invertible &&
-         has_potential_animation == other.has_potential_animation &&
-         is_currently_animating == other.is_currently_animating &&
-         to_screen_is_potentially_animated ==
-             other.to_screen_is_potentially_animated &&
-         has_only_translation_animations ==
-             other.has_only_translation_animations &&
-         flattens_inherited_transform == other.flattens_inherited_transform &&
-         node_and_ancestors_are_flat == other.node_and_ancestors_are_flat &&
-         node_and_ancestors_have_only_integer_translation ==
-             other.node_and_ancestors_have_only_integer_translation &&
-         scrolls == other.scrolls &&
-         needs_sublayer_scale == other.needs_sublayer_scale &&
-         affected_by_inner_viewport_bounds_delta_x ==
-             other.affected_by_inner_viewport_bounds_delta_x &&
-         affected_by_inner_viewport_bounds_delta_y ==
-             other.affected_by_inner_viewport_bounds_delta_y &&
-         affected_by_outer_viewport_bounds_delta_x ==
-             other.affected_by_outer_viewport_bounds_delta_x &&
-         affected_by_outer_viewport_bounds_delta_y ==
-             other.affected_by_outer_viewport_bounds_delta_y &&
-         in_subtree_of_page_scale_layer ==
-             other.in_subtree_of_page_scale_layer &&
-         transform_changed == other.transform_changed &&
-         post_local_scale_factor == other.post_local_scale_factor &&
-         sublayer_scale == other.sublayer_scale &&
-         scroll_offset == other.scroll_offset &&
-         scroll_snap == other.scroll_snap &&
-         source_offset == other.source_offset &&
-         source_to_parent == other.source_to_parent;
-}
-
-void TransformNodeData::update_pre_local_transform(
-    const gfx::Point3F& transform_origin) {
-  pre_local.MakeIdentity();
-  pre_local.Translate3d(-transform_origin.x(), -transform_origin.y(),
-                        -transform_origin.z());
-}
-
-void TransformNodeData::update_post_local_transform(
-    const gfx::PointF& position,
-    const gfx::Point3F& transform_origin) {
-  post_local.MakeIdentity();
-  post_local.Scale(post_local_scale_factor, post_local_scale_factor);
-  post_local.Translate3d(
-      position.x() + source_offset.x() + transform_origin.x(),
-      position.y() + source_offset.y() + transform_origin.y(),
-      transform_origin.z());
-}
-
-void TransformNodeData::ToProtobuf(proto::TreeNode* proto) const {
-  DCHECK(!proto->has_transform_node_data());
-  proto::TranformNodeData* data = proto->mutable_transform_node_data();
-
-  TransformToProto(pre_local, data->mutable_pre_local());
-  TransformToProto(local, data->mutable_local());
-  TransformToProto(post_local, data->mutable_post_local());
-
-  TransformToProto(to_parent, data->mutable_to_parent());
-
-  data->set_source_node_id(source_node_id);
-  data->set_sorting_context_id(sorting_context_id);
-
-  data->set_needs_local_transform_update(needs_local_transform_update);
-
-  data->set_node_and_ancestors_are_animated_or_invertible(
-      node_and_ancestors_are_animated_or_invertible);
-
-  data->set_is_invertible(is_invertible);
-  data->set_ancestors_are_invertible(ancestors_are_invertible);
-
-  data->set_has_potential_animation(has_potential_animation);
-  data->set_is_currently_animating(is_currently_animating);
-  data->set_to_screen_is_potentially_animated(
-      to_screen_is_potentially_animated);
-  data->set_has_only_translation_animations(has_only_translation_animations);
-
-  data->set_flattens_inherited_transform(flattens_inherited_transform);
-  data->set_node_and_ancestors_are_flat(node_and_ancestors_are_flat);
-
-  data->set_node_and_ancestors_have_only_integer_translation(
-      node_and_ancestors_have_only_integer_translation);
-  data->set_scrolls(scrolls);
-  data->set_needs_sublayer_scale(needs_sublayer_scale);
-
-  data->set_affected_by_inner_viewport_bounds_delta_x(
-      affected_by_inner_viewport_bounds_delta_x);
-  data->set_affected_by_inner_viewport_bounds_delta_y(
-      affected_by_inner_viewport_bounds_delta_y);
-  data->set_affected_by_outer_viewport_bounds_delta_x(
-      affected_by_outer_viewport_bounds_delta_x);
-  data->set_affected_by_outer_viewport_bounds_delta_y(
-      affected_by_outer_viewport_bounds_delta_y);
-
-  data->set_in_subtree_of_page_scale_layer(in_subtree_of_page_scale_layer);
-  data->set_transform_changed(transform_changed);
-  data->set_post_local_scale_factor(post_local_scale_factor);
-
-  Vector2dFToProto(sublayer_scale, data->mutable_sublayer_scale());
-  ScrollOffsetToProto(scroll_offset, data->mutable_scroll_offset());
-  Vector2dFToProto(scroll_snap, data->mutable_scroll_snap());
-  Vector2dFToProto(source_offset, data->mutable_source_offset());
-  Vector2dFToProto(source_to_parent, data->mutable_source_to_parent());
-}
-
-void TransformNodeData::FromProtobuf(const proto::TreeNode& proto) {
-  DCHECK(proto.has_transform_node_data());
-  const proto::TranformNodeData& data = proto.transform_node_data();
-
-  pre_local = ProtoToTransform(data.pre_local());
-  local = ProtoToTransform(data.local());
-  post_local = ProtoToTransform(data.post_local());
-
-  to_parent = ProtoToTransform(data.to_parent());
-
-  source_node_id = data.source_node_id();
-  sorting_context_id = data.sorting_context_id();
-
-  needs_local_transform_update = data.needs_local_transform_update();
-
-  node_and_ancestors_are_animated_or_invertible =
-      data.node_and_ancestors_are_animated_or_invertible();
-
-  is_invertible = data.is_invertible();
-  ancestors_are_invertible = data.ancestors_are_invertible();
-
-  has_potential_animation = data.has_potential_animation();
-  is_currently_animating = data.is_currently_animating();
-  to_screen_is_potentially_animated = data.to_screen_is_potentially_animated();
-  has_only_translation_animations = data.has_only_translation_animations();
-
-  flattens_inherited_transform = data.flattens_inherited_transform();
-  node_and_ancestors_are_flat = data.node_and_ancestors_are_flat();
-
-  node_and_ancestors_have_only_integer_translation =
-      data.node_and_ancestors_have_only_integer_translation();
-  scrolls = data.scrolls();
-  needs_sublayer_scale = data.needs_sublayer_scale();
-
-  affected_by_inner_viewport_bounds_delta_x =
-      data.affected_by_inner_viewport_bounds_delta_x();
-  affected_by_inner_viewport_bounds_delta_y =
-      data.affected_by_inner_viewport_bounds_delta_y();
-  affected_by_outer_viewport_bounds_delta_x =
-      data.affected_by_outer_viewport_bounds_delta_x();
-  affected_by_outer_viewport_bounds_delta_y =
-      data.affected_by_outer_viewport_bounds_delta_y();
-
-  in_subtree_of_page_scale_layer = data.in_subtree_of_page_scale_layer();
-  transform_changed = data.transform_changed();
-  post_local_scale_factor = data.post_local_scale_factor();
-
-  sublayer_scale = ProtoToVector2dF(data.sublayer_scale());
-  scroll_offset = ProtoToScrollOffset(data.scroll_offset());
-  scroll_snap = ProtoToVector2dF(data.scroll_snap());
-  source_offset = ProtoToVector2dF(data.source_offset());
-  source_to_parent = ProtoToVector2dF(data.source_to_parent());
-}
-
-void TransformNodeData::AsValueInto(
-    base::trace_event::TracedValue* value) const {
-  MathUtil::AddToTracedValue("pre_local", pre_local, value);
-  MathUtil::AddToTracedValue("local", local, value);
-  MathUtil::AddToTracedValue("post_local", post_local, value);
-  // TODO(sunxd): make frameviewer work without target_id
-  value->SetInteger("target_id", 0);
-  value->SetInteger("content_target_id", 0);
-  value->SetInteger("source_node_id", source_node_id);
-  value->SetInteger("sorting_context_id", sorting_context_id);
-}
-
-TransformCachedNodeData::TransformCachedNodeData()
-    : target_id(-1), content_target_id(-1) {}
-
-TransformCachedNodeData::TransformCachedNodeData(
-    const TransformCachedNodeData& other) = default;
-
-TransformCachedNodeData::~TransformCachedNodeData() {}
-
-bool TransformCachedNodeData::operator==(
-    const TransformCachedNodeData& other) const {
-  return from_target == other.from_target && to_target == other.to_target &&
-         from_screen == other.from_screen && to_screen == other.to_screen &&
-         target_id == other.target_id &&
-         content_target_id == other.content_target_id;
-}
-
-void TransformCachedNodeData::ToProtobuf(
-    proto::TransformCachedNodeData* proto) const {
-  TransformToProto(from_target, proto->mutable_from_target());
-  TransformToProto(to_target, proto->mutable_to_target());
-  TransformToProto(from_screen, proto->mutable_from_screen());
-  TransformToProto(to_screen, proto->mutable_to_screen());
-  proto->set_target_id(target_id);
-  proto->set_content_target_id(content_target_id);
-}
-
-void TransformCachedNodeData::FromProtobuf(
-    const proto::TransformCachedNodeData& proto) {
-  from_target = ProtoToTransform(proto.from_target());
-  to_target = ProtoToTransform(proto.to_target());
-  from_screen = ProtoToTransform(proto.from_screen());
-  to_screen = ProtoToTransform(proto.to_screen());
-  target_id = proto.target_id();
-  content_target_id = proto.content_target_id();
-}
-
-ClipNodeData::ClipNodeData()
-    : transform_id(-1),
-      target_id(-1),
-      applies_local_clip(true),
-      layer_clipping_uses_only_local_clip(false),
-      target_is_clipped(false),
-      layers_are_clipped(false),
-      layers_are_clipped_when_surfaces_disabled(false),
-      resets_clip(false) {}
-
-ClipNodeData::ClipNodeData(const ClipNodeData& other) = default;
-
-bool ClipNodeData::operator==(const ClipNodeData& other) const {
-  return clip == other.clip &&
-         combined_clip_in_target_space == other.combined_clip_in_target_space &&
-         clip_in_target_space == other.clip_in_target_space &&
-         transform_id == other.transform_id && target_id == other.target_id &&
-         applies_local_clip == other.applies_local_clip &&
-         layer_clipping_uses_only_local_clip ==
-             other.layer_clipping_uses_only_local_clip &&
-         target_is_clipped == other.target_is_clipped &&
-         layers_are_clipped == other.layers_are_clipped &&
-         layers_are_clipped_when_surfaces_disabled ==
-             other.layers_are_clipped_when_surfaces_disabled &&
-         resets_clip == other.resets_clip;
-}
-
-void ClipNodeData::ToProtobuf(proto::TreeNode* proto) const {
-  DCHECK(!proto->has_clip_node_data());
-  proto::ClipNodeData* data = proto->mutable_clip_node_data();
-
-  RectFToProto(clip, data->mutable_clip());
-  RectFToProto(combined_clip_in_target_space,
-               data->mutable_combined_clip_in_target_space());
-  RectFToProto(clip_in_target_space, data->mutable_clip_in_target_space());
-
-  data->set_transform_id(transform_id);
-  data->set_target_id(target_id);
-  data->set_applies_local_clip(applies_local_clip);
-  data->set_layer_clipping_uses_only_local_clip(
-      layer_clipping_uses_only_local_clip);
-  data->set_target_is_clipped(target_is_clipped);
-  data->set_layers_are_clipped(layers_are_clipped);
-  data->set_layers_are_clipped_when_surfaces_disabled(
-      layers_are_clipped_when_surfaces_disabled);
-  data->set_resets_clip(resets_clip);
-}
-
-void ClipNodeData::FromProtobuf(const proto::TreeNode& proto) {
-  DCHECK(proto.has_clip_node_data());
-  const proto::ClipNodeData& data = proto.clip_node_data();
-
-  clip = ProtoToRectF(data.clip());
-  combined_clip_in_target_space =
-      ProtoToRectF(data.combined_clip_in_target_space());
-  clip_in_target_space = ProtoToRectF(data.clip_in_target_space());
-
-  transform_id = data.transform_id();
-  target_id = data.target_id();
-  applies_local_clip = data.applies_local_clip();
-  layer_clipping_uses_only_local_clip =
-      data.layer_clipping_uses_only_local_clip();
-  target_is_clipped = data.target_is_clipped();
-  layers_are_clipped = data.layers_are_clipped();
-  layers_are_clipped_when_surfaces_disabled =
-      data.layers_are_clipped_when_surfaces_disabled();
-  resets_clip = data.resets_clip();
-}
-
-void ClipNodeData::AsValueInto(base::trace_event::TracedValue* value) const {
-  MathUtil::AddToTracedValue("clip", clip, value);
-  value->SetInteger("transform_id", transform_id);
-  value->SetInteger("target_id", target_id);
-  value->SetBoolean("applies_local_clip", applies_local_clip);
-  value->SetBoolean("layer_clipping_uses_only_local_clip",
-                    layer_clipping_uses_only_local_clip);
-  value->SetBoolean("target_is_clipped", target_is_clipped);
-  value->SetBoolean("layers_are_clipped", layers_are_clipped);
-  value->SetBoolean("layers_are_clipped_when_surfaces_disabled",
-                    layers_are_clipped_when_surfaces_disabled);
-  value->SetBoolean("resets_clip", resets_clip);
-}
-
-EffectNodeData::EffectNodeData()
-    : opacity(1.f),
-      screen_space_opacity(1.f),
-      has_render_surface(false),
-      render_surface(nullptr),
-      has_copy_request(false),
-      hidden_by_backface_visibility(false),
-      double_sided(false),
-      is_drawn(true),
-      subtree_hidden(false),
-      has_potential_opacity_animation(false),
-      is_currently_animating_opacity(false),
-      effect_changed(false),
-      num_copy_requests_in_subtree(0),
-      has_unclipped_descendants(false),
-      transform_id(0),
-      clip_id(0),
-      target_id(0),
-      mask_layer_id(-1),
-      replica_layer_id(-1),
-      replica_mask_layer_id(-1) {}
-
-EffectNodeData::EffectNodeData(const EffectNodeData& other) = default;
-
-bool EffectNodeData::operator==(const EffectNodeData& other) const {
-  return opacity == other.opacity &&
-         screen_space_opacity == other.screen_space_opacity &&
-         has_render_surface == other.has_render_surface &&
-         has_copy_request == other.has_copy_request &&
-         background_filters == other.background_filters &&
-         sublayer_scale == other.sublayer_scale &&
-         hidden_by_backface_visibility == other.hidden_by_backface_visibility &&
-         double_sided == other.double_sided && is_drawn == other.is_drawn &&
-         subtree_hidden == other.subtree_hidden &&
-         has_potential_opacity_animation ==
-             other.has_potential_opacity_animation &&
-         is_currently_animating_opacity ==
-             other.is_currently_animating_opacity &&
-         effect_changed == other.effect_changed &&
-         num_copy_requests_in_subtree == other.num_copy_requests_in_subtree &&
-         transform_id == other.transform_id && clip_id == other.clip_id &&
-         target_id == other.target_id && mask_layer_id == other.mask_layer_id &&
-         replica_layer_id == other.replica_layer_id &&
-         replica_mask_layer_id == other.replica_mask_layer_id;
-}
-
-void EffectNodeData::ToProtobuf(proto::TreeNode* proto) const {
-  DCHECK(!proto->has_effect_node_data());
-  proto::EffectNodeData* data = proto->mutable_effect_node_data();
-  data->set_opacity(opacity);
-  data->set_screen_space_opacity(screen_space_opacity);
-  data->set_has_render_surface(has_render_surface);
-  data->set_has_copy_request(has_copy_request);
-  data->set_hidden_by_backface_visibility(hidden_by_backface_visibility);
-  data->set_double_sided(double_sided);
-  data->set_is_drawn(is_drawn);
-  data->set_subtree_hidden(subtree_hidden);
-  data->set_has_potential_opacity_animation(has_potential_opacity_animation);
-  data->set_is_currently_animating_opacity(is_currently_animating_opacity);
-  data->set_effect_changed(effect_changed);
-  data->set_num_copy_requests_in_subtree(num_copy_requests_in_subtree);
-  data->set_transform_id(transform_id);
-  data->set_clip_id(clip_id);
-  data->set_target_id(target_id);
-  data->set_mask_layer_id(mask_layer_id);
-  data->set_replica_layer_id(replica_layer_id);
-  data->set_replica_mask_layer_id(replica_mask_layer_id);
-  Vector2dFToProto(sublayer_scale, data->mutable_sublayer_scale());
-}
-
-void EffectNodeData::FromProtobuf(const proto::TreeNode& proto) {
-  DCHECK(proto.has_effect_node_data());
-  const proto::EffectNodeData& data = proto.effect_node_data();
-
-  opacity = data.opacity();
-  screen_space_opacity = data.screen_space_opacity();
-  has_render_surface = data.has_render_surface();
-  has_copy_request = data.has_copy_request();
-  hidden_by_backface_visibility = data.hidden_by_backface_visibility();
-  double_sided = data.double_sided();
-  is_drawn = data.is_drawn();
-  subtree_hidden = data.subtree_hidden();
-  has_potential_opacity_animation = data.has_potential_opacity_animation();
-  is_currently_animating_opacity = data.is_currently_animating_opacity();
-  effect_changed = data.effect_changed();
-  num_copy_requests_in_subtree = data.num_copy_requests_in_subtree();
-  transform_id = data.transform_id();
-  clip_id = data.clip_id();
-  target_id = data.target_id();
-  mask_layer_id = data.mask_layer_id();
-  replica_layer_id = data.replica_layer_id();
-  replica_mask_layer_id = data.replica_mask_layer_id();
-  sublayer_scale = ProtoToVector2dF(data.sublayer_scale());
-}
-
-void EffectNodeData::AsValueInto(base::trace_event::TracedValue* value) const {
-  value->SetDouble("opacity", opacity);
-  value->SetBoolean("has_render_surface", has_render_surface);
-  value->SetBoolean("has_copy_request", has_copy_request);
-  value->SetBoolean("double_sided", double_sided);
-  value->SetBoolean("is_drawn", is_drawn);
-  value->SetBoolean("has_potential_opacity_animation",
-                    has_potential_opacity_animation);
-  value->SetBoolean("effect_changed", effect_changed);
-  value->SetInteger("num_copy_requests_in_subtree",
-                    num_copy_requests_in_subtree);
-  value->SetInteger("transform_id", transform_id);
-  value->SetInteger("clip_id", clip_id);
-  value->SetInteger("target_id", target_id);
-  value->SetInteger("mask_layer_id", mask_layer_id);
-  value->SetInteger("replica_layer_id", replica_layer_id);
-  value->SetInteger("replica_mask_layer_id", replica_mask_layer_id);
-}
-
-ScrollNodeData::ScrollNodeData()
-    : scrollable(false),
-      main_thread_scrolling_reasons(
-          MainThreadScrollingReason::kNotScrollingOnMain),
-      contains_non_fast_scrollable_region(false),
-      max_scroll_offset_affected_by_page_scale(false),
-      is_inner_viewport_scroll_layer(false),
-      is_outer_viewport_scroll_layer(false),
-      should_flatten(false),
-      user_scrollable_horizontal(false),
-      user_scrollable_vertical(false),
-      transform_id(0),
-      num_drawn_descendants(0) {}
-
-ScrollNodeData::ScrollNodeData(const ScrollNodeData& other) = default;
-
-bool ScrollNodeData::operator==(const ScrollNodeData& other) const {
-  return scrollable == other.scrollable &&
-         main_thread_scrolling_reasons == other.main_thread_scrolling_reasons &&
-         contains_non_fast_scrollable_region ==
-             other.contains_non_fast_scrollable_region &&
-         scroll_clip_layer_bounds == other.scroll_clip_layer_bounds &&
-         bounds == other.bounds &&
-         max_scroll_offset_affected_by_page_scale ==
-             other.max_scroll_offset_affected_by_page_scale &&
-         is_inner_viewport_scroll_layer ==
-             other.is_inner_viewport_scroll_layer &&
-         is_outer_viewport_scroll_layer ==
-             other.is_outer_viewport_scroll_layer &&
-         offset_to_transform_parent == other.offset_to_transform_parent &&
-         should_flatten == other.should_flatten &&
-         user_scrollable_horizontal == other.user_scrollable_horizontal &&
-         user_scrollable_vertical == other.user_scrollable_vertical &&
-         element_id == other.element_id && transform_id == other.transform_id;
-}
-
-void ScrollNodeData::ToProtobuf(proto::TreeNode* proto) const {
-  DCHECK(!proto->has_scroll_node_data());
-  proto::ScrollNodeData* data = proto->mutable_scroll_node_data();
-  data->set_scrollable(scrollable);
-  data->set_main_thread_scrolling_reasons(main_thread_scrolling_reasons);
-  data->set_contains_non_fast_scrollable_region(
-      contains_non_fast_scrollable_region);
-  SizeToProto(scroll_clip_layer_bounds,
-              data->mutable_scroll_clip_layer_bounds());
-  SizeToProto(bounds, data->mutable_bounds());
-  data->set_max_scroll_offset_affected_by_page_scale(
-      max_scroll_offset_affected_by_page_scale);
-  data->set_is_inner_viewport_scroll_layer(is_inner_viewport_scroll_layer);
-  data->set_is_outer_viewport_scroll_layer(is_outer_viewport_scroll_layer);
-  Vector2dFToProto(offset_to_transform_parent,
-                   data->mutable_offset_to_transform_parent());
-  data->set_should_flatten(should_flatten);
-  data->set_user_scrollable_horizontal(user_scrollable_horizontal);
-  data->set_user_scrollable_vertical(user_scrollable_vertical);
-  element_id.ToProtobuf(data->mutable_element_id());
-  data->set_transform_id(transform_id);
-}
-
-void ScrollNodeData::FromProtobuf(const proto::TreeNode& proto) {
-  DCHECK(proto.has_scroll_node_data());
-  const proto::ScrollNodeData& data = proto.scroll_node_data();
-
-  scrollable = data.scrollable();
-  main_thread_scrolling_reasons = data.main_thread_scrolling_reasons();
-  contains_non_fast_scrollable_region =
-      data.contains_non_fast_scrollable_region();
-  scroll_clip_layer_bounds = ProtoToSize(data.scroll_clip_layer_bounds());
-  bounds = ProtoToSize(data.bounds());
-  max_scroll_offset_affected_by_page_scale =
-      data.max_scroll_offset_affected_by_page_scale();
-  is_inner_viewport_scroll_layer = data.is_inner_viewport_scroll_layer();
-  is_outer_viewport_scroll_layer = data.is_outer_viewport_scroll_layer();
-  offset_to_transform_parent =
-      ProtoToVector2dF(data.offset_to_transform_parent());
-  should_flatten = data.should_flatten();
-  user_scrollable_horizontal = data.user_scrollable_horizontal();
-  user_scrollable_vertical = data.user_scrollable_vertical();
-  element_id.FromProtobuf(data.element_id());
-  transform_id = data.transform_id();
-}
-
-void ScrollNodeData::AsValueInto(base::trace_event::TracedValue* value) const {
-  value->SetBoolean("scrollable", scrollable);
-  MathUtil::AddToTracedValue("scroll_clip_layer_bounds",
-                             scroll_clip_layer_bounds, value);
-  MathUtil::AddToTracedValue("bounds", bounds, value);
-  MathUtil::AddToTracedValue("offset_to_transform_parent",
-                             offset_to_transform_parent, value);
-  value->SetBoolean("should_flatten", should_flatten);
-  value->SetBoolean("user_scrollable_horizontal", user_scrollable_horizontal);
-  value->SetBoolean("user_scrollable_vertical", user_scrollable_vertical);
-
-  element_id.AddToTracedValue(value);
-  value->SetInteger("transform_id", transform_id);
-}
-
 int TransformTree::Insert(const TransformNode& tree_node, int parent_id) {
   int node_id = PropertyTree<TransformNode>::Insert(tree_node, parent_id);
   DCHECK_EQ(node_id, static_cast<int>(cached_data_.size()));
@@ -734,11 +163,11 @@
   bool success = ComputeTransform(source_id, dest_id, transform);
 
   const TransformNode* dest_node = Node(dest_id);
-  if (!dest_node->data.needs_sublayer_scale)
+  if (!dest_node->needs_sublayer_scale)
     return success;
 
-  transform->matrix().postScale(dest_node->data.sublayer_scale.x(),
-                                dest_node->data.sublayer_scale.y(), 1.f);
+  transform->matrix().postScale(dest_node->sublayer_scale.x(),
+                                dest_node->sublayer_scale.y(), 1.f);
   return success;
 }
 
@@ -749,15 +178,15 @@
   bool success = ComputeTransform(source_id, dest_id, transform);
 
   const TransformNode* source_node = Node(source_id);
-  if (!source_node->data.needs_sublayer_scale)
+  if (!source_node->needs_sublayer_scale)
     return success;
 
-  if (source_node->data.sublayer_scale.x() == 0 ||
-      source_node->data.sublayer_scale.y() == 0)
+  if (source_node->sublayer_scale.x() == 0 ||
+      source_node->sublayer_scale.y() == 0)
     return false;
 
-  transform->Scale(1.f / source_node->data.sublayer_scale.x(),
-                   1.f / source_node->data.sublayer_scale.y());
+  transform->Scale(1.f / source_node->sublayer_scale.x(),
+                   1.f / source_node->sublayer_scale.y());
   return success;
 }
 
@@ -769,13 +198,13 @@
 
 bool TransformTree::NeedsSourceToParentUpdate(TransformNode* node) {
   return (source_to_parent_updates_allowed() &&
-          node->parent_id != node->data.source_node_id);
+          node->parent_id != node->source_node_id);
 }
 
 void TransformTree::ResetChangeTracking() {
   for (int id = 1; id < static_cast<int>(size()); ++id) {
     TransformNode* node = Node(id);
-    node->data.transform_changed = false;
+    node->transform_changed = false;
   }
 }
 
@@ -783,10 +212,9 @@
   TransformNode* node = Node(id);
   TransformNode* parent_node = parent(node);
   TransformNode* target_node = Node(TargetId(id));
-  TransformNode* source_node = Node(node->data.source_node_id);
+  TransformNode* source_node = Node(node->source_node_id);
   property_trees()->UpdateCachedNumber();
-  if (node->data.needs_local_transform_update ||
-      NeedsSourceToParentUpdate(node))
+  if (node->needs_local_transform_update || NeedsSourceToParentUpdate(node))
     UpdateLocalTransform(node);
   else
     UndoSnapping(node);
@@ -825,8 +253,8 @@
   // R^{-1} * A^{-1}. If at least one of A and R isn't flat, the inverse of
   // flattened(A * R) won't be R^{-1} * A{-1}, so multiplying C's to_screen and
   // A's from_screen will not produce the correct result.
-  if (!dest || (dest->data.ancestors_are_invertible &&
-                dest->data.node_and_ancestors_are_flat)) {
+  if (!dest ||
+      (dest->ancestors_are_invertible && dest->node_and_ancestors_are_flat)) {
     transform->ConcatTransform(ToScreen(current->id));
     if (dest)
       transform->ConcatTransform(FromScreen(dest->id));
@@ -846,10 +274,9 @@
   source_to_destination.push_back(current->id);
   current = parent(current);
   bool destination_has_non_zero_sublayer_scale =
-      dest->data.sublayer_scale.x() != 0.f &&
-      dest->data.sublayer_scale.y() != 0.f;
+      dest->sublayer_scale.x() != 0.f && dest->sublayer_scale.y() != 0.f;
   DCHECK(destination_has_non_zero_sublayer_scale ||
-         !dest->data.ancestors_are_invertible);
+         !dest->ancestors_are_invertible);
   for (; current && current->id > dest_id; current = parent(current)) {
     if (destination_has_non_zero_sublayer_scale &&
         TargetId(current->id) == dest_id &&
@@ -863,9 +290,8 @@
     combined_transform = ToTarget(current->id);
     // The stored target space transform has sublayer scale baked in, but we
     // need the unscaled transform.
-    combined_transform.matrix().postScale(1.0f / dest->data.sublayer_scale.x(),
-                                          1.0f / dest->data.sublayer_scale.y(),
-                                          1.0f);
+    combined_transform.matrix().postScale(
+        1.0f / dest->sublayer_scale.x(), 1.0f / dest->sublayer_scale.y(), 1.0f);
   } else if (current->id < dest_id) {
     // We have reached the lowest common ancestor of the source and destination
     // nodes. This case can occur when we are transforming between a node
@@ -894,9 +320,9 @@
   for (size_t i = 0; i < source_to_destination_size; ++i) {
     size_t index = source_to_destination_size - 1 - i;
     const TransformNode* node = Node(source_to_destination[index]);
-    if (node->data.flattens_inherited_transform)
+    if (node->flattens_inherited_transform)
       combined_transform.FlattenTo2d();
-    combined_transform.PreconcatTransform(node->data.to_parent);
+    combined_transform.PreconcatTransform(node->to_parent);
   }
 
   transform->ConcatTransform(combined_transform);
@@ -912,8 +338,8 @@
   // Just as in CombineTransformsBetween, we can use screen space transforms in
   // this computation only when there isn't any non-trivial flattening
   // involved.
-  if (current->data.ancestors_are_invertible &&
-      current->data.node_and_ancestors_are_flat) {
+  if (current->ancestors_are_invertible &&
+      current->node_and_ancestors_are_flat) {
     transform->PreconcatTransform(FromScreen(current->id));
     if (dest)
       transform->PreconcatTransform(ToScreen(dest->id));
@@ -934,11 +360,11 @@
 }
 
 void TransformTree::UpdateLocalTransform(TransformNode* node) {
-  gfx::Transform transform = node->data.post_local;
+  gfx::Transform transform = node->post_local;
   if (NeedsSourceToParentUpdate(node)) {
     gfx::Transform to_parent;
-    ComputeTransform(node->data.source_node_id, node->parent_id, &to_parent);
-    node->data.source_to_parent = to_parent.To2dTranslation();
+    ComputeTransform(node->source_node_id, node->parent_id, &to_parent);
+    node->source_to_parent = to_parent.To2dTranslation();
   }
 
   gfx::Vector2dF fixed_position_adjustment;
@@ -946,76 +372,73 @@
       property_trees()->inner_viewport_container_bounds_delta();
   gfx::Vector2dF outer_viewport_bounds_delta =
       property_trees()->outer_viewport_container_bounds_delta();
-  if (node->data.affected_by_inner_viewport_bounds_delta_x)
+  if (node->affected_by_inner_viewport_bounds_delta_x)
     fixed_position_adjustment.set_x(inner_viewport_bounds_delta.x());
-  else if (node->data.affected_by_outer_viewport_bounds_delta_x)
+  else if (node->affected_by_outer_viewport_bounds_delta_x)
     fixed_position_adjustment.set_x(outer_viewport_bounds_delta.x());
 
-  if (node->data.affected_by_inner_viewport_bounds_delta_y)
+  if (node->affected_by_inner_viewport_bounds_delta_y)
     fixed_position_adjustment.set_y(inner_viewport_bounds_delta.y());
-  else if (node->data.affected_by_outer_viewport_bounds_delta_y)
+  else if (node->affected_by_outer_viewport_bounds_delta_y)
     fixed_position_adjustment.set_y(outer_viewport_bounds_delta.y());
 
-  transform.Translate(
-      node->data.source_to_parent.x() - node->data.scroll_offset.x() +
-          fixed_position_adjustment.x(),
-      node->data.source_to_parent.y() - node->data.scroll_offset.y() +
-          fixed_position_adjustment.y());
-  transform.PreconcatTransform(node->data.local);
-  transform.PreconcatTransform(node->data.pre_local);
-  node->data.set_to_parent(transform);
-  node->data.needs_local_transform_update = false;
+  transform.Translate(node->source_to_parent.x() - node->scroll_offset.x() +
+                          fixed_position_adjustment.x(),
+                      node->source_to_parent.y() - node->scroll_offset.y() +
+                          fixed_position_adjustment.y());
+  transform.PreconcatTransform(node->local);
+  transform.PreconcatTransform(node->pre_local);
+  node->set_to_parent(transform);
+  node->needs_local_transform_update = false;
 }
 
 void TransformTree::UpdateScreenSpaceTransform(TransformNode* node,
                                                TransformNode* parent_node,
                                                TransformNode* target_node) {
   if (!parent_node) {
-    SetToScreen(node->id, node->data.to_parent);
-    node->data.ancestors_are_invertible = true;
-    node->data.to_screen_is_potentially_animated = false;
-    node->data.node_and_ancestors_are_flat = node->data.to_parent.IsFlat();
+    SetToScreen(node->id, node->to_parent);
+    node->ancestors_are_invertible = true;
+    node->to_screen_is_potentially_animated = false;
+    node->node_and_ancestors_are_flat = node->to_parent.IsFlat();
   } else {
     gfx::Transform to_screen_space_transform = ToScreen(parent_node->id);
-    if (node->data.flattens_inherited_transform)
+    if (node->flattens_inherited_transform)
       to_screen_space_transform.FlattenTo2d();
-    to_screen_space_transform.PreconcatTransform(node->data.to_parent);
-    node->data.ancestors_are_invertible =
-        parent_node->data.ancestors_are_invertible;
-    node->data.node_and_ancestors_are_flat =
-        parent_node->data.node_and_ancestors_are_flat &&
-        node->data.to_parent.IsFlat();
+    to_screen_space_transform.PreconcatTransform(node->to_parent);
+    node->ancestors_are_invertible = parent_node->ancestors_are_invertible;
+    node->node_and_ancestors_are_flat =
+        parent_node->node_and_ancestors_are_flat && node->to_parent.IsFlat();
     SetToScreen(node->id, to_screen_space_transform);
   }
 
   gfx::Transform from_screen;
   if (!ToScreen(node->id).GetInverse(&from_screen))
-    node->data.ancestors_are_invertible = false;
+    node->ancestors_are_invertible = false;
   SetFromScreen(node->id, from_screen);
 }
 
 void TransformTree::UpdateSublayerScale(TransformNode* node) {
   // The sublayer scale depends on the screen space transform, so update it too.
-  if (!node->data.needs_sublayer_scale) {
-    node->data.sublayer_scale = gfx::Vector2dF(1.0f, 1.0f);
+  if (!node->needs_sublayer_scale) {
+    node->sublayer_scale = gfx::Vector2dF(1.0f, 1.0f);
     return;
   }
 
   float layer_scale_factor =
       device_scale_factor_ * device_transform_scale_factor_;
-  if (node->data.in_subtree_of_page_scale_layer)
+  if (node->in_subtree_of_page_scale_layer)
     layer_scale_factor *= page_scale_factor_;
-  node->data.sublayer_scale = MathUtil::ComputeTransform2dScaleComponents(
+  node->sublayer_scale = MathUtil::ComputeTransform2dScaleComponents(
       ToScreen(node->id), layer_scale_factor);
 }
 
 void TransformTree::UpdateTargetSpaceTransform(TransformNode* node,
                                                TransformNode* target_node) {
   gfx::Transform target_space_transform;
-  if (node->data.needs_sublayer_scale) {
+  if (node->needs_sublayer_scale) {
     target_space_transform.MakeIdentity();
-    target_space_transform.Scale(node->data.sublayer_scale.x(),
-                                 node->data.sublayer_scale.y());
+    target_space_transform.Scale(node->sublayer_scale.x(),
+                                 node->sublayer_scale.y());
   } else {
     // In order to include the root transform for the root surface, we walk up
     // to the root of the transform tree in ComputeTransform.
@@ -1026,7 +449,7 @@
 
   gfx::Transform from_target;
   if (!target_space_transform.GetInverse(&from_target))
-    node->data.ancestors_are_invertible = false;
+    node->ancestors_are_invertible = false;
   SetToTarget(node->id, target_space_transform);
   SetFromTarget(node->id, from_target);
 }
@@ -1035,23 +458,22 @@
                                               TransformNode* parent_node) {
   bool ancestor_is_animating = false;
   if (parent_node)
-    ancestor_is_animating = parent_node->data.to_screen_is_potentially_animated;
-  node->data.to_screen_is_potentially_animated =
-      node->data.has_potential_animation || ancestor_is_animating;
+    ancestor_is_animating = parent_node->to_screen_is_potentially_animated;
+  node->to_screen_is_potentially_animated =
+      node->has_potential_animation || ancestor_is_animating;
 }
 
 void TransformTree::UndoSnapping(TransformNode* node) {
   // to_parent transform has the scroll snap from previous frame baked in.
   // We need to undo it and use the un-snapped transform to compute current
   // target and screen space transforms.
-  node->data.to_parent.Translate(-node->data.scroll_snap.x(),
-                                 -node->data.scroll_snap.y());
+  node->to_parent.Translate(-node->scroll_snap.x(), -node->scroll_snap.y());
 }
 
 void TransformTree::UpdateSnapping(TransformNode* node) {
-  if (!node->data.scrolls || node->data.to_screen_is_potentially_animated ||
+  if (!node->scrolls || node->to_screen_is_potentially_animated ||
       !ToScreen(node->id).IsScaleOrTranslation() ||
-      !node->data.ancestors_are_invertible) {
+      !node->ancestors_are_invertible) {
     return;
   }
 
@@ -1074,61 +496,60 @@
   // Now that we have our scroll delta, we must apply it to each of our
   // combined, to/from matrices.
   SetToScreen(node->id, rounded);
-  node->data.to_parent.Translate(translation.x(), translation.y());
+  node->to_parent.Translate(translation.x(), translation.y());
   gfx::Transform from_screen = FromScreen(node->id);
   from_screen.matrix().postTranslate(-translation.x(), -translation.y(), 0);
   SetFromScreen(node->id, from_screen);
-  node->data.scroll_snap = translation;
+  node->scroll_snap = translation;
 }
 
 void TransformTree::UpdateTransformChanged(TransformNode* node,
                                            TransformNode* parent_node,
                                            TransformNode* source_node) {
-  if (parent_node && parent_node->data.transform_changed) {
-    node->data.transform_changed = true;
+  if (parent_node && parent_node->transform_changed) {
+    node->transform_changed = true;
     return;
   }
 
   if (source_node && source_node->id != parent_node->id &&
-      source_to_parent_updates_allowed_ && source_node->data.transform_changed)
-    node->data.transform_changed = true;
+      source_to_parent_updates_allowed_ && source_node->transform_changed)
+    node->transform_changed = true;
 }
 
 void TransformTree::UpdateNodeAndAncestorsAreAnimatedOrInvertible(
     TransformNode* node,
     TransformNode* parent_node) {
   if (!parent_node) {
-    node->data.node_and_ancestors_are_animated_or_invertible =
-        node->data.has_potential_animation || node->data.is_invertible;
+    node->node_and_ancestors_are_animated_or_invertible =
+        node->has_potential_animation || node->is_invertible;
     return;
   }
-  if (!parent_node->data.node_and_ancestors_are_animated_or_invertible) {
-    node->data.node_and_ancestors_are_animated_or_invertible = false;
+  if (!parent_node->node_and_ancestors_are_animated_or_invertible) {
+    node->node_and_ancestors_are_animated_or_invertible = false;
     return;
   }
-  bool is_invertible = node->data.is_invertible;
+  bool is_invertible = node->is_invertible;
   // Even when the current node's transform and the parent's screen space
   // transform are invertible, the current node's screen space transform can
   // become uninvertible due to floating-point arithmetic.
-  if (!node->data.ancestors_are_invertible &&
-      parent_node->data.ancestors_are_invertible)
+  if (!node->ancestors_are_invertible && parent_node->ancestors_are_invertible)
     is_invertible = false;
-  node->data.node_and_ancestors_are_animated_or_invertible =
-      node->data.has_potential_animation || is_invertible;
+  node->node_and_ancestors_are_animated_or_invertible =
+      node->has_potential_animation || is_invertible;
 }
 
 void TransformTree::SetDeviceTransform(const gfx::Transform& transform,
                                        gfx::PointF root_position) {
   gfx::Transform root_post_local = transform;
   TransformNode* node = Node(1);
-  root_post_local.Scale(node->data.post_local_scale_factor,
-                        node->data.post_local_scale_factor);
+  root_post_local.Scale(node->post_local_scale_factor,
+                        node->post_local_scale_factor);
   root_post_local.Translate(root_position.x(), root_position.y());
-  if (node->data.post_local == root_post_local)
+  if (node->post_local == root_post_local)
     return;
 
-  node->data.post_local = root_post_local;
-  node->data.needs_local_transform_update = true;
+  node->post_local = root_post_local;
+  node->needs_local_transform_update = true;
   set_needs_update(true);
 }
 
@@ -1149,7 +570,7 @@
 
   set_needs_update(true);
   for (int i : nodes_affected_by_inner_viewport_bounds_delta_)
-    Node(i)->data.needs_local_transform_update = true;
+    Node(i)->needs_local_transform_update = true;
 }
 
 void TransformTree::UpdateOuterViewportContainerBoundsDelta() {
@@ -1158,7 +579,7 @@
 
   set_needs_update(true);
   for (int i : nodes_affected_by_outer_viewport_bounds_delta_)
-    Node(i)->data.needs_local_transform_update = true;
+    Node(i)->needs_local_transform_update = true;
 }
 
 void TransformTree::AddNodeAffectedByInnerViewportBoundsDelta(int node_id) {
@@ -1247,10 +668,9 @@
   }
   const TransformNode* node = Node(id);
   gfx::Transform screen_space_transform = ToScreen(id);
-  if (node->data.sublayer_scale.x() != 0.0 &&
-      node->data.sublayer_scale.y() != 0.0)
-    screen_space_transform.Scale(1.0 / node->data.sublayer_scale.x(),
-                                 1.0 / node->data.sublayer_scale.y());
+  if (node->sublayer_scale.x() != 0.0 && node->sublayer_scale.y() != 0.0)
+    screen_space_transform.Scale(1.0 / node->sublayer_scale.x(),
+                                 1.0 / node->sublayer_scale.y());
   return screen_space_transform;
 }
 
@@ -1337,14 +757,14 @@
 }
 
 float EffectTree::EffectiveOpacity(const EffectNode* node) const {
-  return node->data.subtree_hidden ? 0.f : node->data.opacity;
+  return node->subtree_hidden ? 0.f : node->opacity;
 }
 
 void EffectTree::UpdateOpacities(EffectNode* node, EffectNode* parent_node) {
-  node->data.screen_space_opacity = EffectiveOpacity(node);
+  node->screen_space_opacity = EffectiveOpacity(node);
 
   if (parent_node)
-    node->data.screen_space_opacity *= parent_node->data.screen_space_opacity;
+    node->screen_space_opacity *= parent_node->screen_space_opacity;
 }
 
 void EffectTree::UpdateIsDrawn(EffectNode* node, EffectNode* parent_node) {
@@ -1355,70 +775,68 @@
   // 2) Nodes that have a background filter.
   // 3) Nodes with animating screen space opacity on main thread or pending tree
   //    are drawn if their parent is drawn irrespective of their opacity.
-  if (node->data.has_copy_request)
-    node->data.is_drawn = true;
+  if (node->has_copy_request)
+    node->is_drawn = true;
   else if (EffectiveOpacity(node) == 0.f &&
-           (!node->data.has_potential_opacity_animation ||
+           (!node->has_potential_opacity_animation ||
             property_trees()->is_active) &&
-           node->data.background_filters.IsEmpty())
-    node->data.is_drawn = false;
+           node->background_filters.IsEmpty())
+    node->is_drawn = false;
   else if (parent_node)
-    node->data.is_drawn = parent_node->data.is_drawn;
+    node->is_drawn = parent_node->is_drawn;
   else
-    node->data.is_drawn = true;
+    node->is_drawn = true;
 }
 
 void EffectTree::UpdateEffectChanged(EffectNode* node,
                                      EffectNode* parent_node) {
-  if (parent_node && parent_node->data.effect_changed) {
-    node->data.effect_changed = true;
+  if (parent_node && parent_node->effect_changed) {
+    node->effect_changed = true;
   }
 }
 
 void EffectTree::UpdateBackfaceVisibility(EffectNode* node,
                                           EffectNode* parent_node) {
   if (!parent_node) {
-    node->data.hidden_by_backface_visibility = false;
+    node->hidden_by_backface_visibility = false;
     return;
   }
-  if (parent_node->data.hidden_by_backface_visibility) {
-    node->data.hidden_by_backface_visibility = true;
+  if (parent_node->hidden_by_backface_visibility) {
+    node->hidden_by_backface_visibility = true;
     return;
   }
 
   TransformTree& transform_tree = property_trees()->transform_tree;
-  if (node->data.has_render_surface && !node->data.double_sided) {
-    TransformNode* transform_node =
-        transform_tree.Node(node->data.transform_id);
-    if (transform_node->data.is_invertible &&
-        transform_node->data.ancestors_are_invertible) {
-      if (transform_node->data.sorting_context_id) {
+  if (node->has_render_surface && !node->double_sided) {
+    TransformNode* transform_node = transform_tree.Node(node->transform_id);
+    if (transform_node->is_invertible &&
+        transform_node->ancestors_are_invertible) {
+      if (transform_node->sorting_context_id) {
         const TransformNode* parent_transform_node =
             transform_tree.parent(transform_node);
         if (parent_transform_node &&
-            parent_transform_node->data.sorting_context_id ==
-                transform_node->data.sorting_context_id) {
+            parent_transform_node->sorting_context_id ==
+                transform_node->sorting_context_id) {
           gfx::Transform surface_draw_transform;
           transform_tree.ComputeTransform(
               transform_node->id, transform_tree.TargetId(transform_node->id),
               &surface_draw_transform);
-          node->data.hidden_by_backface_visibility =
+          node->hidden_by_backface_visibility =
               surface_draw_transform.IsBackFaceVisible();
         } else {
-          node->data.hidden_by_backface_visibility =
-              transform_node->data.local.IsBackFaceVisible();
+          node->hidden_by_backface_visibility =
+              transform_node->local.IsBackFaceVisible();
         }
         return;
       }
     }
   }
-  node->data.hidden_by_backface_visibility = false;
+  node->hidden_by_backface_visibility = false;
 }
 
 void EffectTree::UpdateSublayerScale(EffectNode* effect_node) {
-  if (!effect_node->data.has_render_surface ||
-      effect_node->data.transform_id == 0) {
-    effect_node->data.sublayer_scale = gfx::Vector2dF(1.0f, 1.0f);
+  if (!effect_node->has_render_surface || effect_node->transform_id == 0) {
+    effect_node->sublayer_scale = gfx::Vector2dF(1.0f, 1.0f);
     return;
   }
 
@@ -1426,12 +844,11 @@
   float layer_scale_factor = transform_tree.device_scale_factor() *
                              transform_tree.device_transform_scale_factor();
   TransformNode* transform_node =
-      transform_tree.Node(effect_node->data.transform_id);
-  if (transform_node->data.in_subtree_of_page_scale_layer)
+      transform_tree.Node(effect_node->transform_id);
+  if (transform_node->in_subtree_of_page_scale_layer)
     layer_scale_factor *= transform_tree.page_scale_factor();
-  effect_node->data.sublayer_scale =
-      MathUtil::ComputeTransform2dScaleComponents(
-          transform_tree.ToScreen(transform_node->id), layer_scale_factor);
+  effect_node->sublayer_scale = MathUtil::ComputeTransform2dScaleComponents(
+      transform_tree.ToScreen(transform_node->id), layer_scale_factor);
 }
 
 void EffectTree::UpdateEffects(int id) {
@@ -1480,8 +897,8 @@
     int node_id,
     std::vector<std::unique_ptr<CopyOutputRequest>>* requests) {
   EffectNode* effect_node = Node(node_id);
-  DCHECK(effect_node->data.has_render_surface);
-  DCHECK(effect_node->data.has_copy_request);
+  DCHECK(effect_node->has_render_surface);
+  DCHECK(effect_node->has_copy_request);
 
   auto range = copy_requests_.equal_range(node_id);
   for (auto it = range.first; it != range.second; ++it)
@@ -1494,7 +911,7 @@
 
     // The area needs to be transformed from the space of content that draws to
     // the surface to the space of the surface itself.
-    int destination_id = effect_node->data.transform_id;
+    int destination_id = effect_node->transform_id;
     int source_id;
     if (effect_node->parent_id != -1) {
       // For non-root surfaces, transform only by sub-layer scale.
@@ -1520,8 +937,8 @@
 
 void EffectTree::ClearCopyRequests() {
   for (auto& node : nodes()) {
-    node.data.num_copy_requests_in_subtree = 0;
-    node.data.has_copy_request = false;
+    node.num_copy_requests_in_subtree = 0;
+    node.has_copy_request = false;
   }
 
   // Any copy requests that are still left will be aborted (sending an empty
@@ -1534,13 +951,13 @@
   DCHECK_GE(id, 0);
   const EffectNode* node = Node(id);
   while (node->id > 1) {
-    if (node->data.has_copy_request)
+    if (node->has_copy_request)
       return node->id;
 
     node = parent(node);
   }
 
-  if (node->data.has_copy_request)
+  if (node->has_copy_request)
     return node->id;
   else
     return -1;
@@ -1556,41 +973,41 @@
   // copy requests.
   EffectNode* node = Node(id);
   EffectNode* parent_node = parent(node);
-  return node->data.is_drawn && (!parent_node || parent_node->data.is_drawn);
+  return node->is_drawn && (!parent_node || parent_node->is_drawn);
 }
 
 void EffectTree::ResetChangeTracking() {
   for (int id = 1; id < static_cast<int>(size()); ++id) {
     EffectNode* node = Node(id);
-    node->data.effect_changed = false;
+    node->effect_changed = false;
   }
 }
 
 void TransformTree::UpdateNodeAndAncestorsHaveIntegerTranslations(
     TransformNode* node,
     TransformNode* parent_node) {
-  node->data.node_and_ancestors_have_only_integer_translation =
-      node->data.to_parent.IsIdentityOrIntegerTranslation();
+  node->node_and_ancestors_have_only_integer_translation =
+      node->to_parent.IsIdentityOrIntegerTranslation();
   if (parent_node)
-    node->data.node_and_ancestors_have_only_integer_translation =
-        node->data.node_and_ancestors_have_only_integer_translation &&
-        parent_node->data.node_and_ancestors_have_only_integer_translation;
+    node->node_and_ancestors_have_only_integer_translation =
+        node->node_and_ancestors_have_only_integer_translation &&
+        parent_node->node_and_ancestors_have_only_integer_translation;
 }
 
 void ClipTree::SetViewportClip(gfx::RectF viewport_rect) {
   if (size() < 2)
     return;
   ClipNode* node = Node(1);
-  if (viewport_rect == node->data.clip)
+  if (viewport_rect == node->clip)
     return;
-  node->data.clip = viewport_rect;
+  node->clip = viewport_rect;
   set_needs_update(true);
 }
 
 gfx::RectF ClipTree::ViewportClip() {
   const unsigned long min_size = 1;
   DCHECK_GT(size(), min_size);
-  return Node(1)->data.clip;
+  return Node(1)->clip;
 }
 
 bool ClipTree::operator==(const ClipTree& other) const {
@@ -1747,21 +1164,21 @@
 
 gfx::ScrollOffset ScrollTree::MaxScrollOffset(int scroll_node_id) const {
   const ScrollNode* scroll_node = Node(scroll_node_id);
-  gfx::SizeF scroll_bounds = gfx::SizeF(scroll_node->data.bounds.width(),
-                                        scroll_node->data.bounds.height());
+  gfx::SizeF scroll_bounds =
+      gfx::SizeF(scroll_node->bounds.width(), scroll_node->bounds.height());
 
-  if (scroll_node->data.is_inner_viewport_scroll_layer) {
+  if (scroll_node->is_inner_viewport_scroll_layer) {
     scroll_bounds.Enlarge(
         property_trees()->inner_viewport_scroll_bounds_delta().x(),
         property_trees()->inner_viewport_scroll_bounds_delta().y());
   }
 
-  if (!scroll_node->data.scrollable || scroll_bounds.IsEmpty())
+  if (!scroll_node->scrollable || scroll_bounds.IsEmpty())
     return gfx::ScrollOffset();
 
   TransformTree& transform_tree = property_trees()->transform_tree;
   float scale_factor = 1.f;
-  if (scroll_node->data.max_scroll_offset_affected_by_page_scale)
+  if (scroll_node->max_scroll_offset_affected_by_page_scale)
     scale_factor = transform_tree.page_scale_factor();
 
   gfx::SizeF scaled_scroll_bounds = gfx::ScaleSize(scroll_bounds, scale_factor);
@@ -1781,14 +1198,13 @@
 
 gfx::Size ScrollTree::scroll_clip_layer_bounds(int scroll_node_id) const {
   const ScrollNode* scroll_node = Node(scroll_node_id);
-  gfx::Size scroll_clip_layer_bounds =
-      scroll_node->data.scroll_clip_layer_bounds;
+  gfx::Size scroll_clip_layer_bounds = scroll_node->scroll_clip_layer_bounds;
 
   gfx::Vector2dF scroll_clip_layer_bounds_delta;
-  if (scroll_node->data.is_inner_viewport_scroll_layer) {
+  if (scroll_node->is_inner_viewport_scroll_layer) {
     scroll_clip_layer_bounds_delta.Add(
         property_trees()->inner_viewport_container_bounds_delta());
-  } else if (scroll_node->data.is_outer_viewport_scroll_layer) {
+  } else if (scroll_node->is_outer_viewport_scroll_layer) {
     scroll_clip_layer_bounds_delta.Add(
         property_trees()->outer_viewport_container_bounds_delta());
   }
@@ -1819,13 +1235,13 @@
   const ScrollNode* scroll_node = Node(scroll_node_id);
   const TransformTree& transform_tree = property_trees()->transform_tree;
   const TransformNode* transform_node =
-      transform_tree.Node(scroll_node->data.transform_id);
+      transform_tree.Node(scroll_node->transform_id);
   gfx::Transform screen_space_transform(
-      1, 0, 0, 1, scroll_node->data.offset_to_transform_parent.x(),
-      scroll_node->data.offset_to_transform_parent.y());
+      1, 0, 0, 1, scroll_node->offset_to_transform_parent.x(),
+      scroll_node->offset_to_transform_parent.y());
   screen_space_transform.ConcatTransform(
       transform_tree.ToScreen(transform_node->id));
-  if (scroll_node->data.should_flatten)
+  if (scroll_node->should_flatten)
     screen_space_transform.FlattenTo2d();
   return screen_space_transform;
 }
@@ -2033,17 +1449,17 @@
                                     const gfx::Vector2dF& scroll,
                                     LayerTreeImpl* layer_tree_impl) {
   gfx::ScrollOffset adjusted_scroll(scroll);
-  if (!scroll_node->data.user_scrollable_horizontal)
+  if (!scroll_node->user_scrollable_horizontal)
     adjusted_scroll.set_x(0);
-  if (!scroll_node->data.user_scrollable_vertical)
+  if (!scroll_node->user_scrollable_vertical)
     adjusted_scroll.set_y(0);
-  DCHECK(scroll_node->data.scrollable);
+  DCHECK(scroll_node->scrollable);
   gfx::ScrollOffset old_offset = current_scroll_offset(scroll_node->owner_id);
   gfx::ScrollOffset new_offset =
       ClampScrollOffsetToLimits(old_offset + adjusted_scroll, scroll_node);
   if (SetScrollOffset(scroll_node->owner_id, new_offset))
     layer_tree_impl->DidUpdateScrollOffset(scroll_node->owner_id,
-                                           scroll_node->data.transform_id);
+                                           scroll_node->transform_id);
 
   gfx::ScrollOffset unscrolled =
       old_offset + gfx::ScrollOffset(scroll) - new_offset;
@@ -2208,11 +1624,11 @@
         effect_tree.Node(effect_id_to_index_map[id]);
     EffectNode* target_effect_node =
         target_tree->effect_tree.Node(target_tree->effect_id_to_index_map[id]);
-    float source_opacity = source_effect_node->data.opacity;
-    float target_opacity = target_effect_node->data.opacity;
+    float source_opacity = source_effect_node->opacity;
+    float target_opacity = target_effect_node->opacity;
     if (source_opacity == target_opacity)
       continue;
-    target_effect_node->data.opacity = source_opacity;
+    target_effect_node->opacity = source_opacity;
     target_tree->effect_tree.set_needs_update(true);
   }
 }
@@ -2252,7 +1668,7 @@
   for (int i = 1; i < static_cast<int>(transform_tree.size()); ++i) {
     TransformNode* node = transform_tree.Node(i);
     TransformNode* parent_node = transform_tree.parent(node);
-    TransformNode* source_node = transform_tree.Node(node->data.source_node_id);
+    TransformNode* source_node = transform_tree.Node(node->source_node_id);
     transform_tree.UpdateTransformChanged(node, parent_node, source_node);
   }
 }
@@ -2260,16 +1676,16 @@
 void PropertyTrees::PushChangeTrackingTo(PropertyTrees* tree) {
   for (int id = 1; id < static_cast<int>(effect_tree.size()); ++id) {
     EffectNode* node = effect_tree.Node(id);
-    if (node->data.effect_changed) {
+    if (node->effect_changed) {
       EffectNode* target_node = tree->effect_tree.Node(node->id);
-      target_node->data.effect_changed = true;
+      target_node->effect_changed = true;
     }
   }
   for (int id = 1; id < static_cast<int>(transform_tree.size()); ++id) {
     TransformNode* node = transform_tree.Node(id);
-    if (node->data.transform_changed) {
+    if (node->transform_changed) {
       TransformNode* target_node = tree->transform_tree.Node(node->id);
-      target_node->data.transform_changed = true;
+      target_node->transform_changed = true;
     }
   }
   // Ensure that change tracking is updated even if property trees don't have
@@ -2349,8 +1765,7 @@
 
     cached_data_.animation_scales[transform_node_id]
         .to_screen_has_scale_animation =
-        !node->data.has_only_translation_animations ||
-        ancestor_is_animating_scale;
+        !node->has_only_translation_animations || ancestor_is_animating_scale;
 
     // Once we've failed to compute a maximum animated scale at an ancestor, we
     // continue to fail.
@@ -2368,8 +1783,7 @@
     // as another node is decreasing scale from 10 to 1. Naively combining these
     // scales would produce a scale of 100.
     bool failed_for_multiple_scale_animations =
-        ancestor_is_animating_scale &&
-        !node->data.has_only_translation_animations;
+        ancestor_is_animating_scale && !node->has_only_translation_animations;
 
     if (failed_at_ancestor || failed_for_non_scale_or_translation ||
         failed_for_multiple_scale_animations) {
@@ -2388,10 +1802,10 @@
           .combined_maximum_animation_target_scale = 0.f;
       cached_data_.animation_scales[transform_node_id]
           .combined_starting_animation_scale = 0.f;
-    } else if (node->data.has_only_translation_animations) {
+    } else if (node->has_only_translation_animations) {
       // An ancestor is animating scale.
       gfx::Vector2dF local_scales =
-          MathUtil::ComputeTransform2dScaleComponents(node->data.local, 0.f);
+          MathUtil::ComputeTransform2dScaleComponents(node->local, 0.f);
       float max_local_scale = std::max(local_scales.x(), local_scales.y());
       cached_data_.animation_scales[transform_node_id]
           .combined_maximum_animation_target_scale =
@@ -2410,7 +1824,7 @@
           layer_impl, &cached_data_.animation_scales[transform_node_id]
                            .local_starting_animation_scale);
       gfx::Vector2dF local_scales =
-          MathUtil::ComputeTransform2dScaleComponents(node->data.local, 0.f);
+          MathUtil::ComputeTransform2dScaleComponents(node->local, 0.f);
       float max_local_scale = std::max(local_scales.x(), local_scales.y());
 
       if (cached_data_.animation_scales[transform_node_id]
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h
index 68a9976..4dbf6c4 100644
--- a/cc/trees/property_tree.h
+++ b/cc/trees/property_tree.h
@@ -14,7 +14,6 @@
 #include "cc/animation/element_id.h"
 #include "cc/base/cc_export.h"
 #include "cc/base/synced_property.h"
-#include "cc/output/filter_operations.h"
 #include "ui/gfx/geometry/rect_f.h"
 #include "ui/gfx/geometry/scroll_offset.h"
 #include "ui/gfx/transform.h"
@@ -28,22 +27,21 @@
 namespace cc {
 
 namespace proto {
-class ClipNodeData;
-class EffectNodeData;
 class PropertyTree;
 class PropertyTrees;
 class ScrollNodeData;
-class TransformNodeData;
-class TransformCachedNodeData;
-class TransformTreeData;
 class TreeNode;
 }  // namespace proto
 
 class CopyOutputRequest;
 class LayerTreeImpl;
-class RenderSurfaceImpl;
 class ScrollState;
+struct ClipNode;
+struct EffectNode;
 struct ScrollAndScaleSet;
+struct ScrollNode;
+struct TransformNode;
+struct TransformCachedNodeData;
 
 // ------------------------------*IMPORTANT*---------------------------------
 // Each class declared here has a corresponding proto defined in
@@ -54,290 +52,6 @@
 
 typedef SyncedProperty<AdditionGroup<gfx::ScrollOffset>> SyncedScrollOffset;
 
-template <typename T>
-struct CC_EXPORT TreeNode {
-  TreeNode() : id(-1), parent_id(-1), owner_id(-1), data() {}
-  int id;
-  int parent_id;
-  int owner_id;
-  T data;
-
-  bool operator==(const TreeNode<T>& other) const;
-
-  void ToProtobuf(proto::TreeNode* proto) const;
-  void FromProtobuf(const proto::TreeNode& proto);
-
-  void AsValueInto(base::trace_event::TracedValue* value) const;
-};
-
-struct CC_EXPORT TransformNodeData {
-  TransformNodeData();
-  TransformNodeData(const TransformNodeData& other);
-  ~TransformNodeData();
-
-  // The local transform information is combined to form to_parent (ignoring
-  // snapping) as follows:
-  //
-  //   to_parent = M_post_local * T_scroll * M_local * M_pre_local.
-  //
-  // The pre/post may seem odd when read LTR, but we multiply our points from
-  // the right, so the pre_local matrix affects the result "first". This lines
-  // up with the notions of pre/post used in skia and gfx::Transform.
-  //
-  // TODO(vollick): The values labeled with "will be moved..." take up a lot of
-  // space, but are only necessary for animated or scrolled nodes (otherwise
-  // we'll just use the baked to_parent). These values will be ultimately stored
-  // directly on the transform/scroll display list items when that's possible,
-  // or potentially in a scroll tree.
-  //
-  // TODO(vollick): will be moved when accelerated effects are implemented.
-  gfx::Transform pre_local;
-  gfx::Transform local;
-  gfx::Transform post_local;
-
-  gfx::Transform to_parent;
-
-  // This is the node with respect to which source_offset is defined. This will
-  // not be needed once layerization moves to cc, but is needed in order to
-  // efficiently update the transform tree for changes to position in the layer
-  // tree.
-  int source_node_id;
-
-  // This id determines which 3d rendering context the node is in. 0 is a
-  // special value and indicates that the node is not in any 3d rendering
-  // context.
-  int sorting_context_id;
-
-  // TODO(vollick): will be moved when accelerated effects are implemented.
-  bool needs_local_transform_update : 1;
-
-  bool node_and_ancestors_are_animated_or_invertible : 1;
-
-  bool is_invertible : 1;
-  bool ancestors_are_invertible : 1;
-
-  bool has_potential_animation : 1;
-  bool is_currently_animating : 1;
-  bool to_screen_is_potentially_animated : 1;
-  bool has_only_translation_animations : 1;
-
-  // Flattening, when needed, is only applied to a node's inherited transform,
-  // never to its local transform.
-  bool flattens_inherited_transform : 1;
-
-  // This is true if the to_parent transform at every node on the path to the
-  // root is flat.
-  bool node_and_ancestors_are_flat : 1;
-
-  // This is needed to know if a layer can use lcd text.
-  bool node_and_ancestors_have_only_integer_translation : 1;
-
-  bool scrolls : 1;
-
-  bool needs_sublayer_scale : 1;
-
-  // These are used to position nodes wrt the right or bottom of the inner or
-  // outer viewport.
-  bool affected_by_inner_viewport_bounds_delta_x : 1;
-  bool affected_by_inner_viewport_bounds_delta_y : 1;
-  bool affected_by_outer_viewport_bounds_delta_x : 1;
-  bool affected_by_outer_viewport_bounds_delta_y : 1;
-
-  // Layer scale factor is used as a fallback when we either cannot adjust
-  // raster scale or if the raster scale cannot be extracted from the screen
-  // space transform. For layers in the subtree of the page scale layer, the
-  // layer scale factor should include the page scale factor.
-  bool in_subtree_of_page_scale_layer : 1;
-
-  // We need to track changes to to_screen transform to compute the damage rect.
-  bool transform_changed : 1;
-
-  // TODO(vollick): will be moved when accelerated effects are implemented.
-  float post_local_scale_factor;
-
-  gfx::Vector2dF sublayer_scale;
-
-  // TODO(vollick): will be moved when accelerated effects are implemented.
-  gfx::ScrollOffset scroll_offset;
-
-  // We scroll snap where possible, but this means fixed-pos elements must be
-  // adjusted.  This value stores the snapped amount for this purpose.
-  gfx::Vector2dF scroll_snap;
-
-  // TODO(vollick): will be moved when accelerated effects are implemented.
-  gfx::Vector2dF source_offset;
-  gfx::Vector2dF source_to_parent;
-
-  bool operator==(const TransformNodeData& other) const;
-
-  void set_to_parent(const gfx::Transform& transform) {
-    to_parent = transform;
-    is_invertible = to_parent.IsInvertible();
-  }
-
-  void update_pre_local_transform(const gfx::Point3F& transform_origin);
-
-  void update_post_local_transform(const gfx::PointF& position,
-                                   const gfx::Point3F& transform_origin);
-
-  void ToProtobuf(proto::TreeNode* proto) const;
-  void FromProtobuf(const proto::TreeNode& proto);
-
-  void AsValueInto(base::trace_event::TracedValue* value) const;
-};
-
-// TODO(sunxd): move this into PropertyTrees::cached_data_.
-struct CC_EXPORT TransformCachedNodeData {
-  TransformCachedNodeData();
-  TransformCachedNodeData(const TransformCachedNodeData& other);
-  ~TransformCachedNodeData();
-
-  gfx::Transform from_target;
-  gfx::Transform to_target;
-  gfx::Transform from_screen;
-  gfx::Transform to_screen;
-  int target_id;
-  // This id is used for all content that draws into a render surface associated
-  // with this transform node.
-  int content_target_id;
-
-  bool operator==(const TransformCachedNodeData& other) const;
-
-  void ToProtobuf(proto::TransformCachedNodeData* proto) const;
-  void FromProtobuf(const proto::TransformCachedNodeData& proto);
-};
-
-typedef TreeNode<TransformNodeData> TransformNode;
-
-struct CC_EXPORT ClipNodeData {
-  ClipNodeData();
-  ClipNodeData(const ClipNodeData& other);
-
-  // The clip rect that this node contributes, expressed in the space of its
-  // transform node.
-  gfx::RectF clip;
-
-  // Clip nodes are uses for two reasons. First, they are used for determining
-  // which parts of each layer are visible. Second, they are used for
-  // determining whether a clip needs to be applied when drawing a layer, and if
-  // so, the rect that needs to be used. These can be different since not all
-  // clips need to be applied directly to each layer. For example, a layer is
-  // implicitly clipped by the bounds of its target render surface and by clips
-  // applied to this surface. |combined_clip_in_target_space| is used for
-  // computing visible rects, and |clip_in_target_space| is used for computing
-  // clips applied at draw time. Both rects are expressed in the space of the
-  // target transform node, and may include clips contributed by ancestors.
-  gfx::RectF combined_clip_in_target_space;
-  gfx::RectF clip_in_target_space;
-
-  // The id of the transform node that defines the clip node's local space.
-  int transform_id;
-
-  // The id of the transform node that defines the clip node's target space.
-  int target_id;
-
-  // Whether this node contributes a new clip (that is, whether |clip| needs to
-  // be applied), rather than only inheriting ancestor clips.
-  bool applies_local_clip : 1;
-
-  // When true, |clip_in_target_space| does not include clips from ancestor
-  // nodes.
-  bool layer_clipping_uses_only_local_clip : 1;
-
-  // True if target surface needs to be drawn with a clip applied.
-  bool target_is_clipped : 1;
-
-  // True if layers with this clip tree node need to be drawn with a clip
-  // applied.
-  bool layers_are_clipped : 1;
-  bool layers_are_clipped_when_surfaces_disabled : 1;
-
-  // Nodes that correspond to unclipped surfaces disregard ancestor clips.
-  bool resets_clip : 1;
-
-  bool operator==(const ClipNodeData& other) const;
-
-  void ToProtobuf(proto::TreeNode* proto) const;
-  void FromProtobuf(const proto::TreeNode& proto);
-  void AsValueInto(base::trace_event::TracedValue* value) const;
-};
-
-typedef TreeNode<ClipNodeData> ClipNode;
-
-struct CC_EXPORT EffectNodeData {
-  EffectNodeData();
-  EffectNodeData(const EffectNodeData& other);
-
-  float opacity;
-  float screen_space_opacity;
-
-  FilterOperations background_filters;
-
-  gfx::Vector2dF sublayer_scale;
-
-  bool has_render_surface;
-  RenderSurfaceImpl* render_surface;
-  bool has_copy_request;
-  bool hidden_by_backface_visibility;
-  bool double_sided;
-  bool is_drawn;
-  // TODO(jaydasika) : Delete this after implementation of
-  // SetHideLayerAndSubtree is cleaned up. (crbug.com/595843)
-  bool subtree_hidden;
-  bool has_potential_opacity_animation;
-  bool is_currently_animating_opacity;
-  // We need to track changes to effects on the compositor to compute damage
-  // rect.
-  bool effect_changed;
-  int num_copy_requests_in_subtree;
-  bool has_unclipped_descendants;
-  int transform_id;
-  int clip_id;
-  // Effect node id of which this effect contributes to.
-  int target_id;
-  int mask_layer_id;
-  int replica_layer_id;
-  int replica_mask_layer_id;
-
-  bool operator==(const EffectNodeData& other) const;
-
-  void ToProtobuf(proto::TreeNode* proto) const;
-  void FromProtobuf(const proto::TreeNode& proto);
-  void AsValueInto(base::trace_event::TracedValue* value) const;
-};
-
-typedef TreeNode<EffectNodeData> EffectNode;
-
-struct CC_EXPORT ScrollNodeData {
-  ScrollNodeData();
-  ScrollNodeData(const ScrollNodeData& other);
-
-  bool scrollable;
-  uint32_t main_thread_scrolling_reasons;
-  bool contains_non_fast_scrollable_region;
-  gfx::Size scroll_clip_layer_bounds;
-  gfx::Size bounds;
-  bool max_scroll_offset_affected_by_page_scale;
-  bool is_inner_viewport_scroll_layer;
-  bool is_outer_viewport_scroll_layer;
-  gfx::Vector2dF offset_to_transform_parent;
-  bool should_flatten;
-  bool user_scrollable_horizontal;
-  bool user_scrollable_vertical;
-  ElementId element_id;
-  int transform_id;
-  // Number of drawn layers pointing to this node or any of its descendants.
-  int num_drawn_descendants;
-
-  bool operator==(const ScrollNodeData& other) const;
-
-  void ToProtobuf(proto::TreeNode* proto) const;
-  void FromProtobuf(const proto::TreeNode& proto);
-  void AsValueInto(base::trace_event::TracedValue* value) const;
-};
-
-typedef TreeNode<ScrollNodeData> ScrollNode;
-
 class PropertyTrees;
 
 template <typename T>
@@ -345,7 +59,13 @@
  public:
   PropertyTree();
   PropertyTree(const PropertyTree& other) = delete;
+
+  // These C++ special member functions cannot be implicit inline because
+  // they are exported by CC_EXPORT. They will be instantiated in every
+  // compilation units that included this header, and compilation can fail
+  // because T may be incomplete.
   ~PropertyTree();
+  PropertyTree<T>& operator=(const PropertyTree<T>&);
 
   bool operator==(const PropertyTree<T>& other) const;
 
@@ -402,7 +122,14 @@
 class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> {
  public:
   TransformTree();
+
+  // These C++ special member functions cannot be implicit inline because
+  // they are exported by CC_EXPORT. They will be instantiated in every
+  // compilation units that included this header, and compilation can fail
+  // because TransformCachedNodeData may be incomplete.
+  TransformTree(const TransformTree&) = delete;
   ~TransformTree();
+  TransformTree& operator=(const TransformTree&);
 
   bool operator==(const TransformTree& other) const;
 
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 7f35dd9..f9ebb6f 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -13,9 +13,13 @@
 #include "cc/layers/layer.h"
 #include "cc/layers/layer_impl.h"
 #include "cc/output/copy_output_request.h"
+#include "cc/trees/clip_node.h"
 #include "cc/trees/draw_property_utils.h"
+#include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/scroll_node.h"
+#include "cc/trees/transform_node.h"
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
 
@@ -280,7 +284,7 @@
   bool is_root = !Parent(layer);
 
   // Whether we have an ancestor clip that we might need to apply.
-  bool ancestor_clips_subtree = is_root || parent->data.layers_are_clipped;
+  bool ancestor_clips_subtree = is_root || parent->layers_are_clipped;
 
   bool layers_are_clipped = false;
   bool has_unclipped_surface = false;
@@ -299,7 +303,7 @@
       // of its own, but clips from ancestor nodes don't need to be considered
       // when computing clip rects or visibility.
       has_unclipped_surface = true;
-      DCHECK(!parent->data.applies_local_clip);
+      DCHECK(!parent->applies_local_clip);
     }
     // A surface with unclipped descendants cannot be clipped by its ancestor
     // clip at draw time since the unclipped descendants aren't affected by the
@@ -320,8 +324,7 @@
   // Without surfaces, all non-viewport clips have to be applied using layer
   // clipping.
   bool layers_are_clipped_when_surfaces_disabled =
-      layer_clips_subtree ||
-      parent->data.layers_are_clipped_when_surfaces_disabled;
+      layer_clips_subtree || parent->layers_are_clipped_when_surfaces_disabled;
 
   // Render surface's clip is needed during hit testing. So, we need to create
   // a clip node for every render surface.
@@ -329,9 +332,9 @@
 
   if (!requires_node) {
     data_for_children->clip_tree_parent = parent_id;
-    DCHECK_EQ(layers_are_clipped, parent->data.layers_are_clipped);
+    DCHECK_EQ(layers_are_clipped, parent->layers_are_clipped);
     DCHECK_EQ(layers_are_clipped_when_surfaces_disabled,
-              parent->data.layers_are_clipped_when_surfaces_disabled);
+              parent->layers_are_clipped_when_surfaces_disabled);
   } else {
     LayerType* transform_parent = data_for_children->transform_tree_parent;
     if (PositionConstraint(layer).is_fixed_position() &&
@@ -339,32 +342,31 @@
       transform_parent = data_for_children->transform_fixed_parent;
     }
     ClipNode node;
-    node.data.clip =
-        gfx::RectF(gfx::PointF() + layer->offset_to_transform_parent(),
-                   gfx::SizeF(layer->bounds()));
-    node.data.transform_id = transform_parent->transform_tree_index();
-    node.data.target_id = data_for_children->property_trees->effect_tree
-                              .Node(data_for_children->render_target)
-                              ->data.transform_id;
+    node.clip = gfx::RectF(gfx::PointF() + layer->offset_to_transform_parent(),
+                           gfx::SizeF(layer->bounds()));
+    node.transform_id = transform_parent->transform_tree_index();
+    node.target_id = data_for_children->property_trees->effect_tree
+                         .Node(data_for_children->render_target)
+                         ->transform_id;
     node.owner_id = layer->id();
 
     if (ancestor_clips_subtree || layer_clips_subtree) {
       // Surfaces reset the rect used for layer clipping. At other nodes, layer
       // clipping state from ancestors must continue to get propagated.
-      node.data.layer_clipping_uses_only_local_clip =
+      node.layer_clipping_uses_only_local_clip =
           (created_render_surface && NumUnclippedDescendants(layer) == 0) ||
           !ancestor_clips_subtree;
     } else {
       // Otherwise, we're either unclipped, or exist only in order to apply our
       // parent's clips in our space.
-      node.data.layer_clipping_uses_only_local_clip = false;
+      node.layer_clipping_uses_only_local_clip = false;
     }
 
-    node.data.applies_local_clip = layer_clips_subtree;
-    node.data.resets_clip = has_unclipped_surface;
-    node.data.target_is_clipped = data_for_children->target_is_clipped;
-    node.data.layers_are_clipped = layers_are_clipped;
-    node.data.layers_are_clipped_when_surfaces_disabled =
+    node.applies_local_clip = layer_clips_subtree;
+    node.resets_clip = has_unclipped_surface;
+    node.target_is_clipped = data_for_children->target_is_clipped;
+    node.layers_are_clipped = layers_are_clipped;
+    node.layers_are_clipped_when_surfaces_disabled =
         layers_are_clipped_when_surfaces_disabled;
 
     data_for_children->clip_tree_parent =
@@ -528,14 +530,14 @@
   data_for_children->property_trees->transform_id_to_index_map[layer->id()] =
       node->id;
 
-  node->data.scrolls = is_scrollable;
-  node->data.flattens_inherited_transform = data_for_children->should_flatten;
+  node->scrolls = is_scrollable;
+  node->flattens_inherited_transform = data_for_children->should_flatten;
 
-  node->data.sorting_context_id = layer->sorting_context_id();
+  node->sorting_context_id = layer->sorting_context_id();
 
   if (layer == data_from_ancestor.page_scale_layer)
     data_for_children->in_subtree_of_page_scale_layer = true;
-  node->data.in_subtree_of_page_scale_layer =
+  node->in_subtree_of_page_scale_layer =
       data_for_children->in_subtree_of_page_scale_layer;
 
   // Surfaces inherently flatten transforms.
@@ -546,19 +548,19 @@
   data_for_children->property_trees->transform_tree.SetTargetId(
       node->id, data_for_children->property_trees->effect_tree
                     .Node(data_from_ancestor.render_target)
-                    ->data.transform_id);
+                    ->transform_id);
   data_for_children->property_trees->transform_tree.SetContentTargetId(
       node->id, data_for_children->property_trees->effect_tree
                     .Node(data_for_children->render_target)
-                    ->data.transform_id);
+                    ->transform_id);
   DCHECK_NE(
       data_for_children->property_trees->transform_tree.TargetId(node->id),
       kInvalidPropertyTreeNodeId);
 
-  node->data.has_potential_animation = has_potentially_animated_transform;
-  node->data.is_currently_animating = layer->TransformIsAnimating();
+  node->has_potential_animation = has_potentially_animated_transform;
+  node->is_currently_animating = layer->TransformIsAnimating();
   if (has_potentially_animated_transform) {
-    node->data.has_only_translation_animations =
+    node->has_only_translation_animations =
         layer->HasOnlyTranslationTransforms();
   }
 
@@ -574,57 +576,57 @@
   }
 
   if (has_surface && !is_root)
-    node->data.needs_sublayer_scale = true;
+    node->needs_sublayer_scale = true;
 
-  node->data.source_node_id = source_index;
-  node->data.post_local_scale_factor = post_local_scale_factor;
+  node->source_node_id = source_index;
+  node->post_local_scale_factor = post_local_scale_factor;
   if (is_root) {
     data_for_children->property_trees->transform_tree.SetDeviceTransform(
         *data_from_ancestor.device_transform, layer->position());
     data_for_children->property_trees->transform_tree
         .SetDeviceTransformScaleFactor(*data_from_ancestor.device_transform);
   } else {
-    node->data.source_offset = source_offset;
-    node->data.update_post_local_transform(layer->position(),
-                                           TransformOrigin(layer));
+    node->source_offset = source_offset;
+    node->update_post_local_transform(layer->position(),
+                                      TransformOrigin(layer));
   }
 
   if (is_overscroll_elasticity_layer) {
     DCHECK(!is_scrollable);
-    node->data.scroll_offset =
+    node->scroll_offset =
         gfx::ScrollOffset(data_from_ancestor.elastic_overscroll);
   } else if (!ScrollParent(layer)) {
-    node->data.scroll_offset = layer->CurrentScrollOffset();
+    node->scroll_offset = layer->CurrentScrollOffset();
   }
 
   if (is_fixed) {
     if (data_from_ancestor.affected_by_inner_viewport_bounds_delta) {
-      node->data.affected_by_inner_viewport_bounds_delta_x =
+      node->affected_by_inner_viewport_bounds_delta_x =
           PositionConstraint(layer).is_fixed_to_right_edge();
-      node->data.affected_by_inner_viewport_bounds_delta_y =
+      node->affected_by_inner_viewport_bounds_delta_y =
           PositionConstraint(layer).is_fixed_to_bottom_edge();
-      if (node->data.affected_by_inner_viewport_bounds_delta_x ||
-          node->data.affected_by_inner_viewport_bounds_delta_y) {
+      if (node->affected_by_inner_viewport_bounds_delta_x ||
+          node->affected_by_inner_viewport_bounds_delta_y) {
         data_for_children->property_trees->transform_tree
             .AddNodeAffectedByInnerViewportBoundsDelta(node->id);
       }
     } else if (data_from_ancestor.affected_by_outer_viewport_bounds_delta) {
-      node->data.affected_by_outer_viewport_bounds_delta_x =
+      node->affected_by_outer_viewport_bounds_delta_x =
           PositionConstraint(layer).is_fixed_to_right_edge();
-      node->data.affected_by_outer_viewport_bounds_delta_y =
+      node->affected_by_outer_viewport_bounds_delta_y =
           PositionConstraint(layer).is_fixed_to_bottom_edge();
-      if (node->data.affected_by_outer_viewport_bounds_delta_x ||
-          node->data.affected_by_outer_viewport_bounds_delta_y) {
+      if (node->affected_by_outer_viewport_bounds_delta_x ||
+          node->affected_by_outer_viewport_bounds_delta_y) {
         data_for_children->property_trees->transform_tree
             .AddNodeAffectedByOuterViewportBoundsDelta(node->id);
       }
     }
   }
 
-  node->data.local = layer->transform();
-  node->data.update_pre_local_transform(TransformOrigin(layer));
+  node->local = layer->transform();
+  node->update_pre_local_transform(TransformOrigin(layer));
 
-  node->data.needs_local_transform_update = true;
+  node->needs_local_transform_update = true;
   data_from_ancestor.property_trees->transform_tree.UpdateTransforms(node->id);
 
   layer->set_offset_to_transform_parent(gfx::Vector2dF());
@@ -632,7 +634,7 @@
   // Flattening (if needed) will be handled by |node|.
   layer->set_should_flatten_transform_from_property_tree(false);
 
-  data_for_children->scroll_snap += node->data.scroll_snap;
+  data_for_children->scroll_snap += node->scroll_snap;
 
   node->owner_id = layer->id();
 
@@ -893,26 +895,26 @@
         .push_back(node.owner_id);
   }
 
-  node.data.opacity = Opacity(layer);
-  node.data.has_render_surface = should_create_render_surface;
-  node.data.has_copy_request = HasCopyRequest(layer);
-  node.data.background_filters = BackgroundFilters(layer);
-  node.data.has_potential_opacity_animation = has_potential_opacity_animation;
-  node.data.double_sided = DoubleSided(layer);
-  node.data.subtree_hidden = HideLayerAndSubtree(layer);
-  node.data.is_currently_animating_opacity = layer->OpacityIsAnimating();
+  node.opacity = Opacity(layer);
+  node.has_render_surface = should_create_render_surface;
+  node.has_copy_request = HasCopyRequest(layer);
+  node.background_filters = BackgroundFilters(layer);
+  node.has_potential_opacity_animation = has_potential_opacity_animation;
+  node.double_sided = DoubleSided(layer);
+  node.subtree_hidden = HideLayerAndSubtree(layer);
+  node.is_currently_animating_opacity = layer->OpacityIsAnimating();
 
   EffectTree& effect_tree = data_for_children->property_trees->effect_tree;
   if (MaskLayer(layer)) {
-    node.data.mask_layer_id = MaskLayer(layer)->id();
-    effect_tree.AddMaskOrReplicaLayerId(node.data.mask_layer_id);
+    node.mask_layer_id = MaskLayer(layer)->id();
+    effect_tree.AddMaskOrReplicaLayerId(node.mask_layer_id);
   }
   if (ReplicaLayer(layer)) {
-    node.data.replica_layer_id = ReplicaLayer(layer)->id();
-    effect_tree.AddMaskOrReplicaLayerId(node.data.replica_layer_id);
+    node.replica_layer_id = ReplicaLayer(layer)->id();
+    effect_tree.AddMaskOrReplicaLayerId(node.replica_layer_id);
     if (MaskLayer(ReplicaLayer(layer))) {
-      node.data.replica_mask_layer_id = MaskLayer(ReplicaLayer(layer))->id();
-      effect_tree.AddMaskOrReplicaLayerId(node.data.replica_mask_layer_id);
+      node.replica_mask_layer_id = MaskLayer(ReplicaLayer(layer))->id();
+      effect_tree.AddMaskOrReplicaLayerId(node.replica_mask_layer_id);
     }
   }
 
@@ -924,19 +926,18 @@
       // In this case, we will create a transform node, so it's safe to use the
       // next available id from the transform tree as this effect node's
       // transform id.
-      node.data.transform_id =
+      node.transform_id =
           data_from_ancestor.property_trees->transform_tree.next_available_id();
-      node.data.has_unclipped_descendants =
-          (NumUnclippedDescendants(layer) != 0);
+      node.has_unclipped_descendants = (NumUnclippedDescendants(layer) != 0);
     }
-    node.data.clip_id = data_from_ancestor.clip_tree_parent;
+    node.clip_id = data_from_ancestor.clip_tree_parent;
   } else {
     // Root render surface acts the unbounded and untransformed to draw content
     // into. Transform node created from root layer (includes device scale
     // factor) and clip node created from root layer (include viewports) applies
     // to root render surface's content, but not root render surface itself.
-    node.data.transform_id = kRootPropertyTreeNodeId;
-    node.data.clip_id = kViewportClipTreeNodeId;
+    node.transform_id = kRootPropertyTreeNodeId;
+    node.clip_id = kViewportClipTreeNodeId;
   }
   data_for_children->effect_tree_parent = effect_tree.Insert(node, parent_id);
   int node_id = data_for_children->effect_tree_parent;
@@ -991,48 +992,47 @@
   } else {
     ScrollNode node;
     node.owner_id = layer->id();
-    node.data.scrollable = scrollable;
-    node.data.main_thread_scrolling_reasons = main_thread_scrolling_reasons;
-    node.data.contains_non_fast_scrollable_region =
+    node.scrollable = scrollable;
+    node.main_thread_scrolling_reasons = main_thread_scrolling_reasons;
+    node.contains_non_fast_scrollable_region =
         contains_non_fast_scrollable_region;
     gfx::Size clip_bounds;
     if (layer->scroll_clip_layer()) {
       clip_bounds = layer->scroll_clip_layer()->bounds();
       DCHECK(layer->scroll_clip_layer()->transform_tree_index() !=
              kInvalidPropertyTreeNodeId);
-      node.data.max_scroll_offset_affected_by_page_scale =
+      node.max_scroll_offset_affected_by_page_scale =
           !data_from_ancestor.property_trees->transform_tree
                .Node(layer->scroll_clip_layer()->transform_tree_index())
-               ->data.in_subtree_of_page_scale_layer &&
+               ->in_subtree_of_page_scale_layer &&
           data_from_ancestor.in_subtree_of_page_scale_layer;
     }
 
-    node.data.scroll_clip_layer_bounds = clip_bounds;
-    node.data.is_inner_viewport_scroll_layer =
+    node.scroll_clip_layer_bounds = clip_bounds;
+    node.is_inner_viewport_scroll_layer =
         layer == data_from_ancestor.inner_viewport_scroll_layer;
-    node.data.is_outer_viewport_scroll_layer =
+    node.is_outer_viewport_scroll_layer =
         layer == data_from_ancestor.outer_viewport_scroll_layer;
 
-    node.data.bounds = layer->bounds();
-    node.data.offset_to_transform_parent = layer->offset_to_transform_parent();
-    node.data.should_flatten =
-        layer->should_flatten_transform_from_property_tree();
-    node.data.user_scrollable_horizontal = layer->user_scrollable_horizontal();
-    node.data.user_scrollable_vertical = layer->user_scrollable_vertical();
-    node.data.element_id = layer->element_id();
-    node.data.transform_id =
+    node.bounds = layer->bounds();
+    node.offset_to_transform_parent = layer->offset_to_transform_parent();
+    node.should_flatten = layer->should_flatten_transform_from_property_tree();
+    node.user_scrollable_horizontal = layer->user_scrollable_horizontal();
+    node.user_scrollable_vertical = layer->user_scrollable_vertical();
+    node.element_id = layer->element_id();
+    node.transform_id =
         data_for_children->transform_tree_parent->transform_tree_index();
 
     data_for_children->scroll_tree_parent =
         data_for_children->property_trees->scroll_tree.Insert(node, parent_id);
     data_for_children->main_thread_scrolling_reasons =
-        node.data.main_thread_scrolling_reasons;
+        node.main_thread_scrolling_reasons;
     data_for_children->scroll_tree_parent_created_by_uninheritable_criteria =
         scroll_node_uninheritable_criteria;
     data_for_children->property_trees->scroll_id_to_index_map[layer->id()] =
         data_for_children->scroll_tree_parent;
 
-    if (node.data.scrollable) {
+    if (node.scrollable) {
       data_for_children->property_trees->scroll_tree.SetBaseScrollOffset(
           layer->id(), layer->CurrentScrollOffset());
     }
@@ -1182,9 +1182,9 @@
       data_for_children.effect_tree_parent);
 
   if (effect_node->owner_id == layer->id()) {
-    if (effect_node->data.has_copy_request)
+    if (effect_node->has_copy_request)
       data_to_parent->num_copy_requests_in_subtree++;
-    effect_node->data.num_copy_requests_in_subtree =
+    effect_node->num_copy_requests_in_subtree =
         data_to_parent->num_copy_requests_in_subtree;
   }
 }
@@ -1290,10 +1290,10 @@
       .clear();
 
   ClipNode root_clip;
-  root_clip.data.resets_clip = true;
-  root_clip.data.applies_local_clip = true;
-  root_clip.data.clip = gfx::RectF(viewport);
-  root_clip.data.transform_id = kRootPropertyTreeNodeId;
+  root_clip.resets_clip = true;
+  root_clip.applies_local_clip = true;
+  root_clip.clip = gfx::RectF(viewport);
+  root_clip.transform_id = kRootPropertyTreeNodeId;
   data_for_recursion.clip_tree_parent =
       data_for_recursion.property_trees->clip_tree.Insert(
           root_clip, kRootPropertyTreeNodeId);
diff --git a/cc/trees/property_tree_unittest.cc b/cc/trees/property_tree_unittest.cc
index 0cc190f7..d007cb2 100644
--- a/cc/trees/property_tree_unittest.cc
+++ b/cc/trees/property_tree_unittest.cc
@@ -7,14 +7,21 @@
 #include "cc/input/main_thread_scrolling_reason.h"
 #include "cc/proto/property_tree.pb.h"
 #include "cc/test/geometry_test_utils.h"
+#include "cc/trees/clip_node.h"
 #include "cc/trees/draw_property_utils.h"
+#include "cc/trees/effect_node.h"
+#include "cc/trees/scroll_node.h"
+#include "cc/trees/transform_node.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
 namespace {
 
-TEST(PropertyTreeSerializationTest, TransformNodeDataSerialization) {
-  TransformNodeData original;
+TEST(PropertyTreeSerializationTest, TransformNodeSerialization) {
+  TransformNode original;
+  original.id = 3;
+  original.parent_id = 2;
+  original.owner_id = 4;
   original.pre_local.Translate3d(1.f, 2.f, 3.f);
   original.local.Translate3d(3.f, 1.f, 5.f);
   original.post_local.Translate3d(1.f, 8.f, 3.f);
@@ -45,20 +52,6 @@
 
   proto::TreeNode proto;
   original.ToProtobuf(&proto);
-  TransformNodeData result;
-  result.FromProtobuf(proto);
-
-  EXPECT_EQ(original, result);
-}
-
-TEST(PropertyTreeSerializationTest, TransformNodeSerialization) {
-  TransformNode original;
-  original.id = 3;
-  original.parent_id = 2;
-  original.owner_id = 4;
-
-  proto::TreeNode proto;
-  original.ToProtobuf(&proto);
   TransformNode result;
   result.FromProtobuf(proto);
 
@@ -75,14 +68,14 @@
   original.SetContentTargetId(root.id, 4);
   TransformNode second;
   second.owner_id = 2;
-  second.data.local.Translate3d(2.f, 2.f, 0.f);
-  second.data.source_node_id = 0;
+  second.local.Translate3d(2.f, 2.f, 0.f);
+  second.source_node_id = 0;
   second.id = original.Insert(second, 0);
   original.SetTargetId(second.id, 0);
   TransformNode third;
   third.owner_id = 3;
-  third.data.scrolls = true;
-  third.data.source_node_id = 1;
+  third.scrolls = true;
+  third.source_node_id = 1;
   third.id = original.Insert(third, 1);
   original.SetTargetId(third.id, 0);
 
@@ -109,8 +102,11 @@
   EXPECT_EQ(original, result);
 }
 
-TEST(PropertyTreeSerializationTest, ClipNodeDataSerialization) {
-  ClipNodeData original;
+TEST(PropertyTreeSerializationTest, ClipNodeSerialization) {
+  ClipNode original;
+  original.id = 3;
+  original.parent_id = 2;
+  original.owner_id = 4;
   original.clip = gfx::RectF(0.5f, 0.5f);
   original.combined_clip_in_target_space = gfx::RectF(0.6f, 0.6f);
   original.clip_in_target_space = gfx::RectF(0.7f, 0.7f);
@@ -125,20 +121,6 @@
 
   proto::TreeNode proto;
   original.ToProtobuf(&proto);
-  ClipNodeData result;
-  result.FromProtobuf(proto);
-
-  EXPECT_EQ(original, result);
-}
-
-TEST(PropertyTreeSerializationTest, ClipNodeSerialization) {
-  ClipNode original;
-  original.id = 3;
-  original.parent_id = 2;
-  original.owner_id = 4;
-
-  proto::TreeNode proto;
-  original.ToProtobuf(&proto);
   ClipNode result;
   result.FromProtobuf(proto);
 
@@ -149,16 +131,16 @@
   ClipTree original;
   ClipNode& root = *original.Node(0);
   root.owner_id = 1;
-  root.data.transform_id = 2;
-  root.data.target_id = 1;
+  root.transform_id = 2;
+  root.target_id = 1;
   ClipNode second;
   second.owner_id = 2;
-  second.data.transform_id = 4;
-  second.data.applies_local_clip = true;
+  second.transform_id = 4;
+  second.applies_local_clip = true;
   ClipNode third;
   third.owner_id = 3;
-  third.data.target_id = 3;
-  third.data.target_is_clipped = false;
+  third.target_id = 3;
+  third.target_is_clipped = false;
 
   original.Insert(second, 0);
   original.Insert(third, 1);
@@ -176,8 +158,11 @@
   EXPECT_EQ(original, result);
 }
 
-TEST(PropertyTreeSerializationTest, EffectNodeDataSerialization) {
-  EffectNodeData original;
+TEST(PropertyTreeSerializationTest, EffectNodeSerialization) {
+  EffectNode original;
+  original.id = 3;
+  original.parent_id = 2;
+  original.owner_id = 4;
   original.opacity = 0.5f;
   original.screen_space_opacity = 0.6f;
   original.has_render_surface = false;
@@ -190,20 +175,6 @@
 
   proto::TreeNode proto;
   original.ToProtobuf(&proto);
-  EffectNodeData result;
-  result.FromProtobuf(proto);
-
-  EXPECT_EQ(original, result);
-}
-
-TEST(PropertyTreeSerializationTest, EffectNodeSerialization) {
-  EffectNode original;
-  original.id = 3;
-  original.parent_id = 2;
-  original.owner_id = 4;
-
-  proto::TreeNode proto;
-  original.ToProtobuf(&proto);
   EffectNode result;
   result.FromProtobuf(proto);
 
@@ -214,19 +185,19 @@
   EffectTree original;
   EffectNode& root = *original.Node(0);
   root.owner_id = 5;
-  root.data.transform_id = 2;
-  root.data.clip_id = 1;
+  root.transform_id = 2;
+  root.clip_id = 1;
   EffectNode second;
   second.owner_id = 6;
-  second.data.transform_id = 4;
-  second.data.opacity = true;
-  second.data.mask_layer_id = 32;
+  second.transform_id = 4;
+  second.opacity = true;
+  second.mask_layer_id = 32;
   EffectNode third;
   third.owner_id = 7;
-  third.data.clip_id = 3;
-  third.data.replica_layer_id = 44;
-  third.data.replica_mask_layer_id = 45;
-  third.data.has_render_surface = false;
+  third.clip_id = 3;
+  third.replica_layer_id = 44;
+  third.replica_mask_layer_id = 45;
+  third.has_render_surface = false;
 
   original.Insert(second, 0);
   original.Insert(third, 1);
@@ -247,8 +218,11 @@
   EXPECT_EQ(original, result);
 }
 
-TEST(PropertyTreeSerializationTest, ScrollNodeDataSerialization) {
-  ScrollNodeData original;
+TEST(PropertyTreeSerializationTest, ScrollNodeSerialization) {
+  ScrollNode original;
+  original.id = 3;
+  original.parent_id = 2;
+  original.owner_id = 4;
   original.scrollable = true;
   original.main_thread_scrolling_reasons =
       MainThreadScrollingReason::kScrollbarScrolling;
@@ -261,20 +235,6 @@
 
   proto::TreeNode proto;
   original.ToProtobuf(&proto);
-  ScrollNodeData result;
-  result.FromProtobuf(proto);
-
-  EXPECT_EQ(original, result);
-}
-
-TEST(PropertyTreeSerializationTest, ScrollNodeSerialization) {
-  ScrollNode original;
-  original.id = 3;
-  original.parent_id = 2;
-  original.owner_id = 4;
-
-  proto::TreeNode proto;
-  original.ToProtobuf(&proto);
   ScrollNode result;
   result.FromProtobuf(proto);
 
@@ -287,11 +247,11 @@
   ScrollTree& original = property_trees.scroll_tree;
   ScrollNode second;
   second.owner_id = 10;
-  second.data.scrollable = true;
-  second.data.bounds = gfx::Size(15, 15);
+  second.scrollable = true;
+  second.bounds = gfx::Size(15, 15);
   ScrollNode third;
   third.owner_id = 20;
-  third.data.contains_non_fast_scrollable_region = true;
+  third.contains_non_fast_scrollable_region = true;
 
   original.Insert(second, 0);
   original.Insert(third, 1);
@@ -435,7 +395,7 @@
     TransformTree& tree = property_trees.transform_tree;
     TransformNode& root = *tree.Node(0);
     root.id = 0;
-    root.data.local.Translate(2, 2);
+    root.local.Translate(2, 2);
     tree.SetTargetId(root.id, 0);
     SetupTransformTreeForTest(&tree);
     tree.UpdateTransforms(0);
@@ -470,13 +430,13 @@
     PropertyTrees property_trees;
     TransformTree& tree = property_trees.transform_tree;
     TransformNode& root = *tree.Node(0);
-    root.data.local.Translate(2, 2);
+    root.local.Translate(2, 2);
     tree.SetTargetId(root.id, 0);
     tree.UpdateTransforms(0);
 
     TransformNode child;
-    child.data.local.Translate(3, 3);
-    child.data.source_node_id = 0;
+    child.local.Translate(3, 3);
+    child.source_node_id = 0;
     child.id = tree.Insert(child, 0);
     tree.SetTargetId(child.id, 0);
 
@@ -523,19 +483,19 @@
     PropertyTrees property_trees;
     TransformTree& tree = property_trees.transform_tree;
     TransformNode& root = *tree.Node(0);
-    root.data.local.Translate(2, 2);
+    root.local.Translate(2, 2);
     tree.SetTargetId(root.id, 0);
     tree.UpdateTransforms(0);
 
     TransformNode child;
-    child.data.local.Translate(3, 3);
-    child.data.source_node_id = 0;
+    child.local.Translate(3, 3);
+    child.source_node_id = 0;
     child.id = tree.Insert(child, 0);
     tree.SetTargetId(child.id, 0);
 
     TransformNode sibling;
-    sibling.data.local.Translate(7, 7);
-    sibling.data.source_node_id = 0;
+    sibling.local.Translate(7, 7);
+    sibling.source_node_id = 0;
     sibling.id = tree.Insert(sibling, 0);
     tree.SetTargetId(sibling.id, 0);
 
@@ -580,25 +540,25 @@
     PropertyTrees property_trees;
     TransformTree& tree = property_trees.transform_tree;
     TransformNode& root = *tree.Node(0);
-    root.data.local.Translate(2, 2);
+    root.local.Translate(2, 2);
     tree.SetTargetId(root.id, 0);
     tree.UpdateTransforms(0);
 
     TransformNode singular;
-    singular.data.local.matrix().set(2, 2, 0.0);
-    singular.data.source_node_id = 0;
+    singular.local.matrix().set(2, 2, 0.0);
+    singular.source_node_id = 0;
     singular.id = tree.Insert(singular, 0);
     tree.SetTargetId(singular.id, 0);
 
     TransformNode child;
-    child.data.local.Translate(3, 3);
-    child.data.source_node_id = 1;
+    child.local.Translate(3, 3);
+    child.source_node_id = 1;
     child.id = tree.Insert(child, 1);
     tree.SetTargetId(child.id, 0);
 
     TransformNode sibling;
-    sibling.data.local.Translate(7, 7);
-    sibling.data.source_node_id = 1;
+    sibling.local.Translate(7, 7);
+    sibling.source_node_id = 1;
     sibling.id = tree.Insert(sibling, 1);
     tree.SetTargetId(sibling.id, 0);
 
@@ -637,31 +597,31 @@
     int grand_parent = tree.Insert(TransformNode(), 0);
     tree.SetContentTargetId(grand_parent, grand_parent);
     tree.SetTargetId(grand_parent, grand_parent);
-    tree.Node(grand_parent)->data.source_node_id = 0;
+    tree.Node(grand_parent)->source_node_id = 0;
 
     gfx::Transform rotation_about_x;
     rotation_about_x.RotateAboutXAxis(15);
 
     int parent = tree.Insert(TransformNode(), grand_parent);
-    tree.Node(parent)->data.needs_sublayer_scale = true;
+    tree.Node(parent)->needs_sublayer_scale = true;
     tree.SetTargetId(parent, grand_parent);
     tree.SetContentTargetId(parent, parent);
-    tree.Node(parent)->data.source_node_id = grand_parent;
-    tree.Node(parent)->data.local = rotation_about_x;
+    tree.Node(parent)->source_node_id = grand_parent;
+    tree.Node(parent)->local = rotation_about_x;
 
     int child = tree.Insert(TransformNode(), parent);
     tree.SetTargetId(child, parent);
     tree.SetContentTargetId(child, parent);
-    tree.Node(child)->data.source_node_id = parent;
-    tree.Node(child)->data.flattens_inherited_transform = true;
-    tree.Node(child)->data.local = rotation_about_x;
+    tree.Node(child)->source_node_id = parent;
+    tree.Node(child)->flattens_inherited_transform = true;
+    tree.Node(child)->local = rotation_about_x;
 
     int grand_child = tree.Insert(TransformNode(), child);
     tree.SetTargetId(grand_child, parent);
     tree.SetContentTargetId(grand_child, parent);
-    tree.Node(grand_child)->data.source_node_id = child;
-    tree.Node(grand_child)->data.flattens_inherited_transform = true;
-    tree.Node(grand_child)->data.local = rotation_about_x;
+    tree.Node(grand_child)->source_node_id = child;
+    tree.Node(grand_child)->flattens_inherited_transform = true;
+    tree.Node(grand_child)->local = rotation_about_x;
 
     tree.set_needs_update(true);
     SetupTransformTreeForTest(&tree);
@@ -691,7 +651,7 @@
     EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_about_x, grand_child_to_child);
 
     // Remove flattening at grand_child, and recompute transforms.
-    tree.Node(grand_child)->data.flattens_inherited_transform = false;
+    tree.Node(grand_child)->flattens_inherited_transform = false;
     tree.set_needs_update(true);
     SetupTransformTreeForTest(&tree);
     draw_property_utils::ComputeTransforms(&tree);
@@ -718,13 +678,13 @@
     PropertyTrees property_trees;
     TransformTree& tree = property_trees.transform_tree;
     TransformNode& root = *tree.Node(0);
-    root.data.local.Translate(2, 2);
+    root.local.Translate(2, 2);
     tree.SetTargetId(root.id, 0);
     tree.UpdateTransforms(0);
 
     TransformNode child;
-    child.data.local.Scale(2, 2);
-    child.data.source_node_id = 0;
+    child.local.Scale(2, 2);
+    child.source_node_id = 0;
     child.id = tree.Insert(child, 0);
     tree.SetTargetId(child.id, 0);
 
@@ -764,8 +724,8 @@
     tree.UpdateTransforms(0);
 
     TransformNode child;
-    child.data.local.Scale(0, 0);
-    child.data.source_node_id = 0;
+    child.local.Scale(0, 0);
+    child.source_node_id = 0;
     child.id = tree.Insert(child, 0);
     tree.SetTargetId(child.id, 0);
 
@@ -804,40 +764,40 @@
     tree.UpdateTransforms(0);
 
     TransformNode grand_parent;
-    grand_parent.data.local.Scale(2.f, 2.f);
-    grand_parent.data.source_node_id = 0;
-    grand_parent.data.needs_sublayer_scale = true;
+    grand_parent.local.Scale(2.f, 2.f);
+    grand_parent.source_node_id = 0;
+    grand_parent.needs_sublayer_scale = true;
     int grand_parent_id = tree.Insert(grand_parent, 0);
     tree.SetTargetId(grand_parent_id, 0);
     tree.UpdateTransforms(grand_parent_id);
 
     TransformNode parent;
-    parent.data.local.Translate(15.f, 15.f);
-    parent.data.source_node_id = grand_parent_id;
+    parent.local.Translate(15.f, 15.f);
+    parent.source_node_id = grand_parent_id;
     int parent_id = tree.Insert(parent, grand_parent_id);
     tree.SetTargetId(parent_id, grand_parent_id);
     tree.UpdateTransforms(parent_id);
 
     TransformNode child;
-    child.data.local.Scale(3.f, 3.f);
-    child.data.source_node_id = parent_id;
+    child.local.Scale(3.f, 3.f);
+    child.source_node_id = parent_id;
     int child_id = tree.Insert(child, parent_id);
     tree.SetTargetId(child_id, grand_parent_id);
     tree.UpdateTransforms(child_id);
 
     TransformNode grand_child;
-    grand_child.data.local.Scale(5.f, 5.f);
-    grand_child.data.source_node_id = child_id;
-    grand_child.data.needs_sublayer_scale = true;
+    grand_child.local.Scale(5.f, 5.f);
+    grand_child.source_node_id = child_id;
+    grand_child.needs_sublayer_scale = true;
     int grand_child_id = tree.Insert(grand_child, child_id);
     tree.SetTargetId(grand_child_id, grand_parent_id);
     SetupTransformTreeForTest(&tree);
     tree.UpdateTransforms(grand_child_id);
 
     EXPECT_EQ(gfx::Vector2dF(2.f, 2.f),
-              tree.Node(grand_parent_id)->data.sublayer_scale);
+              tree.Node(grand_parent_id)->sublayer_scale);
     EXPECT_EQ(gfx::Vector2dF(30.f, 30.f),
-              tree.Node(grand_child_id)->data.sublayer_scale);
+              tree.Node(grand_child_id)->sublayer_scale);
 
     // Compute transform from grand_parent to grand_child.
     gfx::Transform expected_transform_without_sublayer_scale;
@@ -922,25 +882,25 @@
     tree.UpdateTransforms(0);
 
     TransformNode grand_parent;
-    grand_parent.data.local.Scale(2.f, 0.f);
-    grand_parent.data.source_node_id = 0;
-    grand_parent.data.needs_sublayer_scale = true;
+    grand_parent.local.Scale(2.f, 0.f);
+    grand_parent.source_node_id = 0;
+    grand_parent.needs_sublayer_scale = true;
     int grand_parent_id = tree.Insert(grand_parent, 0);
     tree.SetTargetId(grand_parent_id, 0);
     tree.SetContentTargetId(grand_parent_id, grand_parent_id);
     tree.UpdateTransforms(grand_parent_id);
 
     TransformNode parent;
-    parent.data.local.Translate(1.f, 1.f);
-    parent.data.source_node_id = grand_parent_id;
+    parent.local.Translate(1.f, 1.f);
+    parent.source_node_id = grand_parent_id;
     int parent_id = tree.Insert(parent, grand_parent_id);
     tree.SetTargetId(parent_id, grand_parent_id);
     tree.SetContentTargetId(parent_id, grand_parent_id);
     tree.UpdateTransforms(parent_id);
 
     TransformNode child;
-    child.data.local.Translate(3.f, 4.f);
-    child.data.source_node_id = parent_id;
+    child.local.Translate(3.f, 4.f);
+    child.source_node_id = parent_id;
     int child_id = tree.Insert(child, parent_id);
     tree.SetTargetId(child_id, grand_parent_id);
     tree.SetContentTargetId(child_id, grand_parent_id);
@@ -955,9 +915,9 @@
     EXPECT_TRUE(success);
     EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, transform);
 
-    tree.Node(grand_parent_id)->data.local.MakeIdentity();
-    tree.Node(grand_parent_id)->data.local.Scale(0.f, 2.f);
-    tree.Node(grand_parent_id)->data.needs_local_transform_update = true;
+    tree.Node(grand_parent_id)->local.MakeIdentity();
+    tree.Node(grand_parent_id)->local.Scale(0.f, 2.f);
+    tree.Node(grand_parent_id)->needs_local_transform_update = true;
     tree.set_needs_update(true);
     SetupTransformTreeForTest(&tree);
 
@@ -967,9 +927,9 @@
     EXPECT_TRUE(success);
     EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, transform);
 
-    tree.Node(grand_parent_id)->data.local.MakeIdentity();
-    tree.Node(grand_parent_id)->data.local.Scale(0.f, 0.f);
-    tree.Node(grand_parent_id)->data.needs_local_transform_update = true;
+    tree.Node(grand_parent_id)->local.MakeIdentity();
+    tree.Node(grand_parent_id)->local.Scale(0.f, 0.f);
+    tree.Node(grand_parent_id)->needs_local_transform_update = true;
     tree.set_needs_update(true);
     SetupTransformTreeForTest(&tree);
 
@@ -997,8 +957,8 @@
     int parent = tree.Insert(TransformNode(), 0);
     tree.SetContentTargetId(parent, parent);
     tree.SetTargetId(parent, parent);
-    tree.Node(parent)->data.source_node_id = 0;
-    tree.Node(parent)->data.local.Translate(2, 2);
+    tree.Node(parent)->source_node_id = 0;
+    tree.Node(parent)->local.Translate(2, 2);
 
     gfx::Transform rotation_about_x;
     rotation_about_x.RotateAboutXAxis(15);
@@ -1006,14 +966,14 @@
     int child = tree.Insert(TransformNode(), parent);
     tree.SetContentTargetId(child, child);
     tree.SetTargetId(child, child);
-    tree.Node(child)->data.source_node_id = parent;
-    tree.Node(child)->data.local = rotation_about_x;
+    tree.Node(child)->source_node_id = parent;
+    tree.Node(child)->local = rotation_about_x;
 
     int grand_child = tree.Insert(TransformNode(), child);
     tree.SetContentTargetId(grand_child, grand_child);
     tree.SetTargetId(grand_child, grand_child);
-    tree.Node(grand_child)->data.source_node_id = child;
-    tree.Node(grand_child)->data.flattens_inherited_transform = true;
+    tree.Node(grand_child)->source_node_id = child;
+    tree.Node(grand_child)->flattens_inherited_transform = true;
 
     tree.set_needs_update(true);
     SetupTransformTreeForTest(&tree);
@@ -1045,18 +1005,18 @@
     int child = tree.Insert(EffectNode(), parent);
     SetupEffectTreeForTest(&tree);
 
-    EXPECT_EQ(tree.Node(child)->data.screen_space_opacity, 1.f);
-    tree.Node(parent)->data.opacity = 0.5f;
+    EXPECT_EQ(tree.Node(child)->screen_space_opacity, 1.f);
+    tree.Node(parent)->opacity = 0.5f;
     tree.set_needs_update(true);
     SetupEffectTreeForTest(&tree);
     draw_property_utils::ComputeEffects(&tree);
-    EXPECT_EQ(tree.Node(child)->data.screen_space_opacity, 0.5f);
+    EXPECT_EQ(tree.Node(child)->screen_space_opacity, 0.5f);
 
-    tree.Node(child)->data.opacity = 0.5f;
+    tree.Node(child)->opacity = 0.5f;
     tree.set_needs_update(true);
     SetupEffectTreeForTest(&tree);
     draw_property_utils::ComputeEffects(&tree);
-    EXPECT_EQ(tree.Node(child)->data.screen_space_opacity, 0.25f);
+    EXPECT_EQ(tree.Node(child)->screen_space_opacity, 0.25f);
   }
 };
 
@@ -1073,38 +1033,38 @@
 
     int parent = tree.Insert(TransformNode(), 0);
     tree.SetTargetId(parent, parent);
-    tree.Node(parent)->data.local.Translate(1.5f, 1.5f);
+    tree.Node(parent)->local.Translate(1.5f, 1.5f);
 
     int child = tree.Insert(TransformNode(), parent);
     tree.SetTargetId(child, parent);
-    tree.Node(child)->data.local.Translate(1, 1);
+    tree.Node(child)->local.Translate(1, 1);
     tree.set_needs_update(true);
     SetupTransformTreeForTest(&tree);
     draw_property_utils::ComputeTransforms(&tree);
-    EXPECT_FALSE(tree.Node(parent)
-                     ->data.node_and_ancestors_have_only_integer_translation);
-    EXPECT_FALSE(tree.Node(child)
-                     ->data.node_and_ancestors_have_only_integer_translation);
+    EXPECT_FALSE(
+        tree.Node(parent)->node_and_ancestors_have_only_integer_translation);
+    EXPECT_FALSE(
+        tree.Node(child)->node_and_ancestors_have_only_integer_translation);
 
-    tree.Node(parent)->data.local.Translate(0.5f, 0.5f);
-    tree.Node(child)->data.local.Translate(0.5f, 0.5f);
+    tree.Node(parent)->local.Translate(0.5f, 0.5f);
+    tree.Node(child)->local.Translate(0.5f, 0.5f);
     tree.set_needs_update(true);
     SetupTransformTreeForTest(&tree);
     draw_property_utils::ComputeTransforms(&tree);
-    EXPECT_TRUE(tree.Node(parent)
-                    ->data.node_and_ancestors_have_only_integer_translation);
-    EXPECT_FALSE(tree.Node(child)
-                     ->data.node_and_ancestors_have_only_integer_translation);
+    EXPECT_TRUE(
+        tree.Node(parent)->node_and_ancestors_have_only_integer_translation);
+    EXPECT_FALSE(
+        tree.Node(child)->node_and_ancestors_have_only_integer_translation);
 
-    tree.Node(child)->data.local.Translate(0.5f, 0.5f);
+    tree.Node(child)->local.Translate(0.5f, 0.5f);
     tree.SetTargetId(child, child);
     tree.set_needs_update(true);
     SetupTransformTreeForTest(&tree);
     draw_property_utils::ComputeTransforms(&tree);
-    EXPECT_TRUE(tree.Node(parent)
-                    ->data.node_and_ancestors_have_only_integer_translation);
-    EXPECT_TRUE(tree.Node(child)
-                    ->data.node_and_ancestors_have_only_integer_translation);
+    EXPECT_TRUE(
+        tree.Node(parent)->node_and_ancestors_have_only_integer_translation);
+    EXPECT_TRUE(
+        tree.Node(child)->node_and_ancestors_have_only_integer_translation);
   }
 };
 
@@ -1121,14 +1081,14 @@
 
     int parent = tree.Insert(TransformNode(), 0);
     tree.SetTargetId(parent, parent);
-    tree.Node(parent)->data.scrolls = true;
+    tree.Node(parent)->scrolls = true;
 
     int child = tree.Insert(TransformNode(), parent);
     TransformNode* child_node = tree.Node(child);
     tree.SetTargetId(child, parent);
-    child_node->data.scrolls = true;
-    child_node->data.local.Scale3d(6.0f, 6.0f, 0.0f);
-    child_node->data.local.Translate(1.3f, 1.3f);
+    child_node->scrolls = true;
+    child_node->local.Scale3d(6.0f, 6.0f, 0.0f);
+    child_node->local.Translate(1.3f, 1.3f);
     tree.set_needs_update(true);
 
     SetupTransformTreeForTest(&tree);
@@ -1139,10 +1099,10 @@
     // The following checks are to ensure that snapping is skipped because of
     // singular transform (and not because of other reasons which also cause
     // snapping to be skipped).
-    EXPECT_TRUE(child_node->data.scrolls);
+    EXPECT_TRUE(child_node->scrolls);
     EXPECT_TRUE(tree.ToTarget(child).IsScaleOrTranslation());
-    EXPECT_FALSE(child_node->data.to_screen_is_potentially_animated);
-    EXPECT_FALSE(child_node->data.ancestors_are_invertible);
+    EXPECT_FALSE(child_node->to_screen_is_potentially_animated);
+    EXPECT_FALSE(child_node->ancestors_are_invertible);
 
     gfx::Transform rounded = tree.ToTarget(child);
     rounded.RoundTranslationComponents();
diff --git a/cc/trees/scroll_node.cc b/cc/trees/scroll_node.cc
new file mode 100644
index 0000000..a20fe2f
--- /dev/null
+++ b/cc/trees/scroll_node.cc
@@ -0,0 +1,127 @@
+// Copyright 2016 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 "base/trace_event/trace_event_argument.h"
+#include "cc/animation/element_id.h"
+#include "cc/base/math_util.h"
+#include "cc/input/main_thread_scrolling_reason.h"
+#include "cc/proto/gfx_conversions.h"
+#include "cc/proto/property_tree.pb.h"
+#include "cc/trees/scroll_node.h"
+
+namespace cc {
+
+ScrollNode::ScrollNode()
+    : id(-1),
+      parent_id(-1),
+      owner_id(-1),
+      scrollable(false),
+      main_thread_scrolling_reasons(
+          MainThreadScrollingReason::kNotScrollingOnMain),
+      contains_non_fast_scrollable_region(false),
+      max_scroll_offset_affected_by_page_scale(false),
+      is_inner_viewport_scroll_layer(false),
+      is_outer_viewport_scroll_layer(false),
+      should_flatten(false),
+      user_scrollable_horizontal(false),
+      user_scrollable_vertical(false),
+      transform_id(0),
+      num_drawn_descendants(0) {}
+
+ScrollNode::ScrollNode(const ScrollNode& other) = default;
+
+bool ScrollNode::operator==(const ScrollNode& other) const {
+  return id == other.id && parent_id == other.parent_id &&
+         owner_id == other.owner_id && scrollable == other.scrollable &&
+         main_thread_scrolling_reasons == other.main_thread_scrolling_reasons &&
+         contains_non_fast_scrollable_region ==
+             other.contains_non_fast_scrollable_region &&
+         scroll_clip_layer_bounds == other.scroll_clip_layer_bounds &&
+         bounds == other.bounds &&
+         max_scroll_offset_affected_by_page_scale ==
+             other.max_scroll_offset_affected_by_page_scale &&
+         is_inner_viewport_scroll_layer ==
+             other.is_inner_viewport_scroll_layer &&
+         is_outer_viewport_scroll_layer ==
+             other.is_outer_viewport_scroll_layer &&
+         offset_to_transform_parent == other.offset_to_transform_parent &&
+         should_flatten == other.should_flatten &&
+         user_scrollable_horizontal == other.user_scrollable_horizontal &&
+         user_scrollable_vertical == other.user_scrollable_vertical &&
+         element_id == other.element_id && transform_id == other.transform_id;
+}
+
+void ScrollNode::ToProtobuf(proto::TreeNode* proto) const {
+  proto->set_id(id);
+  proto->set_parent_id(parent_id);
+  proto->set_owner_id(owner_id);
+
+  DCHECK(!proto->has_scroll_node_data());
+  proto::ScrollNodeData* data = proto->mutable_scroll_node_data();
+  data->set_scrollable(scrollable);
+  data->set_main_thread_scrolling_reasons(main_thread_scrolling_reasons);
+  data->set_contains_non_fast_scrollable_region(
+      contains_non_fast_scrollable_region);
+  SizeToProto(scroll_clip_layer_bounds,
+              data->mutable_scroll_clip_layer_bounds());
+  SizeToProto(bounds, data->mutable_bounds());
+  data->set_max_scroll_offset_affected_by_page_scale(
+      max_scroll_offset_affected_by_page_scale);
+  data->set_is_inner_viewport_scroll_layer(is_inner_viewport_scroll_layer);
+  data->set_is_outer_viewport_scroll_layer(is_outer_viewport_scroll_layer);
+  Vector2dFToProto(offset_to_transform_parent,
+                   data->mutable_offset_to_transform_parent());
+  data->set_should_flatten(should_flatten);
+  data->set_user_scrollable_horizontal(user_scrollable_horizontal);
+  data->set_user_scrollable_vertical(user_scrollable_vertical);
+  element_id.ToProtobuf(data->mutable_element_id());
+  data->set_transform_id(transform_id);
+}
+
+void ScrollNode::FromProtobuf(const proto::TreeNode& proto) {
+  id = proto.id();
+  parent_id = proto.parent_id();
+  owner_id = proto.owner_id();
+
+  DCHECK(proto.has_scroll_node_data());
+  const proto::ScrollNodeData& data = proto.scroll_node_data();
+
+  scrollable = data.scrollable();
+  main_thread_scrolling_reasons = data.main_thread_scrolling_reasons();
+  contains_non_fast_scrollable_region =
+      data.contains_non_fast_scrollable_region();
+  scroll_clip_layer_bounds = ProtoToSize(data.scroll_clip_layer_bounds());
+  bounds = ProtoToSize(data.bounds());
+  max_scroll_offset_affected_by_page_scale =
+      data.max_scroll_offset_affected_by_page_scale();
+  is_inner_viewport_scroll_layer = data.is_inner_viewport_scroll_layer();
+  is_outer_viewport_scroll_layer = data.is_outer_viewport_scroll_layer();
+  offset_to_transform_parent =
+      ProtoToVector2dF(data.offset_to_transform_parent());
+  should_flatten = data.should_flatten();
+  user_scrollable_horizontal = data.user_scrollable_horizontal();
+  user_scrollable_vertical = data.user_scrollable_vertical();
+  element_id.FromProtobuf(data.element_id());
+  transform_id = data.transform_id();
+}
+
+void ScrollNode::AsValueInto(base::trace_event::TracedValue* value) const {
+  value->SetInteger("id", id);
+  value->SetInteger("parent_id", parent_id);
+  value->SetInteger("owner_id", owner_id);
+  value->SetBoolean("scrollable", scrollable);
+  MathUtil::AddToTracedValue("scroll_clip_layer_bounds",
+                             scroll_clip_layer_bounds, value);
+  MathUtil::AddToTracedValue("bounds", bounds, value);
+  MathUtil::AddToTracedValue("offset_to_transform_parent",
+                             offset_to_transform_parent, value);
+  value->SetBoolean("should_flatten", should_flatten);
+  value->SetBoolean("user_scrollable_horizontal", user_scrollable_horizontal);
+  value->SetBoolean("user_scrollable_vertical", user_scrollable_vertical);
+
+  element_id.AddToTracedValue(value);
+  value->SetInteger("transform_id", transform_id);
+}
+
+}  // namespace cc
diff --git a/cc/trees/scroll_node.h b/cc/trees/scroll_node.h
new file mode 100644
index 0000000..745ee69
--- /dev/null
+++ b/cc/trees/scroll_node.h
@@ -0,0 +1,58 @@
+// Copyright 2016 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_TREES_SCROLL_NODE_H_
+#define CC_TREES_SCROLL_NODE_H_
+
+#include "cc/base/cc_export.h"
+#include "cc/output/filter_operations.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace base {
+namespace trace_event {
+class TracedValue;
+}  // namespace trace_event
+}  // namespace base
+
+namespace cc {
+
+namespace proto {
+class TreeNode;
+}  // namespace proto
+
+struct CC_EXPORT ScrollNode {
+  ScrollNode();
+  ScrollNode(const ScrollNode& other);
+
+  int id;
+  int parent_id;
+  int owner_id;
+
+  bool scrollable;
+  uint32_t main_thread_scrolling_reasons;
+  bool contains_non_fast_scrollable_region;
+  gfx::Size scroll_clip_layer_bounds;
+  gfx::Size bounds;
+  bool max_scroll_offset_affected_by_page_scale;
+  bool is_inner_viewport_scroll_layer;
+  bool is_outer_viewport_scroll_layer;
+  gfx::Vector2dF offset_to_transform_parent;
+  bool should_flatten;
+  bool user_scrollable_horizontal;
+  bool user_scrollable_vertical;
+  ElementId element_id;
+  int transform_id;
+  // Number of drawn layers pointing to this node or any of its descendants.
+  int num_drawn_descendants;
+
+  bool operator==(const ScrollNode& other) const;
+
+  void ToProtobuf(proto::TreeNode* proto) const;
+  void FromProtobuf(const proto::TreeNode& proto);
+  void AsValueInto(base::trace_event::TracedValue* value) const;
+};
+
+}  // namespace cc
+
+#endif  // CC_TREES_SCROLL_NODE_H_
diff --git a/cc/trees/transform_node.cc b/cc/trees/transform_node.cc
new file mode 100644
index 0000000..ab2693b3
--- /dev/null
+++ b/cc/trees/transform_node.cc
@@ -0,0 +1,271 @@
+// Copyright 2016 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 "base/trace_event/trace_event_argument.h"
+#include "cc/base/math_util.h"
+#include "cc/proto/gfx_conversions.h"
+#include "cc/proto/property_tree.pb.h"
+#include "cc/trees/transform_node.h"
+#include "ui/gfx/geometry/point3_f.h"
+
+namespace cc {
+
+TransformNode::TransformNode()
+    : id(-1),
+      parent_id(-1),
+      owner_id(-1),
+      source_node_id(-1),
+      sorting_context_id(0),
+      needs_local_transform_update(true),
+      node_and_ancestors_are_animated_or_invertible(true),
+      is_invertible(true),
+      ancestors_are_invertible(true),
+      has_potential_animation(false),
+      is_currently_animating(false),
+      to_screen_is_potentially_animated(false),
+      has_only_translation_animations(true),
+      flattens_inherited_transform(false),
+      node_and_ancestors_are_flat(true),
+      node_and_ancestors_have_only_integer_translation(true),
+      scrolls(false),
+      needs_sublayer_scale(false),
+      affected_by_inner_viewport_bounds_delta_x(false),
+      affected_by_inner_viewport_bounds_delta_y(false),
+      affected_by_outer_viewport_bounds_delta_x(false),
+      affected_by_outer_viewport_bounds_delta_y(false),
+      in_subtree_of_page_scale_layer(false),
+      transform_changed(false),
+      post_local_scale_factor(1.0f) {}
+
+TransformNode::TransformNode(const TransformNode&) = default;
+
+bool TransformNode::operator==(const TransformNode& other) const {
+  return id == other.id && parent_id == other.parent_id &&
+         owner_id == other.owner_id && pre_local == other.pre_local &&
+         local == other.local && post_local == other.post_local &&
+         to_parent == other.to_parent &&
+         source_node_id == other.source_node_id &&
+         sorting_context_id == other.sorting_context_id &&
+         needs_local_transform_update == other.needs_local_transform_update &&
+         node_and_ancestors_are_animated_or_invertible ==
+             other.node_and_ancestors_are_animated_or_invertible &&
+         is_invertible == other.is_invertible &&
+         ancestors_are_invertible == other.ancestors_are_invertible &&
+         has_potential_animation == other.has_potential_animation &&
+         is_currently_animating == other.is_currently_animating &&
+         to_screen_is_potentially_animated ==
+             other.to_screen_is_potentially_animated &&
+         has_only_translation_animations ==
+             other.has_only_translation_animations &&
+         flattens_inherited_transform == other.flattens_inherited_transform &&
+         node_and_ancestors_are_flat == other.node_and_ancestors_are_flat &&
+         node_and_ancestors_have_only_integer_translation ==
+             other.node_and_ancestors_have_only_integer_translation &&
+         scrolls == other.scrolls &&
+         needs_sublayer_scale == other.needs_sublayer_scale &&
+         affected_by_inner_viewport_bounds_delta_x ==
+             other.affected_by_inner_viewport_bounds_delta_x &&
+         affected_by_inner_viewport_bounds_delta_y ==
+             other.affected_by_inner_viewport_bounds_delta_y &&
+         affected_by_outer_viewport_bounds_delta_x ==
+             other.affected_by_outer_viewport_bounds_delta_x &&
+         affected_by_outer_viewport_bounds_delta_y ==
+             other.affected_by_outer_viewport_bounds_delta_y &&
+         in_subtree_of_page_scale_layer ==
+             other.in_subtree_of_page_scale_layer &&
+         transform_changed == other.transform_changed &&
+         post_local_scale_factor == other.post_local_scale_factor &&
+         sublayer_scale == other.sublayer_scale &&
+         scroll_offset == other.scroll_offset &&
+         scroll_snap == other.scroll_snap &&
+         source_offset == other.source_offset &&
+         source_to_parent == other.source_to_parent;
+}
+
+void TransformNode::update_pre_local_transform(
+    const gfx::Point3F& transform_origin) {
+  pre_local.MakeIdentity();
+  pre_local.Translate3d(-transform_origin.x(), -transform_origin.y(),
+                        -transform_origin.z());
+}
+
+void TransformNode::update_post_local_transform(
+    const gfx::PointF& position,
+    const gfx::Point3F& transform_origin) {
+  post_local.MakeIdentity();
+  post_local.Scale(post_local_scale_factor, post_local_scale_factor);
+  post_local.Translate3d(
+      position.x() + source_offset.x() + transform_origin.x(),
+      position.y() + source_offset.y() + transform_origin.y(),
+      transform_origin.z());
+}
+
+void TransformNode::ToProtobuf(proto::TreeNode* proto) const {
+  proto->set_id(id);
+  proto->set_parent_id(parent_id);
+  proto->set_owner_id(owner_id);
+
+  DCHECK(!proto->has_transform_node_data());
+  proto::TranformNodeData* data = proto->mutable_transform_node_data();
+
+  TransformToProto(pre_local, data->mutable_pre_local());
+  TransformToProto(local, data->mutable_local());
+  TransformToProto(post_local, data->mutable_post_local());
+
+  TransformToProto(to_parent, data->mutable_to_parent());
+
+  data->set_source_node_id(source_node_id);
+  data->set_sorting_context_id(sorting_context_id);
+
+  data->set_needs_local_transform_update(needs_local_transform_update);
+
+  data->set_node_and_ancestors_are_animated_or_invertible(
+      node_and_ancestors_are_animated_or_invertible);
+
+  data->set_is_invertible(is_invertible);
+  data->set_ancestors_are_invertible(ancestors_are_invertible);
+
+  data->set_has_potential_animation(has_potential_animation);
+  data->set_is_currently_animating(is_currently_animating);
+  data->set_to_screen_is_potentially_animated(
+      to_screen_is_potentially_animated);
+  data->set_has_only_translation_animations(has_only_translation_animations);
+
+  data->set_flattens_inherited_transform(flattens_inherited_transform);
+  data->set_node_and_ancestors_are_flat(node_and_ancestors_are_flat);
+
+  data->set_node_and_ancestors_have_only_integer_translation(
+      node_and_ancestors_have_only_integer_translation);
+  data->set_scrolls(scrolls);
+  data->set_needs_sublayer_scale(needs_sublayer_scale);
+
+  data->set_affected_by_inner_viewport_bounds_delta_x(
+      affected_by_inner_viewport_bounds_delta_x);
+  data->set_affected_by_inner_viewport_bounds_delta_y(
+      affected_by_inner_viewport_bounds_delta_y);
+  data->set_affected_by_outer_viewport_bounds_delta_x(
+      affected_by_outer_viewport_bounds_delta_x);
+  data->set_affected_by_outer_viewport_bounds_delta_y(
+      affected_by_outer_viewport_bounds_delta_y);
+
+  data->set_in_subtree_of_page_scale_layer(in_subtree_of_page_scale_layer);
+  data->set_transform_changed(transform_changed);
+  data->set_post_local_scale_factor(post_local_scale_factor);
+
+  Vector2dFToProto(sublayer_scale, data->mutable_sublayer_scale());
+  ScrollOffsetToProto(scroll_offset, data->mutable_scroll_offset());
+  Vector2dFToProto(scroll_snap, data->mutable_scroll_snap());
+  Vector2dFToProto(source_offset, data->mutable_source_offset());
+  Vector2dFToProto(source_to_parent, data->mutable_source_to_parent());
+}
+
+void TransformNode::FromProtobuf(const proto::TreeNode& proto) {
+  id = proto.id();
+  parent_id = proto.parent_id();
+  owner_id = proto.owner_id();
+
+  DCHECK(proto.has_transform_node_data());
+  const proto::TranformNodeData& data = proto.transform_node_data();
+
+  pre_local = ProtoToTransform(data.pre_local());
+  local = ProtoToTransform(data.local());
+  post_local = ProtoToTransform(data.post_local());
+
+  to_parent = ProtoToTransform(data.to_parent());
+
+  source_node_id = data.source_node_id();
+  sorting_context_id = data.sorting_context_id();
+
+  needs_local_transform_update = data.needs_local_transform_update();
+
+  node_and_ancestors_are_animated_or_invertible =
+      data.node_and_ancestors_are_animated_or_invertible();
+
+  is_invertible = data.is_invertible();
+  ancestors_are_invertible = data.ancestors_are_invertible();
+
+  has_potential_animation = data.has_potential_animation();
+  is_currently_animating = data.is_currently_animating();
+  to_screen_is_potentially_animated = data.to_screen_is_potentially_animated();
+  has_only_translation_animations = data.has_only_translation_animations();
+
+  flattens_inherited_transform = data.flattens_inherited_transform();
+  node_and_ancestors_are_flat = data.node_and_ancestors_are_flat();
+
+  node_and_ancestors_have_only_integer_translation =
+      data.node_and_ancestors_have_only_integer_translation();
+  scrolls = data.scrolls();
+  needs_sublayer_scale = data.needs_sublayer_scale();
+
+  affected_by_inner_viewport_bounds_delta_x =
+      data.affected_by_inner_viewport_bounds_delta_x();
+  affected_by_inner_viewport_bounds_delta_y =
+      data.affected_by_inner_viewport_bounds_delta_y();
+  affected_by_outer_viewport_bounds_delta_x =
+      data.affected_by_outer_viewport_bounds_delta_x();
+  affected_by_outer_viewport_bounds_delta_y =
+      data.affected_by_outer_viewport_bounds_delta_y();
+
+  in_subtree_of_page_scale_layer = data.in_subtree_of_page_scale_layer();
+  transform_changed = data.transform_changed();
+  post_local_scale_factor = data.post_local_scale_factor();
+
+  sublayer_scale = ProtoToVector2dF(data.sublayer_scale());
+  scroll_offset = ProtoToScrollOffset(data.scroll_offset());
+  scroll_snap = ProtoToVector2dF(data.scroll_snap());
+  source_offset = ProtoToVector2dF(data.source_offset());
+  source_to_parent = ProtoToVector2dF(data.source_to_parent());
+}
+
+void TransformNode::AsValueInto(base::trace_event::TracedValue* value) const {
+  value->SetInteger("id", id);
+  value->SetInteger("parent_id", parent_id);
+  value->SetInteger("owner_id", owner_id);
+  MathUtil::AddToTracedValue("pre_local", pre_local, value);
+  MathUtil::AddToTracedValue("local", local, value);
+  MathUtil::AddToTracedValue("post_local", post_local, value);
+  // TODO(sunxd): make frameviewer work without target_id
+  value->SetInteger("target_id", 0);
+  value->SetInteger("content_target_id", 0);
+  value->SetInteger("source_node_id", source_node_id);
+  value->SetInteger("sorting_context_id", sorting_context_id);
+}
+
+TransformCachedNodeData::TransformCachedNodeData()
+    : target_id(-1), content_target_id(-1) {}
+
+TransformCachedNodeData::TransformCachedNodeData(
+    const TransformCachedNodeData& other) = default;
+
+TransformCachedNodeData::~TransformCachedNodeData() {}
+
+bool TransformCachedNodeData::operator==(
+    const TransformCachedNodeData& other) const {
+  return from_target == other.from_target && to_target == other.to_target &&
+         from_screen == other.from_screen && to_screen == other.to_screen &&
+         target_id == other.target_id &&
+         content_target_id == other.content_target_id;
+}
+
+void TransformCachedNodeData::ToProtobuf(
+    proto::TransformCachedNodeData* proto) const {
+  TransformToProto(from_target, proto->mutable_from_target());
+  TransformToProto(to_target, proto->mutable_to_target());
+  TransformToProto(from_screen, proto->mutable_from_screen());
+  TransformToProto(to_screen, proto->mutable_to_screen());
+  proto->set_target_id(target_id);
+  proto->set_content_target_id(content_target_id);
+}
+
+void TransformCachedNodeData::FromProtobuf(
+    const proto::TransformCachedNodeData& proto) {
+  from_target = ProtoToTransform(proto.from_target());
+  to_target = ProtoToTransform(proto.to_target());
+  from_screen = ProtoToTransform(proto.from_screen());
+  to_screen = ProtoToTransform(proto.to_screen());
+  target_id = proto.target_id();
+  content_target_id = proto.content_target_id();
+}
+
+}  // namespace cc
diff --git a/cc/trees/transform_node.h b/cc/trees/transform_node.h
new file mode 100644
index 0000000..b128d4dd
--- /dev/null
+++ b/cc/trees/transform_node.h
@@ -0,0 +1,168 @@
+// Copyright 2016 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_TREES_TRANSFORM_NODE_H_
+#define CC_TREES_TRANSFORM_NODE_H_
+
+#include "cc/base/cc_export.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/scroll_offset.h"
+#include "ui/gfx/transform.h"
+
+namespace base {
+namespace trace_event {
+class TracedValue;
+}  // namespace trace_event
+}  // namespace base
+
+namespace cc {
+
+namespace proto {
+class TransformCachedNodeData;
+class TreeNode;
+}  // namespace proto
+
+struct CC_EXPORT TransformNode {
+  TransformNode();
+  TransformNode(const TransformNode&);
+
+  int id;
+  int parent_id;
+  int owner_id;
+
+  // The local transform information is combined to form to_parent (ignoring
+  // snapping) as follows:
+  //
+  //   to_parent = M_post_local * T_scroll * M_local * M_pre_local.
+  //
+  // The pre/post may seem odd when read LTR, but we multiply our points from
+  // the right, so the pre_local matrix affects the result "first". This lines
+  // up with the notions of pre/post used in skia and gfx::Transform.
+  //
+  // TODO(vollick): The values labeled with "will be moved..." take up a lot of
+  // space, but are only necessary for animated or scrolled nodes (otherwise
+  // we'll just use the baked to_parent). These values will be ultimately stored
+  // directly on the transform/scroll display list items when that's possible,
+  // or potentially in a scroll tree.
+  //
+  // TODO(vollick): will be moved when accelerated effects are implemented.
+  gfx::Transform pre_local;
+  gfx::Transform local;
+  gfx::Transform post_local;
+
+  gfx::Transform to_parent;
+
+  // This is the node with respect to which source_offset is defined. This will
+  // not be needed once layerization moves to cc, but is needed in order to
+  // efficiently update the transform tree for changes to position in the layer
+  // tree.
+  int source_node_id;
+
+  // This id determines which 3d rendering context the node is in. 0 is a
+  // special value and indicates that the node is not in any 3d rendering
+  // context.
+  int sorting_context_id;
+
+  // TODO(vollick): will be moved when accelerated effects are implemented.
+  bool needs_local_transform_update : 1;
+
+  bool node_and_ancestors_are_animated_or_invertible : 1;
+
+  bool is_invertible : 1;
+  bool ancestors_are_invertible : 1;
+
+  bool has_potential_animation : 1;
+  bool is_currently_animating : 1;
+  bool to_screen_is_potentially_animated : 1;
+  bool has_only_translation_animations : 1;
+
+  // Flattening, when needed, is only applied to a node's inherited transform,
+  // never to its local transform.
+  bool flattens_inherited_transform : 1;
+
+  // This is true if the to_parent transform at every node on the path to the
+  // root is flat.
+  bool node_and_ancestors_are_flat : 1;
+
+  // This is needed to know if a layer can use lcd text.
+  bool node_and_ancestors_have_only_integer_translation : 1;
+
+  bool scrolls : 1;
+
+  bool needs_sublayer_scale : 1;
+
+  // These are used to position nodes wrt the right or bottom of the inner or
+  // outer viewport.
+  bool affected_by_inner_viewport_bounds_delta_x : 1;
+  bool affected_by_inner_viewport_bounds_delta_y : 1;
+  bool affected_by_outer_viewport_bounds_delta_x : 1;
+  bool affected_by_outer_viewport_bounds_delta_y : 1;
+
+  // Layer scale factor is used as a fallback when we either cannot adjust
+  // raster scale or if the raster scale cannot be extracted from the screen
+  // space transform. For layers in the subtree of the page scale layer, the
+  // layer scale factor should include the page scale factor.
+  bool in_subtree_of_page_scale_layer : 1;
+
+  // We need to track changes to to_screen transform to compute the damage rect.
+  bool transform_changed : 1;
+
+  // TODO(vollick): will be moved when accelerated effects are implemented.
+  float post_local_scale_factor;
+
+  gfx::Vector2dF sublayer_scale;
+
+  // TODO(vollick): will be moved when accelerated effects are implemented.
+  gfx::ScrollOffset scroll_offset;
+
+  // We scroll snap where possible, but this means fixed-pos elements must be
+  // adjusted.  This value stores the snapped amount for this purpose.
+  gfx::Vector2dF scroll_snap;
+
+  // TODO(vollick): will be moved when accelerated effects are implemented.
+  gfx::Vector2dF source_offset;
+  gfx::Vector2dF source_to_parent;
+
+  bool operator==(const TransformNode& other) const;
+
+  void set_to_parent(const gfx::Transform& transform) {
+    to_parent = transform;
+    is_invertible = to_parent.IsInvertible();
+  }
+
+  void update_pre_local_transform(const gfx::Point3F& transform_origin);
+
+  void update_post_local_transform(const gfx::PointF& position,
+                                   const gfx::Point3F& transform_origin);
+
+  void ToProtobuf(proto::TreeNode* proto) const;
+  void FromProtobuf(const proto::TreeNode& proto);
+
+  void AsValueInto(base::trace_event::TracedValue* value) const;
+};
+
+// TODO(sunxd): move this into PropertyTrees::cached_data_.
+struct CC_EXPORT TransformCachedNodeData {
+  TransformCachedNodeData();
+  TransformCachedNodeData(const TransformCachedNodeData& other);
+  ~TransformCachedNodeData();
+
+  gfx::Transform from_target;
+  gfx::Transform to_target;
+  gfx::Transform from_screen;
+  gfx::Transform to_screen;
+  int target_id;
+  // This id is used for all content that draws into a render surface associated
+  // with this transform node.
+  int content_target_id;
+
+  bool operator==(const TransformCachedNodeData& other) const;
+
+  void ToProtobuf(proto::TransformCachedNodeData* proto) const;
+  void FromProtobuf(const proto::TransformCachedNodeData& proto);
+};
+
+}  // namespace cc
+
+#endif  // CC_TREES_TRANSFORM_NODE_H_
diff --git a/cc/trees/tree_synchronizer_unittest.cc b/cc/trees/tree_synchronizer_unittest.cc
index f91e69d3..c50ff3ef 100644
--- a/cc/trees/tree_synchronizer_unittest.cc
+++ b/cc/trees/tree_synchronizer_unittest.cc
@@ -21,6 +21,7 @@
 #include "cc/test/fake_rendering_stats_instrumentation.h"
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_task_graph_runner.h"
+#include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/single_thread_proxy.h"
 #include "cc/trees/task_runner_provider.h"
@@ -101,25 +102,25 @@
       SCOPED_TRACE("mask_layer");
       int mask_layer_id = layer->mask_layer()->id();
       EXPECT_TRUE(tree_impl->LayerById(mask_layer_id));
-      EXPECT_EQ(mask_layer_id,
-                effect_tree.Node(layer_impl->effect_tree_index())
-                    ->data.mask_layer_id);
+      EXPECT_EQ(
+          mask_layer_id,
+          effect_tree.Node(layer_impl->effect_tree_index())->mask_layer_id);
     }
 
     if (layer->replica_layer()) {
       SCOPED_TRACE("replica_layer");
       int replica_layer_id = layer->replica_layer()->id();
       EXPECT_TRUE(tree_impl->LayerById(layer->replica_layer()->id()));
-      EXPECT_EQ(replica_layer_id,
-                effect_tree.Node(layer_impl->effect_tree_index())
-                    ->data.replica_layer_id);
+      EXPECT_EQ(
+          replica_layer_id,
+          effect_tree.Node(layer_impl->effect_tree_index())->replica_layer_id);
       if (layer->replica_layer()->mask_layer()) {
         SCOPED_TRACE("replica_mask_layer");
         int replica_mask_layer_id = layer->replica_layer()->mask_layer()->id();
         EXPECT_TRUE(tree_impl->LayerById(replica_mask_layer_id));
         EXPECT_EQ(replica_mask_layer_id,
                   effect_tree.Node(layer_impl->effect_tree_index())
-                      ->data.replica_mask_layer_id);
+                      ->replica_mask_layer_id);
       }
     }