layer_impl.cc revision fb250657ef40d7500f20882d5c9909c1013367d3
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/base/math_util.h"
13#include "cc/debug/debug_colors.h"
14#include "cc/debug/layer_tree_debug_state.h"
15#include "cc/debug/traced_value.h"
16#include "cc/input/layer_scroll_offset_delegate.h"
17#include "cc/layers/quad_sink.h"
18#include "cc/layers/scrollbar_layer_impl.h"
19#include "cc/output/copy_output_request.h"
20#include "cc/quads/debug_border_draw_quad.h"
21#include "cc/trees/layer_tree_impl.h"
22#include "cc/trees/layer_tree_settings.h"
23#include "cc/trees/proxy.h"
24#include "ui/gfx/point_conversions.h"
25#include "ui/gfx/quad_f.h"
26#include "ui/gfx/rect_conversions.h"
27
28namespace cc {
29
30LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
31    : parent_(NULL),
32      mask_layer_id_(-1),
33      replica_layer_id_(-1),
34      layer_id_(id),
35      layer_tree_impl_(tree_impl),
36      anchor_point_(0.5f, 0.5f),
37      anchor_point_z_(0.f),
38      scroll_offset_delegate_(NULL),
39      scrollable_(false),
40      should_scroll_on_main_thread_(false),
41      have_wheel_event_handlers_(false),
42      background_color_(0),
43      stacking_order_changed_(false),
44      double_sided_(true),
45      layer_property_changed_(false),
46      layer_surface_property_changed_(false),
47      masks_to_bounds_(false),
48      contents_opaque_(false),
49      opacity_(1.0),
50      preserves_3d_(false),
51      use_parent_backface_visibility_(false),
52      draw_checkerboard_for_missing_tiles_(false),
53      draws_content_(false),
54      hide_layer_and_subtree_(false),
55      force_render_surface_(false),
56      is_container_for_fixed_position_layers_(false),
57      draw_depth_(0.f),
58      compositing_reasons_(kCompositingReasonUnknown),
59      current_draw_mode_(DRAW_MODE_NONE),
60      horizontal_scrollbar_layer_(NULL),
61      vertical_scrollbar_layer_(NULL) {
62  DCHECK_GT(layer_id_, 0);
63  DCHECK(layer_tree_impl_);
64  layer_tree_impl_->RegisterLayer(this);
65  AnimationRegistrar* registrar = layer_tree_impl_->animationRegistrar();
66  layer_animation_controller_ =
67      registrar->GetAnimationControllerForId(layer_id_);
68  layer_animation_controller_->AddValueObserver(this);
69}
70
71LayerImpl::~LayerImpl() {
72  DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
73
74  layer_tree_impl_->UnregisterLayer(this);
75  layer_animation_controller_->RemoveValueObserver(this);
76}
77
78void LayerImpl::AddChild(scoped_ptr<LayerImpl> child) {
79  child->set_parent(this);
80  DCHECK_EQ(layer_tree_impl(), child->layer_tree_impl());
81  children_.push_back(child.Pass());
82  layer_tree_impl()->set_needs_update_draw_properties();
83}
84
85scoped_ptr<LayerImpl> LayerImpl::RemoveChild(LayerImpl* child) {
86  for (OwnedLayerImplList::iterator it = children_.begin();
87       it != children_.end();
88       ++it) {
89    if (*it == child) {
90      scoped_ptr<LayerImpl> ret = children_.take(it);
91      children_.erase(it);
92      layer_tree_impl()->set_needs_update_draw_properties();
93      return ret.Pass();
94    }
95  }
96  return scoped_ptr<LayerImpl>();
97}
98
99void LayerImpl::ClearChildList() {
100  if (children_.empty())
101    return;
102
103  children_.clear();
104  layer_tree_impl()->set_needs_update_draw_properties();
105}
106
107void LayerImpl::PassCopyRequests(ScopedPtrVector<CopyOutputRequest>* requests) {
108  if (requests->empty())
109    return;
110
111  bool was_empty = copy_requests_.empty();
112  copy_requests_.insert_and_take(copy_requests_.end(), *requests);
113  requests->clear();
114
115  if (was_empty && layer_tree_impl()->IsActiveTree())
116    layer_tree_impl()->AddLayerWithCopyOutputRequest(this);
117  NoteLayerPropertyChangedForSubtree();
118}
119
120void LayerImpl::TakeCopyRequestsAndTransformToTarget(
121    ScopedPtrVector<CopyOutputRequest>* requests) {
122  if (copy_requests_.empty())
123    return;
124
125  size_t first_inserted_request = requests->size();
126  requests->insert_and_take(requests->end(), copy_requests_);
127  copy_requests_.clear();
128
129  for (size_t i = first_inserted_request; i < requests->size(); ++i) {
130    CopyOutputRequest* request = requests->at(i);
131    if (!request->has_area())
132      continue;
133
134    gfx::Rect request_in_layer_space = request->area();
135    gfx::Rect request_in_content_space =
136        LayerRectToContentRect(request_in_layer_space);
137    request->set_area(
138        MathUtil::MapClippedRect(draw_properties_.target_space_transform,
139                                 request_in_content_space));
140  }
141
142  if (layer_tree_impl()->IsActiveTree())
143    layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
144}
145
146void LayerImpl::CreateRenderSurface() {
147  DCHECK(!draw_properties_.render_surface);
148  draw_properties_.render_surface =
149      make_scoped_ptr(new RenderSurfaceImpl(this));
150  draw_properties_.render_target = this;
151}
152
153void LayerImpl::ClearRenderSurface() {
154  draw_properties_.render_surface.reset();
155}
156
157scoped_ptr<SharedQuadState> LayerImpl::CreateSharedQuadState() const {
158  scoped_ptr<SharedQuadState> state = SharedQuadState::Create();
159  state->SetAll(draw_properties_.target_space_transform,
160                draw_properties_.content_bounds,
161                draw_properties_.visible_content_rect,
162                draw_properties_.clip_rect,
163                draw_properties_.is_clipped,
164                draw_properties_.opacity);
165  return state.Pass();
166}
167
168bool LayerImpl::WillDraw(DrawMode draw_mode,
169                         ResourceProvider* resource_provider) {
170  // WillDraw/DidDraw must be matched.
171  DCHECK_NE(DRAW_MODE_NONE, draw_mode);
172  DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
173  current_draw_mode_ = draw_mode;
174  return true;
175}
176
177void LayerImpl::DidDraw(ResourceProvider* resource_provider) {
178  DCHECK_NE(DRAW_MODE_NONE, current_draw_mode_);
179  current_draw_mode_ = DRAW_MODE_NONE;
180}
181
182bool LayerImpl::ShowDebugBorders() const {
183  return layer_tree_impl()->debug_state().show_debug_borders;
184}
185
186void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const {
187  if (draws_content_) {
188    *color = DebugColors::ContentLayerBorderColor();
189    *width = DebugColors::ContentLayerBorderWidth(layer_tree_impl());
190    return;
191  }
192
193  if (masks_to_bounds_) {
194    *color = DebugColors::MaskingLayerBorderColor();
195    *width = DebugColors::MaskingLayerBorderWidth(layer_tree_impl());
196    return;
197  }
198
199  *color = DebugColors::ContainerLayerBorderColor();
200  *width = DebugColors::ContainerLayerBorderWidth(layer_tree_impl());
201}
202
203void LayerImpl::AppendDebugBorderQuad(
204    QuadSink* quad_sink,
205    const SharedQuadState* shared_quad_state,
206    AppendQuadsData* append_quads_data) const {
207  SkColor color;
208  float width;
209  GetDebugBorderProperties(&color, &width);
210  AppendDebugBorderQuad(
211      quad_sink, shared_quad_state, append_quads_data, color, width);
212}
213
214void LayerImpl::AppendDebugBorderQuad(QuadSink* quad_sink,
215                                      const SharedQuadState* shared_quad_state,
216                                      AppendQuadsData* append_quads_data,
217                                      SkColor color,
218                                      float width) const {
219  if (!ShowDebugBorders())
220    return;
221
222  gfx::Rect content_rect(content_bounds());
223  scoped_ptr<DebugBorderDrawQuad> debug_border_quad =
224      DebugBorderDrawQuad::Create();
225  debug_border_quad->SetNew(shared_quad_state, content_rect, color, width);
226  quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), append_quads_data);
227}
228
229bool LayerImpl::HasDelegatedContent() const {
230  return false;
231}
232
233bool LayerImpl::HasContributingDelegatedRenderPasses() const {
234  return false;
235}
236
237RenderPass::Id LayerImpl::FirstContributingRenderPassId() const {
238  return RenderPass::Id(0, 0);
239}
240
241RenderPass::Id LayerImpl::NextContributingRenderPassId(RenderPass::Id id)
242    const {
243  return RenderPass::Id(0, 0);
244}
245
246ResourceProvider::ResourceId LayerImpl::ContentsResourceId() const {
247  NOTREACHED();
248  return 0;
249}
250
251void LayerImpl::SetSentScrollDelta(gfx::Vector2d sent_scroll_delta) {
252  // Pending tree never has sent scroll deltas
253  DCHECK(layer_tree_impl()->IsActiveTree());
254
255  if (sent_scroll_delta_ == sent_scroll_delta)
256    return;
257
258  sent_scroll_delta_ = sent_scroll_delta;
259}
260
261gfx::Vector2dF LayerImpl::ScrollBy(gfx::Vector2dF scroll) {
262  gfx::Vector2dF min_delta = -scroll_offset_;
263  gfx::Vector2dF max_delta = max_scroll_offset_ - scroll_offset_;
264  // Clamp new_delta so that position + delta stays within scroll bounds.
265  gfx::Vector2dF new_delta = (ScrollDelta() + scroll);
266  new_delta.SetToMax(min_delta);
267  new_delta.SetToMin(max_delta);
268  gfx::Vector2dF unscrolled = ScrollDelta() + scroll - new_delta;
269  SetScrollDelta(new_delta);
270  return unscrolled;
271}
272
273void LayerImpl::ApplySentScrollDeltas() {
274  // Pending tree never has sent scroll deltas
275  DCHECK(layer_tree_impl()->IsActiveTree());
276
277  // Apply sent scroll deltas to scroll position / scroll delta as if the
278  // main thread had applied them and then committed those values.
279  //
280  // This function should not change the total scroll offset; it just shifts
281  // some of the scroll delta to the scroll offset.  Therefore, adjust these
282  // variables directly rather than calling the scroll offset delegate to
283  // avoid sending it multiple spurious calls.
284  //
285  // Because of the way scroll delta is calculated with a delegate, this will
286  // leave the total scroll offset unchanged on this layer regardless of
287  // whether a delegate is being used.
288  scroll_offset_ += sent_scroll_delta_;
289  scroll_delta_ -= sent_scroll_delta_;
290  sent_scroll_delta_ = gfx::Vector2d();
291}
292
293InputHandler::ScrollStatus LayerImpl::TryScroll(
294    gfx::PointF screen_space_point,
295    InputHandler::ScrollInputType type) const {
296  if (should_scroll_on_main_thread()) {
297    TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
298    return InputHandler::ScrollOnMainThread;
299  }
300
301  if (!screen_space_transform().IsInvertible()) {
302    TRACE_EVENT0("cc", "LayerImpl::TryScroll: Ignored NonInvertibleTransform");
303    return InputHandler::ScrollIgnored;
304  }
305
306  if (!non_fast_scrollable_region().IsEmpty()) {
307    bool clipped = false;
308    gfx::Transform inverse_screen_space_transform(
309        gfx::Transform::kSkipInitialization);
310    if (!screen_space_transform().GetInverse(&inverse_screen_space_transform)) {
311      // TODO(shawnsingh): We shouldn't be applying a projection if screen space
312      // transform is uninvertible here. Perhaps we should be returning
313      // ScrollOnMainThread in this case?
314    }
315
316    gfx::PointF hit_test_point_in_content_space =
317        MathUtil::ProjectPoint(inverse_screen_space_transform,
318                               screen_space_point,
319                               &clipped);
320    gfx::PointF hit_test_point_in_layer_space =
321        gfx::ScalePoint(hit_test_point_in_content_space,
322                        1.f / contents_scale_x(),
323                        1.f / contents_scale_y());
324    if (!clipped &&
325        non_fast_scrollable_region().Contains(
326            gfx::ToRoundedPoint(hit_test_point_in_layer_space))) {
327      TRACE_EVENT0("cc",
328                   "LayerImpl::tryScroll: Failed NonFastScrollableRegion");
329      return InputHandler::ScrollOnMainThread;
330    }
331  }
332
333  if (type == InputHandler::Wheel && have_wheel_event_handlers()) {
334    TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers");
335    return InputHandler::ScrollOnMainThread;
336  }
337
338  if (!scrollable()) {
339    TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable");
340    return InputHandler::ScrollIgnored;
341  }
342
343  if (max_scroll_offset_.x() <= 0 && max_scroll_offset_.y() <= 0) {
344    TRACE_EVENT0("cc",
345                 "LayerImpl::tryScroll: Ignored. Technically scrollable,"
346                 " but has no affordance in either direction.");
347    return InputHandler::ScrollIgnored;
348  }
349
350  return InputHandler::ScrollStarted;
351}
352
353bool LayerImpl::DrawCheckerboardForMissingTiles() const {
354  return draw_checkerboard_for_missing_tiles_ &&
355      !layer_tree_impl()->settings().background_color_instead_of_checkerboard;
356}
357
358gfx::Rect LayerImpl::LayerRectToContentRect(
359    const gfx::RectF& layer_rect) const {
360  gfx::RectF content_rect =
361      gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y());
362  // Intersect with content rect to avoid the extra pixel because for some
363  // values x and y, ceil((x / y) * y) may be x + 1.
364  content_rect.Intersect(gfx::Rect(content_bounds()));
365  return gfx::ToEnclosingRect(content_rect);
366}
367
368skia::RefPtr<SkPicture> LayerImpl::GetPicture() {
369  return skia::RefPtr<SkPicture>();
370}
371
372bool LayerImpl::CanClipSelf() const {
373  return false;
374}
375
376bool LayerImpl::AreVisibleResourcesReady() const {
377  return true;
378}
379
380scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) {
381  return LayerImpl::Create(tree_impl, layer_id_);
382}
383
384void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
385  layer->SetAnchorPoint(anchor_point_);
386  layer->SetAnchorPointZ(anchor_point_z_);
387  layer->SetBackgroundColor(background_color_);
388  layer->SetBounds(bounds_);
389  layer->SetContentBounds(content_bounds());
390  layer->SetContentsScale(contents_scale_x(), contents_scale_y());
391  layer->SetDebugName(debug_name_);
392  layer->SetCompositingReasons(compositing_reasons_);
393  layer->SetDoubleSided(double_sided_);
394  layer->SetDrawCheckerboardForMissingTiles(
395      draw_checkerboard_for_missing_tiles_);
396  layer->SetForceRenderSurface(force_render_surface_);
397  layer->SetDrawsContent(DrawsContent());
398  layer->SetHideLayerAndSubtree(hide_layer_and_subtree_);
399  layer->SetFilters(filters());
400  layer->SetFilter(filter());
401  layer->SetBackgroundFilters(background_filters());
402  layer->SetMasksToBounds(masks_to_bounds_);
403  layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
404  layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
405  layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
406  layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
407  layer->SetContentsOpaque(contents_opaque_);
408  layer->SetOpacity(opacity_);
409  layer->SetPosition(position_);
410  layer->SetIsContainerForFixedPositionLayers(
411      is_container_for_fixed_position_layers_);
412  layer->SetFixedContainerSizeDelta(fixed_container_size_delta_);
413  layer->SetPositionConstraint(position_constraint_);
414  layer->SetPreserves3d(preserves_3d());
415  layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
416  layer->SetSublayerTransform(sublayer_transform_);
417  layer->SetTransform(transform_);
418
419  layer->SetScrollable(scrollable_);
420  layer->SetScrollOffset(scroll_offset_);
421  layer->SetMaxScrollOffset(max_scroll_offset_);
422
423  layer->PassCopyRequests(&copy_requests_);
424
425  // If the main thread commits multiple times before the impl thread actually
426  // draws, then damage tracking will become incorrect if we simply clobber the
427  // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
428  // union) any update changes that have occurred on the main thread.
429  update_rect_.Union(layer->update_rect());
430  layer->set_update_rect(update_rect_);
431
432  layer->SetScrollDelta(layer->ScrollDelta() - layer->sent_scroll_delta());
433  layer->SetSentScrollDelta(gfx::Vector2d());
434
435  layer->SetStackingOrderChanged(stacking_order_changed_);
436
437  // Reset any state that should be cleared for the next update.
438  stacking_order_changed_ = false;
439  update_rect_ = gfx::RectF();
440}
441
442base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
443  base::DictionaryValue* result = new base::DictionaryValue;
444  result->SetString("LayerType", LayerTypeAsString());
445
446  base::ListValue* list = new base::ListValue;
447  list->AppendInteger(bounds().width());
448  list->AppendInteger(bounds().height());
449  result->Set("Bounds", list);
450
451  list = new base::ListValue;
452  list->AppendDouble(position_.x());
453  list->AppendDouble(position_.y());
454  result->Set("Position", list);
455
456  const gfx::Transform& gfx_transform = draw_properties_.target_space_transform;
457  double transform[16];
458  gfx_transform.matrix().asColMajord(transform);
459  list = new base::ListValue;
460  for (int i = 0; i < 16; ++i)
461    list->AppendDouble(transform[i]);
462  result->Set("DrawTransform", list);
463
464  result->SetBoolean("DrawsContent", draws_content_);
465  result->SetDouble("Opacity", opacity());
466  result->SetBoolean("ContentsOpaque", contents_opaque_);
467
468  if (scrollable_)
469    result->SetBoolean("Scrollable", scrollable_);
470
471  list = new base::ListValue;
472  for (size_t i = 0; i < children_.size(); ++i)
473    list->Append(children_[i]->LayerTreeAsJson());
474  result->Set("Children", list);
475
476  return result;
477}
478
479void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) {
480  if (stacking_order_changed) {
481    stacking_order_changed_ = true;
482    NoteLayerPropertyChangedForSubtree();
483  }
484}
485
486bool LayerImpl::LayerSurfacePropertyChanged() const {
487  if (layer_surface_property_changed_)
488    return true;
489
490  // If this layer's surface property hasn't changed, we want to see if
491  // some layer above us has changed this property. This is done for the
492  // case when such parent layer does not draw content, and therefore will
493  // not be traversed by the damage tracker. We need to make sure that
494  // property change on such layer will be caught by its descendants.
495  LayerImpl* current = this->parent_;
496  while (current && !current->draw_properties_.render_surface) {
497    if (current->layer_surface_property_changed_)
498      return true;
499    current = current->parent_;
500  }
501
502  return false;
503}
504
505void LayerImpl::NoteLayerSurfacePropertyChanged() {
506  layer_surface_property_changed_ = true;
507  layer_tree_impl()->set_needs_update_draw_properties();
508}
509
510void LayerImpl::NoteLayerPropertyChanged() {
511  layer_property_changed_ = true;
512  layer_tree_impl()->set_needs_update_draw_properties();
513}
514
515void LayerImpl::NoteLayerPropertyChangedForSubtree() {
516  NoteLayerPropertyChanged();
517  NoteLayerPropertyChangedForDescendants();
518}
519
520void LayerImpl::NoteLayerPropertyChangedForDescendants() {
521  layer_tree_impl()->set_needs_update_draw_properties();
522  for (size_t i = 0; i < children_.size(); ++i)
523    children_[i]->NoteLayerPropertyChangedForSubtree();
524}
525
526const char* LayerImpl::LayerTypeAsString() const {
527  return "cc::LayerImpl";
528}
529
530void LayerImpl::ResetAllChangeTrackingForSubtree() {
531  layer_property_changed_ = false;
532  layer_surface_property_changed_ = false;
533
534  update_rect_ = gfx::RectF();
535
536  if (draw_properties_.render_surface)
537    draw_properties_.render_surface->ResetPropertyChangedFlag();
538
539  if (mask_layer_)
540    mask_layer_->ResetAllChangeTrackingForSubtree();
541
542  if (replica_layer_) {
543    // This also resets the replica mask, if it exists.
544    replica_layer_->ResetAllChangeTrackingForSubtree();
545  }
546
547  for (size_t i = 0; i < children_.size(); ++i)
548    children_[i]->ResetAllChangeTrackingForSubtree();
549}
550
551bool LayerImpl::LayerIsAlwaysDamaged() const {
552  return false;
553}
554
555void LayerImpl::OnOpacityAnimated(float opacity) {
556  SetOpacity(opacity);
557}
558
559void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) {
560  SetTransform(transform);
561}
562
563bool LayerImpl::IsActive() const {
564  return layer_tree_impl_->IsActiveTree();
565}
566
567void LayerImpl::SetBounds(gfx::Size bounds) {
568  if (bounds_ == bounds)
569    return;
570
571  bounds_ = bounds;
572
573  if (masks_to_bounds())
574    NoteLayerPropertyChangedForSubtree();
575  else
576    NoteLayerPropertyChanged();
577}
578
579void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) {
580  int new_layer_id = mask_layer ? mask_layer->id() : -1;
581
582  if (mask_layer) {
583    DCHECK_EQ(layer_tree_impl(), mask_layer->layer_tree_impl());
584    DCHECK_NE(new_layer_id, mask_layer_id_);
585  } else if (new_layer_id == mask_layer_id_) {
586    return;
587  }
588
589  mask_layer_ = mask_layer.Pass();
590  mask_layer_id_ = new_layer_id;
591  if (mask_layer_)
592    mask_layer_->set_parent(this);
593  NoteLayerPropertyChangedForSubtree();
594}
595
596scoped_ptr<LayerImpl> LayerImpl::TakeMaskLayer() {
597  mask_layer_id_ = -1;
598  return mask_layer_.Pass();
599}
600
601void LayerImpl::SetReplicaLayer(scoped_ptr<LayerImpl> replica_layer) {
602  int new_layer_id = replica_layer ? replica_layer->id() : -1;
603
604  if (replica_layer) {
605    DCHECK_EQ(layer_tree_impl(), replica_layer->layer_tree_impl());
606    DCHECK_NE(new_layer_id, replica_layer_id_);
607  } else if (new_layer_id == replica_layer_id_) {
608    return;
609  }
610
611  replica_layer_ = replica_layer.Pass();
612  replica_layer_id_ = new_layer_id;
613  if (replica_layer_)
614    replica_layer_->set_parent(this);
615  NoteLayerPropertyChangedForSubtree();
616}
617
618scoped_ptr<LayerImpl> LayerImpl::TakeReplicaLayer() {
619  replica_layer_id_ = -1;
620  return replica_layer_.Pass();
621}
622
623ScrollbarLayerImpl* LayerImpl::ToScrollbarLayer() {
624  return NULL;
625}
626
627void LayerImpl::SetDrawsContent(bool draws_content) {
628  if (draws_content_ == draws_content)
629    return;
630
631  draws_content_ = draws_content;
632  NoteLayerPropertyChanged();
633}
634
635void LayerImpl::SetHideLayerAndSubtree(bool hide) {
636  if (hide_layer_and_subtree_ == hide)
637    return;
638
639  hide_layer_and_subtree_ = hide;
640  NoteLayerPropertyChangedForSubtree();
641}
642
643void LayerImpl::SetAnchorPoint(gfx::PointF anchor_point) {
644  if (anchor_point_ == anchor_point)
645    return;
646
647  anchor_point_ = anchor_point;
648  NoteLayerPropertyChangedForSubtree();
649}
650
651void LayerImpl::SetAnchorPointZ(float anchor_point_z) {
652  if (anchor_point_z_ == anchor_point_z)
653    return;
654
655  anchor_point_z_ = anchor_point_z;
656  NoteLayerPropertyChangedForSubtree();
657}
658
659void LayerImpl::SetBackgroundColor(SkColor background_color) {
660  if (background_color_ == background_color)
661    return;
662
663  background_color_ = background_color;
664  NoteLayerPropertyChanged();
665}
666
667SkColor LayerImpl::SafeOpaqueBackgroundColor() const {
668  SkColor color = background_color();
669  if (SkColorGetA(color) == 255 && !contents_opaque()) {
670    color = SK_ColorTRANSPARENT;
671  } else if (SkColorGetA(color) != 255 && contents_opaque()) {
672    for (const LayerImpl* layer = parent(); layer;
673         layer = layer->parent()) {
674      color = layer->background_color();
675      if (SkColorGetA(color) == 255)
676        break;
677    }
678    if (SkColorGetA(color) != 255)
679      color = layer_tree_impl()->background_color();
680    if (SkColorGetA(color) != 255)
681      color = SkColorSetA(color, 255);
682  }
683  return color;
684}
685
686void LayerImpl::SetFilters(const FilterOperations& filters) {
687  if (filters_ == filters)
688    return;
689
690  DCHECK(!filter_);
691  filters_ = filters;
692  NoteLayerPropertyChangedForSubtree();
693}
694
695void LayerImpl::SetBackgroundFilters(
696    const FilterOperations& filters) {
697  if (background_filters_ == filters)
698    return;
699
700  background_filters_ = filters;
701  NoteLayerPropertyChanged();
702}
703
704void LayerImpl::SetFilter(const skia::RefPtr<SkImageFilter>& filter) {
705  if (filter_.get() == filter.get())
706    return;
707
708  DCHECK(filters_.IsEmpty());
709  filter_ = filter;
710  NoteLayerPropertyChangedForSubtree();
711}
712
713void LayerImpl::SetMasksToBounds(bool masks_to_bounds) {
714  if (masks_to_bounds_ == masks_to_bounds)
715    return;
716
717  masks_to_bounds_ = masks_to_bounds;
718  NoteLayerPropertyChangedForSubtree();
719}
720
721void LayerImpl::SetContentsOpaque(bool opaque) {
722  if (contents_opaque_ == opaque)
723    return;
724
725  contents_opaque_ = opaque;
726  NoteLayerPropertyChangedForSubtree();
727}
728
729void LayerImpl::SetOpacity(float opacity) {
730  if (opacity_ == opacity)
731    return;
732
733  opacity_ = opacity;
734  NoteLayerSurfacePropertyChanged();
735}
736
737bool LayerImpl::OpacityIsAnimating() const {
738  return layer_animation_controller_->IsAnimatingProperty(Animation::Opacity);
739}
740
741bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
742  Animation* opacity_animation =
743      layer_animation_controller_->GetAnimation(Animation::Opacity);
744  return opacity_animation && opacity_animation->is_impl_only();
745}
746
747void LayerImpl::SetPosition(gfx::PointF position) {
748  if (position_ == position)
749    return;
750
751  position_ = position;
752  NoteLayerPropertyChangedForSubtree();
753}
754
755void LayerImpl::SetPreserves3d(bool preserves3_d) {
756  if (preserves_3d_ == preserves3_d)
757    return;
758
759  preserves_3d_ = preserves3_d;
760  NoteLayerPropertyChangedForSubtree();
761}
762
763void LayerImpl::SetSublayerTransform(const gfx::Transform& sublayer_transform) {
764  if (sublayer_transform_ == sublayer_transform)
765    return;
766
767  sublayer_transform_ = sublayer_transform;
768  // Sublayer transform does not affect the current layer; it affects only its
769  // children.
770  NoteLayerPropertyChangedForDescendants();
771}
772
773void LayerImpl::SetTransform(const gfx::Transform& transform) {
774  if (transform_ == transform)
775    return;
776
777  transform_ = transform;
778  NoteLayerSurfacePropertyChanged();
779}
780
781bool LayerImpl::TransformIsAnimating() const {
782  return layer_animation_controller_->IsAnimatingProperty(Animation::Transform);
783}
784
785bool LayerImpl::TransformIsAnimatingOnImplOnly() const {
786  Animation* transform_animation =
787      layer_animation_controller_->GetAnimation(Animation::Transform);
788  return transform_animation && transform_animation->is_impl_only();
789}
790
791void LayerImpl::SetContentBounds(gfx::Size content_bounds) {
792  if (this->content_bounds() == content_bounds)
793    return;
794
795  draw_properties_.content_bounds = content_bounds;
796  NoteLayerPropertyChanged();
797}
798
799void LayerImpl::SetContentsScale(float contents_scale_x,
800                                 float contents_scale_y) {
801  if (this->contents_scale_x() == contents_scale_x &&
802      this->contents_scale_y() == contents_scale_y)
803    return;
804
805  draw_properties_.contents_scale_x = contents_scale_x;
806  draw_properties_.contents_scale_y = contents_scale_y;
807  NoteLayerPropertyChanged();
808}
809
810void LayerImpl::CalculateContentsScale(
811    float ideal_contents_scale,
812    float device_scale_factor,
813    float page_scale_factor,
814    bool animating_transform_to_screen,
815    float* contents_scale_x,
816    float* contents_scale_y,
817    gfx::Size* content_bounds) {
818  // Base LayerImpl has all of its content scales and content bounds pushed
819  // from its Layer during commit and just reuses those values as-is.
820  *contents_scale_x = this->contents_scale_x();
821  *contents_scale_y = this->contents_scale_y();
822  *content_bounds = this->content_bounds();
823}
824
825void LayerImpl::UpdateScrollbarPositions() {
826  gfx::Vector2dF current_offset = scroll_offset_ + ScrollDelta();
827
828  gfx::RectF viewport(PointAtOffsetFromOrigin(current_offset), bounds_);
829  gfx::SizeF scrollable_size(max_scroll_offset_.x() + bounds_.width(),
830                             max_scroll_offset_.y() + bounds_.height());
831  if (horizontal_scrollbar_layer_) {
832    horizontal_scrollbar_layer_->SetCurrentPos(current_offset.x());
833    horizontal_scrollbar_layer_->SetMaximum(max_scroll_offset_.x());
834    horizontal_scrollbar_layer_->set_visible_to_total_length_ratio(
835        viewport.width() / scrollable_size.width());
836  }
837  if (vertical_scrollbar_layer_) {
838    vertical_scrollbar_layer_->SetCurrentPos(current_offset.y());
839    vertical_scrollbar_layer_->SetMaximum(max_scroll_offset_.y());
840    vertical_scrollbar_layer_->set_visible_to_total_length_ratio(
841        viewport.height() / scrollable_size.height());
842  }
843
844  if (current_offset == last_scroll_offset_)
845    return;
846  last_scroll_offset_ = current_offset;
847
848  if (scrollbar_animation_controller_ &&
849      !scrollbar_animation_controller_->IsScrollGestureInProgress()) {
850    scrollbar_animation_controller_->DidProgrammaticallyUpdateScroll(
851        layer_tree_impl_->CurrentPhysicalTimeTicks());
852  }
853
854  // Get the current_offset_.y() value for a sanity-check on scrolling
855  // benchmark metrics. Specifically, we want to make sure
856  // BasicMouseWheelSmoothScrollGesture has proper scroll curves.
857  if (layer_tree_impl()->IsActiveTree()) {
858    TRACE_COUNTER_ID1("gpu", "scroll_offset_y", this->id(), current_offset.y());
859  }
860}
861
862void LayerImpl::SetScrollOffsetDelegate(
863    LayerScrollOffsetDelegate* scroll_offset_delegate) {
864  if (!scroll_offset_delegate && scroll_offset_delegate_) {
865    scroll_delta_ =
866        scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_;
867  }
868  gfx::Vector2dF total_offset = TotalScrollOffset();
869  scroll_offset_delegate_ = scroll_offset_delegate;
870  if (scroll_offset_delegate_)
871    scroll_offset_delegate_->SetTotalScrollOffset(total_offset);
872}
873
874void LayerImpl::SetScrollOffset(gfx::Vector2d scroll_offset) {
875  if (scroll_offset_ == scroll_offset)
876    return;
877
878  scroll_offset_ = scroll_offset;
879
880  if (scroll_offset_delegate_)
881    scroll_offset_delegate_->SetTotalScrollOffset(TotalScrollOffset());
882
883  NoteLayerPropertyChangedForSubtree();
884  UpdateScrollbarPositions();
885}
886
887gfx::Vector2dF LayerImpl::ScrollDelta() const {
888  if (scroll_offset_delegate_)
889    return scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_;
890  return scroll_delta_;
891}
892
893void LayerImpl::SetScrollDelta(gfx::Vector2dF scroll_delta) {
894  if (ScrollDelta() == scroll_delta)
895    return;
896
897  if (layer_tree_impl()->IsActiveTree()) {
898    LayerImpl* pending_twin = layer_tree_impl()->FindPendingTreeLayerById(id());
899    if (pending_twin) {
900      // The pending twin can't mirror the scroll delta of the active
901      // layer.  Although the delta - sent scroll delta difference is
902      // identical for both twins, the sent scroll delta for the pending
903      // layer is zero, as anything that has been sent has been baked
904      // into the layer's position/scroll offset as a part of commit.
905      DCHECK(pending_twin->sent_scroll_delta().IsZero());
906      pending_twin->SetScrollDelta(scroll_delta - sent_scroll_delta());
907    }
908  }
909
910  if (scroll_offset_delegate_) {
911    scroll_offset_delegate_->SetTotalScrollOffset(
912        scroll_offset_ + scroll_delta);
913  } else {
914    scroll_delta_ = scroll_delta;
915  }
916
917  NoteLayerPropertyChangedForSubtree();
918  UpdateScrollbarPositions();
919}
920
921gfx::Vector2dF LayerImpl::TotalScrollOffset() const {
922  return scroll_offset_ + ScrollDelta();
923}
924
925void LayerImpl::SetDoubleSided(bool double_sided) {
926  if (double_sided_ == double_sided)
927    return;
928
929  double_sided_ = double_sided;
930  NoteLayerPropertyChangedForSubtree();
931}
932
933Region LayerImpl::VisibleContentOpaqueRegion() const {
934  if (contents_opaque())
935    return visible_content_rect();
936  return Region();
937}
938
939void LayerImpl::DidBeginTracing() {}
940
941void LayerImpl::DidLoseOutputSurface() {}
942
943void LayerImpl::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) {
944  if (max_scroll_offset_ == max_scroll_offset)
945    return;
946  max_scroll_offset_ = max_scroll_offset;
947
948  layer_tree_impl()->set_needs_update_draw_properties();
949  UpdateScrollbarPositions();
950}
951
952void LayerImpl::SetScrollbarOpacity(float opacity) {
953  if (horizontal_scrollbar_layer_)
954    horizontal_scrollbar_layer_->SetOpacity(opacity);
955  if (vertical_scrollbar_layer_)
956    vertical_scrollbar_layer_->SetOpacity(opacity);
957}
958
959void LayerImpl::DidBecomeActive() {
960  if (!layer_tree_impl_->settings().use_linear_fade_scrollbar_animator)
961    return;
962
963  bool need_scrollbar_animation_controller = horizontal_scrollbar_layer_ ||
964                                             vertical_scrollbar_layer_;
965  if (need_scrollbar_animation_controller) {
966    if (!scrollbar_animation_controller_) {
967      base::TimeDelta fadeout_delay = base::TimeDelta::FromMilliseconds(
968          layer_tree_impl_->settings().scrollbar_linear_fade_delay_ms);
969      base::TimeDelta fadeout_length = base::TimeDelta::FromMilliseconds(
970          layer_tree_impl_->settings().scrollbar_linear_fade_length_ms);
971      scrollbar_animation_controller_ =
972          ScrollbarAnimationControllerLinearFade::Create(
973              this, fadeout_delay, fadeout_length)
974              .PassAs<ScrollbarAnimationController>();
975    }
976  } else {
977    scrollbar_animation_controller_.reset();
978  }
979}
980void LayerImpl::SetHorizontalScrollbarLayer(
981    ScrollbarLayerImpl* scrollbar_layer) {
982  horizontal_scrollbar_layer_ = scrollbar_layer;
983  if (horizontal_scrollbar_layer_)
984    horizontal_scrollbar_layer_->set_scroll_layer_id(id());
985}
986
987void LayerImpl::SetVerticalScrollbarLayer(ScrollbarLayerImpl* scrollbar_layer) {
988  vertical_scrollbar_layer_ = scrollbar_layer;
989  if (vertical_scrollbar_layer_)
990    vertical_scrollbar_layer_->set_scroll_layer_id(id());
991}
992
993static scoped_ptr<base::Value>
994CompositingReasonsAsValue(CompositingReasons reasons) {
995  scoped_ptr<base::ListValue> reason_list(new base::ListValue());
996
997  if (reasons == kCompositingReasonUnknown) {
998    reason_list->AppendString("No reasons given");
999    return reason_list.PassAs<base::Value>();
1000  }
1001
1002  if (reasons & kCompositingReason3DTransform)
1003    reason_list->AppendString("Has a 3d Transform");
1004
1005  if (reasons & kCompositingReasonVideo)
1006    reason_list->AppendString("Is accelerated video");
1007
1008  if (reasons & kCompositingReasonCanvas)
1009    reason_list->AppendString("Is accelerated canvas");
1010
1011  if (reasons & kCompositingReasonPlugin)
1012    reason_list->AppendString("Is accelerated plugin");
1013
1014  if (reasons & kCompositingReasonIFrame)
1015    reason_list->AppendString("Is accelerated iframe");
1016
1017  if (reasons & kCompositingReasonBackfaceVisibilityHidden)
1018    reason_list->AppendString("Has backface-visibility: hidden");
1019
1020  if (reasons & kCompositingReasonAnimation)
1021    reason_list->AppendString("Has accelerated animation or transition");
1022
1023  if (reasons & kCompositingReasonFilters)
1024    reason_list->AppendString("Has accelerated filters");
1025
1026  if (reasons & kCompositingReasonPositionFixed)
1027    reason_list->AppendString("Is fixed position");
1028
1029  if (reasons & kCompositingReasonPositionSticky)
1030    reason_list->AppendString("Is sticky position");
1031
1032  if (reasons & kCompositingReasonOverflowScrollingTouch)
1033    reason_list->AppendString("Is a scrollable overflow element");
1034
1035  if (reasons & kCompositingReasonBlending)
1036    reason_list->AppendString("Has a blend mode");
1037
1038  if (reasons & kCompositingReasonAssumedOverlap)
1039    reason_list->AppendString("Might overlap a composited animation");
1040
1041  if (reasons & kCompositingReasonOverlap)
1042    reason_list->AppendString("Overlaps other composited content");
1043
1044  if (reasons & kCompositingReasonNegativeZIndexChildren) {
1045    reason_list->AppendString("Might overlap negative z-index "
1046                              "composited content");
1047  }
1048
1049  if (reasons & kCompositingReasonTransformWithCompositedDescendants) {
1050    reason_list->AppendString("Has transform needed by a "
1051                              "composited descendant");
1052  }
1053
1054  if (reasons & kCompositingReasonOpacityWithCompositedDescendants)
1055    reason_list->AppendString("Has opacity needed by a composited descendant");
1056
1057  if (reasons & kCompositingReasonMaskWithCompositedDescendants)
1058    reason_list->AppendString("Has a mask needed by a composited descendant");
1059
1060  if (reasons & kCompositingReasonReflectionWithCompositedDescendants)
1061    reason_list->AppendString("Has a reflection with a composited descendant");
1062
1063  if (reasons & kCompositingReasonFilterWithCompositedDescendants)
1064    reason_list->AppendString("Has filter effect with a composited descendant");
1065
1066  if (reasons & kCompositingReasonBlendingWithCompositedDescendants)
1067    reason_list->AppendString("Has a blend mode with a composited descendant");
1068
1069  if (reasons & kCompositingReasonClipsCompositingDescendants)
1070    reason_list->AppendString("Clips a composited descendant");
1071
1072  if (reasons & kCompositingReasonPerspective) {
1073    reason_list->AppendString("Has a perspective transform needed by a "
1074                              "composited 3d descendant");
1075  }
1076
1077  if (reasons & kCompositingReasonPreserve3D) {
1078    reason_list->AppendString("Has preserves-3d style with composited "
1079                              "3d descendant");
1080  }
1081
1082  if (reasons & kCompositingReasonReflectionOfCompositedParent)
1083    reason_list->AppendString("Is the reflection of a composited layer");
1084
1085  if (reasons & kCompositingReasonRoot)
1086    reason_list->AppendString("Is the root");
1087
1088  if (reasons & kCompositingReasonLayerForClip)
1089    reason_list->AppendString("Convenience layer, to clip subtree");
1090
1091  if (reasons & kCompositingReasonLayerForScrollbar)
1092    reason_list->AppendString("Convenience layer for rendering scrollbar");
1093
1094  if (reasons & kCompositingReasonLayerForScrollingContainer)
1095    reason_list->AppendString("Convenience layer, the scrolling container");
1096
1097  if (reasons & kCompositingReasonLayerForForeground) {
1098    reason_list->AppendString("Convenience layer, foreground when main layer "
1099                              "has negative z-index composited content");
1100  }
1101
1102  if (reasons & kCompositingReasonLayerForBackground) {
1103    reason_list->AppendString("Convenience layer, background when main layer "
1104                              "has a composited background");
1105  }
1106
1107  if (reasons & kCompositingReasonLayerForMask)
1108    reason_list->AppendString("Is a mask layer");
1109
1110  return reason_list.PassAs<base::Value>();
1111}
1112
1113void LayerImpl::AsValueInto(base::DictionaryValue* state) const {
1114  TracedValue::MakeDictIntoImplicitSnapshot(state, LayerTypeAsString(), this);
1115  state->SetInteger("layer_id", id());
1116  state->Set("bounds", MathUtil::AsValue(bounds()).release());
1117  state->SetInteger("draws_content", DrawsContent());
1118  state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes());
1119  state->Set("compositing_reasons",
1120             CompositingReasonsAsValue(compositing_reasons_).release());
1121
1122  bool clipped;
1123  gfx::QuadF layer_quad = MathUtil::MapQuad(
1124      screen_space_transform(),
1125      gfx::QuadF(gfx::Rect(content_bounds())),
1126      &clipped);
1127  state->Set("layer_quad", MathUtil::AsValue(layer_quad).release());
1128
1129
1130  scoped_ptr<base::ListValue> children_list(new base::ListValue());
1131  for (size_t i = 0; i < children_.size(); ++i)
1132    children_list->Append(children_[i]->AsValue().release());
1133  state->Set("children", children_list.release());
1134  if (mask_layer_)
1135    state->Set("mask_layer", mask_layer_->AsValue().release());
1136  if (replica_layer_)
1137    state->Set("replica_layer", replica_layer_->AsValue().release());
1138}
1139
1140size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; }
1141
1142scoped_ptr<base::Value> LayerImpl::AsValue() const {
1143  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1144  AsValueInto(state.get());
1145  return state.PassAs<base::Value>();
1146}
1147
1148}  // namespace cc
1149