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