layer_impl.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
1// Copyright 2011 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/strings/stringprintf.h"
9#include "cc/animation/animation_registrar.h"
10#include "cc/animation/scrollbar_animation_controller.h"
11#include "cc/animation/scrollbar_animation_controller_linear_fade.h"
12#include "cc/animation/scrollbar_animation_controller_thinning.h"
13#include "cc/base/math_util.h"
14#include "cc/debug/debug_colors.h"
15#include "cc/debug/layer_tree_debug_state.h"
16#include "cc/debug/traced_value.h"
17#include "cc/input/layer_scroll_offset_delegate.h"
18#include "cc/layers/painted_scrollbar_layer_impl.h"
19#include "cc/layers/quad_sink.h"
20#include "cc/output/copy_output_request.h"
21#include "cc/quads/debug_border_draw_quad.h"
22#include "cc/trees/layer_tree_impl.h"
23#include "cc/trees/layer_tree_settings.h"
24#include "cc/trees/proxy.h"
25#include "ui/gfx/point_conversions.h"
26#include "ui/gfx/quad_f.h"
27#include "ui/gfx/rect_conversions.h"
28
29namespace cc {
30
31LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
32    : parent_(NULL),
33      scroll_parent_(NULL),
34      clip_parent_(NULL),
35      mask_layer_id_(-1),
36      replica_layer_id_(-1),
37      layer_id_(id),
38      layer_tree_impl_(tree_impl),
39      anchor_point_(0.5f, 0.5f),
40      anchor_point_z_(0.f),
41      scroll_offset_delegate_(NULL),
42      scrollable_(false),
43      should_scroll_on_main_thread_(false),
44      have_wheel_event_handlers_(false),
45      user_scrollable_horizontal_(true),
46      user_scrollable_vertical_(true),
47      background_color_(0),
48      stacking_order_changed_(false),
49      double_sided_(true),
50      layer_property_changed_(false),
51      masks_to_bounds_(false),
52      contents_opaque_(false),
53      opacity_(1.0),
54      preserves_3d_(false),
55      use_parent_backface_visibility_(false),
56      draw_checkerboard_for_missing_tiles_(false),
57      draws_content_(false),
58      hide_layer_and_subtree_(false),
59      force_render_surface_(false),
60      is_container_for_fixed_position_layers_(false),
61      draw_depth_(0.f),
62      compositing_reasons_(kCompositingReasonUnknown),
63      current_draw_mode_(DRAW_MODE_NONE),
64      horizontal_scrollbar_layer_(NULL),
65      vertical_scrollbar_layer_(NULL) {
66  DCHECK_GT(layer_id_, 0);
67  DCHECK(layer_tree_impl_);
68  layer_tree_impl_->RegisterLayer(this);
69  AnimationRegistrar* registrar = layer_tree_impl_->animationRegistrar();
70  layer_animation_controller_ =
71      registrar->GetAnimationControllerForId(layer_id_);
72  layer_animation_controller_->AddValueObserver(this);
73}
74
75LayerImpl::~LayerImpl() {
76  DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
77
78  layer_tree_impl_->UnregisterLayer(this);
79  layer_animation_controller_->RemoveValueObserver(this);
80
81  if (scroll_children_) {
82    for (std::set<LayerImpl*>::iterator it = scroll_children_->begin();
83        it != scroll_children_->end(); ++it)
84      (*it)->scroll_parent_ = NULL;
85  }
86
87  if (scroll_parent_)
88    scroll_parent_->RemoveScrollChild(this);
89
90  if (clip_children_) {
91    for (std::set<LayerImpl*>::iterator it = clip_children_->begin();
92        it != clip_children_->end(); ++it)
93      (*it)->clip_parent_ = NULL;
94  }
95
96  if (clip_parent_)
97    clip_parent_->RemoveClipChild(this);
98}
99
100void LayerImpl::AddChild(scoped_ptr<LayerImpl> child) {
101  child->set_parent(this);
102  DCHECK_EQ(layer_tree_impl(), child->layer_tree_impl());
103  children_.push_back(child.Pass());
104  layer_tree_impl()->set_needs_update_draw_properties();
105}
106
107scoped_ptr<LayerImpl> LayerImpl::RemoveChild(LayerImpl* child) {
108  for (OwnedLayerImplList::iterator it = children_.begin();
109       it != children_.end();
110       ++it) {
111    if (*it == child) {
112      scoped_ptr<LayerImpl> ret = children_.take(it);
113      children_.erase(it);
114      layer_tree_impl()->set_needs_update_draw_properties();
115      return ret.Pass();
116    }
117  }
118  return scoped_ptr<LayerImpl>();
119}
120
121void LayerImpl::ClearChildList() {
122  if (children_.empty())
123    return;
124
125  children_.clear();
126  layer_tree_impl()->set_needs_update_draw_properties();
127}
128
129bool LayerImpl::HasAncestor(const LayerImpl* ancestor) const {
130  if (!ancestor)
131    return false;
132
133  for (const LayerImpl* layer = this; layer; layer = layer->parent()) {
134    if (layer == ancestor)
135      return true;
136  }
137
138  return false;
139}
140
141void LayerImpl::SetScrollParent(LayerImpl* parent) {
142  if (scroll_parent_ == parent)
143    return;
144
145  // Having both a scroll parent and a scroll offset delegate is unsupported.
146  DCHECK(!scroll_offset_delegate_);
147
148  if (scroll_parent_)
149    scroll_parent_->RemoveScrollChild(this);
150
151  scroll_parent_ = parent;
152}
153
154void LayerImpl::SetScrollChildren(std::set<LayerImpl*>* children) {
155  if (scroll_children_.get() == children)
156    return;
157  scroll_children_.reset(children);
158}
159
160void LayerImpl::RemoveScrollChild(LayerImpl* child) {
161  DCHECK(scroll_children_);
162  scroll_children_->erase(child);
163  if (scroll_children_->empty())
164    scroll_children_.reset();
165}
166
167void LayerImpl::SetClipParent(LayerImpl* ancestor) {
168  if (clip_parent_ == ancestor)
169    return;
170
171  if (clip_parent_)
172    clip_parent_->RemoveClipChild(this);
173
174  clip_parent_ = ancestor;
175}
176
177void LayerImpl::SetClipChildren(std::set<LayerImpl*>* children) {
178  if (clip_children_.get() == children)
179    return;
180  clip_children_.reset(children);
181}
182
183void LayerImpl::RemoveClipChild(LayerImpl* child) {
184  DCHECK(clip_children_);
185  clip_children_->erase(child);
186  if (clip_children_->empty())
187    clip_children_.reset();
188}
189
190void LayerImpl::PassCopyRequests(ScopedPtrVector<CopyOutputRequest>* requests) {
191  if (requests->empty())
192    return;
193
194  bool was_empty = copy_requests_.empty();
195  copy_requests_.insert_and_take(copy_requests_.end(), *requests);
196  requests->clear();
197
198  if (was_empty && layer_tree_impl()->IsActiveTree())
199    layer_tree_impl()->AddLayerWithCopyOutputRequest(this);
200  NoteLayerPropertyChangedForSubtree();
201}
202
203void LayerImpl::TakeCopyRequestsAndTransformToTarget(
204    ScopedPtrVector<CopyOutputRequest>* requests) {
205  if (copy_requests_.empty())
206    return;
207
208  size_t first_inserted_request = requests->size();
209  requests->insert_and_take(requests->end(), copy_requests_);
210  copy_requests_.clear();
211
212  for (size_t i = first_inserted_request; i < requests->size(); ++i) {
213    CopyOutputRequest* request = requests->at(i);
214    if (!request->has_area())
215      continue;
216
217    gfx::Rect request_in_layer_space = request->area();
218    gfx::Rect request_in_content_space =
219        LayerRectToContentRect(request_in_layer_space);
220    request->set_area(
221        MathUtil::MapClippedRect(draw_properties_.target_space_transform,
222                                 request_in_content_space));
223  }
224
225  if (layer_tree_impl()->IsActiveTree())
226    layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
227}
228
229void LayerImpl::CreateRenderSurface() {
230  DCHECK(!draw_properties_.render_surface);
231  draw_properties_.render_surface =
232      make_scoped_ptr(new RenderSurfaceImpl(this));
233  draw_properties_.render_target = this;
234}
235
236void LayerImpl::ClearRenderSurface() {
237  draw_properties_.render_surface.reset();
238}
239
240scoped_ptr<SharedQuadState> LayerImpl::CreateSharedQuadState() const {
241  scoped_ptr<SharedQuadState> state = SharedQuadState::Create();
242  state->SetAll(draw_properties_.target_space_transform,
243                draw_properties_.content_bounds,
244                draw_properties_.visible_content_rect,
245                draw_properties_.clip_rect,
246                draw_properties_.is_clipped,
247                draw_properties_.opacity);
248  return state.Pass();
249}
250
251bool LayerImpl::WillDraw(DrawMode draw_mode,
252                         ResourceProvider* resource_provider) {
253  // WillDraw/DidDraw must be matched.
254  DCHECK_NE(DRAW_MODE_NONE, draw_mode);
255  DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
256  current_draw_mode_ = draw_mode;
257  return true;
258}
259
260void LayerImpl::DidDraw(ResourceProvider* resource_provider) {
261  DCHECK_NE(DRAW_MODE_NONE, current_draw_mode_);
262  current_draw_mode_ = DRAW_MODE_NONE;
263}
264
265bool LayerImpl::ShowDebugBorders() const {
266  return layer_tree_impl()->debug_state().show_debug_borders;
267}
268
269void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const {
270  if (draws_content_) {
271    *color = DebugColors::ContentLayerBorderColor();
272    *width = DebugColors::ContentLayerBorderWidth(layer_tree_impl());
273    return;
274  }
275
276  if (masks_to_bounds_) {
277    *color = DebugColors::MaskingLayerBorderColor();
278    *width = DebugColors::MaskingLayerBorderWidth(layer_tree_impl());
279    return;
280  }
281
282  *color = DebugColors::ContainerLayerBorderColor();
283  *width = DebugColors::ContainerLayerBorderWidth(layer_tree_impl());
284}
285
286void LayerImpl::AppendDebugBorderQuad(
287    QuadSink* quad_sink,
288    const SharedQuadState* shared_quad_state,
289    AppendQuadsData* append_quads_data) const {
290  SkColor color;
291  float width;
292  GetDebugBorderProperties(&color, &width);
293  AppendDebugBorderQuad(
294      quad_sink, shared_quad_state, append_quads_data, color, width);
295}
296
297void LayerImpl::AppendDebugBorderQuad(QuadSink* quad_sink,
298                                      const SharedQuadState* shared_quad_state,
299                                      AppendQuadsData* append_quads_data,
300                                      SkColor color,
301                                      float width) const {
302  if (!ShowDebugBorders())
303    return;
304
305  gfx::Rect content_rect(content_bounds());
306  scoped_ptr<DebugBorderDrawQuad> debug_border_quad =
307      DebugBorderDrawQuad::Create();
308  debug_border_quad->SetNew(shared_quad_state, content_rect, color, width);
309  quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), append_quads_data);
310}
311
312bool LayerImpl::HasDelegatedContent() const {
313  return false;
314}
315
316bool LayerImpl::HasContributingDelegatedRenderPasses() const {
317  return false;
318}
319
320RenderPass::Id LayerImpl::FirstContributingRenderPassId() const {
321  return RenderPass::Id(0, 0);
322}
323
324RenderPass::Id LayerImpl::NextContributingRenderPassId(RenderPass::Id id)
325    const {
326  return RenderPass::Id(0, 0);
327}
328
329ResourceProvider::ResourceId LayerImpl::ContentsResourceId() const {
330  NOTREACHED();
331  return 0;
332}
333
334void LayerImpl::SetSentScrollDelta(gfx::Vector2d sent_scroll_delta) {
335  // Pending tree never has sent scroll deltas
336  DCHECK(layer_tree_impl()->IsActiveTree());
337
338  if (sent_scroll_delta_ == sent_scroll_delta)
339    return;
340
341  sent_scroll_delta_ = sent_scroll_delta;
342}
343
344gfx::Vector2dF LayerImpl::ScrollBy(gfx::Vector2dF scroll) {
345  DCHECK(scrollable());
346  gfx::Vector2dF scroll_hidden;
347  if (!user_scrollable_horizontal_) {
348    scroll_hidden.set_x(scroll.x());
349    scroll.set_x(0.f);
350  }
351  if (!user_scrollable_vertical_) {
352    scroll_hidden.set_y(scroll.y());
353    scroll.set_y(0.f);
354  }
355
356  gfx::Vector2dF min_delta = -scroll_offset_;
357  gfx::Vector2dF max_delta = max_scroll_offset_ - scroll_offset_;
358  // Clamp new_delta so that position + delta stays within scroll bounds.
359  gfx::Vector2dF new_delta = (ScrollDelta() + scroll);
360  new_delta.SetToMax(min_delta);
361  new_delta.SetToMin(max_delta);
362  gfx::Vector2dF unscrolled =
363      ScrollDelta() + scroll + scroll_hidden - new_delta;
364  SetScrollDelta(new_delta);
365  return unscrolled;
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::ApplyScrollDeltasSinceBeginFrame() {
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    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  if (max_scroll_offset_.x() <= 0 && max_scroll_offset_.y() <= 0) {
458    TRACE_EVENT0("cc",
459                 "LayerImpl::tryScroll: Ignored. Technically scrollable,"
460                 " but has no affordance in either direction.");
461    return InputHandler::ScrollIgnored;
462  }
463
464  if (!user_scrollable_horizontal_ && !user_scrollable_vertical_) {
465    TRACE_EVENT0("cc",
466                 "LayerImpl::TryScroll: Ignored. User gesture is not allowed"
467                 " to scroll this layer.");
468    return InputHandler::ScrollIgnored;
469  }
470
471  return InputHandler::ScrollStarted;
472}
473
474bool LayerImpl::DrawCheckerboardForMissingTiles() const {
475  return draw_checkerboard_for_missing_tiles_ &&
476      !layer_tree_impl()->settings().background_color_instead_of_checkerboard;
477}
478
479gfx::Rect LayerImpl::LayerRectToContentRect(
480    const gfx::RectF& layer_rect) const {
481  gfx::RectF content_rect =
482      gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y());
483  // Intersect with content rect to avoid the extra pixel because for some
484  // values x and y, ceil((x / y) * y) may be x + 1.
485  content_rect.Intersect(gfx::Rect(content_bounds()));
486  return gfx::ToEnclosingRect(content_rect);
487}
488
489skia::RefPtr<SkPicture> LayerImpl::GetPicture() {
490  return skia::RefPtr<SkPicture>();
491}
492
493bool LayerImpl::AreVisibleResourcesReady() const {
494  return true;
495}
496
497scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) {
498  return LayerImpl::Create(tree_impl, layer_id_);
499}
500
501void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
502  layer->SetAnchorPoint(anchor_point_);
503  layer->SetAnchorPointZ(anchor_point_z_);
504  layer->SetBackgroundColor(background_color_);
505  layer->SetBounds(bounds_);
506  layer->SetContentBounds(content_bounds());
507  layer->SetContentsScale(contents_scale_x(), contents_scale_y());
508  layer->SetDebugName(debug_name_);
509  layer->SetCompositingReasons(compositing_reasons_);
510  layer->SetDoubleSided(double_sided_);
511  layer->SetDrawCheckerboardForMissingTiles(
512      draw_checkerboard_for_missing_tiles_);
513  layer->SetForceRenderSurface(force_render_surface_);
514  layer->SetDrawsContent(DrawsContent());
515  layer->SetHideLayerAndSubtree(hide_layer_and_subtree_);
516  layer->SetFilters(filters());
517  layer->SetBackgroundFilters(background_filters());
518  layer->SetMasksToBounds(masks_to_bounds_);
519  layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
520  layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
521  layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
522  layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
523  layer->SetContentsOpaque(contents_opaque_);
524  layer->SetOpacity(opacity_);
525  layer->SetPosition(position_);
526  layer->SetIsContainerForFixedPositionLayers(
527      is_container_for_fixed_position_layers_);
528  layer->SetFixedContainerSizeDelta(fixed_container_size_delta_);
529  layer->SetPositionConstraint(position_constraint_);
530  layer->SetPreserves3d(preserves_3d());
531  layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
532  layer->SetSublayerTransform(sublayer_transform_);
533  layer->SetTransform(transform_);
534
535  layer->SetScrollable(scrollable_);
536  layer->set_user_scrollable_horizontal(user_scrollable_horizontal_);
537  layer->set_user_scrollable_vertical(user_scrollable_vertical_);
538  layer->SetScrollOffsetAndDelta(
539      scroll_offset_, layer->ScrollDelta() - layer->sent_scroll_delta());
540  layer->SetSentScrollDelta(gfx::Vector2d());
541
542  layer->SetMaxScrollOffset(max_scroll_offset_);
543
544  LayerImpl* scroll_parent = NULL;
545  if (scroll_parent_)
546    scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id());
547
548  layer->SetScrollParent(scroll_parent);
549  if (scroll_children_) {
550    std::set<LayerImpl*>* scroll_children = new std::set<LayerImpl*>;
551    for (std::set<LayerImpl*>::iterator it = scroll_children_->begin();
552        it != scroll_children_->end(); ++it)
553      scroll_children->insert(layer->layer_tree_impl()->LayerById((*it)->id()));
554    layer->SetScrollChildren(scroll_children);
555  }
556
557  LayerImpl* clip_parent = NULL;
558  if (clip_parent_) {
559    clip_parent = layer->layer_tree_impl()->LayerById(
560        clip_parent_->id());
561  }
562
563  layer->SetClipParent(clip_parent);
564  if (clip_children_) {
565    std::set<LayerImpl*>* clip_children = new std::set<LayerImpl*>;
566    for (std::set<LayerImpl*>::iterator it = clip_children_->begin();
567        it != clip_children_->end(); ++it)
568      clip_children->insert(layer->layer_tree_impl()->LayerById((*it)->id()));
569    layer->SetClipChildren(clip_children);
570  }
571
572  layer->PassCopyRequests(&copy_requests_);
573
574  // If the main thread commits multiple times before the impl thread actually
575  // draws, then damage tracking will become incorrect if we simply clobber the
576  // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
577  // union) any update changes that have occurred on the main thread.
578  update_rect_.Union(layer->update_rect());
579  layer->set_update_rect(update_rect_);
580
581  layer->SetStackingOrderChanged(stacking_order_changed_);
582
583  // Reset any state that should be cleared for the next update.
584  stacking_order_changed_ = false;
585  update_rect_ = gfx::RectF();
586}
587
588base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
589  base::DictionaryValue* result = new base::DictionaryValue;
590  result->SetString("LayerType", LayerTypeAsString());
591
592  base::ListValue* list = new base::ListValue;
593  list->AppendInteger(bounds().width());
594  list->AppendInteger(bounds().height());
595  result->Set("Bounds", list);
596
597  list = new base::ListValue;
598  list->AppendDouble(position_.x());
599  list->AppendDouble(position_.y());
600  result->Set("Position", list);
601
602  const gfx::Transform& gfx_transform = draw_properties_.target_space_transform;
603  double transform[16];
604  gfx_transform.matrix().asColMajord(transform);
605  list = new base::ListValue;
606  for (int i = 0; i < 16; ++i)
607    list->AppendDouble(transform[i]);
608  result->Set("DrawTransform", list);
609
610  result->SetBoolean("DrawsContent", draws_content_);
611  result->SetDouble("Opacity", opacity());
612  result->SetBoolean("ContentsOpaque", contents_opaque_);
613
614  if (scrollable_)
615    result->SetBoolean("Scrollable", scrollable_);
616
617  list = new base::ListValue;
618  for (size_t i = 0; i < children_.size(); ++i)
619    list->Append(children_[i]->LayerTreeAsJson());
620  result->Set("Children", list);
621
622  return result;
623}
624
625void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) {
626  if (stacking_order_changed) {
627    stacking_order_changed_ = true;
628    NoteLayerPropertyChangedForSubtree();
629  }
630}
631
632void LayerImpl::NoteLayerPropertyChanged() {
633  layer_property_changed_ = true;
634  layer_tree_impl()->set_needs_update_draw_properties();
635}
636
637void LayerImpl::NoteLayerPropertyChangedForSubtree() {
638  NoteLayerPropertyChanged();
639  NoteLayerPropertyChangedForDescendants();
640}
641
642void LayerImpl::NoteLayerPropertyChangedForDescendants() {
643  layer_tree_impl()->set_needs_update_draw_properties();
644  for (size_t i = 0; i < children_.size(); ++i)
645    children_[i]->NoteLayerPropertyChangedForSubtree();
646}
647
648const char* LayerImpl::LayerTypeAsString() const {
649  return "cc::LayerImpl";
650}
651
652void LayerImpl::ResetAllChangeTrackingForSubtree() {
653  layer_property_changed_ = false;
654
655  update_rect_ = gfx::RectF();
656
657  if (draw_properties_.render_surface)
658    draw_properties_.render_surface->ResetPropertyChangedFlag();
659
660  if (mask_layer_)
661    mask_layer_->ResetAllChangeTrackingForSubtree();
662
663  if (replica_layer_) {
664    // This also resets the replica mask, if it exists.
665    replica_layer_->ResetAllChangeTrackingForSubtree();
666  }
667
668  for (size_t i = 0; i < children_.size(); ++i)
669    children_[i]->ResetAllChangeTrackingForSubtree();
670}
671
672bool LayerImpl::LayerIsAlwaysDamaged() const {
673  return false;
674}
675
676void LayerImpl::OnFilterAnimated(const FilterOperations& filters) {
677  SetFilters(filters);
678}
679
680void LayerImpl::OnOpacityAnimated(float opacity) {
681  SetOpacity(opacity);
682}
683
684void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) {
685  SetTransform(transform);
686}
687
688bool LayerImpl::IsActive() const {
689  return layer_tree_impl_->IsActiveTree();
690}
691
692void LayerImpl::SetBounds(gfx::Size bounds) {
693  if (bounds_ == bounds)
694    return;
695
696  bounds_ = bounds;
697
698  if (masks_to_bounds())
699    NoteLayerPropertyChangedForSubtree();
700  else
701    NoteLayerPropertyChanged();
702}
703
704void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) {
705  int new_layer_id = mask_layer ? mask_layer->id() : -1;
706
707  if (mask_layer) {
708    DCHECK_EQ(layer_tree_impl(), mask_layer->layer_tree_impl());
709    DCHECK_NE(new_layer_id, mask_layer_id_);
710  } else if (new_layer_id == mask_layer_id_) {
711    return;
712  }
713
714  mask_layer_ = mask_layer.Pass();
715  mask_layer_id_ = new_layer_id;
716  if (mask_layer_)
717    mask_layer_->set_parent(this);
718  NoteLayerPropertyChangedForSubtree();
719}
720
721scoped_ptr<LayerImpl> LayerImpl::TakeMaskLayer() {
722  mask_layer_id_ = -1;
723  return mask_layer_.Pass();
724}
725
726void LayerImpl::SetReplicaLayer(scoped_ptr<LayerImpl> replica_layer) {
727  int new_layer_id = replica_layer ? replica_layer->id() : -1;
728
729  if (replica_layer) {
730    DCHECK_EQ(layer_tree_impl(), replica_layer->layer_tree_impl());
731    DCHECK_NE(new_layer_id, replica_layer_id_);
732  } else if (new_layer_id == replica_layer_id_) {
733    return;
734  }
735
736  replica_layer_ = replica_layer.Pass();
737  replica_layer_id_ = new_layer_id;
738  if (replica_layer_)
739    replica_layer_->set_parent(this);
740  NoteLayerPropertyChangedForSubtree();
741}
742
743scoped_ptr<LayerImpl> LayerImpl::TakeReplicaLayer() {
744  replica_layer_id_ = -1;
745  return replica_layer_.Pass();
746}
747
748ScrollbarLayerImplBase* LayerImpl::ToScrollbarLayer() {
749  return NULL;
750}
751
752void LayerImpl::SetDrawsContent(bool draws_content) {
753  if (draws_content_ == draws_content)
754    return;
755
756  draws_content_ = draws_content;
757  NoteLayerPropertyChanged();
758}
759
760void LayerImpl::SetHideLayerAndSubtree(bool hide) {
761  if (hide_layer_and_subtree_ == hide)
762    return;
763
764  hide_layer_and_subtree_ = hide;
765  NoteLayerPropertyChangedForSubtree();
766}
767
768void LayerImpl::SetAnchorPoint(gfx::PointF anchor_point) {
769  if (anchor_point_ == anchor_point)
770    return;
771
772  anchor_point_ = anchor_point;
773  NoteLayerPropertyChangedForSubtree();
774}
775
776void LayerImpl::SetAnchorPointZ(float anchor_point_z) {
777  if (anchor_point_z_ == anchor_point_z)
778    return;
779
780  anchor_point_z_ = anchor_point_z;
781  NoteLayerPropertyChangedForSubtree();
782}
783
784void LayerImpl::SetBackgroundColor(SkColor background_color) {
785  if (background_color_ == background_color)
786    return;
787
788  background_color_ = background_color;
789  NoteLayerPropertyChanged();
790}
791
792SkColor LayerImpl::SafeOpaqueBackgroundColor() const {
793  SkColor color = background_color();
794  if (SkColorGetA(color) == 255 && !contents_opaque()) {
795    color = SK_ColorTRANSPARENT;
796  } else if (SkColorGetA(color) != 255 && contents_opaque()) {
797    for (const LayerImpl* layer = parent(); layer;
798         layer = layer->parent()) {
799      color = layer->background_color();
800      if (SkColorGetA(color) == 255)
801        break;
802    }
803    if (SkColorGetA(color) != 255)
804      color = layer_tree_impl()->background_color();
805    if (SkColorGetA(color) != 255)
806      color = SkColorSetA(color, 255);
807  }
808  return color;
809}
810
811void LayerImpl::SetFilters(const FilterOperations& filters) {
812  if (filters_ == filters)
813    return;
814
815  filters_ = filters;
816  NoteLayerPropertyChangedForSubtree();
817}
818
819bool LayerImpl::FilterIsAnimating() const {
820  return layer_animation_controller_->IsAnimatingProperty(Animation::Filter);
821}
822
823bool LayerImpl::FilterIsAnimatingOnImplOnly() const {
824  Animation* filter_animation =
825      layer_animation_controller_->GetAnimation(Animation::Filter);
826  return filter_animation && filter_animation->is_impl_only();
827}
828
829void LayerImpl::SetBackgroundFilters(
830    const FilterOperations& filters) {
831  if (background_filters_ == filters)
832    return;
833
834  background_filters_ = filters;
835  NoteLayerPropertyChanged();
836}
837
838void LayerImpl::SetMasksToBounds(bool masks_to_bounds) {
839  if (masks_to_bounds_ == masks_to_bounds)
840    return;
841
842  masks_to_bounds_ = masks_to_bounds;
843  NoteLayerPropertyChangedForSubtree();
844}
845
846void LayerImpl::SetContentsOpaque(bool opaque) {
847  if (contents_opaque_ == opaque)
848    return;
849
850  contents_opaque_ = opaque;
851  NoteLayerPropertyChangedForSubtree();
852}
853
854void LayerImpl::SetOpacity(float opacity) {
855  if (opacity_ == opacity)
856    return;
857
858  opacity_ = opacity;
859  NoteLayerPropertyChangedForSubtree();
860}
861
862bool LayerImpl::OpacityIsAnimating() const {
863  return layer_animation_controller_->IsAnimatingProperty(Animation::Opacity);
864}
865
866bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
867  Animation* opacity_animation =
868      layer_animation_controller_->GetAnimation(Animation::Opacity);
869  return opacity_animation && opacity_animation->is_impl_only();
870}
871
872void LayerImpl::SetPosition(gfx::PointF position) {
873  if (position_ == position)
874    return;
875
876  position_ = position;
877  NoteLayerPropertyChangedForSubtree();
878}
879
880void LayerImpl::SetPreserves3d(bool preserves3_d) {
881  if (preserves_3d_ == preserves3_d)
882    return;
883
884  preserves_3d_ = preserves3_d;
885  NoteLayerPropertyChangedForSubtree();
886}
887
888void LayerImpl::SetSublayerTransform(const gfx::Transform& sublayer_transform) {
889  if (sublayer_transform_ == sublayer_transform)
890    return;
891
892  sublayer_transform_ = sublayer_transform;
893  // Sublayer transform does not affect the current layer; it affects only its
894  // children.
895  NoteLayerPropertyChangedForDescendants();
896}
897
898void LayerImpl::SetTransform(const gfx::Transform& transform) {
899  if (transform_ == transform)
900    return;
901
902  transform_ = transform;
903  NoteLayerPropertyChangedForSubtree();
904}
905
906bool LayerImpl::TransformIsAnimating() const {
907  return layer_animation_controller_->IsAnimatingProperty(Animation::Transform);
908}
909
910bool LayerImpl::TransformIsAnimatingOnImplOnly() const {
911  Animation* transform_animation =
912      layer_animation_controller_->GetAnimation(Animation::Transform);
913  return transform_animation && transform_animation->is_impl_only();
914}
915
916void LayerImpl::SetContentBounds(gfx::Size content_bounds) {
917  if (this->content_bounds() == content_bounds)
918    return;
919
920  draw_properties_.content_bounds = content_bounds;
921  NoteLayerPropertyChanged();
922}
923
924void LayerImpl::SetContentsScale(float contents_scale_x,
925                                 float contents_scale_y) {
926  if (this->contents_scale_x() == contents_scale_x &&
927      this->contents_scale_y() == contents_scale_y)
928    return;
929
930  draw_properties_.contents_scale_x = contents_scale_x;
931  draw_properties_.contents_scale_y = contents_scale_y;
932  NoteLayerPropertyChanged();
933}
934
935void LayerImpl::CalculateContentsScale(
936    float ideal_contents_scale,
937    float device_scale_factor,
938    float page_scale_factor,
939    bool animating_transform_to_screen,
940    float* contents_scale_x,
941    float* contents_scale_y,
942    gfx::Size* content_bounds) {
943  // Base LayerImpl has all of its content scales and content bounds pushed
944  // from its Layer during commit and just reuses those values as-is.
945  *contents_scale_x = this->contents_scale_x();
946  *contents_scale_y = this->contents_scale_y();
947  *content_bounds = this->content_bounds();
948}
949
950void LayerImpl::UpdateScrollbarPositions() {
951  gfx::Vector2dF current_offset = scroll_offset_ + ScrollDelta();
952
953  gfx::RectF viewport(PointAtOffsetFromOrigin(current_offset), bounds_);
954  gfx::SizeF scrollable_size(max_scroll_offset_.x() + bounds_.width(),
955                             max_scroll_offset_.y() + bounds_.height());
956  if (horizontal_scrollbar_layer_) {
957    horizontal_scrollbar_layer_->SetCurrentPos(current_offset.x());
958    horizontal_scrollbar_layer_->SetMaximum(max_scroll_offset_.x());
959    horizontal_scrollbar_layer_->SetVisibleToTotalLengthRatio(
960        viewport.width() / scrollable_size.width());
961  }
962  if (vertical_scrollbar_layer_) {
963    vertical_scrollbar_layer_->SetCurrentPos(current_offset.y());
964    vertical_scrollbar_layer_->SetMaximum(max_scroll_offset_.y());
965    vertical_scrollbar_layer_->SetVisibleToTotalLengthRatio(
966        viewport.height() / scrollable_size.height());
967  }
968
969  if (current_offset == last_scroll_offset_)
970    return;
971  last_scroll_offset_ = current_offset;
972
973  if (scrollbar_animation_controller_) {
974    bool should_animate = scrollbar_animation_controller_->DidScrollUpdate(
975        layer_tree_impl_->CurrentPhysicalTimeTicks());
976    if (should_animate)
977      layer_tree_impl_->StartScrollbarAnimation();
978  }
979
980  // Get the current_offset_.y() value for a sanity-check on scrolling
981  // benchmark metrics. Specifically, we want to make sure
982  // BasicMouseWheelSmoothScrollGesture has proper scroll curves.
983  if (layer_tree_impl()->IsActiveTree()) {
984    TRACE_COUNTER_ID1("gpu", "scroll_offset_y", this->id(), current_offset.y());
985  }
986}
987
988void LayerImpl::SetScrollOffsetDelegate(
989    LayerScrollOffsetDelegate* scroll_offset_delegate) {
990  // Having both a scroll parent and a scroll offset delegate is unsupported.
991  DCHECK(!scroll_parent_);
992  if (!scroll_offset_delegate && scroll_offset_delegate_) {
993    scroll_delta_ =
994        scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_;
995  }
996  gfx::Vector2dF total_offset = TotalScrollOffset();
997  scroll_offset_delegate_ = scroll_offset_delegate;
998  if (scroll_offset_delegate_) {
999    scroll_offset_delegate_->SetMaxScrollOffset(max_scroll_offset_);
1000    scroll_offset_delegate_->SetTotalScrollOffset(total_offset);
1001  }
1002}
1003
1004bool LayerImpl::IsExternalFlingActive() const {
1005  return scroll_offset_delegate_ &&
1006         scroll_offset_delegate_->IsExternalFlingActive();
1007}
1008
1009void LayerImpl::SetScrollOffset(gfx::Vector2d scroll_offset) {
1010  SetScrollOffsetAndDelta(scroll_offset, ScrollDelta());
1011}
1012
1013void LayerImpl::SetScrollOffsetAndDelta(gfx::Vector2d scroll_offset,
1014                                        gfx::Vector2dF scroll_delta) {
1015  bool changed = false;
1016
1017  if (scroll_offset_ != scroll_offset) {
1018    changed = true;
1019    scroll_offset_ = scroll_offset;
1020
1021    if (scroll_offset_delegate_)
1022      scroll_offset_delegate_->SetTotalScrollOffset(TotalScrollOffset());
1023  }
1024
1025  if (ScrollDelta() != scroll_delta) {
1026    changed = true;
1027    if (layer_tree_impl()->IsActiveTree()) {
1028      LayerImpl* pending_twin =
1029          layer_tree_impl()->FindPendingTreeLayerById(id());
1030      if (pending_twin) {
1031        // The pending twin can't mirror the scroll delta of the active
1032        // layer.  Although the delta - sent scroll delta difference is
1033        // identical for both twins, the sent scroll delta for the pending
1034        // layer is zero, as anything that has been sent has been baked
1035        // into the layer's position/scroll offset as a part of commit.
1036        DCHECK(pending_twin->sent_scroll_delta().IsZero());
1037        pending_twin->SetScrollDelta(scroll_delta - sent_scroll_delta());
1038      }
1039    }
1040
1041    if (scroll_offset_delegate_) {
1042      scroll_offset_delegate_->SetTotalScrollOffset(scroll_offset_ +
1043                                                    scroll_delta);
1044    } else {
1045      scroll_delta_ = scroll_delta;
1046    }
1047  }
1048
1049  if (changed) {
1050    NoteLayerPropertyChangedForSubtree();
1051    UpdateScrollbarPositions();
1052  }
1053}
1054
1055gfx::Vector2dF LayerImpl::ScrollDelta() const {
1056  if (scroll_offset_delegate_)
1057    return scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_;
1058  return scroll_delta_;
1059}
1060
1061void LayerImpl::SetScrollDelta(gfx::Vector2dF scroll_delta) {
1062  SetScrollOffsetAndDelta(scroll_offset_, scroll_delta);
1063}
1064
1065gfx::Vector2dF LayerImpl::TotalScrollOffset() const {
1066  return scroll_offset_ + ScrollDelta();
1067}
1068
1069void LayerImpl::SetDoubleSided(bool double_sided) {
1070  if (double_sided_ == double_sided)
1071    return;
1072
1073  double_sided_ = double_sided;
1074  NoteLayerPropertyChangedForSubtree();
1075}
1076
1077Region LayerImpl::VisibleContentOpaqueRegion() const {
1078  if (contents_opaque())
1079    return visible_content_rect();
1080  return Region();
1081}
1082
1083void LayerImpl::DidBeginTracing() {}
1084
1085void LayerImpl::DidLoseOutputSurface() {}
1086
1087void LayerImpl::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) {
1088  if (max_scroll_offset_ == max_scroll_offset)
1089    return;
1090  max_scroll_offset_ = max_scroll_offset;
1091
1092  if (scroll_offset_delegate_)
1093    scroll_offset_delegate_->SetMaxScrollOffset(max_scroll_offset_);
1094
1095  layer_tree_impl()->set_needs_update_draw_properties();
1096  UpdateScrollbarPositions();
1097}
1098
1099void LayerImpl::DidBecomeActive() {
1100  if (layer_tree_impl_->settings().scrollbar_animator ==
1101      LayerTreeSettings::NoAnimator) {
1102    return;
1103  }
1104
1105  bool need_scrollbar_animation_controller = horizontal_scrollbar_layer_ ||
1106                                             vertical_scrollbar_layer_;
1107  if (!need_scrollbar_animation_controller) {
1108    scrollbar_animation_controller_.reset();
1109    return;
1110  }
1111
1112  if (scrollbar_animation_controller_)
1113    return;
1114
1115  switch (layer_tree_impl_->settings().scrollbar_animator) {
1116  case LayerTreeSettings::LinearFade: {
1117    base::TimeDelta fadeout_delay = base::TimeDelta::FromMilliseconds(
1118        layer_tree_impl_->settings().scrollbar_linear_fade_delay_ms);
1119    base::TimeDelta fadeout_length = base::TimeDelta::FromMilliseconds(
1120        layer_tree_impl_->settings().scrollbar_linear_fade_length_ms);
1121
1122    scrollbar_animation_controller_ =
1123        ScrollbarAnimationControllerLinearFade::Create(
1124            this, fadeout_delay, fadeout_length)
1125            .PassAs<ScrollbarAnimationController>();
1126    break;
1127  }
1128  case LayerTreeSettings::Thinning: {
1129    scrollbar_animation_controller_ =
1130        ScrollbarAnimationControllerThinning::Create(this)
1131            .PassAs<ScrollbarAnimationController>();
1132    break;
1133  }
1134  case LayerTreeSettings::NoAnimator:
1135    NOTREACHED();
1136    break;
1137  }
1138}
1139void LayerImpl::SetHorizontalScrollbarLayer(
1140    ScrollbarLayerImplBase* scrollbar_layer) {
1141  horizontal_scrollbar_layer_ = scrollbar_layer;
1142  if (horizontal_scrollbar_layer_)
1143    horizontal_scrollbar_layer_->set_scroll_layer_id(id());
1144}
1145
1146void LayerImpl::SetVerticalScrollbarLayer(
1147    ScrollbarLayerImplBase* scrollbar_layer) {
1148  vertical_scrollbar_layer_ = scrollbar_layer;
1149  if (vertical_scrollbar_layer_)
1150    vertical_scrollbar_layer_->set_scroll_layer_id(id());
1151}
1152
1153static scoped_ptr<base::Value>
1154CompositingReasonsAsValue(CompositingReasons reasons) {
1155  scoped_ptr<base::ListValue> reason_list(new base::ListValue());
1156
1157  if (reasons == kCompositingReasonUnknown) {
1158    reason_list->AppendString("No reasons given");
1159    return reason_list.PassAs<base::Value>();
1160  }
1161
1162  if (reasons & kCompositingReason3DTransform)
1163    reason_list->AppendString("Has a 3d Transform");
1164
1165  if (reasons & kCompositingReasonVideo)
1166    reason_list->AppendString("Is accelerated video");
1167
1168  if (reasons & kCompositingReasonCanvas)
1169    reason_list->AppendString("Is accelerated canvas");
1170
1171  if (reasons & kCompositingReasonPlugin)
1172    reason_list->AppendString("Is accelerated plugin");
1173
1174  if (reasons & kCompositingReasonIFrame)
1175    reason_list->AppendString("Is accelerated iframe");
1176
1177  if (reasons & kCompositingReasonBackfaceVisibilityHidden)
1178    reason_list->AppendString("Has backface-visibility: hidden");
1179
1180  if (reasons & kCompositingReasonAnimation)
1181    reason_list->AppendString("Has accelerated animation or transition");
1182
1183  if (reasons & kCompositingReasonFilters)
1184    reason_list->AppendString("Has accelerated filters");
1185
1186  if (reasons & kCompositingReasonPositionFixed)
1187    reason_list->AppendString("Is fixed position");
1188
1189  if (reasons & kCompositingReasonPositionSticky)
1190    reason_list->AppendString("Is sticky position");
1191
1192  if (reasons & kCompositingReasonOverflowScrollingTouch)
1193    reason_list->AppendString("Is a scrollable overflow element");
1194
1195  if (reasons & kCompositingReasonAssumedOverlap)
1196    reason_list->AppendString("Might overlap a composited animation");
1197
1198  if (reasons & kCompositingReasonOverlap)
1199    reason_list->AppendString("Overlaps other composited content");
1200
1201  if (reasons & kCompositingReasonNegativeZIndexChildren) {
1202    reason_list->AppendString("Might overlap negative z-index "
1203                              "composited content");
1204  }
1205
1206  if (reasons & kCompositingReasonTransformWithCompositedDescendants) {
1207    reason_list->AppendString("Has transform needed by a "
1208                              "composited descendant");
1209  }
1210
1211  if (reasons & kCompositingReasonOpacityWithCompositedDescendants)
1212    reason_list->AppendString("Has opacity needed by a composited descendant");
1213
1214  if (reasons & kCompositingReasonMaskWithCompositedDescendants)
1215    reason_list->AppendString("Has a mask needed by a composited descendant");
1216
1217  if (reasons & kCompositingReasonReflectionWithCompositedDescendants)
1218    reason_list->AppendString("Has a reflection with a composited descendant");
1219
1220  if (reasons & kCompositingReasonFilterWithCompositedDescendants)
1221    reason_list->AppendString("Has filter effect with a composited descendant");
1222
1223  if (reasons & kCompositingReasonBlendingWithCompositedDescendants)
1224    reason_list->AppendString("Has a blend mode with a composited descendant");
1225
1226  if (reasons & kCompositingReasonClipsCompositingDescendants)
1227    reason_list->AppendString("Clips a composited descendant");
1228
1229  if (reasons & kCompositingReasonPerspective) {
1230    reason_list->AppendString("Has a perspective transform needed by a "
1231                              "composited 3d descendant");
1232  }
1233
1234  if (reasons & kCompositingReasonPreserve3D) {
1235    reason_list->AppendString("Has preserves-3d style with composited "
1236                              "3d descendant");
1237  }
1238
1239  if (reasons & kCompositingReasonReflectionOfCompositedParent)
1240    reason_list->AppendString("Is the reflection of a composited layer");
1241
1242  if (reasons & kCompositingReasonRoot)
1243    reason_list->AppendString("Is the root");
1244
1245  if (reasons & kCompositingReasonLayerForClip)
1246    reason_list->AppendString("Convenience layer, to clip subtree");
1247
1248  if (reasons & kCompositingReasonLayerForScrollbar)
1249    reason_list->AppendString("Convenience layer for rendering scrollbar");
1250
1251  if (reasons & kCompositingReasonLayerForScrollingContainer)
1252    reason_list->AppendString("Convenience layer, the scrolling container");
1253
1254  if (reasons & kCompositingReasonLayerForForeground) {
1255    reason_list->AppendString("Convenience layer, foreground when main layer "
1256                              "has negative z-index composited content");
1257  }
1258
1259  if (reasons & kCompositingReasonLayerForBackground) {
1260    reason_list->AppendString("Convenience layer, background when main layer "
1261                              "has a composited background");
1262  }
1263
1264  if (reasons & kCompositingReasonLayerForMask)
1265    reason_list->AppendString("Is a mask layer");
1266
1267  if (reasons & kCompositingReasonOverflowScrollingParent)
1268    reason_list->AppendString("Scroll parent is not an ancestor");
1269
1270  if (reasons & kCompositingReasonOutOfFlowClipping)
1271    reason_list->AppendString("Has clipping ancestor");
1272
1273  return reason_list.PassAs<base::Value>();
1274}
1275
1276void LayerImpl::AsValueInto(base::DictionaryValue* state) const {
1277  TracedValue::MakeDictIntoImplicitSnapshot(state, LayerTypeAsString(), this);
1278  state->SetInteger("layer_id", id());
1279  state->SetString("layer_name", debug_name());
1280  state->Set("bounds", MathUtil::AsValue(bounds()).release());
1281  state->SetInteger("draws_content", DrawsContent());
1282  state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes());
1283  state->Set("compositing_reasons",
1284             CompositingReasonsAsValue(compositing_reasons_).release());
1285
1286  bool clipped;
1287  gfx::QuadF layer_quad = MathUtil::MapQuad(
1288      screen_space_transform(),
1289      gfx::QuadF(gfx::Rect(content_bounds())),
1290      &clipped);
1291  state->Set("layer_quad", MathUtil::AsValue(layer_quad).release());
1292
1293  if (!touch_event_handler_region_.IsEmpty()) {
1294    state->Set("touch_event_handler_region",
1295               touch_event_handler_region_.AsValue().release());
1296  }
1297  if (have_wheel_event_handlers_) {
1298    gfx::Rect wheel_rect(content_bounds());
1299    Region wheel_region(wheel_rect);
1300    state->Set("wheel_event_handler_region",
1301               wheel_region.AsValue().release());
1302  }
1303  if (!non_fast_scrollable_region_.IsEmpty()) {
1304    state->Set("non_fast_scrollable_region",
1305               non_fast_scrollable_region_.AsValue().release());
1306  }
1307
1308  scoped_ptr<base::ListValue> children_list(new base::ListValue());
1309  for (size_t i = 0; i < children_.size(); ++i)
1310    children_list->Append(children_[i]->AsValue().release());
1311  state->Set("children", children_list.release());
1312  if (mask_layer_)
1313    state->Set("mask_layer", mask_layer_->AsValue().release());
1314  if (replica_layer_)
1315    state->Set("replica_layer", replica_layer_->AsValue().release());
1316
1317  if (scroll_parent_)
1318    state->SetInteger("scroll_parent", scroll_parent_->id());
1319
1320  if (clip_parent_)
1321    state->SetInteger("clip_parent", clip_parent_->id());
1322
1323  state->SetBoolean("can_use_lcd_text", can_use_lcd_text());
1324  state->SetBoolean("contents_opaque", contents_opaque());
1325}
1326
1327size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; }
1328
1329scoped_ptr<base::Value> LayerImpl::AsValue() const {
1330  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1331  AsValueInto(state.get());
1332  return state.PassAs<base::Value>();
1333}
1334
1335}  // namespace cc
1336