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