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