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