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