layer_impl.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/stringprintf.h"
9#include "base/values.h"
10#include "cc/animation/animation_registrar.h"
11#include "cc/animation/scrollbar_animation_controller.h"
12#include "cc/animation/scrollbar_animation_controller_linear_fade.h"
13#include "cc/base/math_util.h"
14#include "cc/debug/debug_colors.h"
15#include "cc/debug/layer_tree_debug_state.h"
16#include "cc/layers/quad_sink.h"
17#include "cc/layers/scrollbar_layer_impl.h"
18#include "cc/quads/debug_border_draw_quad.h"
19#include "cc/trees/layer_tree_impl.h"
20#include "cc/trees/layer_tree_settings.h"
21#include "cc/trees/proxy.h"
22#include "ui/gfx/point_conversions.h"
23#include "ui/gfx/quad_f.h"
24#include "ui/gfx/rect_conversions.h"
25
26namespace cc {
27
28LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
29    : parent_(NULL),
30      mask_layer_id_(-1),
31      replica_layer_id_(-1),
32      layer_id_(id),
33      layer_tree_impl_(tree_impl),
34      anchor_point_(0.5f, 0.5f),
35      anchor_point_z_(0.f),
36      scrollable_(false),
37      should_scroll_on_main_thread_(false),
38      have_wheel_event_handlers_(false),
39      background_color_(0),
40      stacking_order_changed_(false),
41      double_sided_(true),
42      layer_property_changed_(false),
43      layer_surface_property_changed_(false),
44      masks_to_bounds_(false),
45      contents_opaque_(false),
46      opacity_(1.0),
47      preserves_3d_(false),
48      use_parent_backface_visibility_(false),
49      draw_checkerboard_for_missing_tiles_(false),
50      draws_content_(false),
51      force_render_surface_(false),
52      is_container_for_fixed_position_layers_(false),
53      fixed_to_container_layer_(false),
54      draw_depth_(0.f),
55#ifndef NDEBUG
56      between_will_draw_and_did_draw_(false),
57#endif
58      horizontal_scrollbar_layer_(NULL),
59      vertical_scrollbar_layer_(NULL) {
60  DCHECK(layer_id_ > 0);
61  DCHECK(layer_tree_impl_);
62  layer_tree_impl_->RegisterLayer(this);
63  AnimationRegistrar* registrar = layer_tree_impl_->animationRegistrar();
64  layer_animation_controller_ =
65      registrar->GetAnimationControllerForId(layer_id_);
66  layer_animation_controller_->AddObserver(this);
67}
68
69LayerImpl::~LayerImpl() {
70#ifndef NDEBUG
71  DCHECK(!between_will_draw_and_did_draw_);
72#endif
73  layer_tree_impl_->UnregisterLayer(this);
74  layer_animation_controller_->RemoveObserver(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 (ScopedPtrVector<LayerImpl>::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::CreateRenderSurface() {
107  DCHECK(!draw_properties_.render_surface);
108  draw_properties_.render_surface =
109      make_scoped_ptr(new RenderSurfaceImpl(this));
110  draw_properties_.render_target = this;
111}
112
113scoped_ptr<SharedQuadState> LayerImpl::CreateSharedQuadState() const {
114  scoped_ptr<SharedQuadState> state = SharedQuadState::Create();
115  state->SetAll(draw_properties_.target_space_transform,
116                draw_properties_.content_bounds,
117                draw_properties_.visible_content_rect,
118                draw_properties_.clip_rect,
119                draw_properties_.is_clipped,
120                draw_properties_.opacity);
121  return state.Pass();
122}
123
124void LayerImpl::WillDraw(ResourceProvider* resource_provider) {
125#ifndef NDEBUG
126  // WillDraw/DidDraw must be matched.
127  DCHECK(!between_will_draw_and_did_draw_);
128  between_will_draw_and_did_draw_ = true;
129#endif
130}
131
132void LayerImpl::DidDraw(ResourceProvider* resource_provider) {
133#ifndef NDEBUG
134  DCHECK(between_will_draw_and_did_draw_);
135  between_will_draw_and_did_draw_ = false;
136#endif
137}
138
139bool LayerImpl::ShowDebugBorders() const {
140  return layer_tree_impl()->debug_state().show_debug_borders;
141}
142
143void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const {
144  if (draws_content_) {
145    *color = DebugColors::ContentLayerBorderColor();
146    *width = DebugColors::ContentLayerBorderWidth(layer_tree_impl());
147    return;
148  }
149
150  if (masks_to_bounds_) {
151    *color = DebugColors::MaskingLayerBorderColor();
152    *width = DebugColors::MaskingLayerBorderWidth(layer_tree_impl());
153    return;
154  }
155
156  *color = DebugColors::ContainerLayerBorderColor();
157  *width = DebugColors::ContainerLayerBorderWidth(layer_tree_impl());
158}
159
160void LayerImpl::AppendDebugBorderQuad(
161    QuadSink* quad_sink,
162    const SharedQuadState* shared_quad_state,
163    AppendQuadsData* append_quads_data) const {
164  if (!ShowDebugBorders())
165    return;
166
167  SkColor color;
168  float width;
169  GetDebugBorderProperties(&color, &width);
170
171  gfx::Rect content_rect(content_bounds());
172  scoped_ptr<DebugBorderDrawQuad> debug_border_quad =
173      DebugBorderDrawQuad::Create();
174  debug_border_quad->SetNew(shared_quad_state, content_rect, color, width);
175  quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), append_quads_data);
176}
177
178bool LayerImpl::HasDelegatedContent() const {
179  return false;
180}
181
182bool LayerImpl::HasContributingDelegatedRenderPasses() const {
183  return false;
184}
185
186RenderPass::Id LayerImpl::FirstContributingRenderPassId() const {
187  return RenderPass::Id(0, 0);
188}
189
190RenderPass::Id LayerImpl::NextContributingRenderPassId(RenderPass::Id id)
191    const {
192  return RenderPass::Id(0, 0);
193}
194
195ResourceProvider::ResourceId LayerImpl::ContentsResourceId() const {
196  NOTREACHED();
197  return 0;
198}
199
200void LayerImpl::SetSentScrollDelta(gfx::Vector2d sent_scroll_delta) {
201  // Pending tree never has sent scroll deltas
202  DCHECK(layer_tree_impl()->IsActiveTree());
203
204  if (sent_scroll_delta_ == sent_scroll_delta)
205    return;
206
207  sent_scroll_delta_ = sent_scroll_delta;
208}
209
210gfx::Vector2dF LayerImpl::ScrollBy(gfx::Vector2dF scroll) {
211  gfx::Vector2dF min_delta = -scroll_offset_;
212  gfx::Vector2dF max_delta = max_scroll_offset_ - scroll_offset_;
213  // Clamp new_delta so that position + delta stays within scroll bounds.
214  gfx::Vector2dF new_delta = (scroll_delta_ + scroll);
215  new_delta.ClampToMin(min_delta);
216  new_delta.ClampToMax(max_delta);
217  gfx::Vector2dF unscrolled = scroll_delta_ + scroll - new_delta;
218
219  SetScrollDelta(new_delta);
220  return unscrolled;
221}
222
223InputHandlerClient::ScrollStatus LayerImpl::TryScroll(
224    gfx::PointF screen_space_point,
225    InputHandlerClient::ScrollInputType type) const {
226  if (should_scroll_on_main_thread()) {
227    TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
228    return InputHandlerClient::ScrollOnMainThread;
229  }
230
231  if (!screen_space_transform().IsInvertible()) {
232    TRACE_EVENT0("cc", "LayerImpl::TryScroll: Ignored NonInvertibleTransform");
233    return InputHandlerClient::ScrollIgnored;
234  }
235
236  if (!non_fast_scrollable_region().IsEmpty()) {
237    bool clipped = false;
238    gfx::Transform inverse_screen_space_transform(
239        gfx::Transform::kSkipInitialization);
240    if (!screen_space_transform().GetInverse(&inverse_screen_space_transform)) {
241      // TODO(shawnsingh): We shouldn't be applying a projection if screen space
242      // transform is uninvertible here. Perhaps we should be returning
243      // ScrollOnMainThread in this case?
244    }
245
246    gfx::PointF hit_test_point_in_content_space =
247        MathUtil::ProjectPoint(inverse_screen_space_transform,
248                               screen_space_point,
249                               &clipped);
250    gfx::PointF hit_test_point_in_layer_space =
251        gfx::ScalePoint(hit_test_point_in_content_space,
252                        1.f / contents_scale_x(),
253                        1.f / contents_scale_y());
254    if (!clipped &&
255        non_fast_scrollable_region().Contains(
256            gfx::ToRoundedPoint(hit_test_point_in_layer_space))) {
257      TRACE_EVENT0("cc",
258                   "LayerImpl::tryScroll: Failed NonFastScrollableRegion");
259      return InputHandlerClient::ScrollOnMainThread;
260    }
261  }
262
263  if (type == InputHandlerClient::Wheel && have_wheel_event_handlers()) {
264    TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers");
265    return InputHandlerClient::ScrollOnMainThread;
266  }
267
268  if (!scrollable()) {
269    TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable");
270    return InputHandlerClient::ScrollIgnored;
271  }
272
273  if (max_scroll_offset_.x() <= 0 && max_scroll_offset_.y() <= 0) {
274    TRACE_EVENT0("cc",
275                 "LayerImpl::tryScroll: Ignored. Technically scrollable,"
276                 " but has no affordance in either direction.");
277    return InputHandlerClient::ScrollIgnored;
278  }
279
280  return InputHandlerClient::ScrollStarted;
281}
282
283bool LayerImpl::DrawCheckerboardForMissingTiles() const {
284  return draw_checkerboard_for_missing_tiles_ &&
285      !layer_tree_impl()->settings().background_color_instead_of_checkerboard;
286}
287
288gfx::Rect LayerImpl::LayerRectToContentRect(
289    const gfx::RectF& layer_rect) const {
290  gfx::RectF content_rect =
291      gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y());
292  // Intersect with content rect to avoid the extra pixel because for some
293  // values x and y, ceil((x / y) * y) may be x + 1.
294  content_rect.Intersect(gfx::Rect(content_bounds()));
295  return gfx::ToEnclosingRect(content_rect);
296}
297
298skia::RefPtr<SkPicture> LayerImpl::GetPicture() {
299  return skia::RefPtr<SkPicture>();
300}
301
302bool LayerImpl::CanClipSelf() const {
303  return false;
304}
305
306bool LayerImpl::AreVisibleResourcesReady() const {
307  return true;
308}
309
310scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) {
311  return LayerImpl::Create(tree_impl, layer_id_);
312}
313
314void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
315  layer->SetAnchorPoint(anchor_point_);
316  layer->SetAnchorPointZ(anchor_point_z_);
317  layer->SetBackgroundColor(background_color_);
318  layer->SetBounds(bounds_);
319  layer->SetContentBounds(content_bounds());
320  layer->SetContentsScale(contents_scale_x(), contents_scale_y());
321  layer->SetDebugName(debug_name_);
322  layer->SetDoubleSided(double_sided_);
323  layer->SetDrawCheckerboardForMissingTiles(
324      draw_checkerboard_for_missing_tiles_);
325  layer->SetForceRenderSurface(force_render_surface_);
326  layer->SetDrawsContent(DrawsContent());
327  layer->SetFilters(filters());
328  layer->SetFilter(filter());
329  layer->SetBackgroundFilters(background_filters());
330  layer->SetMasksToBounds(masks_to_bounds_);
331  layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
332  layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
333  layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
334  layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
335  layer->SetContentsOpaque(contents_opaque_);
336  layer->SetOpacity(opacity_);
337  layer->SetPosition(position_);
338  layer->SetIsContainerForFixedPositionLayers(
339      is_container_for_fixed_position_layers_);
340  layer->SetFixedToContainerLayer(fixed_to_container_layer_);
341  layer->SetPreserves3d(preserves_3d());
342  layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
343  layer->SetSublayerTransform(sublayer_transform_);
344  layer->SetTransform(transform_);
345
346  layer->SetScrollable(scrollable_);
347  layer->SetScrollOffset(scroll_offset_);
348  layer->SetMaxScrollOffset(max_scroll_offset_);
349
350  // If the main thread commits multiple times before the impl thread actually
351  // draws, then damage tracking will become incorrect if we simply clobber the
352  // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
353  // union) any update changes that have occurred on the main thread.
354  update_rect_.Union(layer->update_rect());
355  layer->set_update_rect(update_rect_);
356
357  layer->SetScrollDelta(layer->scroll_delta() - layer->sent_scroll_delta());
358  layer->SetSentScrollDelta(gfx::Vector2d());
359
360  layer->SetStackingOrderChanged(stacking_order_changed_);
361
362  layer_animation_controller_->PushAnimationUpdatesTo(
363      layer->layer_animation_controller());
364
365  // Reset any state that should be cleared for the next update.
366  stacking_order_changed_ = false;
367  update_rect_ = gfx::RectF();
368}
369
370std::string LayerImpl::IndentString(int indent) {
371  std::string str;
372  for (int i = 0; i != indent; ++i)
373    str.append("  ");
374  return str;
375}
376
377void LayerImpl::DumpLayerProperties(std::string* str, int indent) const {
378  std::string indent_str = IndentString(indent);
379  str->append(indent_str);
380  base::StringAppendF(str, "layer ID: %d\n", layer_id_);
381
382  str->append(indent_str);
383  base::StringAppendF(
384      str, "bounds: %d, %d\n", bounds().width(), bounds().height());
385
386  if (draw_properties_.render_target) {
387    str->append(indent_str);
388    base::StringAppendF(
389        str, "renderTarget: %d\n", draw_properties_.render_target->layer_id_);
390  }
391
392  str->append(indent_str);
393  base::StringAppendF(str, "position: %f, %f\n", position_.x(), position_.y());
394
395  str->append(indent_str);
396  base::StringAppendF(str, "contentsOpaque: %d\n", contents_opaque_);
397
398  str->append(indent_str);
399  const gfx::Transform& transform = draw_properties_.target_space_transform;
400  base::StringAppendF(str,
401                      "drawTransform: %f, %f, %f, %f  //  %f, %f, %f, %f"
402                      "  //  %f, %f, %f, %f  //  %f, %f, %f, %f\n",
403                      transform.matrix().getDouble(0, 0),
404                      transform.matrix().getDouble(0, 1),
405                      transform.matrix().getDouble(0, 2),
406                      transform.matrix().getDouble(0, 3),
407                      transform.matrix().getDouble(1, 0),
408                      transform.matrix().getDouble(1, 1),
409                      transform.matrix().getDouble(1, 2),
410                      transform.matrix().getDouble(1, 3),
411                      transform.matrix().getDouble(2, 0),
412                      transform.matrix().getDouble(2, 1),
413                      transform.matrix().getDouble(2, 2),
414                      transform.matrix().getDouble(2, 3),
415                      transform.matrix().getDouble(3, 0),
416                      transform.matrix().getDouble(3, 1),
417                      transform.matrix().getDouble(3, 2),
418                      transform.matrix().getDouble(3, 3));
419
420  str->append(indent_str);
421  base::StringAppendF(
422      str, "draws_content: %s\n", draws_content_ ? "yes" : "no");
423}
424
425std::string LayerImpl::LayerTreeAsText() const {
426  std::string str;
427  DumpLayer(&str, 0);
428  return str;
429}
430
431void LayerImpl::DumpLayer(std::string* str, int indent) const {
432  str->append(IndentString(indent));
433  base::StringAppendF(str, "%s(%s)\n", LayerTypeAsString(), debug_name_.data());
434  DumpLayerProperties(str, indent+2);
435  if (replica_layer_) {
436    str->append(IndentString(indent+2));
437    str->append("Replica:\n");
438    replica_layer_->DumpLayer(str, indent+3);
439  }
440  if (mask_layer_) {
441    str->append(IndentString(indent+2));
442    str->append("Mask:\n");
443    mask_layer_->DumpLayer(str, indent+3);
444  }
445  for (size_t i = 0; i < children_.size(); ++i)
446    children_[i]->DumpLayer(str, indent+1);
447}
448
449base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
450  base::ListValue* list;
451  base::DictionaryValue* result = new base::DictionaryValue;
452  result->SetString("LayerType", LayerTypeAsString());
453
454  list = new base::ListValue;
455  list->AppendInteger(bounds().width());
456  list->AppendInteger(bounds().height());
457  result->Set("Bounds", list);
458
459  list = new base::ListValue;
460  list->AppendDouble(position_.x());
461  list->AppendDouble(position_.y());
462  result->Set("Position", list);
463
464  const gfx::Transform& gfx_transform = draw_properties_.target_space_transform;
465  double transform[16];
466  gfx_transform.matrix().asColMajord(transform);
467  list = new base::ListValue;
468  for (int i = 0; i < 16; ++i)
469    list->AppendDouble(transform[i]);
470  result->Set("DrawTransform", list);
471
472  result->SetBoolean("DrawsContent", draws_content_);
473  result->SetDouble("Opacity", opacity());
474
475  list = new base::ListValue;
476  for (size_t i = 0; i < children_.size(); ++i)
477    list->Append(children_[i]->LayerTreeAsJson());
478  result->Set("Children", list);
479
480  return result;
481}
482
483void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) {
484  if (stacking_order_changed) {
485    stacking_order_changed_ = true;
486    NoteLayerPropertyChangedForSubtree();
487  }
488}
489
490bool LayerImpl::LayerSurfacePropertyChanged() const {
491  if (layer_surface_property_changed_)
492    return true;
493
494  // If this layer's surface property hasn't changed, we want to see if
495  // some layer above us has changed this property. This is done for the
496  // case when such parent layer does not draw content, and therefore will
497  // not be traversed by the damage tracker. We need to make sure that
498  // property change on such layer will be caught by its descendants.
499  LayerImpl* current = this->parent_;
500  while (current && !current->draw_properties_.render_surface) {
501    if (current->layer_surface_property_changed_)
502      return true;
503    current = current->parent_;
504  }
505
506  return false;
507}
508
509void LayerImpl::NoteLayerSurfacePropertyChanged() {
510  layer_surface_property_changed_ = true;
511  layer_tree_impl()->set_needs_update_draw_properties();
512}
513
514void LayerImpl::NoteLayerPropertyChanged() {
515  layer_property_changed_ = true;
516  layer_tree_impl()->set_needs_update_draw_properties();
517}
518
519void LayerImpl::NoteLayerPropertyChangedForSubtree() {
520  NoteLayerPropertyChanged();
521  NoteLayerPropertyChangedForDescendants();
522}
523
524void LayerImpl::NoteLayerPropertyChangedForDescendants() {
525  layer_tree_impl()->set_needs_update_draw_properties();
526  for (size_t i = 0; i < children_.size(); ++i)
527    children_[i]->NoteLayerPropertyChangedForSubtree();
528}
529
530const char* LayerImpl::LayerTypeAsString() const {
531  return "Layer";
532}
533
534void LayerImpl::ResetAllChangeTrackingForSubtree() {
535  layer_property_changed_ = false;
536  layer_surface_property_changed_ = false;
537
538  update_rect_ = gfx::RectF();
539
540  if (draw_properties_.render_surface)
541    draw_properties_.render_surface->ResetPropertyChangedFlag();
542
543  if (mask_layer_)
544    mask_layer_->ResetAllChangeTrackingForSubtree();
545
546  if (replica_layer_) {
547    // This also resets the replica mask, if it exists.
548    replica_layer_->ResetAllChangeTrackingForSubtree();
549  }
550
551  for (size_t i = 0; i < children_.size(); ++i)
552    children_[i]->ResetAllChangeTrackingForSubtree();
553}
554
555bool LayerImpl::LayerIsAlwaysDamaged() const {
556  return false;
557}
558
559void LayerImpl::OnOpacityAnimated(float opacity) {
560  SetOpacity(opacity);
561}
562
563void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) {
564  SetTransform(transform);
565}
566
567bool LayerImpl::IsActive() const {
568  return layer_tree_impl_->IsActiveTree();
569}
570
571void LayerImpl::SetBounds(gfx::Size bounds) {
572  if (bounds_ == bounds)
573    return;
574
575  bounds_ = bounds;
576
577  if (masks_to_bounds())
578    NoteLayerPropertyChangedForSubtree();
579  else
580    NoteLayerPropertyChanged();
581}
582
583void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) {
584  int new_layer_id = mask_layer ? mask_layer->id() : -1;
585
586  if (mask_layer) {
587    DCHECK_EQ(layer_tree_impl(), mask_layer->layer_tree_impl());
588    DCHECK_NE(new_layer_id, mask_layer_id_);
589  } else if (new_layer_id == mask_layer_id_) {
590    return;
591  }
592
593  mask_layer_ = mask_layer.Pass();
594  mask_layer_id_ = new_layer_id;
595  if (mask_layer_)
596    mask_layer_->set_parent(this);
597  NoteLayerPropertyChangedForSubtree();
598}
599
600scoped_ptr<LayerImpl> LayerImpl::TakeMaskLayer() {
601  mask_layer_id_ = -1;
602  return mask_layer_.Pass();
603}
604
605void LayerImpl::SetReplicaLayer(scoped_ptr<LayerImpl> replica_layer) {
606  int new_layer_id = replica_layer ? replica_layer->id() : -1;
607
608  if (replica_layer) {
609    DCHECK_EQ(layer_tree_impl(), replica_layer->layer_tree_impl());
610    DCHECK_NE(new_layer_id, replica_layer_id_);
611  } else if (new_layer_id == replica_layer_id_) {
612    return;
613  }
614
615  replica_layer_ = replica_layer.Pass();
616  replica_layer_id_ = new_layer_id;
617  if (replica_layer_)
618    replica_layer_->set_parent(this);
619  NoteLayerPropertyChangedForSubtree();
620}
621
622scoped_ptr<LayerImpl> LayerImpl::TakeReplicaLayer() {
623  replica_layer_id_ = -1;
624  return replica_layer_.Pass();
625}
626
627ScrollbarLayerImpl* LayerImpl::ToScrollbarLayer() {
628  return NULL;
629}
630
631void LayerImpl::SetDrawsContent(bool draws_content) {
632  if (draws_content_ == draws_content)
633    return;
634
635  draws_content_ = draws_content;
636  NoteLayerPropertyChanged();
637}
638
639void LayerImpl::SetAnchorPoint(gfx::PointF anchor_point) {
640  if (anchor_point_ == anchor_point)
641    return;
642
643  anchor_point_ = anchor_point;
644  NoteLayerPropertyChangedForSubtree();
645}
646
647void LayerImpl::SetAnchorPointZ(float anchor_point_z) {
648  if (anchor_point_z_ == anchor_point_z)
649    return;
650
651  anchor_point_z_ = anchor_point_z;
652  NoteLayerPropertyChangedForSubtree();
653}
654
655void LayerImpl::SetBackgroundColor(SkColor background_color) {
656  if (background_color_ == background_color)
657    return;
658
659  background_color_ = background_color;
660  NoteLayerPropertyChanged();
661}
662
663void LayerImpl::SetFilters(const WebKit::WebFilterOperations& filters) {
664  if (filters_ == filters)
665    return;
666
667  DCHECK(!filter_);
668  filters_ = filters;
669  NoteLayerPropertyChangedForSubtree();
670}
671
672void LayerImpl::SetBackgroundFilters(
673    const WebKit::WebFilterOperations& filters) {
674  if (background_filters_ == filters)
675    return;
676
677  background_filters_ = filters;
678  NoteLayerPropertyChanged();
679}
680
681void LayerImpl::SetFilter(const skia::RefPtr<SkImageFilter>& filter) {
682  if (filter_.get() == filter.get())
683    return;
684
685  DCHECK(filters_.isEmpty());
686  filter_ = filter;
687  NoteLayerPropertyChangedForSubtree();
688}
689
690void LayerImpl::SetMasksToBounds(bool masks_to_bounds) {
691  if (masks_to_bounds_ == masks_to_bounds)
692    return;
693
694  masks_to_bounds_ = masks_to_bounds;
695  NoteLayerPropertyChangedForSubtree();
696}
697
698void LayerImpl::SetContentsOpaque(bool opaque) {
699  if (contents_opaque_ == opaque)
700    return;
701
702  contents_opaque_ = opaque;
703  NoteLayerPropertyChangedForSubtree();
704}
705
706void LayerImpl::SetOpacity(float opacity) {
707  if (opacity_ == opacity)
708    return;
709
710  opacity_ = opacity;
711  NoteLayerSurfacePropertyChanged();
712}
713
714bool LayerImpl::OpacityIsAnimating() const {
715  return layer_animation_controller_->IsAnimatingProperty(Animation::Opacity);
716}
717
718bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
719  Animation* opacity_animation =
720      layer_animation_controller_->GetAnimation(Animation::Opacity);
721  return opacity_animation && opacity_animation->is_impl_only();
722}
723
724void LayerImpl::SetPosition(gfx::PointF position) {
725  if (position_ == position)
726    return;
727
728  position_ = position;
729  NoteLayerPropertyChangedForSubtree();
730}
731
732void LayerImpl::SetPreserves3d(bool preserves3_d) {
733  if (preserves_3d_ == preserves3_d)
734    return;
735
736  preserves_3d_ = preserves3_d;
737  NoteLayerPropertyChangedForSubtree();
738}
739
740void LayerImpl::SetSublayerTransform(const gfx::Transform& sublayer_transform) {
741  if (sublayer_transform_ == sublayer_transform)
742    return;
743
744  sublayer_transform_ = sublayer_transform;
745  // Sublayer transform does not affect the current layer; it affects only its
746  // children.
747  NoteLayerPropertyChangedForDescendants();
748}
749
750void LayerImpl::SetTransform(const gfx::Transform& transform) {
751  if (transform_ == transform)
752    return;
753
754  transform_ = transform;
755  NoteLayerSurfacePropertyChanged();
756}
757
758bool LayerImpl::TransformIsAnimating() const {
759  return layer_animation_controller_->IsAnimatingProperty(Animation::Transform);
760}
761
762bool LayerImpl::TransformIsAnimatingOnImplOnly() const {
763  Animation* transform_animation =
764      layer_animation_controller_->GetAnimation(Animation::Transform);
765  return transform_animation && transform_animation->is_impl_only();
766}
767
768void LayerImpl::SetContentBounds(gfx::Size content_bounds) {
769  if (this->content_bounds() == content_bounds)
770    return;
771
772  draw_properties_.content_bounds = content_bounds;
773  NoteLayerPropertyChanged();
774}
775
776void LayerImpl::SetContentsScale(float contents_scale_x,
777                                 float contents_scale_y) {
778  if (this->contents_scale_x() == contents_scale_x &&
779      this->contents_scale_y() == contents_scale_y)
780    return;
781
782  draw_properties_.contents_scale_x = contents_scale_x;
783  draw_properties_.contents_scale_y = contents_scale_y;
784  NoteLayerPropertyChanged();
785}
786
787void LayerImpl::CalculateContentsScale(
788    float ideal_contents_scale,
789    bool animating_transform_to_screen,
790    float* contents_scale_x,
791    float* contents_scale_y,
792    gfx::Size* content_bounds) {
793  // Base LayerImpl has all of its content scales and content bounds pushed
794  // from its Layer during commit and just reuses those values as-is.
795  *contents_scale_x = this->contents_scale_x();
796  *contents_scale_y = this->contents_scale_y();
797  *content_bounds = this->content_bounds();
798}
799
800void LayerImpl::UpdateScrollbarPositions() {
801  gfx::Vector2dF current_offset = scroll_offset_ + scroll_delta_;
802
803  gfx::RectF viewport(PointAtOffsetFromOrigin(current_offset), bounds_);
804  gfx::SizeF scrollable_size(max_scroll_offset_.x() + bounds_.width(),
805                             max_scroll_offset_.y() + bounds_.height());
806  if (horizontal_scrollbar_layer_) {
807    horizontal_scrollbar_layer_->SetCurrentPos(current_offset.x());
808    horizontal_scrollbar_layer_->SetTotalSize(bounds_.width());
809    horizontal_scrollbar_layer_->SetMaximum(max_scroll_offset_.x());
810    horizontal_scrollbar_layer_->SetViewportWithinScrollableArea(
811        viewport, scrollable_size);
812  }
813  if (vertical_scrollbar_layer_) {
814    vertical_scrollbar_layer_->SetCurrentPos(current_offset.y());
815    vertical_scrollbar_layer_->SetTotalSize(bounds_.height());
816    vertical_scrollbar_layer_->SetMaximum(max_scroll_offset_.y());
817    vertical_scrollbar_layer_->SetViewportWithinScrollableArea(
818        viewport, scrollable_size);
819  }
820
821  if (current_offset == last_scroll_offset_)
822    return;
823  last_scroll_offset_ = current_offset;
824
825  if (scrollbar_animation_controller_ &&
826      !scrollbar_animation_controller_->IsScrollGestureInProgress()) {
827    scrollbar_animation_controller_->DidProgrammaticallyUpdateScroll(
828        base::TimeTicks::Now());
829  }
830
831  // Get the current_offset_.y() value for a sanity-check on scrolling
832  // benchmark metrics. Specifically, we want to make sure
833  // BasicMouseWheelSmoothScrollGesture has proper scroll curves.
834  if (layer_tree_impl()->IsActiveTree()) {
835    TRACE_COUNTER_ID1("gpu", "scroll_offset_y", this->id(), current_offset.y());
836  }
837}
838
839void LayerImpl::SetScrollOffset(gfx::Vector2d scroll_offset) {
840  if (scroll_offset_ == scroll_offset)
841    return;
842
843  scroll_offset_ = scroll_offset;
844  NoteLayerPropertyChangedForSubtree();
845  UpdateScrollbarPositions();
846}
847
848void LayerImpl::SetScrollDelta(gfx::Vector2dF scroll_delta) {
849  if (scroll_delta_ == scroll_delta)
850    return;
851
852  if (layer_tree_impl()->IsActiveTree()) {
853    LayerImpl* pending_twin = layer_tree_impl()->FindPendingTreeLayerById(id());
854    if (pending_twin) {
855      // The pending twin can't mirror the scroll delta of the active
856      // layer.  Although the delta - sent scroll delta difference is
857      // identical for both twins, the sent scroll delta for the pending
858      // layer is zero, as anything that has been sent has been baked
859      // into the layer's position/scroll offset as a part of commit.
860      DCHECK(pending_twin->sent_scroll_delta().IsZero());
861      pending_twin->SetScrollDelta(scroll_delta - sent_scroll_delta());
862    }
863  }
864
865  scroll_delta_ = scroll_delta;
866  NoteLayerPropertyChangedForSubtree();
867
868  UpdateScrollbarPositions();
869}
870
871gfx::Vector2dF LayerImpl::TotalScrollOffset() const {
872  return scroll_offset_ + scroll_delta_;
873}
874
875void LayerImpl::SetImplTransform(const gfx::Transform& transform) {
876  if (impl_transform_ == transform)
877    return;
878
879  impl_transform_ = transform;
880  NoteLayerPropertyChangedForSubtree();
881}
882
883void LayerImpl::SetDoubleSided(bool double_sided) {
884  if (double_sided_ == double_sided)
885    return;
886
887  double_sided_ = double_sided;
888  NoteLayerPropertyChangedForSubtree();
889}
890
891Region LayerImpl::VisibleContentOpaqueRegion() const {
892  if (contents_opaque())
893    return visible_content_rect();
894  return Region();
895}
896
897void LayerImpl::DidLoseOutputSurface() {}
898
899void LayerImpl::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) {
900  if (max_scroll_offset_ == max_scroll_offset)
901    return;
902  max_scroll_offset_ = max_scroll_offset;
903
904  layer_tree_impl()->set_needs_update_draw_properties();
905  UpdateScrollbarPositions();
906}
907
908void LayerImpl::SetScrollbarOpacity(float opacity) {
909  if (horizontal_scrollbar_layer_)
910    horizontal_scrollbar_layer_->SetOpacity(opacity);
911  if (vertical_scrollbar_layer_)
912    vertical_scrollbar_layer_->SetOpacity(opacity);
913}
914
915inline scoped_ptr<ScrollbarAnimationController>
916CreateScrollbarAnimationControllerWithFade(LayerImpl* layer) {
917  base::TimeDelta fadeout_delay = base::TimeDelta::FromMilliseconds(300);
918  base::TimeDelta fadeout_length = base::TimeDelta::FromMilliseconds(300);
919  return ScrollbarAnimationControllerLinearFade::Create(
920      layer, fadeout_delay, fadeout_length)
921      .PassAs<ScrollbarAnimationController>();
922}
923
924void LayerImpl::DidBecomeActive() {
925  if (!layer_tree_impl_->settings().use_linear_fade_scrollbar_animator)
926    return;
927
928  bool need_scrollbar_animation_controller = horizontal_scrollbar_layer_ ||
929                                             vertical_scrollbar_layer_;
930  if (need_scrollbar_animation_controller) {
931    if (!scrollbar_animation_controller_) {
932      scrollbar_animation_controller_ =
933          CreateScrollbarAnimationControllerWithFade(this);
934    }
935  } else {
936    scrollbar_animation_controller_.reset();
937  }
938
939}
940void LayerImpl::SetHorizontalScrollbarLayer(
941    ScrollbarLayerImpl* scrollbar_layer) {
942  horizontal_scrollbar_layer_ = scrollbar_layer;
943  if (horizontal_scrollbar_layer_)
944    horizontal_scrollbar_layer_->set_scroll_layer_id(id());
945}
946
947void LayerImpl::SetVerticalScrollbarLayer(ScrollbarLayerImpl* scrollbar_layer) {
948  vertical_scrollbar_layer_ = scrollbar_layer;
949  if (vertical_scrollbar_layer_)
950    vertical_scrollbar_layer_->set_scroll_layer_id(id());
951}
952
953void LayerImpl::AsValueInto(base::DictionaryValue* dict) const {
954  dict->SetInteger("id", id());
955  dict->Set("bounds", MathUtil::AsValue(bounds()).release());
956  dict->SetInteger("draws_content", DrawsContent());
957
958  bool clipped;
959  gfx::QuadF layer_quad = MathUtil::MapQuad(
960      screen_space_transform(),
961      gfx::QuadF(gfx::Rect(content_bounds())),
962      &clipped);
963  dict->Set("layer_quad", MathUtil::AsValue(layer_quad).release());
964
965}
966
967scoped_ptr<base::Value> LayerImpl::AsValue() const {
968  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
969  AsValueInto(state.get());
970  return state.PassAs<base::Value>();
971}
972
973}  // namespace cc
974