layer_impl.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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 "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/quads/debug_border_draw_quad.h"
20#include "cc/trees/layer_tree_impl.h"
21#include "cc/trees/layer_tree_settings.h"
22#include "cc/trees/proxy.h"
23#include "ui/gfx/point_conversions.h"
24#include "ui/gfx/quad_f.h"
25#include "ui/gfx/rect_conversions.h"
26
27namespace cc {
28
29LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
30    : parent_(NULL),
31      mask_layer_id_(-1),
32      replica_layer_id_(-1),
33      layer_id_(id),
34      layer_tree_impl_(tree_impl),
35      anchor_point_(0.5f, 0.5f),
36      anchor_point_z_(0.f),
37      scroll_offset_delegate_(NULL),
38      scrollable_(false),
39      should_scroll_on_main_thread_(false),
40      have_wheel_event_handlers_(false),
41      background_color_(0),
42      stacking_order_changed_(false),
43      double_sided_(true),
44      layer_property_changed_(false),
45      layer_surface_property_changed_(false),
46      masks_to_bounds_(false),
47      contents_opaque_(false),
48      opacity_(1.0),
49      preserves_3d_(false),
50      use_parent_backface_visibility_(false),
51      draw_checkerboard_for_missing_tiles_(false),
52      draws_content_(false),
53      force_render_surface_(false),
54      is_container_for_fixed_position_layers_(false),
55      draw_depth_(0.f),
56#ifndef NDEBUG
57      between_will_draw_and_did_draw_(false),
58#endif
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#ifndef NDEBUG
72  DCHECK(!between_will_draw_and_did_draw_);
73#endif
74
75  for (size_t i = 0; i < request_copy_callbacks_.size(); ++i)
76    request_copy_callbacks_[i].Run(scoped_ptr<SkBitmap>());
77
78  layer_tree_impl_->UnregisterLayer(this);
79  layer_animation_controller_->RemoveValueObserver(this);
80}
81
82void LayerImpl::AddChild(scoped_ptr<LayerImpl> child) {
83  child->set_parent(this);
84  DCHECK_EQ(layer_tree_impl(), child->layer_tree_impl());
85  children_.push_back(child.Pass());
86  layer_tree_impl()->set_needs_update_draw_properties();
87}
88
89scoped_ptr<LayerImpl> LayerImpl::RemoveChild(LayerImpl* child) {
90  for (OwnedLayerImplList::iterator it = children_.begin();
91       it != children_.end();
92       ++it) {
93    if (*it == child) {
94      scoped_ptr<LayerImpl> ret = children_.take(it);
95      children_.erase(it);
96      layer_tree_impl()->set_needs_update_draw_properties();
97      return ret.Pass();
98    }
99  }
100  return scoped_ptr<LayerImpl>();
101}
102
103void LayerImpl::ClearChildList() {
104  if (children_.empty())
105    return;
106
107  children_.clear();
108  layer_tree_impl()->set_needs_update_draw_properties();
109}
110
111void LayerImpl::PassRequestCopyCallbacks(
112    std::vector<RenderPass::RequestCopyAsBitmapCallback>* callbacks) {
113  if (callbacks->empty())
114    return;
115
116  request_copy_callbacks_.insert(request_copy_callbacks_.end(),
117                                 callbacks->begin(),
118                                 callbacks->end());
119  callbacks->clear();
120
121  NoteLayerPropertyChangedForSubtree();
122}
123
124void LayerImpl::TakeRequestCopyCallbacks(
125    std::vector<RenderPass::RequestCopyAsBitmapCallback>* callbacks) {
126  if (request_copy_callbacks_.empty())
127    return;
128
129  callbacks->insert(callbacks->end(),
130                    request_copy_callbacks_.begin(),
131                    request_copy_callbacks_.end());
132  request_copy_callbacks_.clear();
133}
134
135void LayerImpl::CreateRenderSurface() {
136  DCHECK(!draw_properties_.render_surface);
137  draw_properties_.render_surface =
138      make_scoped_ptr(new RenderSurfaceImpl(this));
139  draw_properties_.render_target = this;
140}
141
142void LayerImpl::ClearRenderSurface() {
143  draw_properties_.render_surface.reset();
144}
145
146scoped_ptr<SharedQuadState> LayerImpl::CreateSharedQuadState() const {
147  scoped_ptr<SharedQuadState> state = SharedQuadState::Create();
148  state->SetAll(draw_properties_.target_space_transform,
149                draw_properties_.content_bounds,
150                draw_properties_.visible_content_rect,
151                draw_properties_.clip_rect,
152                draw_properties_.is_clipped,
153                draw_properties_.opacity);
154  return state.Pass();
155}
156
157void LayerImpl::WillDraw(ResourceProvider* resource_provider) {
158#ifndef NDEBUG
159  // WillDraw/DidDraw must be matched.
160  DCHECK(!between_will_draw_and_did_draw_);
161  between_will_draw_and_did_draw_ = true;
162#endif
163}
164
165void LayerImpl::DidDraw(ResourceProvider* resource_provider) {
166#ifndef NDEBUG
167  DCHECK(between_will_draw_and_did_draw_);
168  between_will_draw_and_did_draw_ = false;
169#endif
170}
171
172bool LayerImpl::ShowDebugBorders() const {
173  return layer_tree_impl()->debug_state().show_debug_borders;
174}
175
176void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const {
177  if (draws_content_) {
178    *color = DebugColors::ContentLayerBorderColor();
179    *width = DebugColors::ContentLayerBorderWidth(layer_tree_impl());
180    return;
181  }
182
183  if (masks_to_bounds_) {
184    *color = DebugColors::MaskingLayerBorderColor();
185    *width = DebugColors::MaskingLayerBorderWidth(layer_tree_impl());
186    return;
187  }
188
189  *color = DebugColors::ContainerLayerBorderColor();
190  *width = DebugColors::ContainerLayerBorderWidth(layer_tree_impl());
191}
192
193void LayerImpl::AppendDebugBorderQuad(
194    QuadSink* quad_sink,
195    const SharedQuadState* shared_quad_state,
196    AppendQuadsData* append_quads_data) const {
197  if (!ShowDebugBorders())
198    return;
199
200  SkColor color;
201  float width;
202  GetDebugBorderProperties(&color, &width);
203
204  gfx::Rect content_rect(content_bounds());
205  scoped_ptr<DebugBorderDrawQuad> debug_border_quad =
206      DebugBorderDrawQuad::Create();
207  debug_border_quad->SetNew(shared_quad_state, content_rect, color, width);
208  quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), append_quads_data);
209}
210
211bool LayerImpl::HasDelegatedContent() const {
212  return false;
213}
214
215bool LayerImpl::HasContributingDelegatedRenderPasses() const {
216  return false;
217}
218
219RenderPass::Id LayerImpl::FirstContributingRenderPassId() const {
220  return RenderPass::Id(0, 0);
221}
222
223RenderPass::Id LayerImpl::NextContributingRenderPassId(RenderPass::Id id)
224    const {
225  return RenderPass::Id(0, 0);
226}
227
228ResourceProvider::ResourceId LayerImpl::ContentsResourceId() const {
229  NOTREACHED();
230  return 0;
231}
232
233void LayerImpl::SetSentScrollDelta(gfx::Vector2d sent_scroll_delta) {
234  // Pending tree never has sent scroll deltas
235  DCHECK(layer_tree_impl()->IsActiveTree());
236
237  if (sent_scroll_delta_ == sent_scroll_delta)
238    return;
239
240  sent_scroll_delta_ = sent_scroll_delta;
241}
242
243gfx::Vector2dF LayerImpl::ScrollBy(gfx::Vector2dF scroll) {
244  gfx::Vector2dF min_delta = -scroll_offset_;
245  gfx::Vector2dF max_delta = max_scroll_offset_ - scroll_offset_;
246  // Clamp new_delta so that position + delta stays within scroll bounds.
247  gfx::Vector2dF new_delta = (ScrollDelta() + scroll);
248  new_delta.ClampToMin(min_delta);
249  new_delta.ClampToMax(max_delta);
250  gfx::Vector2dF unscrolled = ScrollDelta() + scroll - new_delta;
251
252  SetScrollDelta(new_delta);
253  return unscrolled;
254}
255
256InputHandler::ScrollStatus LayerImpl::TryScroll(
257    gfx::PointF screen_space_point,
258    InputHandler::ScrollInputType type) const {
259  if (should_scroll_on_main_thread()) {
260    TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
261    return InputHandler::ScrollOnMainThread;
262  }
263
264  if (!screen_space_transform().IsInvertible()) {
265    TRACE_EVENT0("cc", "LayerImpl::TryScroll: Ignored NonInvertibleTransform");
266    return InputHandler::ScrollIgnored;
267  }
268
269  if (!non_fast_scrollable_region().IsEmpty()) {
270    bool clipped = false;
271    gfx::Transform inverse_screen_space_transform(
272        gfx::Transform::kSkipInitialization);
273    if (!screen_space_transform().GetInverse(&inverse_screen_space_transform)) {
274      // TODO(shawnsingh): We shouldn't be applying a projection if screen space
275      // transform is uninvertible here. Perhaps we should be returning
276      // ScrollOnMainThread in this case?
277    }
278
279    gfx::PointF hit_test_point_in_content_space =
280        MathUtil::ProjectPoint(inverse_screen_space_transform,
281                               screen_space_point,
282                               &clipped);
283    gfx::PointF hit_test_point_in_layer_space =
284        gfx::ScalePoint(hit_test_point_in_content_space,
285                        1.f / contents_scale_x(),
286                        1.f / contents_scale_y());
287    if (!clipped &&
288        non_fast_scrollable_region().Contains(
289            gfx::ToRoundedPoint(hit_test_point_in_layer_space))) {
290      TRACE_EVENT0("cc",
291                   "LayerImpl::tryScroll: Failed NonFastScrollableRegion");
292      return InputHandler::ScrollOnMainThread;
293    }
294  }
295
296  if (type == InputHandler::Wheel && have_wheel_event_handlers()) {
297    TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers");
298    return InputHandler::ScrollOnMainThread;
299  }
300
301  if (!scrollable()) {
302    TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable");
303    return InputHandler::ScrollIgnored;
304  }
305
306  if (max_scroll_offset_.x() <= 0 && max_scroll_offset_.y() <= 0) {
307    TRACE_EVENT0("cc",
308                 "LayerImpl::tryScroll: Ignored. Technically scrollable,"
309                 " but has no affordance in either direction.");
310    return InputHandler::ScrollIgnored;
311  }
312
313  return InputHandler::ScrollStarted;
314}
315
316bool LayerImpl::DrawCheckerboardForMissingTiles() const {
317  return draw_checkerboard_for_missing_tiles_ &&
318      !layer_tree_impl()->settings().background_color_instead_of_checkerboard;
319}
320
321gfx::Rect LayerImpl::LayerRectToContentRect(
322    const gfx::RectF& layer_rect) const {
323  gfx::RectF content_rect =
324      gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y());
325  // Intersect with content rect to avoid the extra pixel because for some
326  // values x and y, ceil((x / y) * y) may be x + 1.
327  content_rect.Intersect(gfx::Rect(content_bounds()));
328  return gfx::ToEnclosingRect(content_rect);
329}
330
331skia::RefPtr<SkPicture> LayerImpl::GetPicture() {
332  return skia::RefPtr<SkPicture>();
333}
334
335bool LayerImpl::CanClipSelf() const {
336  return false;
337}
338
339bool LayerImpl::AreVisibleResourcesReady() const {
340  return true;
341}
342
343scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) {
344  return LayerImpl::Create(tree_impl, layer_id_);
345}
346
347void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
348  layer->SetAnchorPoint(anchor_point_);
349  layer->SetAnchorPointZ(anchor_point_z_);
350  layer->SetBackgroundColor(background_color_);
351  layer->SetBounds(bounds_);
352  layer->SetContentBounds(content_bounds());
353  layer->SetContentsScale(contents_scale_x(), contents_scale_y());
354  layer->SetDebugName(debug_name_);
355  layer->SetDoubleSided(double_sided_);
356  layer->SetDrawCheckerboardForMissingTiles(
357      draw_checkerboard_for_missing_tiles_);
358  layer->SetForceRenderSurface(force_render_surface_);
359  layer->SetDrawsContent(DrawsContent());
360  layer->SetFilters(filters());
361  layer->SetFilter(filter());
362  layer->SetBackgroundFilters(background_filters());
363  layer->SetMasksToBounds(masks_to_bounds_);
364  layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
365  layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
366  layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
367  layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
368  layer->SetContentsOpaque(contents_opaque_);
369  layer->SetOpacity(opacity_);
370  layer->SetPosition(position_);
371  layer->SetIsContainerForFixedPositionLayers(
372      is_container_for_fixed_position_layers_);
373  layer->SetFixedContainerSizeDelta(fixed_container_size_delta_);
374  layer->SetPositionConstraint(position_constraint_);
375  layer->SetPreserves3d(preserves_3d());
376  layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
377  layer->SetSublayerTransform(sublayer_transform_);
378  layer->SetTransform(transform_);
379
380  layer->SetScrollable(scrollable_);
381  layer->SetScrollOffset(scroll_offset_);
382  layer->SetMaxScrollOffset(max_scroll_offset_);
383
384  layer->PassRequestCopyCallbacks(&request_copy_callbacks_);
385
386  // If the main thread commits multiple times before the impl thread actually
387  // draws, then damage tracking will become incorrect if we simply clobber the
388  // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
389  // union) any update changes that have occurred on the main thread.
390  update_rect_.Union(layer->update_rect());
391  layer->set_update_rect(update_rect_);
392
393  layer->SetScrollDelta(layer->ScrollDelta() - layer->sent_scroll_delta());
394  layer->SetSentScrollDelta(gfx::Vector2d());
395
396  layer->SetStackingOrderChanged(stacking_order_changed_);
397
398  // Reset any state that should be cleared for the next update.
399  stacking_order_changed_ = false;
400  update_rect_ = gfx::RectF();
401}
402
403std::string LayerImpl::IndentString(int indent) {
404  std::string str;
405  for (int i = 0; i != indent; ++i)
406    str.append("  ");
407  return str;
408}
409
410void LayerImpl::DumpLayerProperties(std::string* str, int indent) const {
411  std::string indent_str = IndentString(indent);
412  str->append(indent_str);
413  base::StringAppendF(str, "layer ID: %d\n", layer_id_);
414
415  str->append(indent_str);
416  base::StringAppendF(
417      str, "bounds: %d, %d\n", bounds().width(), bounds().height());
418
419  if (draw_properties_.render_target) {
420    str->append(indent_str);
421    base::StringAppendF(
422        str, "renderTarget: %d\n", draw_properties_.render_target->layer_id_);
423  }
424
425  str->append(indent_str);
426  base::StringAppendF(str, "position: %f, %f\n", position_.x(), position_.y());
427
428  str->append(indent_str);
429  base::StringAppendF(str, "contentsOpaque: %d\n", contents_opaque_);
430
431  str->append(indent_str);
432  const gfx::Transform& transform = draw_properties_.target_space_transform;
433  base::StringAppendF(str,
434                      "drawTransform: %f, %f, %f, %f  //  %f, %f, %f, %f"
435                      "  //  %f, %f, %f, %f  //  %f, %f, %f, %f\n",
436                      transform.matrix().getDouble(0, 0),
437                      transform.matrix().getDouble(0, 1),
438                      transform.matrix().getDouble(0, 2),
439                      transform.matrix().getDouble(0, 3),
440                      transform.matrix().getDouble(1, 0),
441                      transform.matrix().getDouble(1, 1),
442                      transform.matrix().getDouble(1, 2),
443                      transform.matrix().getDouble(1, 3),
444                      transform.matrix().getDouble(2, 0),
445                      transform.matrix().getDouble(2, 1),
446                      transform.matrix().getDouble(2, 2),
447                      transform.matrix().getDouble(2, 3),
448                      transform.matrix().getDouble(3, 0),
449                      transform.matrix().getDouble(3, 1),
450                      transform.matrix().getDouble(3, 2),
451                      transform.matrix().getDouble(3, 3));
452
453  str->append(indent_str);
454  base::StringAppendF(
455      str, "draws_content: %s\n", draws_content_ ? "yes" : "no");
456}
457
458std::string LayerImpl::LayerTreeAsText() const {
459  std::string str;
460  DumpLayer(&str, 0);
461  return str;
462}
463
464void LayerImpl::DumpLayer(std::string* str, int indent) const {
465  str->append(IndentString(indent));
466  base::StringAppendF(str, "%s(%s)\n", LayerTypeAsString(), debug_name_.data());
467  DumpLayerProperties(str, indent+2);
468  if (replica_layer_) {
469    str->append(IndentString(indent+2));
470    str->append("Replica:\n");
471    replica_layer_->DumpLayer(str, indent+3);
472  }
473  if (mask_layer_) {
474    str->append(IndentString(indent+2));
475    str->append("Mask:\n");
476    mask_layer_->DumpLayer(str, indent+3);
477  }
478  for (size_t i = 0; i < children_.size(); ++i)
479    children_[i]->DumpLayer(str, indent+1);
480}
481
482base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
483  base::ListValue* list;
484  base::DictionaryValue* result = new base::DictionaryValue;
485  result->SetString("LayerType", LayerTypeAsString());
486
487  list = new base::ListValue;
488  list->AppendInteger(bounds().width());
489  list->AppendInteger(bounds().height());
490  result->Set("Bounds", list);
491
492  list = new base::ListValue;
493  list->AppendDouble(position_.x());
494  list->AppendDouble(position_.y());
495  result->Set("Position", list);
496
497  const gfx::Transform& gfx_transform = draw_properties_.target_space_transform;
498  double transform[16];
499  gfx_transform.matrix().asColMajord(transform);
500  list = new base::ListValue;
501  for (int i = 0; i < 16; ++i)
502    list->AppendDouble(transform[i]);
503  result->Set("DrawTransform", list);
504
505  result->SetBoolean("DrawsContent", draws_content_);
506  result->SetDouble("Opacity", opacity());
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
696void LayerImpl::SetFilters(const WebKit::WebFilterOperations& filters) {
697  if (filters_ == filters)
698    return;
699
700  DCHECK(!filter_);
701  filters_ = filters;
702  NoteLayerPropertyChangedForSubtree();
703}
704
705void LayerImpl::SetBackgroundFilters(
706    const WebKit::WebFilterOperations& filters) {
707  if (background_filters_ == filters)
708    return;
709
710  background_filters_ = filters;
711  NoteLayerPropertyChanged();
712}
713
714void LayerImpl::SetFilter(const skia::RefPtr<SkImageFilter>& filter) {
715  if (filter_.get() == filter.get())
716    return;
717
718  DCHECK(filters_.isEmpty());
719  filter_ = filter;
720  NoteLayerPropertyChangedForSubtree();
721}
722
723void LayerImpl::SetMasksToBounds(bool masks_to_bounds) {
724  if (masks_to_bounds_ == masks_to_bounds)
725    return;
726
727  masks_to_bounds_ = masks_to_bounds;
728  NoteLayerPropertyChangedForSubtree();
729}
730
731void LayerImpl::SetContentsOpaque(bool opaque) {
732  if (contents_opaque_ == opaque)
733    return;
734
735  contents_opaque_ = opaque;
736  NoteLayerPropertyChangedForSubtree();
737}
738
739void LayerImpl::SetOpacity(float opacity) {
740  if (opacity_ == opacity)
741    return;
742
743  opacity_ = opacity;
744  NoteLayerSurfacePropertyChanged();
745}
746
747bool LayerImpl::OpacityIsAnimating() const {
748  return layer_animation_controller_->IsAnimatingProperty(Animation::Opacity);
749}
750
751bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
752  Animation* opacity_animation =
753      layer_animation_controller_->GetAnimation(Animation::Opacity);
754  return opacity_animation && opacity_animation->is_impl_only();
755}
756
757void LayerImpl::SetPosition(gfx::PointF position) {
758  if (position_ == position)
759    return;
760
761  position_ = position;
762  NoteLayerPropertyChangedForSubtree();
763}
764
765void LayerImpl::SetPreserves3d(bool preserves3_d) {
766  if (preserves_3d_ == preserves3_d)
767    return;
768
769  preserves_3d_ = preserves3_d;
770  NoteLayerPropertyChangedForSubtree();
771}
772
773void LayerImpl::SetSublayerTransform(const gfx::Transform& sublayer_transform) {
774  if (sublayer_transform_ == sublayer_transform)
775    return;
776
777  sublayer_transform_ = sublayer_transform;
778  // Sublayer transform does not affect the current layer; it affects only its
779  // children.
780  NoteLayerPropertyChangedForDescendants();
781}
782
783void LayerImpl::SetTransform(const gfx::Transform& transform) {
784  if (transform_ == transform)
785    return;
786
787  transform_ = transform;
788  NoteLayerSurfacePropertyChanged();
789}
790
791bool LayerImpl::TransformIsAnimating() const {
792  return layer_animation_controller_->IsAnimatingProperty(Animation::Transform);
793}
794
795bool LayerImpl::TransformIsAnimatingOnImplOnly() const {
796  Animation* transform_animation =
797      layer_animation_controller_->GetAnimation(Animation::Transform);
798  return transform_animation && transform_animation->is_impl_only();
799}
800
801void LayerImpl::SetContentBounds(gfx::Size content_bounds) {
802  if (this->content_bounds() == content_bounds)
803    return;
804
805  draw_properties_.content_bounds = content_bounds;
806  NoteLayerPropertyChanged();
807}
808
809void LayerImpl::SetContentsScale(float contents_scale_x,
810                                 float contents_scale_y) {
811  if (this->contents_scale_x() == contents_scale_x &&
812      this->contents_scale_y() == contents_scale_y)
813    return;
814
815  draw_properties_.contents_scale_x = contents_scale_x;
816  draw_properties_.contents_scale_y = contents_scale_y;
817  NoteLayerPropertyChanged();
818}
819
820void LayerImpl::CalculateContentsScale(
821    float ideal_contents_scale,
822    float device_scale_factor,
823    float page_scale_factor,
824    bool animating_transform_to_screen,
825    float* contents_scale_x,
826    float* contents_scale_y,
827    gfx::Size* content_bounds) {
828  // Base LayerImpl has all of its content scales and content bounds pushed
829  // from its Layer during commit and just reuses those values as-is.
830  *contents_scale_x = this->contents_scale_x();
831  *contents_scale_y = this->contents_scale_y();
832  *content_bounds = this->content_bounds();
833}
834
835void LayerImpl::UpdateScrollbarPositions() {
836  gfx::Vector2dF current_offset = scroll_offset_ + ScrollDelta();
837
838  gfx::RectF viewport(PointAtOffsetFromOrigin(current_offset), bounds_);
839  gfx::SizeF scrollable_size(max_scroll_offset_.x() + bounds_.width(),
840                             max_scroll_offset_.y() + bounds_.height());
841  if (horizontal_scrollbar_layer_) {
842    horizontal_scrollbar_layer_->SetCurrentPos(current_offset.x());
843    horizontal_scrollbar_layer_->SetTotalSize(bounds_.width());
844    horizontal_scrollbar_layer_->SetMaximum(max_scroll_offset_.x());
845    horizontal_scrollbar_layer_->SetViewportWithinScrollableArea(
846        viewport, scrollable_size);
847  }
848  if (vertical_scrollbar_layer_) {
849    vertical_scrollbar_layer_->SetCurrentPos(current_offset.y());
850    vertical_scrollbar_layer_->SetTotalSize(bounds_.height());
851    vertical_scrollbar_layer_->SetMaximum(max_scroll_offset_.y());
852    vertical_scrollbar_layer_->SetViewportWithinScrollableArea(
853        viewport, scrollable_size);
854  }
855
856  if (current_offset == last_scroll_offset_)
857    return;
858  last_scroll_offset_ = current_offset;
859
860  if (scrollbar_animation_controller_ &&
861      !scrollbar_animation_controller_->IsScrollGestureInProgress()) {
862    scrollbar_animation_controller_->DidProgrammaticallyUpdateScroll(
863        layer_tree_impl()->CurrentFrameTimeTicks());
864  }
865
866  // Get the current_offset_.y() value for a sanity-check on scrolling
867  // benchmark metrics. Specifically, we want to make sure
868  // BasicMouseWheelSmoothScrollGesture has proper scroll curves.
869  if (layer_tree_impl()->IsActiveTree()) {
870    TRACE_COUNTER_ID1("gpu", "scroll_offset_y", this->id(), current_offset.y());
871  }
872}
873
874void LayerImpl::SetScrollOffsetDelegate(
875    LayerScrollOffsetDelegate* scroll_offset_delegate) {
876  if (!scroll_offset_delegate && scroll_offset_delegate_) {
877    scroll_delta_ =
878        scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_;
879  }
880  gfx::Vector2dF total_offset = TotalScrollOffset();
881  scroll_offset_delegate_ = scroll_offset_delegate;
882  if (scroll_offset_delegate_)
883    scroll_offset_delegate_->SetTotalScrollOffset(total_offset);
884}
885
886void LayerImpl::SetScrollOffset(gfx::Vector2d scroll_offset) {
887  if (scroll_offset_ == scroll_offset)
888    return;
889
890  scroll_offset_ = scroll_offset;
891
892  if (scroll_offset_delegate_)
893    scroll_offset_delegate_->SetTotalScrollOffset(TotalScrollOffset());
894
895  NoteLayerPropertyChangedForSubtree();
896  UpdateScrollbarPositions();
897}
898
899gfx::Vector2dF LayerImpl::ScrollDelta() const {
900  if (scroll_offset_delegate_)
901    return scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_;
902  return scroll_delta_;
903}
904
905void LayerImpl::SetScrollDelta(gfx::Vector2dF scroll_delta) {
906  if (ScrollDelta() == scroll_delta)
907    return;
908
909  if (layer_tree_impl()->IsActiveTree()) {
910    LayerImpl* pending_twin = layer_tree_impl()->FindPendingTreeLayerById(id());
911    if (pending_twin) {
912      // The pending twin can't mirror the scroll delta of the active
913      // layer.  Although the delta - sent scroll delta difference is
914      // identical for both twins, the sent scroll delta for the pending
915      // layer is zero, as anything that has been sent has been baked
916      // into the layer's position/scroll offset as a part of commit.
917      DCHECK(pending_twin->sent_scroll_delta().IsZero());
918      pending_twin->SetScrollDelta(scroll_delta - sent_scroll_delta());
919    }
920  }
921
922  if (scroll_offset_delegate_) {
923    scroll_offset_delegate_->SetTotalScrollOffset(
924        scroll_offset_ + scroll_delta);
925  } else {
926    scroll_delta_ = scroll_delta;
927  }
928  NoteLayerPropertyChangedForSubtree();
929
930  UpdateScrollbarPositions();
931}
932
933gfx::Vector2dF LayerImpl::TotalScrollOffset() const {
934  return scroll_offset_ + ScrollDelta();
935}
936
937void LayerImpl::SetDoubleSided(bool double_sided) {
938  if (double_sided_ == double_sided)
939    return;
940
941  double_sided_ = double_sided;
942  NoteLayerPropertyChangedForSubtree();
943}
944
945Region LayerImpl::VisibleContentOpaqueRegion() const {
946  if (contents_opaque())
947    return visible_content_rect();
948  return Region();
949}
950
951void LayerImpl::DidLoseOutputSurface() {}
952
953void LayerImpl::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) {
954  if (max_scroll_offset_ == max_scroll_offset)
955    return;
956  max_scroll_offset_ = max_scroll_offset;
957
958  layer_tree_impl()->set_needs_update_draw_properties();
959  UpdateScrollbarPositions();
960}
961
962void LayerImpl::SetScrollbarOpacity(float opacity) {
963  if (horizontal_scrollbar_layer_)
964    horizontal_scrollbar_layer_->SetOpacity(opacity);
965  if (vertical_scrollbar_layer_)
966    vertical_scrollbar_layer_->SetOpacity(opacity);
967}
968
969inline scoped_ptr<ScrollbarAnimationController>
970CreateScrollbarAnimationControllerWithFade(LayerImpl* layer) {
971  base::TimeDelta fadeout_delay = base::TimeDelta::FromMilliseconds(300);
972  base::TimeDelta fadeout_length = base::TimeDelta::FromMilliseconds(300);
973  return ScrollbarAnimationControllerLinearFade::Create(
974      layer, fadeout_delay, fadeout_length)
975      .PassAs<ScrollbarAnimationController>();
976}
977
978void LayerImpl::DidBecomeActive() {
979  if (!layer_tree_impl_->settings().use_linear_fade_scrollbar_animator)
980    return;
981
982  bool need_scrollbar_animation_controller = horizontal_scrollbar_layer_ ||
983                                             vertical_scrollbar_layer_;
984  if (need_scrollbar_animation_controller) {
985    if (!scrollbar_animation_controller_) {
986      scrollbar_animation_controller_ =
987          CreateScrollbarAnimationControllerWithFade(this);
988    }
989  } else {
990    scrollbar_animation_controller_.reset();
991  }
992}
993void LayerImpl::SetHorizontalScrollbarLayer(
994    ScrollbarLayerImpl* scrollbar_layer) {
995  horizontal_scrollbar_layer_ = scrollbar_layer;
996  if (horizontal_scrollbar_layer_)
997    horizontal_scrollbar_layer_->set_scroll_layer_id(id());
998}
999
1000void LayerImpl::SetVerticalScrollbarLayer(ScrollbarLayerImpl* scrollbar_layer) {
1001  vertical_scrollbar_layer_ = scrollbar_layer;
1002  if (vertical_scrollbar_layer_)
1003    vertical_scrollbar_layer_->set_scroll_layer_id(id());
1004}
1005
1006void LayerImpl::AsValueInto(base::DictionaryValue* state) const {
1007  TracedValue::MakeDictIntoImplicitSnapshot(state, LayerTypeAsString(), this);
1008  state->SetInteger("layer_id", id());
1009  state->Set("bounds", MathUtil::AsValue(bounds()).release());
1010  state->SetInteger("draws_content", DrawsContent());
1011
1012  bool clipped;
1013  gfx::QuadF layer_quad = MathUtil::MapQuad(
1014      screen_space_transform(),
1015      gfx::QuadF(gfx::Rect(content_bounds())),
1016      &clipped);
1017  state->Set("layer_quad", MathUtil::AsValue(layer_quad).release());
1018
1019
1020  scoped_ptr<base::ListValue> children_list(new base::ListValue());
1021  for (size_t i = 0; i < children_.size(); ++i)
1022    children_list->Append(children_[i]->AsValue().release());
1023  state->Set("children", children_list.release());
1024  if (mask_layer_)
1025    state->Set("mask_layer", mask_layer_->AsValue().release());
1026  if (replica_layer_)
1027    state->Set("replica_layer", replica_layer_->AsValue().release());
1028}
1029
1030scoped_ptr<base::Value> LayerImpl::AsValue() const {
1031  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1032  AsValueInto(state.get());
1033  return state.PassAs<base::Value>();
1034}
1035
1036}  // namespace cc
1037