layer.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright (c) 2012 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 "ui/compositor/layer.h"
6
7#include <algorithm>
8
9#include "base/command_line.h"
10#include "base/debug/trace_event.h"
11#include "base/json/json_writer.h"
12#include "base/logging.h"
13#include "base/memory/scoped_ptr.h"
14#include "cc/base/scoped_ptr_algorithm.h"
15#include "cc/layers/content_layer.h"
16#include "cc/layers/delegated_renderer_layer.h"
17#include "cc/layers/picture_layer.h"
18#include "cc/layers/solid_color_layer.h"
19#include "cc/layers/texture_layer.h"
20#include "cc/output/copy_output_request.h"
21#include "cc/output/delegated_frame_data.h"
22#include "cc/output/filter_operation.h"
23#include "cc/output/filter_operations.h"
24#include "cc/resources/transferable_resource.h"
25#include "ui/compositor/compositor_switches.h"
26#include "ui/compositor/dip_util.h"
27#include "ui/compositor/layer_animator.h"
28#include "ui/gfx/animation/animation.h"
29#include "ui/gfx/canvas.h"
30#include "ui/gfx/display.h"
31#include "ui/gfx/interpolated_transform.h"
32#include "ui/gfx/point3_f.h"
33#include "ui/gfx/point_conversions.h"
34#include "ui/gfx/size_conversions.h"
35
36namespace {
37
38const ui::Layer* GetRoot(const ui::Layer* layer) {
39  while (layer->parent())
40    layer = layer->parent();
41  return layer;
42}
43
44struct UIImplSidePaintingStatus {
45  UIImplSidePaintingStatus()
46      : enabled(ui::IsUIImplSidePaintingEnabled()) {
47  }
48  bool enabled;
49};
50base::LazyInstance<UIImplSidePaintingStatus> g_ui_impl_side_painting_status =
51    LAZY_INSTANCE_INITIALIZER;
52
53}  // namespace
54
55namespace ui {
56
57Layer::Layer()
58    : type_(LAYER_TEXTURED),
59      compositor_(NULL),
60      parent_(NULL),
61      visible_(true),
62      force_render_surface_(false),
63      fills_bounds_opaquely_(true),
64      fills_bounds_completely_(false),
65      background_blur_radius_(0),
66      layer_saturation_(0.0f),
67      layer_brightness_(0.0f),
68      layer_grayscale_(0.0f),
69      layer_inverted_(false),
70      layer_mask_(NULL),
71      layer_mask_back_link_(NULL),
72      zoom_(1),
73      zoom_inset_(0),
74      delegate_(NULL),
75      owner_(NULL),
76      cc_layer_(NULL),
77      device_scale_factor_(1.0f) {
78  CreateWebLayer();
79}
80
81Layer::Layer(LayerType type)
82    : type_(type),
83      compositor_(NULL),
84      parent_(NULL),
85      visible_(true),
86      force_render_surface_(false),
87      fills_bounds_opaquely_(true),
88      fills_bounds_completely_(false),
89      background_blur_radius_(0),
90      layer_saturation_(0.0f),
91      layer_brightness_(0.0f),
92      layer_grayscale_(0.0f),
93      layer_inverted_(false),
94      layer_mask_(NULL),
95      layer_mask_back_link_(NULL),
96      zoom_(1),
97      zoom_inset_(0),
98      delegate_(NULL),
99      owner_(NULL),
100      cc_layer_(NULL),
101      device_scale_factor_(1.0f) {
102  CreateWebLayer();
103}
104
105Layer::~Layer() {
106  // Destroying the animator may cause observers to use the layer (and
107  // indirectly the WebLayer). Destroy the animator first so that the WebLayer
108  // is still around.
109  if (animator_.get())
110    animator_->SetDelegate(NULL);
111  animator_ = NULL;
112  if (compositor_)
113    compositor_->SetRootLayer(NULL);
114  if (parent_)
115    parent_->Remove(this);
116  if (layer_mask_)
117    SetMaskLayer(NULL);
118  if (layer_mask_back_link_)
119    layer_mask_back_link_->SetMaskLayer(NULL);
120  for (size_t i = 0; i < children_.size(); ++i)
121    children_[i]->parent_ = NULL;
122  cc_layer_->RemoveLayerAnimationEventObserver(this);
123  cc_layer_->RemoveFromParent();
124}
125
126// static
127bool Layer::UsingPictureLayer() {
128  return g_ui_impl_side_painting_status.Get().enabled;
129}
130
131Compositor* Layer::GetCompositor() {
132  return GetRoot(this)->compositor_;
133}
134
135float Layer::opacity() const {
136  return cc_layer_->opacity();
137}
138
139void Layer::SetCompositor(Compositor* compositor) {
140  // This function must only be called to set the compositor on the root layer,
141  // or to reset it.
142  DCHECK(!compositor || !compositor_);
143  DCHECK(!compositor || compositor->root_layer() == this);
144  DCHECK(!parent_);
145  compositor_ = compositor;
146  if (compositor) {
147    OnDeviceScaleFactorChanged(compositor->device_scale_factor());
148    SendPendingThreadedAnimations();
149  }
150}
151
152void Layer::Add(Layer* child) {
153  DCHECK(!child->compositor_);
154  if (child->parent_)
155    child->parent_->Remove(child);
156  child->parent_ = this;
157  children_.push_back(child);
158  cc_layer_->AddChild(child->cc_layer_);
159  child->OnDeviceScaleFactorChanged(device_scale_factor_);
160  if (GetCompositor())
161    child->SendPendingThreadedAnimations();
162}
163
164void Layer::Remove(Layer* child) {
165  // Current bounds are used to calculate offsets when layers are reparented.
166  // Stop (and complete) an ongoing animation to update the bounds immediately.
167  if (child->GetAnimator()) {
168    child->GetAnimator()->StopAnimatingProperty(
169        ui::LayerAnimationElement::BOUNDS);
170  }
171  std::vector<Layer*>::iterator i =
172      std::find(children_.begin(), children_.end(), child);
173  DCHECK(i != children_.end());
174  children_.erase(i);
175  child->parent_ = NULL;
176  child->cc_layer_->RemoveFromParent();
177}
178
179void Layer::StackAtTop(Layer* child) {
180  if (children_.size() <= 1 || child == children_.back())
181    return;  // Already in front.
182  StackAbove(child, children_.back());
183}
184
185void Layer::StackAbove(Layer* child, Layer* other) {
186  StackRelativeTo(child, other, true);
187}
188
189void Layer::StackAtBottom(Layer* child) {
190  if (children_.size() <= 1 || child == children_.front())
191    return;  // Already on bottom.
192  StackBelow(child, children_.front());
193}
194
195void Layer::StackBelow(Layer* child, Layer* other) {
196  StackRelativeTo(child, other, false);
197}
198
199bool Layer::Contains(const Layer* other) const {
200  for (const Layer* parent = other; parent; parent = parent->parent()) {
201    if (parent == this)
202      return true;
203  }
204  return false;
205}
206
207void Layer::SetAnimator(LayerAnimator* animator) {
208  if (animator)
209    animator->SetDelegate(this);
210  animator_ = animator;
211}
212
213LayerAnimator* Layer::GetAnimator() {
214  if (!animator_.get())
215    SetAnimator(LayerAnimator::CreateDefaultAnimator());
216  return animator_.get();
217}
218
219void Layer::SetTransform(const gfx::Transform& transform) {
220  GetAnimator()->SetTransform(transform);
221}
222
223gfx::Transform Layer::GetTargetTransform() const {
224  if (animator_.get() && animator_->IsAnimatingProperty(
225      LayerAnimationElement::TRANSFORM)) {
226    return animator_->GetTargetTransform();
227  }
228  return transform();
229}
230
231void Layer::SetBounds(const gfx::Rect& bounds) {
232  GetAnimator()->SetBounds(bounds);
233}
234
235gfx::Rect Layer::GetTargetBounds() const {
236  if (animator_.get() && animator_->IsAnimatingProperty(
237      LayerAnimationElement::BOUNDS)) {
238    return animator_->GetTargetBounds();
239  }
240  return bounds_;
241}
242
243void Layer::SetMasksToBounds(bool masks_to_bounds) {
244  cc_layer_->SetMasksToBounds(masks_to_bounds);
245}
246
247bool Layer::GetMasksToBounds() const {
248  return cc_layer_->masks_to_bounds();
249}
250
251void Layer::SetOpacity(float opacity) {
252  GetAnimator()->SetOpacity(opacity);
253}
254
255float Layer::GetCombinedOpacity() const {
256  float opacity = this->opacity();
257  Layer* current = this->parent_;
258  while (current) {
259    opacity *= current->opacity();
260    current = current->parent_;
261  }
262  return opacity;
263}
264
265void Layer::SetBackgroundBlur(int blur_radius) {
266  background_blur_radius_ = blur_radius;
267
268  SetLayerBackgroundFilters();
269}
270
271void Layer::SetLayerSaturation(float saturation) {
272  layer_saturation_ = saturation;
273  SetLayerFilters();
274}
275
276void Layer::SetLayerBrightness(float brightness) {
277  GetAnimator()->SetBrightness(brightness);
278}
279
280float Layer::GetTargetBrightness() const {
281  if (animator_.get() && animator_->IsAnimatingProperty(
282      LayerAnimationElement::BRIGHTNESS)) {
283    return animator_->GetTargetBrightness();
284  }
285  return layer_brightness();
286}
287
288void Layer::SetLayerGrayscale(float grayscale) {
289  GetAnimator()->SetGrayscale(grayscale);
290}
291
292float Layer::GetTargetGrayscale() const {
293  if (animator_.get() && animator_->IsAnimatingProperty(
294      LayerAnimationElement::GRAYSCALE)) {
295    return animator_->GetTargetGrayscale();
296  }
297  return layer_grayscale();
298}
299
300void Layer::SetLayerInverted(bool inverted) {
301  layer_inverted_ = inverted;
302  SetLayerFilters();
303}
304
305void Layer::SetMaskLayer(Layer* layer_mask) {
306  // The provided mask should not have a layer mask itself.
307  DCHECK(!layer_mask ||
308         (!layer_mask->layer_mask_layer() &&
309          layer_mask->children().empty() &&
310          !layer_mask->layer_mask_back_link_));
311  DCHECK(!layer_mask_back_link_);
312  if (layer_mask_ == layer_mask)
313    return;
314  // We need to de-reference the currently linked object so that no problem
315  // arises if the mask layer gets deleted before this object.
316  if (layer_mask_)
317    layer_mask_->layer_mask_back_link_ = NULL;
318  layer_mask_ = layer_mask;
319  cc_layer_->SetMaskLayer(
320      layer_mask ? layer_mask->cc_layer() : NULL);
321  // We need to reference the linked object so that it can properly break the
322  // link to us when it gets deleted.
323  if (layer_mask) {
324    layer_mask->layer_mask_back_link_ = this;
325    layer_mask->OnDeviceScaleFactorChanged(device_scale_factor_);
326  }
327}
328
329void Layer::SetBackgroundZoom(float zoom, int inset) {
330  zoom_ = zoom;
331  zoom_inset_ = inset;
332
333  SetLayerBackgroundFilters();
334}
335
336void Layer::SetAlphaShape(scoped_ptr<SkRegion> region) {
337  alpha_shape_ = region.Pass();
338
339  SetLayerFilters();
340}
341
342void Layer::SetLayerFilters() {
343  cc::FilterOperations filters;
344  if (layer_saturation_) {
345    filters.Append(cc::FilterOperation::CreateSaturateFilter(
346        layer_saturation_));
347  }
348  if (layer_grayscale_) {
349    filters.Append(cc::FilterOperation::CreateGrayscaleFilter(
350        layer_grayscale_));
351  }
352  if (layer_inverted_)
353    filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
354  // Brightness goes last, because the resulting colors neeed clamping, which
355  // cause further color matrix filters to be applied separately. In this order,
356  // they all can be combined in a single pass.
357  if (layer_brightness_) {
358    filters.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter(
359        layer_brightness_));
360  }
361  if (alpha_shape_) {
362    filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter(
363            *alpha_shape_, 1.f, 0.f));
364  }
365
366  cc_layer_->SetFilters(filters);
367}
368
369void Layer::SetLayerBackgroundFilters() {
370  cc::FilterOperations filters;
371  if (zoom_ != 1)
372    filters.Append(cc::FilterOperation::CreateZoomFilter(zoom_, zoom_inset_));
373
374  if (background_blur_radius_) {
375    filters.Append(cc::FilterOperation::CreateBlurFilter(
376        background_blur_radius_));
377  }
378
379  cc_layer_->SetBackgroundFilters(filters);
380}
381
382float Layer::GetTargetOpacity() const {
383  if (animator_.get() && animator_->IsAnimatingProperty(
384      LayerAnimationElement::OPACITY))
385    return animator_->GetTargetOpacity();
386  return opacity();
387}
388
389void Layer::SetVisible(bool visible) {
390  GetAnimator()->SetVisibility(visible);
391}
392
393bool Layer::GetTargetVisibility() const {
394  if (animator_.get() && animator_->IsAnimatingProperty(
395      LayerAnimationElement::VISIBILITY))
396    return animator_->GetTargetVisibility();
397  return visible_;
398}
399
400bool Layer::IsDrawn() const {
401  const Layer* layer = this;
402  while (layer && layer->visible_)
403    layer = layer->parent_;
404  return layer == NULL;
405}
406
407bool Layer::ShouldDraw() const {
408  return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f;
409}
410
411// static
412void Layer::ConvertPointToLayer(const Layer* source,
413                                const Layer* target,
414                                gfx::Point* point) {
415  if (source == target)
416    return;
417
418  const Layer* root_layer = GetRoot(source);
419  CHECK_EQ(root_layer, GetRoot(target));
420
421  if (source != root_layer)
422    source->ConvertPointForAncestor(root_layer, point);
423  if (target != root_layer)
424    target->ConvertPointFromAncestor(root_layer, point);
425}
426
427bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor,
428                                         gfx::Transform* transform) const {
429  const Layer* p = this;
430  for (; p && p != ancestor; p = p->parent()) {
431    gfx::Transform translation;
432    translation.Translate(static_cast<float>(p->bounds().x()),
433                          static_cast<float>(p->bounds().y()));
434    // Use target transform so that result will be correct once animation is
435    // finished.
436    if (!p->GetTargetTransform().IsIdentity())
437      transform->ConcatTransform(p->GetTargetTransform());
438    transform->ConcatTransform(translation);
439  }
440  return p == ancestor;
441}
442
443void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
444  if (fills_bounds_opaquely_ == fills_bounds_opaquely)
445    return;
446
447  fills_bounds_opaquely_ = fills_bounds_opaquely;
448
449  cc_layer_->SetContentsOpaque(fills_bounds_opaquely);
450}
451
452void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) {
453  fills_bounds_completely_ = fills_bounds_completely;
454}
455
456void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
457  // Finish animations being handled by cc_layer_.
458  if (animator_.get()) {
459    animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
460    animator_->StopAnimatingProperty(LayerAnimationElement::OPACITY);
461  }
462
463  if (texture_layer_.get())
464    texture_layer_->ClearClient();
465  // TODO(piman): delegated_renderer_layer_ cleanup.
466
467  cc_layer_->RemoveAllChildren();
468  if (cc_layer_->parent()) {
469    cc_layer_->parent()->ReplaceChild(cc_layer_, new_layer);
470  }
471  cc_layer_->SetLayerClient(NULL);
472  cc_layer_->RemoveLayerAnimationEventObserver(this);
473  new_layer->SetOpacity(cc_layer_->opacity());
474  new_layer->SetTransform(cc_layer_->transform());
475  new_layer->SetPosition(cc_layer_->position());
476
477  cc_layer_ = new_layer.get();
478  content_layer_ = NULL;
479  solid_color_layer_ = NULL;
480  texture_layer_ = NULL;
481  delegated_renderer_layer_ = NULL;
482
483  cc_layer_->AddLayerAnimationEventObserver(this);
484  for (size_t i = 0; i < children_.size(); ++i) {
485    DCHECK(children_[i]->cc_layer_);
486    cc_layer_->AddChild(children_[i]->cc_layer_);
487  }
488  cc_layer_->SetLayerClient(this);
489  cc_layer_->SetAnchorPoint(gfx::PointF());
490  cc_layer_->SetContentsOpaque(fills_bounds_opaquely_);
491  cc_layer_->SetForceRenderSurface(force_render_surface_);
492  cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
493  cc_layer_->SetHideLayerAndSubtree(!visible_);
494}
495
496void Layer::SwitchCCLayerForTest() {
497  scoped_refptr<cc::Layer> new_layer;
498  if (Layer::UsingPictureLayer())
499    new_layer = cc::PictureLayer::Create(this);
500  else
501    new_layer = cc::ContentLayer::Create(this);
502  SwitchToLayer(new_layer);
503  content_layer_ = new_layer;
504}
505
506void Layer::SetTextureMailbox(
507    const cc::TextureMailbox& mailbox,
508    scoped_ptr<cc::SingleReleaseCallback> release_callback,
509    gfx::Size texture_size_in_dip) {
510  DCHECK_EQ(type_, LAYER_TEXTURED);
511  DCHECK(!solid_color_layer_.get());
512  DCHECK(mailbox.IsValid());
513  DCHECK(release_callback);
514  if (!texture_layer_) {
515    scoped_refptr<cc::TextureLayer> new_layer =
516        cc::TextureLayer::CreateForMailbox(this);
517    new_layer->SetFlipped(true);
518    SwitchToLayer(new_layer);
519    texture_layer_ = new_layer;
520  }
521  if (mailbox_release_callback_)
522    mailbox_release_callback_->Run(0, false);
523  mailbox_release_callback_ = release_callback.Pass();
524  mailbox_ = mailbox;
525  SetTextureSize(texture_size_in_dip);
526}
527
528void Layer::SetTextureSize(gfx::Size texture_size_in_dip) {
529  DCHECK(texture_layer_.get());
530  if (frame_size_in_dip_ == texture_size_in_dip)
531    return;
532  frame_size_in_dip_ = texture_size_in_dip;
533  RecomputeDrawsContentAndUVRect();
534  texture_layer_->SetNeedsDisplay();
535}
536
537void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider,
538                                    gfx::Size frame_size_in_dip) {
539  DCHECK_EQ(type_, LAYER_TEXTURED);
540
541  scoped_refptr<cc::DelegatedRendererLayer> new_layer =
542      cc::DelegatedRendererLayer::Create(frame_provider);
543  SwitchToLayer(new_layer);
544  delegated_renderer_layer_ = new_layer;
545
546  frame_size_in_dip_ = frame_size_in_dip;
547  RecomputeDrawsContentAndUVRect();
548}
549
550void Layer::SetShowPaintedContent() {
551  if (content_layer_.get())
552    return;
553
554  scoped_refptr<cc::Layer> new_layer;
555  if (Layer::UsingPictureLayer())
556    new_layer = cc::PictureLayer::Create(this);
557  else
558    new_layer = cc::ContentLayer::Create(this);
559  SwitchToLayer(new_layer);
560  content_layer_ = new_layer;
561
562  mailbox_ = cc::TextureMailbox();
563  if (mailbox_release_callback_) {
564    mailbox_release_callback_->Run(0, false);
565    mailbox_release_callback_.reset();
566  }
567  RecomputeDrawsContentAndUVRect();
568}
569
570void Layer::SetColor(SkColor color) { GetAnimator()->SetColor(color); }
571
572bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) {
573  if (type_ == LAYER_SOLID_COLOR || (!delegate_ && !mailbox_.IsValid()))
574    return false;
575
576  damaged_region_.op(invalid_rect.x(),
577                     invalid_rect.y(),
578                     invalid_rect.right(),
579                     invalid_rect.bottom(),
580                     SkRegion::kUnion_Op);
581  ScheduleDraw();
582  return true;
583}
584
585void Layer::ScheduleDraw() {
586  Compositor* compositor = GetCompositor();
587  if (compositor)
588    compositor->ScheduleDraw();
589}
590
591void Layer::SendDamagedRects() {
592  if ((delegate_ || mailbox_.IsValid()) && !damaged_region_.isEmpty()) {
593    for (SkRegion::Iterator iter(damaged_region_); !iter.done(); iter.next()) {
594      const SkIRect& sk_damaged = iter.rect();
595      gfx::Rect damaged(
596          sk_damaged.x(),
597          sk_damaged.y(),
598          sk_damaged.width(),
599          sk_damaged.height());
600      cc_layer_->SetNeedsDisplayRect(damaged);
601    }
602    damaged_region_.setEmpty();
603  }
604  for (size_t i = 0; i < children_.size(); ++i)
605    children_[i]->SendDamagedRects();
606}
607
608void Layer::SuppressPaint() {
609  if (!delegate_)
610    return;
611  delegate_ = NULL;
612  for (size_t i = 0; i < children_.size(); ++i)
613    children_[i]->SuppressPaint();
614}
615
616void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) {
617  if (device_scale_factor_ == device_scale_factor)
618    return;
619  if (animator_.get())
620    animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
621  device_scale_factor_ = device_scale_factor;
622  RecomputeDrawsContentAndUVRect();
623  RecomputePosition();
624  SchedulePaint(gfx::Rect(bounds_.size()));
625  if (delegate_)
626    delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
627  for (size_t i = 0; i < children_.size(); ++i)
628    children_[i]->OnDeviceScaleFactorChanged(device_scale_factor);
629  if (layer_mask_)
630    layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor);
631}
632
633void Layer::RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) {
634  cc_layer_->RequestCopyOfOutput(request.Pass());
635}
636
637void Layer::PaintContents(SkCanvas* sk_canvas,
638                          const gfx::Rect& clip,
639                          gfx::RectF* opaque,
640                          ContentLayerClient::GraphicsContextStatus gc_status) {
641  TRACE_EVENT0("ui", "Layer::PaintContents");
642  scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling(
643      sk_canvas, device_scale_factor_));
644  if (delegate_)
645    delegate_->OnPaintLayer(canvas.get());
646}
647
648bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; }
649
650bool Layer::PrepareTextureMailbox(
651    cc::TextureMailbox* mailbox,
652    scoped_ptr<cc::SingleReleaseCallback>* release_callback,
653    bool use_shared_memory) {
654  if (!mailbox_release_callback_)
655    return false;
656  *mailbox = mailbox_;
657  *release_callback = mailbox_release_callback_.Pass();
658  return true;
659}
660
661void Layer::SetForceRenderSurface(bool force) {
662  if (force_render_surface_ == force)
663    return;
664
665  force_render_surface_ = force;
666  cc_layer_->SetForceRenderSurface(force_render_surface_);
667}
668
669class LayerDebugInfo : public base::debug::ConvertableToTraceFormat {
670 public:
671  explicit LayerDebugInfo(std::string name) : name_(name) { }
672  virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE {
673    base::DictionaryValue dictionary;
674    dictionary.SetString("layer_name", name_);
675    base::JSONWriter::Write(&dictionary, out);
676  }
677
678 private:
679  virtual ~LayerDebugInfo() { }
680  std::string name_;
681};
682
683scoped_refptr<base::debug::ConvertableToTraceFormat> Layer::TakeDebugInfo() {
684  return new LayerDebugInfo(name_);
685}
686
687void Layer::OnAnimationStarted(const cc::AnimationEvent& event) {
688  if (animator_.get())
689    animator_->OnThreadedAnimationStarted(event);
690}
691
692void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) {
693  DCHECK_NE(child, other);
694  DCHECK_EQ(this, child->parent());
695  DCHECK_EQ(this, other->parent());
696
697  const size_t child_i =
698      std::find(children_.begin(), children_.end(), child) - children_.begin();
699  const size_t other_i =
700      std::find(children_.begin(), children_.end(), other) - children_.begin();
701  if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i))
702    return;
703
704  const size_t dest_i =
705      above ?
706      (child_i < other_i ? other_i : other_i + 1) :
707      (child_i < other_i ? other_i - 1 : other_i);
708  children_.erase(children_.begin() + child_i);
709  children_.insert(children_.begin() + dest_i, child);
710
711  child->cc_layer_->RemoveFromParent();
712  cc_layer_->InsertChild(child->cc_layer_, dest_i);
713}
714
715bool Layer::ConvertPointForAncestor(const Layer* ancestor,
716                                    gfx::Point* point) const {
717  gfx::Transform transform;
718  bool result = GetTargetTransformRelativeTo(ancestor, &transform);
719  gfx::Point3F p(*point);
720  transform.TransformPoint(&p);
721  *point = gfx::ToFlooredPoint(p.AsPointF());
722  return result;
723}
724
725bool Layer::ConvertPointFromAncestor(const Layer* ancestor,
726                                     gfx::Point* point) const {
727  gfx::Transform transform;
728  bool result = GetTargetTransformRelativeTo(ancestor, &transform);
729  gfx::Point3F p(*point);
730  transform.TransformPointReverse(&p);
731  *point = gfx::ToFlooredPoint(p.AsPointF());
732  return result;
733}
734
735void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) {
736  if (bounds == bounds_)
737    return;
738
739  base::Closure closure;
740  if (delegate_)
741    closure = delegate_->PrepareForLayerBoundsChange();
742  bool was_move = bounds_.size() == bounds.size();
743  bounds_ = bounds;
744
745  RecomputeDrawsContentAndUVRect();
746  RecomputePosition();
747
748  if (!closure.is_null())
749    closure.Run();
750
751  if (was_move) {
752    // Don't schedule a draw if we're invisible. We'll schedule one
753    // automatically when we get visible.
754    if (IsDrawn())
755      ScheduleDraw();
756  } else {
757    // Always schedule a paint, even if we're invisible.
758    SchedulePaint(gfx::Rect(bounds.size()));
759  }
760}
761
762void Layer::SetTransformFromAnimation(const gfx::Transform& transform) {
763  cc_layer_->SetTransform(transform);
764}
765
766void Layer::SetOpacityFromAnimation(float opacity) {
767  cc_layer_->SetOpacity(opacity);
768  ScheduleDraw();
769}
770
771void Layer::SetVisibilityFromAnimation(bool visible) {
772  if (visible_ == visible)
773    return;
774
775  visible_ = visible;
776  cc_layer_->SetHideLayerAndSubtree(!visible_);
777}
778
779void Layer::SetBrightnessFromAnimation(float brightness) {
780  layer_brightness_ = brightness;
781  SetLayerFilters();
782}
783
784void Layer::SetGrayscaleFromAnimation(float grayscale) {
785  layer_grayscale_ = grayscale;
786  SetLayerFilters();
787}
788
789void Layer::SetColorFromAnimation(SkColor color) {
790  DCHECK_EQ(type_, LAYER_SOLID_COLOR);
791  solid_color_layer_->SetBackgroundColor(color);
792  SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF);
793}
794
795void Layer::ScheduleDrawForAnimation() {
796  ScheduleDraw();
797}
798
799const gfx::Rect& Layer::GetBoundsForAnimation() const {
800  return bounds();
801}
802
803gfx::Transform Layer::GetTransformForAnimation() const {
804  return transform();
805}
806
807float Layer::GetOpacityForAnimation() const {
808  return opacity();
809}
810
811bool Layer::GetVisibilityForAnimation() const {
812  return visible();
813}
814
815float Layer::GetBrightnessForAnimation() const {
816  return layer_brightness();
817}
818
819float Layer::GetGrayscaleForAnimation() const {
820  return layer_grayscale();
821}
822
823SkColor Layer::GetColorForAnimation() const {
824  // WebColor is equivalent to SkColor, per WebColor.h.
825  // The NULL check is here since this is invoked regardless of whether we have
826  // been configured as LAYER_SOLID_COLOR.
827  return solid_color_layer_.get() ?
828      solid_color_layer_->background_color() : SK_ColorBLACK;
829}
830
831float Layer::GetDeviceScaleFactor() const {
832  return device_scale_factor_;
833}
834
835void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) {
836  DCHECK(cc_layer_);
837  // Until this layer has a compositor (and hence cc_layer_ has a
838  // LayerTreeHost), addAnimation will fail.
839  if (GetCompositor())
840    cc_layer_->AddAnimation(animation.Pass());
841  else
842    pending_threaded_animations_.push_back(animation.Pass());
843}
844
845namespace{
846
847struct HasAnimationId {
848  HasAnimationId(int id): id_(id) {
849  }
850
851  bool operator()(cc::Animation* animation) const {
852    return animation->id() == id_;
853  }
854
855 private:
856  int id_;
857};
858
859}
860
861void Layer::RemoveThreadedAnimation(int animation_id) {
862  DCHECK(cc_layer_);
863  if (pending_threaded_animations_.size() == 0) {
864    cc_layer_->RemoveAnimation(animation_id);
865    return;
866  }
867
868  pending_threaded_animations_.erase(
869      cc::remove_if(&pending_threaded_animations_,
870                    pending_threaded_animations_.begin(),
871                    pending_threaded_animations_.end(),
872                    HasAnimationId(animation_id)),
873      pending_threaded_animations_.end());
874}
875
876void Layer::SendPendingThreadedAnimations() {
877  for (cc::ScopedPtrVector<cc::Animation>::iterator it =
878           pending_threaded_animations_.begin();
879       it != pending_threaded_animations_.end();
880       ++it)
881    cc_layer_->AddAnimation(pending_threaded_animations_.take(it));
882
883  pending_threaded_animations_.clear();
884
885  for (size_t i = 0; i < children_.size(); ++i)
886    children_[i]->SendPendingThreadedAnimations();
887}
888
889void Layer::CreateWebLayer() {
890  if (type_ == LAYER_SOLID_COLOR) {
891    solid_color_layer_ = cc::SolidColorLayer::Create();
892    cc_layer_ = solid_color_layer_.get();
893  } else {
894    if (Layer::UsingPictureLayer())
895      content_layer_ = cc::PictureLayer::Create(this);
896    else
897      content_layer_ = cc::ContentLayer::Create(this);
898    cc_layer_ = content_layer_.get();
899  }
900  cc_layer_->SetAnchorPoint(gfx::PointF());
901  cc_layer_->SetContentsOpaque(true);
902  cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
903  cc_layer_->AddLayerAnimationEventObserver(this);
904  cc_layer_->SetLayerClient(this);
905  RecomputePosition();
906}
907
908gfx::Transform Layer::transform() const {
909  return cc_layer_->transform();
910}
911
912void Layer::RecomputeDrawsContentAndUVRect() {
913  DCHECK(cc_layer_);
914  gfx::Size size(bounds_.size());
915  if (texture_layer_.get()) {
916    size.SetToMin(frame_size_in_dip_);
917    gfx::PointF uv_top_left(0.f, 0.f);
918    gfx::PointF uv_bottom_right(
919        static_cast<float>(size.width()) / frame_size_in_dip_.width(),
920        static_cast<float>(size.height()) / frame_size_in_dip_.height());
921    texture_layer_->SetUV(uv_top_left, uv_bottom_right);
922  } else if (delegated_renderer_layer_.get()) {
923    size.SetToMin(frame_size_in_dip_);
924    delegated_renderer_layer_->SetDisplaySize(frame_size_in_dip_);
925  }
926  cc_layer_->SetBounds(size);
927}
928
929void Layer::RecomputePosition() {
930  cc_layer_->SetPosition(gfx::PointF(bounds_.x(), bounds_.y()));
931}
932
933}  // namespace ui
934