Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / cc / layers / layer_impl.cc
index 894daf1..a6738cc 100644 (file)
@@ -1,33 +1,37 @@
-// Copyright 2011 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "cc/layers/layer_impl.h"
 
 #include "base/debug/trace_event.h"
+#include "base/json/json_reader.h"
 #include "base/strings/stringprintf.h"
 #include "cc/animation/animation_registrar.h"
 #include "cc/animation/scrollbar_animation_controller.h"
-#include "cc/animation/scrollbar_animation_controller_linear_fade.h"
-#include "cc/animation/scrollbar_animation_controller_thinning.h"
 #include "cc/base/math_util.h"
 #include "cc/debug/debug_colors.h"
 #include "cc/debug/layer_tree_debug_state.h"
+#include "cc/debug/micro_benchmark_impl.h"
 #include "cc/debug/traced_value.h"
 #include "cc/input/layer_scroll_offset_delegate.h"
+#include "cc/layers/layer_utils.h"
 #include "cc/layers/painted_scrollbar_layer_impl.h"
 #include "cc/layers/quad_sink.h"
 #include "cc/output/copy_output_request.h"
 #include "cc/quads/debug_border_draw_quad.h"
+#include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/layer_tree_settings.h"
 #include "cc/trees/proxy.h"
+#include "ui/gfx/box_f.h"
+#include "ui/gfx/geometry/vector2d_conversions.h"
 #include "ui/gfx/point_conversions.h"
 #include "ui/gfx/quad_f.h"
 #include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/size_conversions.h"
 
 namespace cc {
-
 LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
     : parent_(NULL),
       scroll_parent_(NULL),
@@ -39,30 +43,34 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
       anchor_point_(0.5f, 0.5f),
       anchor_point_z_(0.f),
       scroll_offset_delegate_(NULL),
-      scrollable_(false),
+      scroll_clip_layer_(NULL),
       should_scroll_on_main_thread_(false),
       have_wheel_event_handlers_(false),
+      have_scroll_event_handlers_(false),
       user_scrollable_horizontal_(true),
       user_scrollable_vertical_(true),
-      background_color_(0),
       stacking_order_changed_(false),
       double_sided_(true),
+      should_flatten_transform_(true),
       layer_property_changed_(false),
       masks_to_bounds_(false),
       contents_opaque_(false),
-      opacity_(1.0),
-      preserves_3d_(false),
+      is_root_for_isolated_group_(false),
       use_parent_backface_visibility_(false),
       draw_checkerboard_for_missing_tiles_(false),
       draws_content_(false),
       hide_layer_and_subtree_(false),
       force_render_surface_(false),
+      transform_is_invertible_(true),
       is_container_for_fixed_position_layers_(false),
+      is_3d_sorted_(false),
+      background_color_(0),
+      opacity_(1.0),
+      blend_mode_(SkXfermode::kSrcOver_Mode),
       draw_depth_(0.f),
-      compositing_reasons_(kCompositingReasonUnknown),
-      current_draw_mode_(DRAW_MODE_NONE),
-      horizontal_scrollbar_layer_(NULL),
-      vertical_scrollbar_layer_(NULL) {
+      needs_push_properties_(false),
+      num_dependents_need_push_properties_(0),
+      current_draw_mode_(DRAW_MODE_NONE) {
   DCHECK_GT(layer_id_, 0);
   DCHECK(layer_tree_impl_);
   layer_tree_impl_->RegisterLayer(this);
@@ -70,35 +78,27 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
   layer_animation_controller_ =
       registrar->GetAnimationControllerForId(layer_id_);
   layer_animation_controller_->AddValueObserver(this);
+  if (IsActive())
+    layer_animation_controller_->set_value_provider(this);
+  SetNeedsPushProperties();
 }
 
 LayerImpl::~LayerImpl() {
   DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
 
-  layer_tree_impl_->UnregisterLayer(this);
   layer_animation_controller_->RemoveValueObserver(this);
+  layer_animation_controller_->remove_value_provider(this);
 
-  if (scroll_children_) {
-    for (std::set<LayerImpl*>::iterator it = scroll_children_->begin();
-        it != scroll_children_->end(); ++it)
-      (*it)->scroll_parent_ = NULL;
-  }
-
-  if (scroll_parent_)
-    scroll_parent_->RemoveScrollChild(this);
-
-  if (clip_children_) {
-    for (std::set<LayerImpl*>::iterator it = clip_children_->begin();
-        it != clip_children_->end(); ++it)
-      (*it)->clip_parent_ = NULL;
-  }
+  if (!copy_requests_.empty() && layer_tree_impl_->IsActiveTree())
+    layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
+  layer_tree_impl_->UnregisterLayer(this);
 
-  if (clip_parent_)
-    clip_parent_->RemoveClipChild(this);
+  TRACE_EVENT_OBJECT_DELETED_WITH_ID(
+      TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerImpl", this);
 }
 
 void LayerImpl::AddChild(scoped_ptr<LayerImpl> child) {
-  child->set_parent(this);
+  child->SetParent(this);
   DCHECK_EQ(layer_tree_impl(), child->layer_tree_impl());
   children_.push_back(child.Pass());
   layer_tree_impl()->set_needs_update_draw_properties();
@@ -118,6 +118,16 @@ scoped_ptr<LayerImpl> LayerImpl::RemoveChild(LayerImpl* child) {
   return scoped_ptr<LayerImpl>();
 }
 
+void LayerImpl::SetParent(LayerImpl* parent) {
+  if (parent_should_know_need_push_properties()) {
+    if (parent_)
+      parent_->RemoveDependentNeedsPushProperties();
+    if (parent)
+      parent->AddDependentNeedsPushProperties();
+  }
+  parent_ = parent;
+}
+
 void LayerImpl::ClearChildList() {
   if (children_.empty())
     return;
@@ -145,46 +155,39 @@ void LayerImpl::SetScrollParent(LayerImpl* parent) {
   // Having both a scroll parent and a scroll offset delegate is unsupported.
   DCHECK(!scroll_offset_delegate_);
 
-  if (scroll_parent_)
-    scroll_parent_->RemoveScrollChild(this);
+  if (parent)
+    DCHECK_EQ(layer_tree_impl()->LayerById(parent->id()), parent);
 
   scroll_parent_ = parent;
+  SetNeedsPushProperties();
+}
+
+void LayerImpl::SetDebugInfo(
+    scoped_refptr<base::debug::ConvertableToTraceFormat> other) {
+  debug_info_ = other;
+  SetNeedsPushProperties();
 }
 
 void LayerImpl::SetScrollChildren(std::set<LayerImpl*>* children) {
   if (scroll_children_.get() == children)
     return;
   scroll_children_.reset(children);
-}
-
-void LayerImpl::RemoveScrollChild(LayerImpl* child) {
-  DCHECK(scroll_children_);
-  scroll_children_->erase(child);
-  if (scroll_children_->empty())
-    scroll_children_.reset();
+  SetNeedsPushProperties();
 }
 
 void LayerImpl::SetClipParent(LayerImpl* ancestor) {
   if (clip_parent_ == ancestor)
     return;
 
-  if (clip_parent_)
-    clip_parent_->RemoveClipChild(this);
-
   clip_parent_ = ancestor;
+  SetNeedsPushProperties();
 }
 
 void LayerImpl::SetClipChildren(std::set<LayerImpl*>* children) {
   if (clip_children_.get() == children)
     return;
   clip_children_.reset(children);
-}
-
-void LayerImpl::RemoveClipChild(LayerImpl* child) {
-  DCHECK(clip_children_);
-  clip_children_->erase(child);
-  if (clip_children_->empty())
-    clip_children_.reset();
+  SetNeedsPushProperties();
 }
 
 void LayerImpl::PassCopyRequests(ScopedPtrVector<CopyOutputRequest>* requests) {
@@ -202,8 +205,8 @@ void LayerImpl::PassCopyRequests(ScopedPtrVector<CopyOutputRequest>* requests) {
 
 void LayerImpl::TakeCopyRequestsAndTransformToTarget(
     ScopedPtrVector<CopyOutputRequest>* requests) {
-  if (copy_requests_.empty())
-    return;
+  DCHECK(!copy_requests_.empty());
+  DCHECK(layer_tree_impl()->IsActiveTree());
 
   size_t first_inserted_request = requests->size();
   requests->insert_and_take(requests->end(), copy_requests_);
@@ -217,13 +220,11 @@ void LayerImpl::TakeCopyRequestsAndTransformToTarget(
     gfx::Rect request_in_layer_space = request->area();
     gfx::Rect request_in_content_space =
         LayerRectToContentRect(request_in_layer_space);
-    request->set_area(
-        MathUtil::MapClippedRect(draw_properties_.target_space_transform,
-                                 request_in_content_space));
+    request->set_area(MathUtil::MapEnclosingClippedRect(
+        draw_properties_.target_space_transform, request_in_content_space));
   }
 
-  if (layer_tree_impl()->IsActiveTree())
-    layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
+  layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
 }
 
 void LayerImpl::CreateRenderSurface() {
@@ -237,15 +238,19 @@ void LayerImpl::ClearRenderSurface() {
   draw_properties_.render_surface.reset();
 }
 
-scoped_ptr<SharedQuadState> LayerImpl::CreateSharedQuadState() const {
-  scoped_ptr<SharedQuadState> state = SharedQuadState::Create();
+void LayerImpl::ClearRenderSurfaceLayerList() {
+  if (draw_properties_.render_surface)
+    draw_properties_.render_surface->layer_list().clear();
+}
+
+void LayerImpl::PopulateSharedQuadState(SharedQuadState* state) const {
   state->SetAll(draw_properties_.target_space_transform,
                 draw_properties_.content_bounds,
                 draw_properties_.visible_content_rect,
                 draw_properties_.clip_rect,
                 draw_properties_.is_clipped,
-                draw_properties_.opacity);
-  return state.Pass();
+                draw_properties_.opacity,
+                blend_mode_);
 }
 
 bool LayerImpl::WillDraw(DrawMode draw_mode,
@@ -302,11 +307,13 @@ void LayerImpl::AppendDebugBorderQuad(QuadSink* quad_sink,
   if (!ShowDebugBorders())
     return;
 
-  gfx::Rect content_rect(content_bounds());
+  gfx::Rect quad_rect(content_bounds());
+  gfx::Rect visible_quad_rect(quad_rect);
   scoped_ptr<DebugBorderDrawQuad> debug_border_quad =
       DebugBorderDrawQuad::Create();
-  debug_border_quad->SetNew(shared_quad_state, content_rect, color, width);
-  quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), append_quads_data);
+  debug_border_quad->SetNew(
+      shared_quad_state, quad_rect, visible_quad_rect, color, width);
+  quad_sink->Append(debug_border_quad.PassAs<DrawQuad>());
 }
 
 bool LayerImpl::HasDelegatedContent() const {
@@ -331,7 +338,7 @@ ResourceProvider::ResourceId LayerImpl::ContentsResourceId() const {
   return 0;
 }
 
-void LayerImpl::SetSentScrollDelta(gfx::Vector2d sent_scroll_delta) {
+void LayerImpl::SetSentScrollDelta(const gfx::Vector2d& sent_scroll_delta) {
   // Pending tree never has sent scroll deltas
   DCHECK(layer_tree_impl()->IsActiveTree());
 
@@ -341,30 +348,25 @@ void LayerImpl::SetSentScrollDelta(gfx::Vector2d sent_scroll_delta) {
   sent_scroll_delta_ = sent_scroll_delta;
 }
 
-gfx::Vector2dF LayerImpl::ScrollBy(gfx::Vector2dF scroll) {
+gfx::Vector2dF LayerImpl::ScrollBy(const gfx::Vector2dF& scroll) {
   DCHECK(scrollable());
-  gfx::Vector2dF scroll_hidden;
-  if (!user_scrollable_horizontal_) {
-    scroll_hidden.set_x(scroll.x());
-    scroll.set_x(0.f);
-  }
-  if (!user_scrollable_vertical_) {
-    scroll_hidden.set_y(scroll.y());
-    scroll.set_y(0.f);
-  }
-
   gfx::Vector2dF min_delta = -scroll_offset_;
-  gfx::Vector2dF max_delta = max_scroll_offset_ - scroll_offset_;
+  gfx::Vector2dF max_delta = MaxScrollOffset() - scroll_offset_;
   // Clamp new_delta so that position + delta stays within scroll bounds.
   gfx::Vector2dF new_delta = (ScrollDelta() + scroll);
   new_delta.SetToMax(min_delta);
   new_delta.SetToMin(max_delta);
   gfx::Vector2dF unscrolled =
-      ScrollDelta() + scroll + scroll_hidden - new_delta;
+      ScrollDelta() + scroll - new_delta;
   SetScrollDelta(new_delta);
+
   return unscrolled;
 }
 
+void LayerImpl::SetScrollClipLayer(int scroll_clip_layer_id) {
+  scroll_clip_layer_ = layer_tree_impl()->LayerById(scroll_clip_layer_id);
+}
+
 void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() {
   // Pending tree never has sent scroll deltas
   DCHECK(layer_tree_impl()->IsActiveTree());
@@ -405,7 +407,7 @@ void LayerImpl::ApplyScrollDeltasSinceBeginMainFrame() {
 }
 
 InputHandler::ScrollStatus LayerImpl::TryScroll(
-    gfx::PointF screen_space_point,
+    const gfx::PointF& screen_space_point,
     InputHandler::ScrollInputType type) const {
   if (should_scroll_on_main_thread()) {
     TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
@@ -454,28 +456,17 @@ InputHandler::ScrollStatus LayerImpl::TryScroll(
     return InputHandler::ScrollIgnored;
   }
 
-  if (max_scroll_offset_.x() <= 0 && max_scroll_offset_.y() <= 0) {
+  gfx::Vector2d max_scroll_offset = MaxScrollOffset();
+  if (max_scroll_offset.x() <= 0 && max_scroll_offset.y() <= 0) {
     TRACE_EVENT0("cc",
                  "LayerImpl::tryScroll: Ignored. Technically scrollable,"
                  " but has no affordance in either direction.");
     return InputHandler::ScrollIgnored;
   }
 
-  if (!user_scrollable_horizontal_ && !user_scrollable_vertical_) {
-    TRACE_EVENT0("cc",
-                 "LayerImpl::TryScroll: Ignored. User gesture is not allowed"
-                 " to scroll this layer.");
-    return InputHandler::ScrollIgnored;
-  }
-
   return InputHandler::ScrollStarted;
 }
 
-bool LayerImpl::DrawCheckerboardForMissingTiles() const {
-  return draw_checkerboard_for_missing_tiles_ &&
-      !layer_tree_impl()->settings().background_color_instead_of_checkerboard;
-}
-
 gfx::Rect LayerImpl::LayerRectToContentRect(
     const gfx::RectF& layer_rect) const {
   gfx::RectF content_rect =
@@ -505,8 +496,6 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
   layer->SetBounds(bounds_);
   layer->SetContentBounds(content_bounds());
   layer->SetContentsScale(contents_scale_x(), contents_scale_y());
-  layer->SetDebugName(debug_name_);
-  layer->SetCompositingReasons(compositing_reasons_);
   layer->SetDoubleSided(double_sided_);
   layer->SetDrawCheckerboardForMissingTiles(
       draw_checkerboard_for_missing_tiles_);
@@ -518,46 +507,58 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
   layer->SetMasksToBounds(masks_to_bounds_);
   layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
   layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
+  layer->SetHaveScrollEventHandlers(have_scroll_event_handlers_);
   layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
   layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
   layer->SetContentsOpaque(contents_opaque_);
   layer->SetOpacity(opacity_);
+  layer->SetBlendMode(blend_mode_);
+  layer->SetIsRootForIsolatedGroup(is_root_for_isolated_group_);
   layer->SetPosition(position_);
   layer->SetIsContainerForFixedPositionLayers(
       is_container_for_fixed_position_layers_);
-  layer->SetFixedContainerSizeDelta(fixed_container_size_delta_);
   layer->SetPositionConstraint(position_constraint_);
-  layer->SetPreserves3d(preserves_3d());
+  layer->SetShouldFlattenTransform(should_flatten_transform_);
+  layer->SetIs3dSorted(is_3d_sorted_);
   layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
-  layer->SetSublayerTransform(sublayer_transform_);
-  layer->SetTransform(transform_);
+  layer->SetTransformAndInvertibility(transform_, transform_is_invertible_);
 
-  layer->SetScrollable(scrollable_);
+  layer->SetScrollClipLayer(scroll_clip_layer_ ? scroll_clip_layer_->id()
+                                               : Layer::INVALID_ID);
   layer->set_user_scrollable_horizontal(user_scrollable_horizontal_);
   layer->set_user_scrollable_vertical(user_scrollable_vertical_);
   layer->SetScrollOffsetAndDelta(
       scroll_offset_, layer->ScrollDelta() - layer->sent_scroll_delta());
   layer->SetSentScrollDelta(gfx::Vector2d());
 
-  layer->SetMaxScrollOffset(max_scroll_offset_);
-
   LayerImpl* scroll_parent = NULL;
-  if (scroll_parent_)
+  if (scroll_parent_) {
     scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id());
+    DCHECK(scroll_parent);
+  }
 
   layer->SetScrollParent(scroll_parent);
   if (scroll_children_) {
     std::set<LayerImpl*>* scroll_children = new std::set<LayerImpl*>;
     for (std::set<LayerImpl*>::iterator it = scroll_children_->begin();
-        it != scroll_children_->end(); ++it)
-      scroll_children->insert(layer->layer_tree_impl()->LayerById((*it)->id()));
+         it != scroll_children_->end();
+         ++it) {
+      DCHECK_EQ((*it)->scroll_parent(), this);
+      LayerImpl* scroll_child =
+          layer->layer_tree_impl()->LayerById((*it)->id());
+      DCHECK(scroll_child);
+      scroll_children->insert(scroll_child);
+    }
     layer->SetScrollChildren(scroll_children);
+  } else {
+    layer->SetScrollChildren(NULL);
   }
 
   LayerImpl* clip_parent = NULL;
   if (clip_parent_) {
     clip_parent = layer->layer_tree_impl()->LayerById(
         clip_parent_->id());
+    DCHECK(clip_parent);
   }
 
   layer->SetClipParent(clip_parent);
@@ -567,6 +568,8 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
         it != clip_children_->end(); ++it)
       clip_children->insert(layer->layer_tree_impl()->LayerById((*it)->id()));
     layer->SetClipChildren(clip_children);
+  } else {
+    layer->SetClipChildren(NULL);
   }
 
   layer->PassCopyRequests(&copy_requests_);
@@ -576,13 +579,40 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
   // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
   // union) any update changes that have occurred on the main thread.
   update_rect_.Union(layer->update_rect());
-  layer->set_update_rect(update_rect_);
+  layer->SetUpdateRect(update_rect_);
 
   layer->SetStackingOrderChanged(stacking_order_changed_);
+  layer->SetDebugInfo(debug_info_);
 
   // Reset any state that should be cleared for the next update.
   stacking_order_changed_ = false;
   update_rect_ = gfx::RectF();
+  needs_push_properties_ = false;
+  num_dependents_need_push_properties_ = 0;
+}
+
+gfx::Vector2dF LayerImpl::FixedContainerSizeDelta() const {
+  if (!scroll_clip_layer_)
+    return gfx::Vector2dF();
+
+  float scale_delta = layer_tree_impl()->page_scale_delta();
+  float scale = layer_tree_impl()->page_scale_factor();
+
+  gfx::Vector2dF delta_from_scroll = scroll_clip_layer_->BoundsDelta();
+  delta_from_scroll.Scale(1.f / scale);
+
+  // The delta-from-pinch component requires some explanation: A viewport of
+  // size (w,h) will appear to be size (w/s,h/s) under scale s in the content
+  // space. If s -> s' on the impl thread, where s' = s * ds, then the apparent
+  // viewport size change in the content space due to ds is:
+  //
+  // (w/s',h/s') - (w/s,h/s) = (w,h)(1/s' - 1/s) = (w,h)(1 - ds)/(s ds)
+  //
+  gfx::Vector2dF delta_from_pinch =
+      gfx::Rect(scroll_clip_layer_->bounds()).bottom_right() - gfx::PointF();
+  delta_from_pinch.Scale((1.f - scale_delta) / (scale * scale_delta));
+
+  return delta_from_scroll + delta_from_pinch;
 }
 
 base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
@@ -611,11 +641,13 @@ base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
   result->SetDouble("Opacity", opacity());
   result->SetBoolean("ContentsOpaque", contents_opaque_);
 
-  if (scrollable_)
-    result->SetBoolean("Scrollable", scrollable_);
+  if (scrollable())
+    result->SetBoolean("Scrollable", true);
 
   if (have_wheel_event_handlers_)
     result->SetBoolean("WheelHandler", have_wheel_event_handlers_);
+  if (have_scroll_event_handlers_)
+    result->SetBoolean("ScrollHandler", have_scroll_event_handlers_);
   if (!touch_event_handler_region_.IsEmpty()) {
     scoped_ptr<base::Value> region = touch_event_handler_region_.AsValue();
     result->Set("TouchRegion", region.release());
@@ -639,17 +671,28 @@ void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) {
 void LayerImpl::NoteLayerPropertyChanged() {
   layer_property_changed_ = true;
   layer_tree_impl()->set_needs_update_draw_properties();
+  SetNeedsPushProperties();
 }
 
 void LayerImpl::NoteLayerPropertyChangedForSubtree() {
-  NoteLayerPropertyChanged();
-  NoteLayerPropertyChangedForDescendants();
+  layer_property_changed_ = true;
+  layer_tree_impl()->set_needs_update_draw_properties();
+  for (size_t i = 0; i < children_.size(); ++i)
+    children_[i]->NoteLayerPropertyChangedForDescendantsInternal();
+  SetNeedsPushProperties();
+}
+
+void LayerImpl::NoteLayerPropertyChangedForDescendantsInternal() {
+  layer_property_changed_ = true;
+  for (size_t i = 0; i < children_.size(); ++i)
+    children_[i]->NoteLayerPropertyChangedForDescendantsInternal();
 }
 
 void LayerImpl::NoteLayerPropertyChangedForDescendants() {
   layer_tree_impl()->set_needs_update_draw_properties();
   for (size_t i = 0; i < children_.size(); ++i)
-    children_[i]->NoteLayerPropertyChangedForSubtree();
+    children_[i]->NoteLayerPropertyChangedForDescendantsInternal();
+  SetNeedsPushProperties();
 }
 
 const char* LayerImpl::LayerTypeAsString() const {
@@ -660,6 +703,7 @@ void LayerImpl::ResetAllChangeTrackingForSubtree() {
   layer_property_changed_ = false;
 
   update_rect_ = gfx::RectF();
+  damage_rect_ = gfx::RectF();
 
   if (draw_properties_.render_surface)
     draw_properties_.render_surface->ResetPropertyChangedFlag();
@@ -674,10 +718,13 @@ void LayerImpl::ResetAllChangeTrackingForSubtree() {
 
   for (size_t i = 0; i < children_.size(); ++i)
     children_[i]->ResetAllChangeTrackingForSubtree();
+
+  needs_push_properties_ = false;
+  num_dependents_need_push_properties_ = 0;
 }
 
-bool LayerImpl::LayerIsAlwaysDamaged() const {
-  return false;
+gfx::Vector2dF LayerImpl::ScrollOffsetForAnimation() const {
+  return TotalScrollOffset();
 }
 
 void LayerImpl::OnFilterAnimated(const FilterOperations& filters) {
@@ -692,16 +739,50 @@ void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) {
   SetTransform(transform);
 }
 
+void LayerImpl::OnScrollOffsetAnimated(const gfx::Vector2dF& scroll_offset) {
+  // Only layers in the active tree should need to do anything here, since
+  // layers in the pending tree will find out about these changes as a
+  // result of the call to SetScrollDelta.
+  if (!IsActive())
+    return;
+
+  SetScrollDelta(scroll_offset - scroll_offset_);
+
+  layer_tree_impl_->DidAnimateScrollOffset();
+}
+
+void LayerImpl::OnAnimationWaitingForDeletion() {}
+
 bool LayerImpl::IsActive() const {
   return layer_tree_impl_->IsActiveTree();
 }
 
-void LayerImpl::SetBounds(gfx::Size bounds) {
+// TODO(wjmaclean) Convert so that bounds returns SizeF.
+gfx::Size LayerImpl::bounds() const {
+  return ToFlooredSize(temporary_impl_bounds_);
+}
+
+void LayerImpl::SetBounds(const gfx::Size& bounds) {
   if (bounds_ == bounds)
     return;
 
   bounds_ = bounds;
+  temporary_impl_bounds_ = bounds;
+
+  ScrollbarParametersDidChange();
+  if (masks_to_bounds())
+    NoteLayerPropertyChangedForSubtree();
+  else
+    NoteLayerPropertyChanged();
+}
 
+void LayerImpl::SetTemporaryImplBounds(const gfx::SizeF& bounds) {
+  if (temporary_impl_bounds_ == bounds)
+    return;
+
+  temporary_impl_bounds_ = bounds;
+
+  ScrollbarParametersDidChange();
   if (masks_to_bounds())
     NoteLayerPropertyChangedForSubtree();
   else
@@ -721,7 +802,7 @@ void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) {
   mask_layer_ = mask_layer.Pass();
   mask_layer_id_ = new_layer_id;
   if (mask_layer_)
-    mask_layer_->set_parent(this);
+    mask_layer_->SetParent(this);
   NoteLayerPropertyChangedForSubtree();
 }
 
@@ -743,7 +824,7 @@ void LayerImpl::SetReplicaLayer(scoped_ptr<LayerImpl> replica_layer) {
   replica_layer_ = replica_layer.Pass();
   replica_layer_id_ = new_layer_id;
   if (replica_layer_)
-    replica_layer_->set_parent(this);
+    replica_layer_->SetParent(this);
   NoteLayerPropertyChangedForSubtree();
 }
 
@@ -772,7 +853,7 @@ void LayerImpl::SetHideLayerAndSubtree(bool hide) {
   NoteLayerPropertyChangedForSubtree();
 }
 
-void LayerImpl::SetAnchorPoint(gfx::PointF anchor_point) {
+void LayerImpl::SetAnchorPoint(const gfx::PointF& anchor_point) {
   if (anchor_point_ == anchor_point)
     return;
 
@@ -876,7 +957,23 @@ bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
   return opacity_animation && opacity_animation->is_impl_only();
 }
 
-void LayerImpl::SetPosition(gfx::PointF position) {
+void LayerImpl::SetBlendMode(SkXfermode::Mode blend_mode) {
+  if (blend_mode_ == blend_mode)
+    return;
+
+  blend_mode_ = blend_mode;
+  NoteLayerPropertyChangedForSubtree();
+}
+
+void LayerImpl::SetIsRootForIsolatedGroup(bool root) {
+  if (is_root_for_isolated_group_ == root)
+    return;
+
+  is_root_for_isolated_group_ = root;
+  SetNeedsPushProperties();
+}
+
+void LayerImpl::SetPosition(const gfx::PointF& position) {
   if (position_ == position)
     return;
 
@@ -884,22 +981,20 @@ void LayerImpl::SetPosition(gfx::PointF position) {
   NoteLayerPropertyChangedForSubtree();
 }
 
-void LayerImpl::SetPreserves3d(bool preserves3_d) {
-  if (preserves_3d_ == preserves3_d)
+void LayerImpl::SetShouldFlattenTransform(bool flatten) {
+  if (should_flatten_transform_ == flatten)
     return;
 
-  preserves_3d_ = preserves3_d;
+  should_flatten_transform_ = flatten;
   NoteLayerPropertyChangedForSubtree();
 }
 
-void LayerImpl::SetSublayerTransform(const gfx::Transform& sublayer_transform) {
-  if (sublayer_transform_ == sublayer_transform)
+void LayerImpl::SetIs3dSorted(bool sorted) {
+  if (is_3d_sorted_ == sorted)
     return;
 
-  sublayer_transform_ = sublayer_transform;
-  // Sublayer transform does not affect the current layer; it affects only its
-  // children.
-  NoteLayerPropertyChangedForDescendants();
+  is_3d_sorted_ = sorted;
+  NoteLayerPropertyChangedForSubtree();
 }
 
 void LayerImpl::SetTransform(const gfx::Transform& transform) {
@@ -907,6 +1002,19 @@ void LayerImpl::SetTransform(const gfx::Transform& transform) {
     return;
 
   transform_ = transform;
+  transform_is_invertible_ = transform_.IsInvertible();
+  NoteLayerPropertyChangedForSubtree();
+}
+
+void LayerImpl::SetTransformAndInvertibility(const gfx::Transform& transform,
+                                             bool transform_is_invertible) {
+  if (transform_ == transform) {
+    DCHECK(transform_is_invertible_ == transform_is_invertible)
+        << "Can't change invertibility if transform is unchanged";
+    return;
+  }
+  transform_ = transform;
+  transform_is_invertible_ = transform_is_invertible;
   NoteLayerPropertyChangedForSubtree();
 }
 
@@ -920,7 +1028,16 @@ bool LayerImpl::TransformIsAnimatingOnImplOnly() const {
   return transform_animation && transform_animation->is_impl_only();
 }
 
-void LayerImpl::SetContentBounds(gfx::Size content_bounds) {
+void LayerImpl::SetUpdateRect(const gfx::RectF& update_rect) {
+  update_rect_ = update_rect;
+  SetNeedsPushProperties();
+}
+
+void LayerImpl::AddDamageRect(const gfx::RectF& damage_rect) {
+  damage_rect_ = gfx::UnionRects(damage_rect_, damage_rect);
+}
+
+void LayerImpl::SetContentBounds(const gfx::Size& content_bounds) {
   if (this->content_bounds() == content_bounds)
     return;
 
@@ -939,14 +1056,14 @@ void LayerImpl::SetContentsScale(float contents_scale_x,
   NoteLayerPropertyChanged();
 }
 
-void LayerImpl::CalculateContentsScale(
-    float ideal_contents_scale,
-    float device_scale_factor,
-    float page_scale_factor,
-    bool animating_transform_to_screen,
-    float* contents_scale_x,
-    float* contents_scale_y,
-    gfx::Size* content_bounds) {
+void LayerImpl::CalculateContentsScale(float ideal_contents_scale,
+                                       float device_scale_factor,
+                                       float page_scale_factor,
+                                       float maximum_animation_contents_scale,
+                                       bool animating_transform_to_screen,
+                                       float* contents_scale_x,
+                                       float* contents_scale_y,
+                                       gfx::Size* content_bounds) {
   // Base LayerImpl has all of its content scales and content bounds pushed
   // from its Layer during commit and just reuses those values as-is.
   *contents_scale_x = this->contents_scale_x();
@@ -954,44 +1071,6 @@ void LayerImpl::CalculateContentsScale(
   *content_bounds = this->content_bounds();
 }
 
-void LayerImpl::UpdateScrollbarPositions() {
-  gfx::Vector2dF current_offset = scroll_offset_ + ScrollDelta();
-
-  gfx::RectF viewport(PointAtOffsetFromOrigin(current_offset), bounds_);
-  gfx::SizeF scrollable_size(max_scroll_offset_.x() + bounds_.width(),
-                             max_scroll_offset_.y() + bounds_.height());
-  if (horizontal_scrollbar_layer_) {
-    horizontal_scrollbar_layer_->SetCurrentPos(current_offset.x());
-    horizontal_scrollbar_layer_->SetMaximum(max_scroll_offset_.x());
-    horizontal_scrollbar_layer_->SetVisibleToTotalLengthRatio(
-        viewport.width() / scrollable_size.width());
-  }
-  if (vertical_scrollbar_layer_) {
-    vertical_scrollbar_layer_->SetCurrentPos(current_offset.y());
-    vertical_scrollbar_layer_->SetMaximum(max_scroll_offset_.y());
-    vertical_scrollbar_layer_->SetVisibleToTotalLengthRatio(
-        viewport.height() / scrollable_size.height());
-  }
-
-  if (current_offset == last_scroll_offset_)
-    return;
-  last_scroll_offset_ = current_offset;
-
-  if (scrollbar_animation_controller_) {
-    bool should_animate = scrollbar_animation_controller_->DidScrollUpdate(
-        layer_tree_impl_->CurrentPhysicalTimeTicks());
-    if (should_animate)
-      layer_tree_impl_->StartScrollbarAnimation();
-  }
-
-  // Get the current_offset_.y() value for a sanity-check on scrolling
-  // benchmark metrics. Specifically, we want to make sure
-  // BasicMouseWheelSmoothScrollGesture has proper scroll curves.
-  if (layer_tree_impl()->IsActiveTree()) {
-    TRACE_COUNTER_ID1("gpu", "scroll_offset_y", this->id(), current_offset.y());
-  }
-}
-
 void LayerImpl::SetScrollOffsetDelegate(
     LayerScrollOffsetDelegate* scroll_offset_delegate) {
   // Having both a scroll parent and a scroll offset delegate is unsupported.
@@ -1002,10 +1081,8 @@ void LayerImpl::SetScrollOffsetDelegate(
   }
   gfx::Vector2dF total_offset = TotalScrollOffset();
   scroll_offset_delegate_ = scroll_offset_delegate;
-  if (scroll_offset_delegate_) {
-    scroll_offset_delegate_->SetMaxScrollOffset(max_scroll_offset_);
+  if (scroll_offset_delegate_)
     scroll_offset_delegate_->SetTotalScrollOffset(total_offset);
-  }
 }
 
 bool LayerImpl::IsExternalFlingActive() const {
@@ -1013,14 +1090,16 @@ bool LayerImpl::IsExternalFlingActive() const {
          scroll_offset_delegate_->IsExternalFlingActive();
 }
 
-void LayerImpl::SetScrollOffset(gfx::Vector2d scroll_offset) {
+void LayerImpl::SetScrollOffset(const gfx::Vector2d& scroll_offset) {
   SetScrollOffsetAndDelta(scroll_offset, ScrollDelta());
 }
 
-void LayerImpl::SetScrollOffsetAndDelta(gfx::Vector2d scroll_offset,
-                                        gfx::Vector2dF scroll_delta) {
+void LayerImpl::SetScrollOffsetAndDelta(const gfx::Vector2d& scroll_offset,
+                                        const gfx::Vector2dF& scroll_delta) {
   bool changed = false;
 
+  last_scroll_offset_ = scroll_offset;
+
   if (scroll_offset_ != scroll_offset) {
     changed = true;
     scroll_offset_ = scroll_offset;
@@ -1055,7 +1134,7 @@ void LayerImpl::SetScrollOffsetAndDelta(gfx::Vector2d scroll_offset,
 
   if (changed) {
     NoteLayerPropertyChangedForSubtree();
-    UpdateScrollbarPositions();
+    ScrollbarParametersDidChange();
   }
 }
 
@@ -1065,7 +1144,7 @@ gfx::Vector2dF LayerImpl::ScrollDelta() const {
   return scroll_delta_;
 }
 
-void LayerImpl::SetScrollDelta(gfx::Vector2dF scroll_delta) {
+void LayerImpl::SetScrollDelta(const gfx::Vector2dF& scroll_delta) {
   SetScrollOffsetAndDelta(scroll_offset_, scroll_delta);
 }
 
@@ -1089,18 +1168,157 @@ Region LayerImpl::VisibleContentOpaqueRegion() const {
 
 void LayerImpl::DidBeginTracing() {}
 
-void LayerImpl::DidLoseOutputSurface() {}
+void LayerImpl::ReleaseResources() {}
+
+gfx::Vector2d LayerImpl::MaxScrollOffset() const {
+  if (!scroll_clip_layer_ || bounds().IsEmpty())
+    return gfx::Vector2d();
+
+  LayerImpl const* page_scale_layer = layer_tree_impl()->page_scale_layer();
+  DCHECK(this != page_scale_layer);
+  DCHECK(scroll_clip_layer_);
+  DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
+         IsContainerForFixedPositionLayers());
+
+  gfx::SizeF scaled_scroll_bounds(bounds());
+
+  float scale_factor = 1.f;
+  for (LayerImpl const* current_layer = this;
+       current_layer != scroll_clip_layer_;
+       current_layer = current_layer->parent()) {
+    DCHECK(current_layer);
+    float current_layer_scale = 1.f;
 
-void LayerImpl::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) {
-  if (max_scroll_offset_ == max_scroll_offset)
+    const gfx::Transform& layer_transform = current_layer->transform();
+    if (current_layer == page_scale_layer) {
+      DCHECK(layer_transform.IsIdentity());
+      current_layer_scale = layer_tree_impl()->total_page_scale_factor();
+    } else {
+      // TODO(wjmaclean) Should we allow for translation too?
+      DCHECK(layer_transform.IsScale2d());
+      gfx::Vector2dF layer_scale = layer_transform.Scale2d();
+      // TODO(wjmaclean) Allow for non-isotropic scales.
+      DCHECK(layer_scale.x() == layer_scale.y());
+      current_layer_scale = layer_scale.x();
+    }
+
+    scale_factor *= current_layer_scale;
+  }
+  // TODO(wjmaclean) Once we move to a model where the two-viewport model is
+  // turned on in all builds, remove the next two lines. For now however, the
+  // page scale layer may coincide with the clip layer, and so this is
+  // necessary.
+  if (page_scale_layer == scroll_clip_layer_)
+    scale_factor *= layer_tree_impl()->total_page_scale_factor();
+
+  scaled_scroll_bounds.SetSize(scale_factor * scaled_scroll_bounds.width(),
+                               scale_factor * scaled_scroll_bounds.height());
+  scaled_scroll_bounds = gfx::ToFlooredSize(scaled_scroll_bounds);
+
+  gfx::Vector2dF max_offset(
+      scaled_scroll_bounds.width() - scroll_clip_layer_->bounds().width(),
+      scaled_scroll_bounds.height() - scroll_clip_layer_->bounds().height());
+  // We need the final scroll offset to be in CSS coords.
+  max_offset.Scale(1 / scale_factor);
+  max_offset.SetToMax(gfx::Vector2dF());
+  return gfx::ToFlooredVector2d(max_offset);
+}
+
+gfx::Vector2dF LayerImpl::ClampScrollToMaxScrollOffset() {
+  gfx::Vector2dF max_offset = MaxScrollOffset();
+  gfx::Vector2dF old_offset = TotalScrollOffset();
+  gfx::Vector2dF clamped_offset = old_offset;
+
+  clamped_offset.SetToMin(max_offset);
+  clamped_offset.SetToMax(gfx::Vector2d());
+  gfx::Vector2dF delta = clamped_offset - old_offset;
+  if (!delta.IsZero())
+    ScrollBy(delta);
+
+  return delta;
+}
+
+void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase* scrollbar_layer,
+                                     LayerImpl* scrollbar_clip_layer) const {
+  DCHECK(scrollbar_layer);
+  LayerImpl* page_scale_layer = layer_tree_impl()->page_scale_layer();
+
+  DCHECK(this != page_scale_layer);
+  DCHECK(scrollbar_clip_layer);
+  DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
+         IsContainerForFixedPositionLayers());
+  gfx::RectF clip_rect(gfx::PointF(), scrollbar_clip_layer->bounds());
+
+  // See comment in MaxScrollOffset() regarding the use of the content layer
+  // bounds here.
+  gfx::RectF scroll_rect(gfx::PointF(), bounds());
+
+  if (scroll_rect.size().IsEmpty())
     return;
-  max_scroll_offset_ = max_scroll_offset;
 
-  if (scroll_offset_delegate_)
-    scroll_offset_delegate_->SetMaxScrollOffset(max_scroll_offset_);
+  // TODO(wjmaclean) This computation is nearly identical to the one in
+  // MaxScrollOffset. Find some way to combine these.
+  gfx::Vector2dF current_offset;
+  for (LayerImpl const* current_layer = this;
+       current_layer != scrollbar_clip_layer;
+       current_layer = current_layer->parent()) {
+    DCHECK(current_layer);
+    const gfx::Transform& layer_transform = current_layer->transform();
+    if (current_layer == page_scale_layer) {
+      DCHECK(layer_transform.IsIdentity());
+      float scale_factor = layer_tree_impl()->total_page_scale_factor();
+      current_offset.Scale(scale_factor);
+      scroll_rect.Scale(scale_factor);
+    } else {
+      DCHECK(layer_transform.IsScale2d());
+      gfx::Vector2dF layer_scale = layer_transform.Scale2d();
+      DCHECK(layer_scale.x() == layer_scale.y());
+      gfx::Vector2dF new_offset =
+          current_layer->scroll_offset() + current_layer->ScrollDelta();
+      new_offset.Scale(layer_scale.x(), layer_scale.y());
+      current_offset += new_offset;
+    }
+  }
+  // TODO(wjmaclean) Once we move to a model where the two-viewport model is
+  // turned on in all builds, remove the next two lines. For now however, the
+  // page scale layer may coincide with the clip layer, and so this is
+  // necessary.
+  if (page_scale_layer == scrollbar_clip_layer) {
+    scroll_rect.Scale(layer_tree_impl()->total_page_scale_factor());
+    current_offset.Scale(layer_tree_impl()->total_page_scale_factor());
+  }
+
+  scrollbar_layer->SetVerticalAdjust(
+      layer_tree_impl()->VerticalAdjust(scrollbar_clip_layer->id()));
+  if (scrollbar_layer->orientation() == HORIZONTAL) {
+    float visible_ratio = clip_rect.width() / scroll_rect.width();
+    scrollbar_layer->SetCurrentPos(current_offset.x());
+    scrollbar_layer->SetMaximum(scroll_rect.width() - clip_rect.width());
+    scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio);
+  } else {
+    float visible_ratio = clip_rect.height() / scroll_rect.height();
+    scrollbar_layer->SetCurrentPos(current_offset.y());
+    scrollbar_layer->SetMaximum(scroll_rect.height() - clip_rect.height());
+    scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio);
+  }
 
   layer_tree_impl()->set_needs_update_draw_properties();
-  UpdateScrollbarPositions();
+  // TODO(wjmaclean) The scrollbar animator for the pinch-zoom scrollbars should
+  // activate for every scroll on the main frame, not just the scrolls that move
+  // the pinch virtual viewport (i.e. trigger from either inner or outer
+  // viewport).
+  if (scrollbar_animation_controller_) {
+    // When both non-overlay and overlay scrollbars are both present, don't
+    // animate the overlay scrollbars when page scale factor is at the min.
+    // Non-overlay scrollbars also shouldn't trigger animations.
+    bool is_animatable_scrollbar =
+        scrollbar_layer->is_overlay_scrollbar() &&
+        ((layer_tree_impl()->total_page_scale_factor() >
+          layer_tree_impl()->min_page_scale_factor()) ||
+         !layer_tree_impl()->settings().use_pinch_zoom_scrollbars);
+    if (is_animatable_scrollbar)
+      scrollbar_animation_controller_->DidScrollUpdate();
+  }
 }
 
 void LayerImpl::DidBecomeActive() {
@@ -1109,8 +1327,7 @@ void LayerImpl::DidBecomeActive() {
     return;
   }
 
-  bool need_scrollbar_animation_controller = horizontal_scrollbar_layer_ ||
-                                             vertical_scrollbar_layer_;
+  bool need_scrollbar_animation_controller = scrollable() && scrollbars_;
   if (!need_scrollbar_animation_controller) {
     scrollbar_animation_controller_.reset();
     return;
@@ -1119,176 +1336,97 @@ void LayerImpl::DidBecomeActive() {
   if (scrollbar_animation_controller_)
     return;
 
-  switch (layer_tree_impl_->settings().scrollbar_animator) {
-  case LayerTreeSettings::LinearFade: {
-    base::TimeDelta fadeout_delay = base::TimeDelta::FromMilliseconds(
-        layer_tree_impl_->settings().scrollbar_linear_fade_delay_ms);
-    base::TimeDelta fadeout_length = base::TimeDelta::FromMilliseconds(
-        layer_tree_impl_->settings().scrollbar_linear_fade_length_ms);
-
-    scrollbar_animation_controller_ =
-        ScrollbarAnimationControllerLinearFade::Create(
-            this, fadeout_delay, fadeout_length)
-            .PassAs<ScrollbarAnimationController>();
-    break;
-  }
-  case LayerTreeSettings::Thinning: {
-    scrollbar_animation_controller_ =
-        ScrollbarAnimationControllerThinning::Create(this)
-            .PassAs<ScrollbarAnimationController>();
-    break;
-  }
-  case LayerTreeSettings::NoAnimator:
-    NOTREACHED();
-    break;
-  }
-}
-void LayerImpl::SetHorizontalScrollbarLayer(
-    ScrollbarLayerImplBase* scrollbar_layer) {
-  horizontal_scrollbar_layer_ = scrollbar_layer;
-  if (horizontal_scrollbar_layer_)
-    horizontal_scrollbar_layer_->set_scroll_layer_id(id());
-}
-
-void LayerImpl::SetVerticalScrollbarLayer(
-    ScrollbarLayerImplBase* scrollbar_layer) {
-  vertical_scrollbar_layer_ = scrollbar_layer;
-  if (vertical_scrollbar_layer_)
-    vertical_scrollbar_layer_->set_scroll_layer_id(id());
+  scrollbar_animation_controller_ =
+      layer_tree_impl_->CreateScrollbarAnimationController(this);
 }
 
-static scoped_ptr<base::Value>
-CompositingReasonsAsValue(CompositingReasons reasons) {
-  scoped_ptr<base::ListValue> reason_list(new base::ListValue());
-
-  if (reasons == kCompositingReasonUnknown) {
-    reason_list->AppendString("No reasons given");
-    return reason_list.PassAs<base::Value>();
-  }
-
-  if (reasons & kCompositingReason3DTransform)
-    reason_list->AppendString("Has a 3d Transform");
-
-  if (reasons & kCompositingReasonVideo)
-    reason_list->AppendString("Is accelerated video");
-
-  if (reasons & kCompositingReasonCanvas)
-    reason_list->AppendString("Is accelerated canvas");
-
-  if (reasons & kCompositingReasonPlugin)
-    reason_list->AppendString("Is accelerated plugin");
-
-  if (reasons & kCompositingReasonIFrame)
-    reason_list->AppendString("Is accelerated iframe");
-
-  if (reasons & kCompositingReasonBackfaceVisibilityHidden)
-    reason_list->AppendString("Has backface-visibility: hidden");
-
-  if (reasons & kCompositingReasonAnimation)
-    reason_list->AppendString("Has accelerated animation or transition");
-
-  if (reasons & kCompositingReasonFilters)
-    reason_list->AppendString("Has accelerated filters");
-
-  if (reasons & kCompositingReasonPositionFixed)
-    reason_list->AppendString("Is fixed position");
-
-  if (reasons & kCompositingReasonPositionSticky)
-    reason_list->AppendString("Is sticky position");
-
-  if (reasons & kCompositingReasonOverflowScrollingTouch)
-    reason_list->AppendString("Is a scrollable overflow element");
-
-  if (reasons & kCompositingReasonAssumedOverlap)
-    reason_list->AppendString("Might overlap a composited animation");
-
-  if (reasons & kCompositingReasonOverlap)
-    reason_list->AppendString("Overlaps other composited content");
-
-  if (reasons & kCompositingReasonNegativeZIndexChildren) {
-    reason_list->AppendString("Might overlap negative z-index "
-                              "composited content");
-  }
-
-  if (reasons & kCompositingReasonTransformWithCompositedDescendants) {
-    reason_list->AppendString("Has transform needed by a "
-                              "composited descendant");
-  }
-
-  if (reasons & kCompositingReasonOpacityWithCompositedDescendants)
-    reason_list->AppendString("Has opacity needed by a composited descendant");
-
-  if (reasons & kCompositingReasonMaskWithCompositedDescendants)
-    reason_list->AppendString("Has a mask needed by a composited descendant");
-
-  if (reasons & kCompositingReasonReflectionWithCompositedDescendants)
-    reason_list->AppendString("Has a reflection with a composited descendant");
+void LayerImpl::ClearScrollbars() {
+  if (!scrollbars_)
+    return;
 
-  if (reasons & kCompositingReasonFilterWithCompositedDescendants)
-    reason_list->AppendString("Has filter effect with a composited descendant");
+  scrollbars_.reset(NULL);
+}
 
-  if (reasons & kCompositingReasonBlendingWithCompositedDescendants)
-    reason_list->AppendString("Has a blend mode with a composited descendant");
+void LayerImpl::AddScrollbar(ScrollbarLayerImplBase* layer) {
+  DCHECK(layer);
+  DCHECK(!scrollbars_ || scrollbars_->find(layer) == scrollbars_->end());
+  if (!scrollbars_)
+    scrollbars_.reset(new ScrollbarSet());
 
-  if (reasons & kCompositingReasonClipsCompositingDescendants)
-    reason_list->AppendString("Clips a composited descendant");
+  scrollbars_->insert(layer);
+}
 
-  if (reasons & kCompositingReasonPerspective) {
-    reason_list->AppendString("Has a perspective transform needed by a "
-                              "composited 3d descendant");
-  }
+void LayerImpl::RemoveScrollbar(ScrollbarLayerImplBase* layer) {
+  DCHECK(scrollbars_);
+  DCHECK(layer);
+  DCHECK(scrollbars_->find(layer) != scrollbars_->end());
 
-  if (reasons & kCompositingReasonPreserve3D) {
-    reason_list->AppendString("Has preserves-3d style with composited "
-                              "3d descendant");
-  }
+  scrollbars_->erase(layer);
+  if (scrollbars_->empty())
+    scrollbars_.reset();
+}
 
-  if (reasons & kCompositingReasonReflectionOfCompositedParent)
-    reason_list->AppendString("Is the reflection of a composited layer");
+bool LayerImpl::HasScrollbar(ScrollbarOrientation orientation) const {
+  if (!scrollbars_)
+    return false;
 
-  if (reasons & kCompositingReasonRoot)
-    reason_list->AppendString("Is the root");
+  for (ScrollbarSet::iterator it = scrollbars_->begin();
+       it != scrollbars_->end();
+       ++it)
+    if ((*it)->orientation() == orientation)
+      return true;
 
-  if (reasons & kCompositingReasonLayerForClip)
-    reason_list->AppendString("Convenience layer, to clip subtree");
+  return false;
+}
 
-  if (reasons & kCompositingReasonLayerForScrollbar)
-    reason_list->AppendString("Convenience layer for rendering scrollbar");
+void LayerImpl::ScrollbarParametersDidChange() {
+  if (!scrollbars_)
+    return;
 
-  if (reasons & kCompositingReasonLayerForScrollingContainer)
-    reason_list->AppendString("Convenience layer, the scrolling container");
+  for (ScrollbarSet::iterator it = scrollbars_->begin();
+       it != scrollbars_->end();
+       ++it)
+    (*it)->ScrollbarParametersDidChange();
+}
 
-  if (reasons & kCompositingReasonLayerForForeground) {
-    reason_list->AppendString("Convenience layer, foreground when main layer "
-                              "has negative z-index composited content");
-  }
+void LayerImpl::SetNeedsPushProperties() {
+  if (needs_push_properties_)
+    return;
+  if (!parent_should_know_need_push_properties() && parent_)
+    parent_->AddDependentNeedsPushProperties();
+  needs_push_properties_ = true;
+}
 
-  if (reasons & kCompositingReasonLayerForBackground) {
-    reason_list->AppendString("Convenience layer, background when main layer "
-                              "has a composited background");
-  }
+void LayerImpl::AddDependentNeedsPushProperties() {
+  DCHECK_GE(num_dependents_need_push_properties_, 0);
 
-  if (reasons & kCompositingReasonLayerForMask)
-    reason_list->AppendString("Is a mask layer");
+  if (!parent_should_know_need_push_properties() && parent_)
+    parent_->AddDependentNeedsPushProperties();
 
-  if (reasons & kCompositingReasonOverflowScrollingParent)
-    reason_list->AppendString("Scroll parent is not an ancestor");
+  num_dependents_need_push_properties_++;
+}
 
-  if (reasons & kCompositingReasonOutOfFlowClipping)
-    reason_list->AppendString("Has clipping ancestor");
+void LayerImpl::RemoveDependentNeedsPushProperties() {
+  num_dependents_need_push_properties_--;
+  DCHECK_GE(num_dependents_need_push_properties_, 0);
 
-  return reason_list.PassAs<base::Value>();
+  if (!parent_should_know_need_push_properties() && parent_)
+      parent_->RemoveDependentNeedsPushProperties();
 }
 
 void LayerImpl::AsValueInto(base::DictionaryValue* state) const {
-  TracedValue::MakeDictIntoImplicitSnapshot(state, LayerTypeAsString(), this);
+  TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
+      TRACE_DISABLED_BY_DEFAULT("cc.debug"),
+      state,
+      "cc::LayerImpl",
+      LayerTypeAsString(),
+      this);
   state->SetInteger("layer_id", id());
-  state->SetString("layer_name", debug_name());
-  state->Set("bounds", MathUtil::AsValue(bounds()).release());
+  state->Set("bounds", MathUtil::AsValue(bounds_).release());
+  state->Set("position", MathUtil::AsValue(position_).release());
   state->SetInteger("draws_content", DrawsContent());
   state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes());
-  state->Set("compositing_reasons",
-             CompositingReasonsAsValue(compositing_reasons_).release());
+  state->Set("scroll_offset", MathUtil::AsValue(scroll_offset_).release());
 
   bool clipped;
   gfx::QuadF layer_quad = MathUtil::MapQuad(
@@ -1307,6 +1445,12 @@ void LayerImpl::AsValueInto(base::DictionaryValue* state) const {
     state->Set("wheel_event_handler_region",
                wheel_region.AsValue().release());
   }
+  if (have_scroll_event_handlers_) {
+    gfx::Rect scroll_rect(content_bounds());
+    Region scroll_region(scroll_rect);
+    state->Set("scroll_event_handler_region",
+               scroll_region.AsValue().release());
+  }
   if (!non_fast_scrollable_region_.IsEmpty()) {
     state->Set("non_fast_scrollable_region",
                non_fast_scrollable_region_.AsValue().release());
@@ -1329,6 +1473,36 @@ void LayerImpl::AsValueInto(base::DictionaryValue* state) const {
 
   state->SetBoolean("can_use_lcd_text", can_use_lcd_text());
   state->SetBoolean("contents_opaque", contents_opaque());
+
+  state->SetBoolean(
+      "has_animation_bounds",
+      layer_animation_controller()->HasAnimationThatInflatesBounds());
+
+  gfx::BoxF box;
+  if (LayerUtils::GetAnimationBounds(*this, &box))
+    state->Set("animation_bounds", MathUtil::AsValue(box).release());
+
+  if (debug_info_.get()) {
+    std::string str;
+    debug_info_->AppendAsTraceFormat(&str);
+    base::JSONReader json_reader;
+    scoped_ptr<base::Value> debug_info_value(json_reader.ReadToValue(str));
+
+    if (debug_info_value->IsType(base::Value::TYPE_DICTIONARY)) {
+      base::DictionaryValue* dictionary_value = NULL;
+      bool converted_to_dictionary =
+          debug_info_value->GetAsDictionary(&dictionary_value);
+      DCHECK(converted_to_dictionary);
+      state->MergeDictionary(dictionary_value);
+    } else {
+      NOTREACHED();
+    }
+  }
+}
+
+bool LayerImpl::IsDrawnRenderSurfaceLayerListMember() const {
+  return draw_properties_.last_drawn_render_surface_layer_list_id ==
+         layer_tree_impl_->current_render_surface_list_id();
 }
 
 size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; }
@@ -1339,4 +1513,7 @@ scoped_ptr<base::Value> LayerImpl::AsValue() const {
   return state.PassAs<base::Value>();
 }
 
+void LayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
+  benchmark->RunOnLayer(this);
+}
 }  // namespace cc