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