layer.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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::SetAlphaShape(scoped_ptr<SkRegion> region) {
333  alpha_shape_ = region.Pass();
334
335  SetLayerFilters();
336}
337
338void Layer::SetLayerFilters() {
339  cc::FilterOperations filters;
340  if (layer_saturation_) {
341    filters.Append(cc::FilterOperation::CreateSaturateFilter(
342        layer_saturation_));
343  }
344  if (layer_grayscale_) {
345    filters.Append(cc::FilterOperation::CreateGrayscaleFilter(
346        layer_grayscale_));
347  }
348  if (layer_inverted_)
349    filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
350  // Brightness goes last, because the resulting colors neeed clamping, which
351  // cause further color matrix filters to be applied separately. In this order,
352  // they all can be combined in a single pass.
353  if (layer_brightness_) {
354    filters.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter(
355        layer_brightness_));
356  }
357  if (alpha_shape_) {
358    filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter(
359            *alpha_shape_, 1.f, 0.f));
360  }
361
362  cc_layer_->SetFilters(filters);
363}
364
365void Layer::SetLayerBackgroundFilters() {
366  cc::FilterOperations filters;
367  if (zoom_ != 1)
368    filters.Append(cc::FilterOperation::CreateZoomFilter(zoom_, zoom_inset_));
369
370  if (background_blur_radius_) {
371    filters.Append(cc::FilterOperation::CreateBlurFilter(
372        background_blur_radius_));
373  }
374
375  cc_layer_->SetBackgroundFilters(filters);
376}
377
378float Layer::GetTargetOpacity() const {
379  if (animator_.get() && animator_->IsAnimatingProperty(
380      LayerAnimationElement::OPACITY))
381    return animator_->GetTargetOpacity();
382  return opacity();
383}
384
385void Layer::SetVisible(bool visible) {
386  GetAnimator()->SetVisibility(visible);
387}
388
389bool Layer::GetTargetVisibility() const {
390  if (animator_.get() && animator_->IsAnimatingProperty(
391      LayerAnimationElement::VISIBILITY))
392    return animator_->GetTargetVisibility();
393  return visible_;
394}
395
396bool Layer::IsDrawn() const {
397  const Layer* layer = this;
398  while (layer && layer->visible_)
399    layer = layer->parent_;
400  return layer == NULL;
401}
402
403bool Layer::ShouldDraw() const {
404  return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f;
405}
406
407// static
408void Layer::ConvertPointToLayer(const Layer* source,
409                                const Layer* target,
410                                gfx::Point* point) {
411  if (source == target)
412    return;
413
414  const Layer* root_layer = GetRoot(source);
415  CHECK_EQ(root_layer, GetRoot(target));
416
417  if (source != root_layer)
418    source->ConvertPointForAncestor(root_layer, point);
419  if (target != root_layer)
420    target->ConvertPointFromAncestor(root_layer, point);
421}
422
423bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor,
424                                         gfx::Transform* transform) const {
425  const Layer* p = this;
426  for (; p && p != ancestor; p = p->parent()) {
427    gfx::Transform translation;
428    translation.Translate(static_cast<float>(p->bounds().x()),
429                          static_cast<float>(p->bounds().y()));
430    // Use target transform so that result will be correct once animation is
431    // finished.
432    if (!p->GetTargetTransform().IsIdentity())
433      transform->ConcatTransform(p->GetTargetTransform());
434    transform->ConcatTransform(translation);
435  }
436  return p == ancestor;
437}
438
439// static
440gfx::Transform Layer::ConvertTransformToCCTransform(
441    const gfx::Transform& transform,
442    float device_scale_factor) {
443  gfx::Transform cc_transform;
444  cc_transform.Scale(device_scale_factor, device_scale_factor);
445  cc_transform.PreconcatTransform(transform);
446  cc_transform.Scale(1.0f / device_scale_factor, 1.0f / device_scale_factor);
447  return cc_transform;
448}
449
450void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
451  if (fills_bounds_opaquely_ == fills_bounds_opaquely)
452    return;
453
454  fills_bounds_opaquely_ = fills_bounds_opaquely;
455
456  cc_layer_->SetContentsOpaque(fills_bounds_opaquely);
457}
458
459void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) {
460  fills_bounds_completely_ = fills_bounds_completely;
461}
462
463void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
464  // Finish animations being handled by cc_layer_.
465  if (animator_.get()) {
466    animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
467    animator_->StopAnimatingProperty(LayerAnimationElement::OPACITY);
468  }
469
470  if (texture_layer_.get())
471    texture_layer_->ClearClient();
472  // TODO(piman): delegated_renderer_layer_ cleanup.
473
474  cc_layer_->RemoveAllChildren();
475  if (parent_) {
476    DCHECK(parent_->cc_layer_);
477    parent_->cc_layer_->ReplaceChild(cc_layer_, new_layer);
478  }
479  cc_layer_->SetLayerClient(NULL);
480  cc_layer_->RemoveLayerAnimationEventObserver(this);
481  new_layer->SetOpacity(cc_layer_->opacity());
482  new_layer->SetTransform(cc_layer_->transform());
483  new_layer->SetPosition(cc_layer_->position());
484
485  cc_layer_ = new_layer.get();
486  content_layer_ = NULL;
487  solid_color_layer_ = NULL;
488  texture_layer_ = NULL;
489  delegated_renderer_layer_ = NULL;
490
491  cc_layer_->AddLayerAnimationEventObserver(this);
492  for (size_t i = 0; i < children_.size(); ++i) {
493    DCHECK(children_[i]->cc_layer_);
494    cc_layer_->AddChild(children_[i]->cc_layer_);
495  }
496  cc_layer_->SetLayerClient(this);
497  cc_layer_->SetAnchorPoint(gfx::PointF());
498  cc_layer_->SetContentsOpaque(fills_bounds_opaquely_);
499  cc_layer_->SetForceRenderSurface(force_render_surface_);
500  cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
501  cc_layer_->SetHideLayerAndSubtree(!visible_);
502}
503
504void Layer::SwitchCCLayerForTest() {
505  scoped_refptr<cc::Layer> new_layer;
506  if (Layer::UsingPictureLayer())
507    new_layer = cc::PictureLayer::Create(this);
508  else
509    new_layer = cc::ContentLayer::Create(this);
510  SwitchToLayer(new_layer);
511  content_layer_ = new_layer;
512}
513
514void Layer::SetTextureMailbox(
515    const cc::TextureMailbox& mailbox,
516    scoped_ptr<cc::SingleReleaseCallback> release_callback,
517    gfx::Size texture_size_in_dip) {
518  DCHECK_EQ(type_, LAYER_TEXTURED);
519  DCHECK(!solid_color_layer_.get());
520  DCHECK(mailbox.IsValid());
521  DCHECK(release_callback);
522  if (!texture_layer_) {
523    scoped_refptr<cc::TextureLayer> new_layer =
524        cc::TextureLayer::CreateForMailbox(this);
525    new_layer->SetFlipped(true);
526    SwitchToLayer(new_layer);
527    texture_layer_ = new_layer;
528  }
529  if (mailbox_release_callback_)
530    mailbox_release_callback_->Run(0, false);
531  mailbox_release_callback_ = release_callback.Pass();
532  mailbox_ = mailbox;
533  SetTextureSize(texture_size_in_dip);
534}
535
536void Layer::SetTextureSize(gfx::Size texture_size_in_dip) {
537  DCHECK(texture_layer_.get());
538  if (frame_size_in_dip_ == texture_size_in_dip)
539    return;
540  frame_size_in_dip_ = texture_size_in_dip;
541  RecomputeDrawsContentAndUVRect();
542  texture_layer_->SetNeedsDisplay();
543}
544
545void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider,
546                                    gfx::Size frame_size_in_dip) {
547  DCHECK_EQ(type_, LAYER_TEXTURED);
548
549  scoped_refptr<cc::DelegatedRendererLayer> new_layer =
550      cc::DelegatedRendererLayer::Create(frame_provider);
551  SwitchToLayer(new_layer);
552  delegated_renderer_layer_ = new_layer;
553
554  frame_size_in_dip_ = frame_size_in_dip;
555  RecomputeDrawsContentAndUVRect();
556}
557
558void Layer::SetShowPaintedContent() {
559  if (content_layer_.get())
560    return;
561
562  scoped_refptr<cc::Layer> new_layer;
563  if (Layer::UsingPictureLayer())
564    new_layer = cc::PictureLayer::Create(this);
565  else
566    new_layer = cc::ContentLayer::Create(this);
567  SwitchToLayer(new_layer);
568  content_layer_ = new_layer;
569
570  mailbox_ = cc::TextureMailbox();
571  if (mailbox_release_callback_) {
572    mailbox_release_callback_->Run(0, false);
573    mailbox_release_callback_.reset();
574  }
575  RecomputeDrawsContentAndUVRect();
576}
577
578void Layer::SetColor(SkColor color) { GetAnimator()->SetColor(color); }
579
580bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) {
581  if (type_ == LAYER_SOLID_COLOR || (!delegate_ && !mailbox_.IsValid()))
582    return false;
583
584  damaged_region_.op(invalid_rect.x(),
585                     invalid_rect.y(),
586                     invalid_rect.right(),
587                     invalid_rect.bottom(),
588                     SkRegion::kUnion_Op);
589  ScheduleDraw();
590  return true;
591}
592
593void Layer::ScheduleDraw() {
594  Compositor* compositor = GetCompositor();
595  if (compositor)
596    compositor->ScheduleDraw();
597}
598
599void Layer::SendDamagedRects() {
600  if ((delegate_ || mailbox_.IsValid()) && !damaged_region_.isEmpty()) {
601    for (SkRegion::Iterator iter(damaged_region_); !iter.done(); iter.next()) {
602      const SkIRect& sk_damaged = iter.rect();
603      gfx::Rect damaged(
604          sk_damaged.x(),
605          sk_damaged.y(),
606          sk_damaged.width(),
607          sk_damaged.height());
608
609      gfx::Rect damaged_in_pixel = ConvertRectToPixel(this, damaged);
610      cc_layer_->SetNeedsDisplayRect(damaged_in_pixel);
611    }
612    damaged_region_.setEmpty();
613  }
614  for (size_t i = 0; i < children_.size(); ++i)
615    children_[i]->SendDamagedRects();
616}
617
618void Layer::SuppressPaint() {
619  if (!delegate_)
620    return;
621  delegate_ = NULL;
622  for (size_t i = 0; i < children_.size(); ++i)
623    children_[i]->SuppressPaint();
624}
625
626void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) {
627  if (device_scale_factor_ == device_scale_factor)
628    return;
629  if (animator_.get())
630    animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
631  gfx::Transform transform = this->transform();
632  device_scale_factor_ = device_scale_factor;
633  RecomputeCCTransformFromTransform(transform);
634  RecomputeDrawsContentAndUVRect();
635  RecomputePosition();
636  SchedulePaint(gfx::Rect(bounds_.size()));
637  if (delegate_)
638    delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
639  for (size_t i = 0; i < children_.size(); ++i)
640    children_[i]->OnDeviceScaleFactorChanged(device_scale_factor);
641  if (layer_mask_)
642    layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor);
643}
644
645void Layer::RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) {
646  cc_layer_->RequestCopyOfOutput(request.Pass());
647}
648
649void Layer::PaintContents(SkCanvas* sk_canvas,
650                          const gfx::Rect& clip,
651                          gfx::RectF* opaque) {
652  TRACE_EVENT0("ui", "Layer::PaintContents");
653  scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling(
654      sk_canvas, device_scale_factor_));
655
656  bool scale_content = scale_content_;
657  if (scale_content) {
658    canvas->Save();
659    canvas->sk_canvas()->scale(SkFloatToScalar(device_scale_factor_),
660                               SkFloatToScalar(device_scale_factor_));
661  }
662
663  if (delegate_)
664    delegate_->OnPaintLayer(canvas.get());
665  if (scale_content)
666    canvas->Restore();
667}
668
669bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; }
670
671bool Layer::PrepareTextureMailbox(
672    cc::TextureMailbox* mailbox,
673    scoped_ptr<cc::SingleReleaseCallback>* release_callback,
674    bool use_shared_memory) {
675  if (!mailbox_release_callback_)
676    return false;
677  *mailbox = mailbox_;
678  *release_callback = mailbox_release_callback_.Pass();
679  return true;
680}
681
682void Layer::SetForceRenderSurface(bool force) {
683  if (force_render_surface_ == force)
684    return;
685
686  force_render_surface_ = force;
687  cc_layer_->SetForceRenderSurface(force_render_surface_);
688}
689
690class LayerDebugInfo : public base::debug::ConvertableToTraceFormat {
691 public:
692  explicit LayerDebugInfo(std::string name) : name_(name) { }
693  virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE {
694    base::DictionaryValue dictionary;
695    dictionary.SetString("layer_name", name_);
696    base::JSONWriter::Write(&dictionary, out);
697  }
698
699 private:
700  virtual ~LayerDebugInfo() { }
701  std::string name_;
702};
703
704scoped_refptr<base::debug::ConvertableToTraceFormat> Layer::TakeDebugInfo() {
705  return new LayerDebugInfo(name_);
706}
707
708void Layer::OnAnimationStarted(const cc::AnimationEvent& event) {
709  if (animator_.get())
710    animator_->OnThreadedAnimationStarted(event);
711}
712
713void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) {
714  DCHECK_NE(child, other);
715  DCHECK_EQ(this, child->parent());
716  DCHECK_EQ(this, other->parent());
717
718  const size_t child_i =
719      std::find(children_.begin(), children_.end(), child) - children_.begin();
720  const size_t other_i =
721      std::find(children_.begin(), children_.end(), other) - children_.begin();
722  if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i))
723    return;
724
725  const size_t dest_i =
726      above ?
727      (child_i < other_i ? other_i : other_i + 1) :
728      (child_i < other_i ? other_i - 1 : other_i);
729  children_.erase(children_.begin() + child_i);
730  children_.insert(children_.begin() + dest_i, child);
731
732  child->cc_layer_->RemoveFromParent();
733  cc_layer_->InsertChild(child->cc_layer_, dest_i);
734}
735
736bool Layer::ConvertPointForAncestor(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.TransformPoint(&p);
742  *point = gfx::ToFlooredPoint(p.AsPointF());
743  return result;
744}
745
746bool Layer::ConvertPointFromAncestor(const Layer* ancestor,
747                                     gfx::Point* point) const {
748  gfx::Transform transform;
749  bool result = GetTargetTransformRelativeTo(ancestor, &transform);
750  gfx::Point3F p(*point);
751  transform.TransformPointReverse(&p);
752  *point = gfx::ToFlooredPoint(p.AsPointF());
753  return result;
754}
755
756void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) {
757  if (bounds == bounds_)
758    return;
759
760  base::Closure closure;
761  if (delegate_)
762    closure = delegate_->PrepareForLayerBoundsChange();
763  bool was_move = bounds_.size() == bounds.size();
764  bounds_ = bounds;
765
766  RecomputeDrawsContentAndUVRect();
767  RecomputePosition();
768
769  if (!closure.is_null())
770    closure.Run();
771
772  if (was_move) {
773    // Don't schedule a draw if we're invisible. We'll schedule one
774    // automatically when we get visible.
775    if (IsDrawn())
776      ScheduleDraw();
777  } else {
778    // Always schedule a paint, even if we're invisible.
779    SchedulePaint(gfx::Rect(bounds.size()));
780  }
781}
782
783void Layer::SetTransformFromAnimation(const gfx::Transform& transform) {
784  RecomputeCCTransformFromTransform(transform);
785}
786
787void Layer::SetOpacityFromAnimation(float opacity) {
788  cc_layer_->SetOpacity(opacity);
789  ScheduleDraw();
790}
791
792void Layer::SetVisibilityFromAnimation(bool visible) {
793  if (visible_ == visible)
794    return;
795
796  visible_ = visible;
797  cc_layer_->SetHideLayerAndSubtree(!visible_);
798}
799
800void Layer::SetBrightnessFromAnimation(float brightness) {
801  layer_brightness_ = brightness;
802  SetLayerFilters();
803}
804
805void Layer::SetGrayscaleFromAnimation(float grayscale) {
806  layer_grayscale_ = grayscale;
807  SetLayerFilters();
808}
809
810void Layer::SetColorFromAnimation(SkColor color) {
811  DCHECK_EQ(type_, LAYER_SOLID_COLOR);
812  solid_color_layer_->SetBackgroundColor(color);
813  SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF);
814}
815
816void Layer::ScheduleDrawForAnimation() {
817  ScheduleDraw();
818}
819
820const gfx::Rect& Layer::GetBoundsForAnimation() const {
821  return bounds();
822}
823
824gfx::Transform Layer::GetTransformForAnimation() const {
825  return transform();
826}
827
828float Layer::GetOpacityForAnimation() const {
829  return opacity();
830}
831
832bool Layer::GetVisibilityForAnimation() const {
833  return visible();
834}
835
836float Layer::GetBrightnessForAnimation() const {
837  return layer_brightness();
838}
839
840float Layer::GetGrayscaleForAnimation() const {
841  return layer_grayscale();
842}
843
844SkColor Layer::GetColorForAnimation() const {
845  // WebColor is equivalent to SkColor, per WebColor.h.
846  // The NULL check is here since this is invoked regardless of whether we have
847  // been configured as LAYER_SOLID_COLOR.
848  return solid_color_layer_.get() ?
849      solid_color_layer_->background_color() : SK_ColorBLACK;
850}
851
852float Layer::GetDeviceScaleFactor() const {
853  return device_scale_factor_;
854}
855
856void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) {
857  DCHECK(cc_layer_);
858  // Until this layer has a compositor (and hence cc_layer_ has a
859  // LayerTreeHost), addAnimation will fail.
860  if (GetCompositor())
861    cc_layer_->AddAnimation(animation.Pass());
862  else
863    pending_threaded_animations_.push_back(animation.Pass());
864}
865
866namespace{
867
868struct HasAnimationId {
869  HasAnimationId(int id): id_(id) {
870  }
871
872  bool operator()(cc::Animation* animation) const {
873    return animation->id() == id_;
874  }
875
876 private:
877  int id_;
878};
879
880}
881
882void Layer::RemoveThreadedAnimation(int animation_id) {
883  DCHECK(cc_layer_);
884  if (pending_threaded_animations_.size() == 0) {
885    cc_layer_->RemoveAnimation(animation_id);
886    return;
887  }
888
889  pending_threaded_animations_.erase(
890      cc::remove_if(&pending_threaded_animations_,
891                    pending_threaded_animations_.begin(),
892                    pending_threaded_animations_.end(),
893                    HasAnimationId(animation_id)),
894      pending_threaded_animations_.end());
895}
896
897void Layer::SendPendingThreadedAnimations() {
898  for (cc::ScopedPtrVector<cc::Animation>::iterator it =
899           pending_threaded_animations_.begin();
900       it != pending_threaded_animations_.end();
901       ++it)
902    cc_layer_->AddAnimation(pending_threaded_animations_.take(it));
903
904  pending_threaded_animations_.clear();
905
906  for (size_t i = 0; i < children_.size(); ++i)
907    children_[i]->SendPendingThreadedAnimations();
908}
909
910void Layer::CreateWebLayer() {
911  if (type_ == LAYER_SOLID_COLOR) {
912    solid_color_layer_ = cc::SolidColorLayer::Create();
913    cc_layer_ = solid_color_layer_.get();
914  } else {
915    if (Layer::UsingPictureLayer())
916      content_layer_ = cc::PictureLayer::Create(this);
917    else
918      content_layer_ = cc::ContentLayer::Create(this);
919    cc_layer_ = content_layer_.get();
920  }
921  cc_layer_->SetAnchorPoint(gfx::PointF());
922  cc_layer_->SetContentsOpaque(true);
923  cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
924  cc_layer_->AddLayerAnimationEventObserver(this);
925  cc_layer_->SetLayerClient(this);
926  RecomputePosition();
927}
928
929void Layer::RecomputeCCTransformFromTransform(const gfx::Transform& transform) {
930  cc_layer_->SetTransform(ConvertTransformToCCTransform(transform,
931                                                        device_scale_factor_));
932}
933
934gfx::Transform Layer::transform() const {
935  gfx::Transform transform;
936  transform.Scale(1.0f / device_scale_factor_, 1.0f / device_scale_factor_);
937  transform.PreconcatTransform(cc_layer_->transform());
938  transform.Scale(device_scale_factor_, device_scale_factor_);
939  return transform;
940}
941
942void Layer::RecomputeDrawsContentAndUVRect() {
943  DCHECK(cc_layer_);
944  gfx::Size size(bounds_.size());
945  if (texture_layer_.get()) {
946    size.SetToMin(frame_size_in_dip_);
947    gfx::PointF uv_top_left(0.f, 0.f);
948    gfx::PointF uv_bottom_right(
949        static_cast<float>(size.width()) / frame_size_in_dip_.width(),
950        static_cast<float>(size.height()) / frame_size_in_dip_.height());
951    texture_layer_->SetUV(uv_top_left, uv_bottom_right);
952  } else if (delegated_renderer_layer_.get()) {
953    size.SetToMin(frame_size_in_dip_);
954    delegated_renderer_layer_->SetDisplaySize(
955        ConvertSizeToPixel(this, frame_size_in_dip_));
956  }
957  cc_layer_->SetBounds(ConvertSizeToPixel(this, size));
958}
959
960void Layer::RecomputePosition() {
961  cc_layer_->SetPosition(gfx::ScalePoint(
962        gfx::PointF(bounds_.x(), bounds_.y()),
963        device_scale_factor_));
964}
965
966}  // namespace ui
967