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