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