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