layer_impl.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1// Copyright 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cc/layers/layer_impl.h"
6
7#include "base/debug/trace_event.h"
8#include "base/json/json_reader.h"
9#include "base/strings/stringprintf.h"
10#include "cc/animation/animation_registrar.h"
11#include "cc/animation/scrollbar_animation_controller.h"
12#include "cc/base/math_util.h"
13#include "cc/debug/debug_colors.h"
14#include "cc/debug/layer_tree_debug_state.h"
15#include "cc/debug/micro_benchmark_impl.h"
16#include "cc/debug/traced_value.h"
17#include "cc/input/layer_scroll_offset_delegate.h"
18#include "cc/layers/layer_utils.h"
19#include "cc/layers/painted_scrollbar_layer_impl.h"
20#include "cc/layers/quad_sink.h"
21#include "cc/output/copy_output_request.h"
22#include "cc/quads/debug_border_draw_quad.h"
23#include "cc/trees/layer_tree_host_common.h"
24#include "cc/trees/layer_tree_impl.h"
25#include "cc/trees/layer_tree_settings.h"
26#include "cc/trees/proxy.h"
27#include "ui/gfx/box_f.h"
28#include "ui/gfx/geometry/vector2d_conversions.h"
29#include "ui/gfx/point_conversions.h"
30#include "ui/gfx/quad_f.h"
31#include "ui/gfx/rect_conversions.h"
32#include "ui/gfx/size_conversions.h"
33
34namespace cc {
35LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
36    : parent_(NULL),
37      scroll_parent_(NULL),
38      clip_parent_(NULL),
39      mask_layer_id_(-1),
40      replica_layer_id_(-1),
41      layer_id_(id),
42      layer_tree_impl_(tree_impl),
43      scroll_offset_delegate_(NULL),
44      scroll_clip_layer_(NULL),
45      should_scroll_on_main_thread_(false),
46      have_wheel_event_handlers_(false),
47      have_scroll_event_handlers_(false),
48      user_scrollable_horizontal_(true),
49      user_scrollable_vertical_(true),
50      stacking_order_changed_(false),
51      double_sided_(true),
52      should_flatten_transform_(true),
53      layer_property_changed_(false),
54      masks_to_bounds_(false),
55      contents_opaque_(false),
56      is_root_for_isolated_group_(false),
57      use_parent_backface_visibility_(false),
58      draw_checkerboard_for_missing_tiles_(false),
59      draws_content_(false),
60      hide_layer_and_subtree_(false),
61      force_render_surface_(false),
62      transform_is_invertible_(true),
63      is_container_for_fixed_position_layers_(false),
64      is_3d_sorted_(false),
65      background_color_(0),
66      opacity_(1.0),
67      blend_mode_(SkXfermode::kSrcOver_Mode),
68      draw_depth_(0.f),
69      needs_push_properties_(false),
70      num_dependents_need_push_properties_(0),
71      current_draw_mode_(DRAW_MODE_NONE) {
72  DCHECK_GT(layer_id_, 0);
73  DCHECK(layer_tree_impl_);
74  layer_tree_impl_->RegisterLayer(this);
75  AnimationRegistrar* registrar = layer_tree_impl_->animationRegistrar();
76  layer_animation_controller_ =
77      registrar->GetAnimationControllerForId(layer_id_);
78  layer_animation_controller_->AddValueObserver(this);
79  if (IsActive())
80    layer_animation_controller_->set_value_provider(this);
81  SetNeedsPushProperties();
82}
83
84LayerImpl::~LayerImpl() {
85  DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
86
87  layer_animation_controller_->RemoveValueObserver(this);
88  layer_animation_controller_->remove_value_provider(this);
89
90  if (!copy_requests_.empty() && layer_tree_impl_->IsActiveTree())
91    layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
92  layer_tree_impl_->UnregisterLayer(this);
93
94  TRACE_EVENT_OBJECT_DELETED_WITH_ID(
95      TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerImpl", this);
96}
97
98void LayerImpl::AddChild(scoped_ptr<LayerImpl> child) {
99  child->SetParent(this);
100  DCHECK_EQ(layer_tree_impl(), child->layer_tree_impl());
101  children_.push_back(child.Pass());
102  layer_tree_impl()->set_needs_update_draw_properties();
103}
104
105scoped_ptr<LayerImpl> LayerImpl::RemoveChild(LayerImpl* child) {
106  for (OwnedLayerImplList::iterator it = children_.begin();
107       it != children_.end();
108       ++it) {
109    if (*it == child) {
110      scoped_ptr<LayerImpl> ret = children_.take(it);
111      children_.erase(it);
112      layer_tree_impl()->set_needs_update_draw_properties();
113      return ret.Pass();
114    }
115  }
116  return scoped_ptr<LayerImpl>();
117}
118
119void LayerImpl::SetParent(LayerImpl* parent) {
120  if (parent_should_know_need_push_properties()) {
121    if (parent_)
122      parent_->RemoveDependentNeedsPushProperties();
123    if (parent)
124      parent->AddDependentNeedsPushProperties();
125  }
126  parent_ = parent;
127}
128
129void LayerImpl::ClearChildList() {
130  if (children_.empty())
131    return;
132
133  children_.clear();
134  layer_tree_impl()->set_needs_update_draw_properties();
135}
136
137bool LayerImpl::HasAncestor(const LayerImpl* ancestor) const {
138  if (!ancestor)
139    return false;
140
141  for (const LayerImpl* layer = this; layer; layer = layer->parent()) {
142    if (layer == ancestor)
143      return true;
144  }
145
146  return false;
147}
148
149void LayerImpl::SetScrollParent(LayerImpl* parent) {
150  if (scroll_parent_ == parent)
151    return;
152
153  // Having both a scroll parent and a scroll offset delegate is unsupported.
154  DCHECK(!scroll_offset_delegate_);
155
156  if (parent)
157    DCHECK_EQ(layer_tree_impl()->LayerById(parent->id()), parent);
158
159  scroll_parent_ = parent;
160  SetNeedsPushProperties();
161}
162
163void LayerImpl::SetDebugInfo(
164    scoped_refptr<base::debug::ConvertableToTraceFormat> other) {
165  debug_info_ = other;
166  SetNeedsPushProperties();
167}
168
169void LayerImpl::SetScrollChildren(std::set<LayerImpl*>* children) {
170  if (scroll_children_.get() == children)
171    return;
172  scroll_children_.reset(children);
173  SetNeedsPushProperties();
174}
175
176void LayerImpl::SetClipParent(LayerImpl* ancestor) {
177  if (clip_parent_ == ancestor)
178    return;
179
180  clip_parent_ = ancestor;
181  SetNeedsPushProperties();
182}
183
184void LayerImpl::SetClipChildren(std::set<LayerImpl*>* children) {
185  if (clip_children_.get() == children)
186    return;
187  clip_children_.reset(children);
188  SetNeedsPushProperties();
189}
190
191void LayerImpl::PassCopyRequests(ScopedPtrVector<CopyOutputRequest>* requests) {
192  if (requests->empty())
193    return;
194
195  bool was_empty = copy_requests_.empty();
196  copy_requests_.insert_and_take(copy_requests_.end(), *requests);
197  requests->clear();
198
199  if (was_empty && layer_tree_impl()->IsActiveTree())
200    layer_tree_impl()->AddLayerWithCopyOutputRequest(this);
201  NoteLayerPropertyChangedForSubtree();
202}
203
204void LayerImpl::TakeCopyRequestsAndTransformToTarget(
205    ScopedPtrVector<CopyOutputRequest>* requests) {
206  DCHECK(!copy_requests_.empty());
207  DCHECK(layer_tree_impl()->IsActiveTree());
208
209  size_t first_inserted_request = requests->size();
210  requests->insert_and_take(requests->end(), copy_requests_);
211  copy_requests_.clear();
212
213  for (size_t i = first_inserted_request; i < requests->size(); ++i) {
214    CopyOutputRequest* request = requests->at(i);
215    if (!request->has_area())
216      continue;
217
218    gfx::Rect request_in_layer_space = request->area();
219    gfx::Rect request_in_content_space =
220        LayerRectToContentRect(request_in_layer_space);
221    request->set_area(MathUtil::MapEnclosingClippedRect(
222        draw_properties_.target_space_transform, request_in_content_space));
223  }
224
225  layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
226}
227
228void LayerImpl::CreateRenderSurface() {
229  DCHECK(!draw_properties_.render_surface);
230  draw_properties_.render_surface =
231      make_scoped_ptr(new RenderSurfaceImpl(this));
232  draw_properties_.render_target = this;
233}
234
235void LayerImpl::ClearRenderSurface() {
236  draw_properties_.render_surface.reset();
237}
238
239void LayerImpl::ClearRenderSurfaceLayerList() {
240  if (draw_properties_.render_surface)
241    draw_properties_.render_surface->layer_list().clear();
242}
243
244void LayerImpl::PopulateSharedQuadState(SharedQuadState* state) const {
245  state->SetAll(draw_properties_.target_space_transform,
246                draw_properties_.content_bounds,
247                draw_properties_.visible_content_rect,
248                draw_properties_.clip_rect,
249                draw_properties_.is_clipped,
250                draw_properties_.opacity,
251                blend_mode_);
252}
253
254bool LayerImpl::WillDraw(DrawMode draw_mode,
255                         ResourceProvider* resource_provider) {
256  // WillDraw/DidDraw must be matched.
257  DCHECK_NE(DRAW_MODE_NONE, draw_mode);
258  DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
259  current_draw_mode_ = draw_mode;
260  return true;
261}
262
263void LayerImpl::DidDraw(ResourceProvider* resource_provider) {
264  DCHECK_NE(DRAW_MODE_NONE, current_draw_mode_);
265  current_draw_mode_ = DRAW_MODE_NONE;
266}
267
268bool LayerImpl::ShowDebugBorders() const {
269  return layer_tree_impl()->debug_state().show_debug_borders;
270}
271
272void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const {
273  if (draws_content_) {
274    *color = DebugColors::ContentLayerBorderColor();
275    *width = DebugColors::ContentLayerBorderWidth(layer_tree_impl());
276    return;
277  }
278
279  if (masks_to_bounds_) {
280    *color = DebugColors::MaskingLayerBorderColor();
281    *width = DebugColors::MaskingLayerBorderWidth(layer_tree_impl());
282    return;
283  }
284
285  *color = DebugColors::ContainerLayerBorderColor();
286  *width = DebugColors::ContainerLayerBorderWidth(layer_tree_impl());
287}
288
289void LayerImpl::AppendDebugBorderQuad(
290    QuadSink* quad_sink,
291    const SharedQuadState* shared_quad_state,
292    AppendQuadsData* append_quads_data) const {
293  SkColor color;
294  float width;
295  GetDebugBorderProperties(&color, &width);
296  AppendDebugBorderQuad(
297      quad_sink, shared_quad_state, append_quads_data, color, width);
298}
299
300void LayerImpl::AppendDebugBorderQuad(QuadSink* quad_sink,
301                                      const SharedQuadState* shared_quad_state,
302                                      AppendQuadsData* append_quads_data,
303                                      SkColor color,
304                                      float width) const {
305  if (!ShowDebugBorders())
306    return;
307
308  gfx::Rect quad_rect(content_bounds());
309  gfx::Rect visible_quad_rect(quad_rect);
310  scoped_ptr<DebugBorderDrawQuad> debug_border_quad =
311      DebugBorderDrawQuad::Create();
312  debug_border_quad->SetNew(
313      shared_quad_state, quad_rect, visible_quad_rect, color, width);
314  quad_sink->Append(debug_border_quad.PassAs<DrawQuad>());
315}
316
317bool LayerImpl::HasDelegatedContent() const {
318  return false;
319}
320
321bool LayerImpl::HasContributingDelegatedRenderPasses() const {
322  return false;
323}
324
325RenderPass::Id LayerImpl::FirstContributingRenderPassId() const {
326  return RenderPass::Id(0, 0);
327}
328
329RenderPass::Id LayerImpl::NextContributingRenderPassId(RenderPass::Id id)
330    const {
331  return RenderPass::Id(0, 0);
332}
333
334ResourceProvider::ResourceId LayerImpl::ContentsResourceId() const {
335  NOTREACHED();
336  return 0;
337}
338
339void LayerImpl::SetSentScrollDelta(const gfx::Vector2d& sent_scroll_delta) {
340  // Pending tree never has sent scroll deltas
341  DCHECK(layer_tree_impl()->IsActiveTree());
342
343  if (sent_scroll_delta_ == sent_scroll_delta)
344    return;
345
346  sent_scroll_delta_ = sent_scroll_delta;
347}
348
349gfx::Vector2dF LayerImpl::ScrollBy(const gfx::Vector2dF& scroll) {
350  DCHECK(scrollable());
351  gfx::Vector2dF min_delta = -scroll_offset_;
352  gfx::Vector2dF max_delta = MaxScrollOffset() - scroll_offset_;
353  // Clamp new_delta so that position + delta stays within scroll bounds.
354  gfx::Vector2dF new_delta = (ScrollDelta() + scroll);
355  new_delta.SetToMax(min_delta);
356  new_delta.SetToMin(max_delta);
357  gfx::Vector2dF unscrolled =
358      ScrollDelta() + scroll - new_delta;
359  SetScrollDelta(new_delta);
360
361  return unscrolled;
362}
363
364void LayerImpl::SetScrollClipLayer(int scroll_clip_layer_id) {
365  scroll_clip_layer_ = layer_tree_impl()->LayerById(scroll_clip_layer_id);
366}
367
368void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() {
369  // Pending tree never has sent scroll deltas
370  DCHECK(layer_tree_impl()->IsActiveTree());
371
372  // Apply sent scroll deltas to scroll position / scroll delta as if the
373  // main thread had applied them and then committed those values.
374  //
375  // This function should not change the total scroll offset; it just shifts
376  // some of the scroll delta to the scroll offset.  Therefore, adjust these
377  // variables directly rather than calling the scroll offset delegate to
378  // avoid sending it multiple spurious calls.
379  //
380  // Because of the way scroll delta is calculated with a delegate, this will
381  // leave the total scroll offset unchanged on this layer regardless of
382  // whether a delegate is being used.
383  scroll_offset_ += sent_scroll_delta_;
384  scroll_delta_ -= sent_scroll_delta_;
385  sent_scroll_delta_ = gfx::Vector2d();
386}
387
388void LayerImpl::ApplyScrollDeltasSinceBeginMainFrame() {
389  // Only the pending tree can have missing scrolls.
390  DCHECK(layer_tree_impl()->IsPendingTree());
391  if (!scrollable())
392    return;
393
394  // Pending tree should never have sent scroll deltas.
395  DCHECK(sent_scroll_delta().IsZero());
396
397  LayerImpl* active_twin = layer_tree_impl()->FindActiveTreeLayerById(id());
398  if (active_twin) {
399    // Scrolls that happens after begin frame (where the sent scroll delta
400    // comes from) and commit need to be applied to the pending tree
401    // so that it is up to date with the total scroll.
402    SetScrollDelta(active_twin->ScrollDelta() -
403                   active_twin->sent_scroll_delta());
404  }
405}
406
407InputHandler::ScrollStatus LayerImpl::TryScroll(
408    const gfx::PointF& screen_space_point,
409    InputHandler::ScrollInputType type) const {
410  if (should_scroll_on_main_thread()) {
411    TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
412    return InputHandler::ScrollOnMainThread;
413  }
414
415  if (!screen_space_transform().IsInvertible()) {
416    TRACE_EVENT0("cc", "LayerImpl::TryScroll: Ignored NonInvertibleTransform");
417    return InputHandler::ScrollIgnored;
418  }
419
420  if (!non_fast_scrollable_region().IsEmpty()) {
421    bool clipped = false;
422    gfx::Transform inverse_screen_space_transform(
423        gfx::Transform::kSkipInitialization);
424    if (!screen_space_transform().GetInverse(&inverse_screen_space_transform)) {
425      // TODO(shawnsingh): We shouldn't be applying a projection if screen space
426      // transform is uninvertible here. Perhaps we should be returning
427      // ScrollOnMainThread in this case?
428    }
429
430    gfx::PointF hit_test_point_in_content_space =
431        MathUtil::ProjectPoint(inverse_screen_space_transform,
432                               screen_space_point,
433                               &clipped);
434    gfx::PointF hit_test_point_in_layer_space =
435        gfx::ScalePoint(hit_test_point_in_content_space,
436                        1.f / contents_scale_x(),
437                        1.f / contents_scale_y());
438    if (!clipped &&
439        non_fast_scrollable_region().Contains(
440            gfx::ToRoundedPoint(hit_test_point_in_layer_space))) {
441      TRACE_EVENT0("cc",
442                   "LayerImpl::tryScroll: Failed NonFastScrollableRegion");
443      return InputHandler::ScrollOnMainThread;
444    }
445  }
446
447  if (type == InputHandler::Wheel && have_wheel_event_handlers()) {
448    TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers");
449    return InputHandler::ScrollOnMainThread;
450  }
451
452  if (!scrollable()) {
453    TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable");
454    return InputHandler::ScrollIgnored;
455  }
456
457  gfx::Vector2d max_scroll_offset = MaxScrollOffset();
458  if (max_scroll_offset.x() <= 0 && max_scroll_offset.y() <= 0) {
459    TRACE_EVENT0("cc",
460                 "LayerImpl::tryScroll: Ignored. Technically scrollable,"
461                 " but has no affordance in either direction.");
462    return InputHandler::ScrollIgnored;
463  }
464
465  return InputHandler::ScrollStarted;
466}
467
468gfx::Rect LayerImpl::LayerRectToContentRect(
469    const gfx::RectF& layer_rect) const {
470  gfx::RectF content_rect =
471      gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y());
472  // Intersect with content rect to avoid the extra pixel because for some
473  // values x and y, ceil((x / y) * y) may be x + 1.
474  content_rect.Intersect(gfx::Rect(content_bounds()));
475  return gfx::ToEnclosingRect(content_rect);
476}
477
478skia::RefPtr<SkPicture> LayerImpl::GetPicture() {
479  return skia::RefPtr<SkPicture>();
480}
481
482scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) {
483  return LayerImpl::Create(tree_impl, layer_id_);
484}
485
486void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
487  layer->SetTransformOrigin(transform_origin_);
488  layer->SetBackgroundColor(background_color_);
489  layer->SetBounds(bounds_);
490  layer->SetContentBounds(content_bounds());
491  layer->SetContentsScale(contents_scale_x(), contents_scale_y());
492  layer->SetDoubleSided(double_sided_);
493  layer->SetDrawCheckerboardForMissingTiles(
494      draw_checkerboard_for_missing_tiles_);
495  layer->SetForceRenderSurface(force_render_surface_);
496  layer->SetDrawsContent(DrawsContent());
497  layer->SetHideLayerAndSubtree(hide_layer_and_subtree_);
498  layer->SetFilters(filters());
499  layer->SetBackgroundFilters(background_filters());
500  layer->SetMasksToBounds(masks_to_bounds_);
501  layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
502  layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
503  layer->SetHaveScrollEventHandlers(have_scroll_event_handlers_);
504  layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
505  layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
506  layer->SetContentsOpaque(contents_opaque_);
507  layer->SetOpacity(opacity_);
508  layer->SetBlendMode(blend_mode_);
509  layer->SetIsRootForIsolatedGroup(is_root_for_isolated_group_);
510  layer->SetPosition(position_);
511  layer->SetIsContainerForFixedPositionLayers(
512      is_container_for_fixed_position_layers_);
513  layer->SetPositionConstraint(position_constraint_);
514  layer->SetShouldFlattenTransform(should_flatten_transform_);
515  layer->SetIs3dSorted(is_3d_sorted_);
516  layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
517  layer->SetTransformAndInvertibility(transform_, transform_is_invertible_);
518
519  layer->SetScrollClipLayer(scroll_clip_layer_ ? scroll_clip_layer_->id()
520                                               : Layer::INVALID_ID);
521  layer->set_user_scrollable_horizontal(user_scrollable_horizontal_);
522  layer->set_user_scrollable_vertical(user_scrollable_vertical_);
523  layer->SetScrollOffsetAndDelta(
524      scroll_offset_, layer->ScrollDelta() - layer->sent_scroll_delta());
525  layer->SetSentScrollDelta(gfx::Vector2d());
526
527  LayerImpl* scroll_parent = NULL;
528  if (scroll_parent_) {
529    scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id());
530    DCHECK(scroll_parent);
531  }
532
533  layer->SetScrollParent(scroll_parent);
534  if (scroll_children_) {
535    std::set<LayerImpl*>* scroll_children = new std::set<LayerImpl*>;
536    for (std::set<LayerImpl*>::iterator it = scroll_children_->begin();
537         it != scroll_children_->end();
538         ++it) {
539      DCHECK_EQ((*it)->scroll_parent(), this);
540      LayerImpl* scroll_child =
541          layer->layer_tree_impl()->LayerById((*it)->id());
542      DCHECK(scroll_child);
543      scroll_children->insert(scroll_child);
544    }
545    layer->SetScrollChildren(scroll_children);
546  } else {
547    layer->SetScrollChildren(NULL);
548  }
549
550  LayerImpl* clip_parent = NULL;
551  if (clip_parent_) {
552    clip_parent = layer->layer_tree_impl()->LayerById(
553        clip_parent_->id());
554    DCHECK(clip_parent);
555  }
556
557  layer->SetClipParent(clip_parent);
558  if (clip_children_) {
559    std::set<LayerImpl*>* clip_children = new std::set<LayerImpl*>;
560    for (std::set<LayerImpl*>::iterator it = clip_children_->begin();
561        it != clip_children_->end(); ++it)
562      clip_children->insert(layer->layer_tree_impl()->LayerById((*it)->id()));
563    layer->SetClipChildren(clip_children);
564  } else {
565    layer->SetClipChildren(NULL);
566  }
567
568  layer->PassCopyRequests(&copy_requests_);
569
570  // If the main thread commits multiple times before the impl thread actually
571  // draws, then damage tracking will become incorrect if we simply clobber the
572  // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
573  // union) any update changes that have occurred on the main thread.
574  update_rect_.Union(layer->update_rect());
575  layer->SetUpdateRect(update_rect_);
576
577  layer->SetStackingOrderChanged(stacking_order_changed_);
578  layer->SetDebugInfo(debug_info_);
579
580  // Reset any state that should be cleared for the next update.
581  stacking_order_changed_ = false;
582  update_rect_ = gfx::RectF();
583  needs_push_properties_ = false;
584  num_dependents_need_push_properties_ = 0;
585}
586
587gfx::Vector2dF LayerImpl::FixedContainerSizeDelta() const {
588  if (!scroll_clip_layer_)
589    return gfx::Vector2dF();
590
591  float scale_delta = layer_tree_impl()->page_scale_delta();
592  float scale = layer_tree_impl()->page_scale_factor();
593
594  gfx::Vector2dF delta_from_scroll = scroll_clip_layer_->BoundsDelta();
595  delta_from_scroll.Scale(1.f / scale);
596
597  // The delta-from-pinch component requires some explanation: A viewport of
598  // size (w,h) will appear to be size (w/s,h/s) under scale s in the content
599  // space. If s -> s' on the impl thread, where s' = s * ds, then the apparent
600  // viewport size change in the content space due to ds is:
601  //
602  // (w/s',h/s') - (w/s,h/s) = (w,h)(1/s' - 1/s) = (w,h)(1 - ds)/(s ds)
603  //
604  gfx::Vector2dF delta_from_pinch =
605      gfx::Rect(scroll_clip_layer_->bounds()).bottom_right() - gfx::PointF();
606  delta_from_pinch.Scale((1.f - scale_delta) / (scale * scale_delta));
607
608  return delta_from_scroll + delta_from_pinch;
609}
610
611base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
612  base::DictionaryValue* result = new base::DictionaryValue;
613  result->SetString("LayerType", LayerTypeAsString());
614
615  base::ListValue* list = new base::ListValue;
616  list->AppendInteger(bounds().width());
617  list->AppendInteger(bounds().height());
618  result->Set("Bounds", list);
619
620  list = new base::ListValue;
621  list->AppendDouble(position_.x());
622  list->AppendDouble(position_.y());
623  result->Set("Position", list);
624
625  const gfx::Transform& gfx_transform = draw_properties_.target_space_transform;
626  double transform[16];
627  gfx_transform.matrix().asColMajord(transform);
628  list = new base::ListValue;
629  for (int i = 0; i < 16; ++i)
630    list->AppendDouble(transform[i]);
631  result->Set("DrawTransform", list);
632
633  result->SetBoolean("DrawsContent", draws_content_);
634  result->SetBoolean("Is3DSorted", is_3d_sorted_);
635  result->SetDouble("Opacity", opacity());
636  result->SetBoolean("ContentsOpaque", contents_opaque_);
637
638  if (scrollable())
639    result->SetBoolean("Scrollable", true);
640
641  if (have_wheel_event_handlers_)
642    result->SetBoolean("WheelHandler", have_wheel_event_handlers_);
643  if (have_scroll_event_handlers_)
644    result->SetBoolean("ScrollHandler", have_scroll_event_handlers_);
645  if (!touch_event_handler_region_.IsEmpty()) {
646    scoped_ptr<base::Value> region = touch_event_handler_region_.AsValue();
647    result->Set("TouchRegion", region.release());
648  }
649
650  list = new base::ListValue;
651  for (size_t i = 0; i < children_.size(); ++i)
652    list->Append(children_[i]->LayerTreeAsJson());
653  result->Set("Children", list);
654
655  return result;
656}
657
658void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) {
659  if (stacking_order_changed) {
660    stacking_order_changed_ = true;
661    NoteLayerPropertyChangedForSubtree();
662  }
663}
664
665void LayerImpl::NoteLayerPropertyChanged() {
666  layer_property_changed_ = true;
667  layer_tree_impl()->set_needs_update_draw_properties();
668  SetNeedsPushProperties();
669}
670
671void LayerImpl::NoteLayerPropertyChangedForSubtree() {
672  layer_property_changed_ = true;
673  layer_tree_impl()->set_needs_update_draw_properties();
674  for (size_t i = 0; i < children_.size(); ++i)
675    children_[i]->NoteLayerPropertyChangedForDescendantsInternal();
676  SetNeedsPushProperties();
677}
678
679void LayerImpl::NoteLayerPropertyChangedForDescendantsInternal() {
680  layer_property_changed_ = true;
681  for (size_t i = 0; i < children_.size(); ++i)
682    children_[i]->NoteLayerPropertyChangedForDescendantsInternal();
683}
684
685void LayerImpl::NoteLayerPropertyChangedForDescendants() {
686  layer_tree_impl()->set_needs_update_draw_properties();
687  for (size_t i = 0; i < children_.size(); ++i)
688    children_[i]->NoteLayerPropertyChangedForDescendantsInternal();
689  SetNeedsPushProperties();
690}
691
692const char* LayerImpl::LayerTypeAsString() const {
693  return "cc::LayerImpl";
694}
695
696void LayerImpl::ResetAllChangeTrackingForSubtree() {
697  layer_property_changed_ = false;
698
699  update_rect_ = gfx::RectF();
700  damage_rect_ = gfx::RectF();
701
702  if (draw_properties_.render_surface)
703    draw_properties_.render_surface->ResetPropertyChangedFlag();
704
705  if (mask_layer_)
706    mask_layer_->ResetAllChangeTrackingForSubtree();
707
708  if (replica_layer_) {
709    // This also resets the replica mask, if it exists.
710    replica_layer_->ResetAllChangeTrackingForSubtree();
711  }
712
713  for (size_t i = 0; i < children_.size(); ++i)
714    children_[i]->ResetAllChangeTrackingForSubtree();
715
716  needs_push_properties_ = false;
717  num_dependents_need_push_properties_ = 0;
718}
719
720gfx::Vector2dF LayerImpl::ScrollOffsetForAnimation() const {
721  return TotalScrollOffset();
722}
723
724void LayerImpl::OnFilterAnimated(const FilterOperations& filters) {
725  SetFilters(filters);
726}
727
728void LayerImpl::OnOpacityAnimated(float opacity) {
729  SetOpacity(opacity);
730}
731
732void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) {
733  SetTransform(transform);
734}
735
736void LayerImpl::OnScrollOffsetAnimated(const gfx::Vector2dF& scroll_offset) {
737  // Only layers in the active tree should need to do anything here, since
738  // layers in the pending tree will find out about these changes as a
739  // result of the call to SetScrollDelta.
740  if (!IsActive())
741    return;
742
743  SetScrollDelta(scroll_offset - scroll_offset_);
744
745  layer_tree_impl_->DidAnimateScrollOffset();
746}
747
748void LayerImpl::OnAnimationWaitingForDeletion() {}
749
750bool LayerImpl::IsActive() const {
751  return layer_tree_impl_->IsActiveTree();
752}
753
754// TODO(wjmaclean) Convert so that bounds returns SizeF.
755gfx::Size LayerImpl::bounds() const {
756  return ToFlooredSize(temporary_impl_bounds_);
757}
758
759void LayerImpl::SetBounds(const gfx::Size& bounds) {
760  if (bounds_ == bounds)
761    return;
762
763  bounds_ = bounds;
764  temporary_impl_bounds_ = bounds;
765
766  ScrollbarParametersDidChange();
767  if (masks_to_bounds())
768    NoteLayerPropertyChangedForSubtree();
769  else
770    NoteLayerPropertyChanged();
771}
772
773void LayerImpl::SetTemporaryImplBounds(const gfx::SizeF& bounds) {
774  if (temporary_impl_bounds_ == bounds)
775    return;
776
777  temporary_impl_bounds_ = bounds;
778
779  ScrollbarParametersDidChange();
780  if (masks_to_bounds())
781    NoteLayerPropertyChangedForSubtree();
782  else
783    NoteLayerPropertyChanged();
784}
785
786void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) {
787  int new_layer_id = mask_layer ? mask_layer->id() : -1;
788
789  if (mask_layer) {
790    DCHECK_EQ(layer_tree_impl(), mask_layer->layer_tree_impl());
791    DCHECK_NE(new_layer_id, mask_layer_id_);
792  } else if (new_layer_id == mask_layer_id_) {
793    return;
794  }
795
796  mask_layer_ = mask_layer.Pass();
797  mask_layer_id_ = new_layer_id;
798  if (mask_layer_)
799    mask_layer_->SetParent(this);
800  NoteLayerPropertyChangedForSubtree();
801}
802
803scoped_ptr<LayerImpl> LayerImpl::TakeMaskLayer() {
804  mask_layer_id_ = -1;
805  return mask_layer_.Pass();
806}
807
808void LayerImpl::SetReplicaLayer(scoped_ptr<LayerImpl> replica_layer) {
809  int new_layer_id = replica_layer ? replica_layer->id() : -1;
810
811  if (replica_layer) {
812    DCHECK_EQ(layer_tree_impl(), replica_layer->layer_tree_impl());
813    DCHECK_NE(new_layer_id, replica_layer_id_);
814  } else if (new_layer_id == replica_layer_id_) {
815    return;
816  }
817
818  replica_layer_ = replica_layer.Pass();
819  replica_layer_id_ = new_layer_id;
820  if (replica_layer_)
821    replica_layer_->SetParent(this);
822  NoteLayerPropertyChangedForSubtree();
823}
824
825scoped_ptr<LayerImpl> LayerImpl::TakeReplicaLayer() {
826  replica_layer_id_ = -1;
827  return replica_layer_.Pass();
828}
829
830ScrollbarLayerImplBase* LayerImpl::ToScrollbarLayer() {
831  return NULL;
832}
833
834void LayerImpl::SetDrawsContent(bool draws_content) {
835  if (draws_content_ == draws_content)
836    return;
837
838  draws_content_ = draws_content;
839  NoteLayerPropertyChanged();
840}
841
842void LayerImpl::SetHideLayerAndSubtree(bool hide) {
843  if (hide_layer_and_subtree_ == hide)
844    return;
845
846  hide_layer_and_subtree_ = hide;
847  NoteLayerPropertyChangedForSubtree();
848}
849
850void LayerImpl::SetTransformOrigin(const gfx::Point3F& transform_origin) {
851  if (transform_origin_ == transform_origin)
852    return;
853  transform_origin_ = transform_origin;
854  NoteLayerPropertyChangedForSubtree();
855}
856
857void LayerImpl::SetBackgroundColor(SkColor background_color) {
858  if (background_color_ == background_color)
859    return;
860
861  background_color_ = background_color;
862  NoteLayerPropertyChanged();
863}
864
865SkColor LayerImpl::SafeOpaqueBackgroundColor() const {
866  SkColor color = background_color();
867  if (SkColorGetA(color) == 255 && !contents_opaque()) {
868    color = SK_ColorTRANSPARENT;
869  } else if (SkColorGetA(color) != 255 && contents_opaque()) {
870    for (const LayerImpl* layer = parent(); layer;
871         layer = layer->parent()) {
872      color = layer->background_color();
873      if (SkColorGetA(color) == 255)
874        break;
875    }
876    if (SkColorGetA(color) != 255)
877      color = layer_tree_impl()->background_color();
878    if (SkColorGetA(color) != 255)
879      color = SkColorSetA(color, 255);
880  }
881  return color;
882}
883
884void LayerImpl::SetFilters(const FilterOperations& filters) {
885  if (filters_ == filters)
886    return;
887
888  filters_ = filters;
889  NoteLayerPropertyChangedForSubtree();
890}
891
892bool LayerImpl::FilterIsAnimating() const {
893  return layer_animation_controller_->IsAnimatingProperty(Animation::Filter);
894}
895
896bool LayerImpl::FilterIsAnimatingOnImplOnly() const {
897  Animation* filter_animation =
898      layer_animation_controller_->GetAnimation(Animation::Filter);
899  return filter_animation && filter_animation->is_impl_only();
900}
901
902void LayerImpl::SetBackgroundFilters(
903    const FilterOperations& filters) {
904  if (background_filters_ == filters)
905    return;
906
907  background_filters_ = filters;
908  NoteLayerPropertyChanged();
909}
910
911void LayerImpl::SetMasksToBounds(bool masks_to_bounds) {
912  if (masks_to_bounds_ == masks_to_bounds)
913    return;
914
915  masks_to_bounds_ = masks_to_bounds;
916  NoteLayerPropertyChangedForSubtree();
917}
918
919void LayerImpl::SetContentsOpaque(bool opaque) {
920  if (contents_opaque_ == opaque)
921    return;
922
923  contents_opaque_ = opaque;
924  NoteLayerPropertyChangedForSubtree();
925}
926
927void LayerImpl::SetOpacity(float opacity) {
928  if (opacity_ == opacity)
929    return;
930
931  opacity_ = opacity;
932  NoteLayerPropertyChangedForSubtree();
933}
934
935bool LayerImpl::OpacityIsAnimating() const {
936  return layer_animation_controller_->IsAnimatingProperty(Animation::Opacity);
937}
938
939bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
940  Animation* opacity_animation =
941      layer_animation_controller_->GetAnimation(Animation::Opacity);
942  return opacity_animation && opacity_animation->is_impl_only();
943}
944
945void LayerImpl::SetBlendMode(SkXfermode::Mode blend_mode) {
946  if (blend_mode_ == blend_mode)
947    return;
948
949  blend_mode_ = blend_mode;
950  NoteLayerPropertyChangedForSubtree();
951}
952
953void LayerImpl::SetIsRootForIsolatedGroup(bool root) {
954  if (is_root_for_isolated_group_ == root)
955    return;
956
957  is_root_for_isolated_group_ = root;
958  SetNeedsPushProperties();
959}
960
961void LayerImpl::SetPosition(const gfx::PointF& position) {
962  if (position_ == position)
963    return;
964
965  position_ = position;
966  NoteLayerPropertyChangedForSubtree();
967}
968
969void LayerImpl::SetShouldFlattenTransform(bool flatten) {
970  if (should_flatten_transform_ == flatten)
971    return;
972
973  should_flatten_transform_ = flatten;
974  NoteLayerPropertyChangedForSubtree();
975}
976
977void LayerImpl::SetIs3dSorted(bool sorted) {
978  if (is_3d_sorted_ == sorted)
979    return;
980
981  is_3d_sorted_ = sorted;
982  NoteLayerPropertyChangedForSubtree();
983}
984
985void LayerImpl::SetTransform(const gfx::Transform& transform) {
986  if (transform_ == transform)
987    return;
988
989  transform_ = transform;
990  transform_is_invertible_ = transform_.IsInvertible();
991  NoteLayerPropertyChangedForSubtree();
992}
993
994void LayerImpl::SetTransformAndInvertibility(const gfx::Transform& transform,
995                                             bool transform_is_invertible) {
996  if (transform_ == transform) {
997    DCHECK(transform_is_invertible_ == transform_is_invertible)
998        << "Can't change invertibility if transform is unchanged";
999    return;
1000  }
1001  transform_ = transform;
1002  transform_is_invertible_ = transform_is_invertible;
1003  NoteLayerPropertyChangedForSubtree();
1004}
1005
1006bool LayerImpl::TransformIsAnimating() const {
1007  return layer_animation_controller_->IsAnimatingProperty(Animation::Transform);
1008}
1009
1010bool LayerImpl::TransformIsAnimatingOnImplOnly() const {
1011  Animation* transform_animation =
1012      layer_animation_controller_->GetAnimation(Animation::Transform);
1013  return transform_animation && transform_animation->is_impl_only();
1014}
1015
1016void LayerImpl::SetUpdateRect(const gfx::RectF& update_rect) {
1017  update_rect_ = update_rect;
1018  SetNeedsPushProperties();
1019}
1020
1021void LayerImpl::AddDamageRect(const gfx::RectF& damage_rect) {
1022  damage_rect_ = gfx::UnionRects(damage_rect_, damage_rect);
1023}
1024
1025void LayerImpl::SetContentBounds(const gfx::Size& content_bounds) {
1026  if (this->content_bounds() == content_bounds)
1027    return;
1028
1029  draw_properties_.content_bounds = content_bounds;
1030  NoteLayerPropertyChanged();
1031}
1032
1033void LayerImpl::SetContentsScale(float contents_scale_x,
1034                                 float contents_scale_y) {
1035  if (this->contents_scale_x() == contents_scale_x &&
1036      this->contents_scale_y() == contents_scale_y)
1037    return;
1038
1039  draw_properties_.contents_scale_x = contents_scale_x;
1040  draw_properties_.contents_scale_y = contents_scale_y;
1041  NoteLayerPropertyChanged();
1042}
1043
1044void LayerImpl::SetScrollOffsetDelegate(
1045    ScrollOffsetDelegate* scroll_offset_delegate) {
1046  // Having both a scroll parent and a scroll offset delegate is unsupported.
1047  DCHECK(!scroll_parent_);
1048  if (!scroll_offset_delegate && scroll_offset_delegate_) {
1049    scroll_delta_ =
1050        scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_;
1051  }
1052  gfx::Vector2dF total_offset = TotalScrollOffset();
1053  scroll_offset_delegate_ = scroll_offset_delegate;
1054  if (scroll_offset_delegate_)
1055    scroll_offset_delegate_->SetTotalScrollOffset(total_offset);
1056}
1057
1058bool LayerImpl::IsExternalFlingActive() const {
1059  return scroll_offset_delegate_ &&
1060         scroll_offset_delegate_->IsExternalFlingActive();
1061}
1062
1063void LayerImpl::SetScrollOffset(const gfx::Vector2d& scroll_offset) {
1064  SetScrollOffsetAndDelta(scroll_offset, ScrollDelta());
1065}
1066
1067void LayerImpl::SetScrollOffsetAndDelta(const gfx::Vector2d& scroll_offset,
1068                                        const gfx::Vector2dF& scroll_delta) {
1069  bool changed = false;
1070
1071  last_scroll_offset_ = scroll_offset;
1072
1073  if (scroll_offset_ != scroll_offset) {
1074    changed = true;
1075    scroll_offset_ = scroll_offset;
1076
1077    if (scroll_offset_delegate_)
1078      scroll_offset_delegate_->SetTotalScrollOffset(TotalScrollOffset());
1079  }
1080
1081  if (ScrollDelta() != scroll_delta) {
1082    changed = true;
1083    if (layer_tree_impl()->IsActiveTree()) {
1084      LayerImpl* pending_twin =
1085          layer_tree_impl()->FindPendingTreeLayerById(id());
1086      if (pending_twin) {
1087        // The pending twin can't mirror the scroll delta of the active
1088        // layer.  Although the delta - sent scroll delta difference is
1089        // identical for both twins, the sent scroll delta for the pending
1090        // layer is zero, as anything that has been sent has been baked
1091        // into the layer's position/scroll offset as a part of commit.
1092        DCHECK(pending_twin->sent_scroll_delta().IsZero());
1093        pending_twin->SetScrollDelta(scroll_delta - sent_scroll_delta());
1094      }
1095    }
1096
1097    if (scroll_offset_delegate_) {
1098      scroll_offset_delegate_->SetTotalScrollOffset(scroll_offset_ +
1099                                                    scroll_delta);
1100    } else {
1101      scroll_delta_ = scroll_delta;
1102    }
1103  }
1104
1105  if (changed) {
1106    NoteLayerPropertyChangedForSubtree();
1107    ScrollbarParametersDidChange();
1108  }
1109}
1110
1111gfx::Vector2dF LayerImpl::ScrollDelta() const {
1112  if (scroll_offset_delegate_)
1113    return scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_;
1114  return scroll_delta_;
1115}
1116
1117void LayerImpl::SetScrollDelta(const gfx::Vector2dF& scroll_delta) {
1118  SetScrollOffsetAndDelta(scroll_offset_, scroll_delta);
1119}
1120
1121gfx::Vector2dF LayerImpl::TotalScrollOffset() const {
1122  return scroll_offset_ + ScrollDelta();
1123}
1124
1125void LayerImpl::SetDoubleSided(bool double_sided) {
1126  if (double_sided_ == double_sided)
1127    return;
1128
1129  double_sided_ = double_sided;
1130  NoteLayerPropertyChangedForSubtree();
1131}
1132
1133Region LayerImpl::VisibleContentOpaqueRegion() const {
1134  if (contents_opaque())
1135    return visible_content_rect();
1136  return Region();
1137}
1138
1139void LayerImpl::DidBeginTracing() {}
1140
1141void LayerImpl::ReleaseResources() {}
1142
1143gfx::Vector2d LayerImpl::MaxScrollOffset() const {
1144  if (!scroll_clip_layer_ || bounds().IsEmpty())
1145    return gfx::Vector2d();
1146
1147  LayerImpl const* page_scale_layer = layer_tree_impl()->page_scale_layer();
1148  DCHECK(this != page_scale_layer);
1149  DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
1150         IsContainerForFixedPositionLayers());
1151
1152  gfx::SizeF scaled_scroll_bounds(bounds());
1153
1154  float scale_factor = 1.f;
1155  for (LayerImpl const* current_layer = this;
1156       current_layer != scroll_clip_layer_;
1157       current_layer = current_layer->parent()) {
1158    DCHECK(current_layer);
1159    float current_layer_scale = 1.f;
1160
1161    const gfx::Transform& layer_transform = current_layer->transform();
1162    if (current_layer == page_scale_layer) {
1163      DCHECK(layer_transform.IsIdentity());
1164      current_layer_scale = layer_tree_impl()->total_page_scale_factor();
1165    } else {
1166      // TODO(wjmaclean) Should we allow for translation too?
1167      DCHECK(layer_transform.IsScale2d());
1168      gfx::Vector2dF layer_scale = layer_transform.Scale2d();
1169      // TODO(wjmaclean) Allow for non-isotropic scales.
1170      DCHECK(layer_scale.x() == layer_scale.y());
1171      current_layer_scale = layer_scale.x();
1172    }
1173
1174    scale_factor *= current_layer_scale;
1175  }
1176  // TODO(wjmaclean) Once we move to a model where the two-viewport model is
1177  // turned on in all builds, remove the next two lines. For now however, the
1178  // page scale layer may coincide with the clip layer, and so this is
1179  // necessary.
1180  if (page_scale_layer == scroll_clip_layer_)
1181    scale_factor *= layer_tree_impl()->total_page_scale_factor();
1182
1183  scaled_scroll_bounds.SetSize(scale_factor * scaled_scroll_bounds.width(),
1184                               scale_factor * scaled_scroll_bounds.height());
1185  scaled_scroll_bounds = gfx::ToFlooredSize(scaled_scroll_bounds);
1186
1187  gfx::Vector2dF max_offset(
1188      scaled_scroll_bounds.width() - scroll_clip_layer_->bounds().width(),
1189      scaled_scroll_bounds.height() - scroll_clip_layer_->bounds().height());
1190  // We need the final scroll offset to be in CSS coords.
1191  max_offset.Scale(1 / scale_factor);
1192  max_offset.SetToMax(gfx::Vector2dF());
1193  return gfx::ToFlooredVector2d(max_offset);
1194}
1195
1196gfx::Vector2dF LayerImpl::ClampScrollToMaxScrollOffset() {
1197  gfx::Vector2dF max_offset = MaxScrollOffset();
1198  gfx::Vector2dF old_offset = TotalScrollOffset();
1199  gfx::Vector2dF clamped_offset = old_offset;
1200
1201  clamped_offset.SetToMin(max_offset);
1202  clamped_offset.SetToMax(gfx::Vector2d());
1203  gfx::Vector2dF delta = clamped_offset - old_offset;
1204  if (!delta.IsZero())
1205    ScrollBy(delta);
1206
1207  return delta;
1208}
1209
1210void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase* scrollbar_layer,
1211                                     LayerImpl* scrollbar_clip_layer) const {
1212  DCHECK(scrollbar_layer);
1213  LayerImpl* page_scale_layer = layer_tree_impl()->page_scale_layer();
1214
1215  DCHECK(this != page_scale_layer);
1216  DCHECK(scrollbar_clip_layer);
1217  DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
1218         IsContainerForFixedPositionLayers());
1219  gfx::RectF clip_rect(gfx::PointF(), scrollbar_clip_layer->bounds());
1220
1221  // See comment in MaxScrollOffset() regarding the use of the content layer
1222  // bounds here.
1223  gfx::RectF scroll_rect(gfx::PointF(), bounds());
1224
1225  if (scroll_rect.size().IsEmpty())
1226    return;
1227
1228  // TODO(wjmaclean) This computation is nearly identical to the one in
1229  // MaxScrollOffset. Find some way to combine these.
1230  gfx::Vector2dF current_offset;
1231  for (LayerImpl const* current_layer = this;
1232       current_layer != scrollbar_clip_layer;
1233       current_layer = current_layer->parent()) {
1234    DCHECK(current_layer);
1235    const gfx::Transform& layer_transform = current_layer->transform();
1236    if (current_layer == page_scale_layer) {
1237      DCHECK(layer_transform.IsIdentity());
1238      float scale_factor = layer_tree_impl()->total_page_scale_factor();
1239      current_offset.Scale(scale_factor);
1240      scroll_rect.Scale(scale_factor);
1241    } else {
1242      DCHECK(layer_transform.IsScale2d());
1243      gfx::Vector2dF layer_scale = layer_transform.Scale2d();
1244      DCHECK(layer_scale.x() == layer_scale.y());
1245      gfx::Vector2dF new_offset =
1246          current_layer->scroll_offset() + current_layer->ScrollDelta();
1247      new_offset.Scale(layer_scale.x(), layer_scale.y());
1248      current_offset += new_offset;
1249    }
1250  }
1251  // TODO(wjmaclean) Once we move to a model where the two-viewport model is
1252  // turned on in all builds, remove the next two lines. For now however, the
1253  // page scale layer may coincide with the clip layer, and so this is
1254  // necessary.
1255  if (page_scale_layer == scrollbar_clip_layer) {
1256    scroll_rect.Scale(layer_tree_impl()->total_page_scale_factor());
1257    current_offset.Scale(layer_tree_impl()->total_page_scale_factor());
1258  }
1259
1260  scrollbar_layer->SetVerticalAdjust(
1261      layer_tree_impl()->VerticalAdjust(scrollbar_clip_layer->id()));
1262  if (scrollbar_layer->orientation() == HORIZONTAL) {
1263    float visible_ratio = clip_rect.width() / scroll_rect.width();
1264    scrollbar_layer->SetCurrentPos(current_offset.x());
1265    scrollbar_layer->SetMaximum(scroll_rect.width() - clip_rect.width());
1266    scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio);
1267  } else {
1268    float visible_ratio = clip_rect.height() / scroll_rect.height();
1269    scrollbar_layer->SetCurrentPos(current_offset.y());
1270    scrollbar_layer->SetMaximum(scroll_rect.height() - clip_rect.height());
1271    scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio);
1272  }
1273
1274  layer_tree_impl()->set_needs_update_draw_properties();
1275  // TODO(wjmaclean) The scrollbar animator for the pinch-zoom scrollbars should
1276  // activate for every scroll on the main frame, not just the scrolls that move
1277  // the pinch virtual viewport (i.e. trigger from either inner or outer
1278  // viewport).
1279  if (scrollbar_animation_controller_) {
1280    // When both non-overlay and overlay scrollbars are both present, don't
1281    // animate the overlay scrollbars when page scale factor is at the min.
1282    // Non-overlay scrollbars also shouldn't trigger animations.
1283    bool is_animatable_scrollbar =
1284        scrollbar_layer->is_overlay_scrollbar() &&
1285        ((layer_tree_impl()->total_page_scale_factor() >
1286          layer_tree_impl()->min_page_scale_factor()) ||
1287         !layer_tree_impl()->settings().use_pinch_zoom_scrollbars);
1288    if (is_animatable_scrollbar)
1289      scrollbar_animation_controller_->DidScrollUpdate();
1290  }
1291}
1292
1293void LayerImpl::DidBecomeActive() {
1294  if (layer_tree_impl_->settings().scrollbar_animator ==
1295      LayerTreeSettings::NoAnimator) {
1296    return;
1297  }
1298
1299  bool need_scrollbar_animation_controller = scrollable() && scrollbars_;
1300  if (!need_scrollbar_animation_controller) {
1301    scrollbar_animation_controller_.reset();
1302    return;
1303  }
1304
1305  if (scrollbar_animation_controller_)
1306    return;
1307
1308  scrollbar_animation_controller_ =
1309      layer_tree_impl_->CreateScrollbarAnimationController(this);
1310}
1311
1312void LayerImpl::ClearScrollbars() {
1313  if (!scrollbars_)
1314    return;
1315
1316  scrollbars_.reset(NULL);
1317}
1318
1319void LayerImpl::AddScrollbar(ScrollbarLayerImplBase* layer) {
1320  DCHECK(layer);
1321  DCHECK(!scrollbars_ || scrollbars_->find(layer) == scrollbars_->end());
1322  if (!scrollbars_)
1323    scrollbars_.reset(new ScrollbarSet());
1324
1325  scrollbars_->insert(layer);
1326}
1327
1328void LayerImpl::RemoveScrollbar(ScrollbarLayerImplBase* layer) {
1329  DCHECK(scrollbars_);
1330  DCHECK(layer);
1331  DCHECK(scrollbars_->find(layer) != scrollbars_->end());
1332
1333  scrollbars_->erase(layer);
1334  if (scrollbars_->empty())
1335    scrollbars_.reset();
1336}
1337
1338bool LayerImpl::HasScrollbar(ScrollbarOrientation orientation) const {
1339  if (!scrollbars_)
1340    return false;
1341
1342  for (ScrollbarSet::iterator it = scrollbars_->begin();
1343       it != scrollbars_->end();
1344       ++it)
1345    if ((*it)->orientation() == orientation)
1346      return true;
1347
1348  return false;
1349}
1350
1351void LayerImpl::ScrollbarParametersDidChange() {
1352  if (!scrollbars_)
1353    return;
1354
1355  for (ScrollbarSet::iterator it = scrollbars_->begin();
1356       it != scrollbars_->end();
1357       ++it)
1358    (*it)->ScrollbarParametersDidChange();
1359}
1360
1361void LayerImpl::SetNeedsPushProperties() {
1362  if (needs_push_properties_)
1363    return;
1364  if (!parent_should_know_need_push_properties() && parent_)
1365    parent_->AddDependentNeedsPushProperties();
1366  needs_push_properties_ = true;
1367}
1368
1369void LayerImpl::AddDependentNeedsPushProperties() {
1370  DCHECK_GE(num_dependents_need_push_properties_, 0);
1371
1372  if (!parent_should_know_need_push_properties() && parent_)
1373    parent_->AddDependentNeedsPushProperties();
1374
1375  num_dependents_need_push_properties_++;
1376}
1377
1378void LayerImpl::RemoveDependentNeedsPushProperties() {
1379  num_dependents_need_push_properties_--;
1380  DCHECK_GE(num_dependents_need_push_properties_, 0);
1381
1382  if (!parent_should_know_need_push_properties() && parent_)
1383      parent_->RemoveDependentNeedsPushProperties();
1384}
1385
1386void LayerImpl::AsValueInto(base::DictionaryValue* state) const {
1387  TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
1388      TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1389      state,
1390      "cc::LayerImpl",
1391      LayerTypeAsString(),
1392      this);
1393  state->SetInteger("layer_id", id());
1394  state->Set("bounds", MathUtil::AsValue(bounds_).release());
1395  state->Set("position", MathUtil::AsValue(position_).release());
1396  state->SetInteger("draws_content", DrawsContent());
1397  state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes());
1398  state->Set("scroll_offset", MathUtil::AsValue(scroll_offset_).release());
1399  state->Set("transform_origin",
1400             MathUtil::AsValue(transform_origin_).release());
1401
1402  bool clipped;
1403  gfx::QuadF layer_quad = MathUtil::MapQuad(
1404      screen_space_transform(),
1405      gfx::QuadF(gfx::Rect(content_bounds())),
1406      &clipped);
1407  state->Set("layer_quad", MathUtil::AsValue(layer_quad).release());
1408
1409  if (!touch_event_handler_region_.IsEmpty()) {
1410    state->Set("touch_event_handler_region",
1411               touch_event_handler_region_.AsValue().release());
1412  }
1413  if (have_wheel_event_handlers_) {
1414    gfx::Rect wheel_rect(content_bounds());
1415    Region wheel_region(wheel_rect);
1416    state->Set("wheel_event_handler_region",
1417               wheel_region.AsValue().release());
1418  }
1419  if (have_scroll_event_handlers_) {
1420    gfx::Rect scroll_rect(content_bounds());
1421    Region scroll_region(scroll_rect);
1422    state->Set("scroll_event_handler_region",
1423               scroll_region.AsValue().release());
1424  }
1425  if (!non_fast_scrollable_region_.IsEmpty()) {
1426    state->Set("non_fast_scrollable_region",
1427               non_fast_scrollable_region_.AsValue().release());
1428  }
1429
1430  scoped_ptr<base::ListValue> children_list(new base::ListValue());
1431  for (size_t i = 0; i < children_.size(); ++i)
1432    children_list->Append(children_[i]->AsValue().release());
1433  state->Set("children", children_list.release());
1434  if (mask_layer_)
1435    state->Set("mask_layer", mask_layer_->AsValue().release());
1436  if (replica_layer_)
1437    state->Set("replica_layer", replica_layer_->AsValue().release());
1438
1439  if (scroll_parent_)
1440    state->SetInteger("scroll_parent", scroll_parent_->id());
1441
1442  if (clip_parent_)
1443    state->SetInteger("clip_parent", clip_parent_->id());
1444
1445  state->SetBoolean("can_use_lcd_text", can_use_lcd_text());
1446  state->SetBoolean("contents_opaque", contents_opaque());
1447
1448  state->SetBoolean(
1449      "has_animation_bounds",
1450      layer_animation_controller()->HasAnimationThatInflatesBounds());
1451
1452  gfx::BoxF box;
1453  if (LayerUtils::GetAnimationBounds(*this, &box))
1454    state->Set("animation_bounds", MathUtil::AsValue(box).release());
1455
1456  if (debug_info_.get()) {
1457    std::string str;
1458    debug_info_->AppendAsTraceFormat(&str);
1459    base::JSONReader json_reader;
1460    scoped_ptr<base::Value> debug_info_value(json_reader.ReadToValue(str));
1461
1462    if (debug_info_value->IsType(base::Value::TYPE_DICTIONARY)) {
1463      base::DictionaryValue* dictionary_value = NULL;
1464      bool converted_to_dictionary =
1465          debug_info_value->GetAsDictionary(&dictionary_value);
1466      DCHECK(converted_to_dictionary);
1467      state->MergeDictionary(dictionary_value);
1468    } else {
1469      NOTREACHED();
1470    }
1471  }
1472}
1473
1474bool LayerImpl::IsDrawnRenderSurfaceLayerListMember() const {
1475  return draw_properties_.last_drawn_render_surface_layer_list_id ==
1476         layer_tree_impl_->current_render_surface_list_id();
1477}
1478
1479size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; }
1480
1481scoped_ptr<base::Value> LayerImpl::AsValue() const {
1482  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1483  AsValueInto(state.get());
1484  return state.PassAs<base::Value>();
1485}
1486
1487void LayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
1488  benchmark->RunOnLayer(this);
1489}
1490}  // namespace cc
1491