Correct the way that ui::Layers are reparented
[chromium-blink-merge.git] / ui / compositor / layer.cc
blobca3ff288ee293a43b49d39bee0f6f97311e6a0cd
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.
5 #include "ui/compositor/layer.h"
7 #include <algorithm>
9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h"
11 #include "base/json/json_writer.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "cc/base/scoped_ptr_algorithm.h"
15 #include "cc/layers/content_layer.h"
16 #include "cc/layers/delegated_renderer_layer.h"
17 #include "cc/layers/picture_layer.h"
18 #include "cc/layers/solid_color_layer.h"
19 #include "cc/layers/texture_layer.h"
20 #include "cc/output/copy_output_request.h"
21 #include "cc/output/delegated_frame_data.h"
22 #include "cc/output/filter_operation.h"
23 #include "cc/output/filter_operations.h"
24 #include "cc/resources/transferable_resource.h"
25 #include "ui/compositor/compositor_switches.h"
26 #include "ui/compositor/dip_util.h"
27 #include "ui/compositor/layer_animator.h"
28 #include "ui/gfx/animation/animation.h"
29 #include "ui/gfx/canvas.h"
30 #include "ui/gfx/display.h"
31 #include "ui/gfx/interpolated_transform.h"
32 #include "ui/gfx/point3_f.h"
33 #include "ui/gfx/point_conversions.h"
34 #include "ui/gfx/size_conversions.h"
36 namespace {
38 const ui::Layer* GetRoot(const ui::Layer* layer) {
39 while (layer->parent())
40 layer = layer->parent();
41 return layer;
44 struct UIImplSidePaintingStatus {
45 UIImplSidePaintingStatus()
46 : enabled(ui::IsUIImplSidePaintingEnabled()) {
48 bool enabled;
50 base::LazyInstance<UIImplSidePaintingStatus> g_ui_impl_side_painting_status =
51 LAZY_INSTANCE_INITIALIZER;
53 } // namespace
55 namespace ui {
57 Layer::Layer()
58 : type_(LAYER_TEXTURED),
59 compositor_(NULL),
60 parent_(NULL),
61 visible_(true),
62 force_render_surface_(false),
63 fills_bounds_opaquely_(true),
64 fills_bounds_completely_(false),
65 background_blur_radius_(0),
66 layer_saturation_(0.0f),
67 layer_brightness_(0.0f),
68 layer_grayscale_(0.0f),
69 layer_inverted_(false),
70 layer_mask_(NULL),
71 layer_mask_back_link_(NULL),
72 zoom_(1),
73 zoom_inset_(0),
74 delegate_(NULL),
75 owner_(NULL),
76 cc_layer_(NULL),
77 device_scale_factor_(1.0f) {
78 CreateWebLayer();
81 Layer::Layer(LayerType type)
82 : type_(type),
83 compositor_(NULL),
84 parent_(NULL),
85 visible_(true),
86 force_render_surface_(false),
87 fills_bounds_opaquely_(true),
88 fills_bounds_completely_(false),
89 background_blur_radius_(0),
90 layer_saturation_(0.0f),
91 layer_brightness_(0.0f),
92 layer_grayscale_(0.0f),
93 layer_inverted_(false),
94 layer_mask_(NULL),
95 layer_mask_back_link_(NULL),
96 zoom_(1),
97 zoom_inset_(0),
98 delegate_(NULL),
99 owner_(NULL),
100 cc_layer_(NULL),
101 device_scale_factor_(1.0f) {
102 CreateWebLayer();
105 Layer::~Layer() {
106 // Destroying the animator may cause observers to use the layer (and
107 // indirectly the WebLayer). Destroy the animator first so that the WebLayer
108 // is still around.
109 if (animator_.get())
110 animator_->SetDelegate(NULL);
111 animator_ = NULL;
112 if (compositor_)
113 compositor_->SetRootLayer(NULL);
114 if (parent_)
115 parent_->Remove(this);
116 if (layer_mask_)
117 SetMaskLayer(NULL);
118 if (layer_mask_back_link_)
119 layer_mask_back_link_->SetMaskLayer(NULL);
120 for (size_t i = 0; i < children_.size(); ++i)
121 children_[i]->parent_ = NULL;
122 cc_layer_->RemoveLayerAnimationEventObserver(this);
123 cc_layer_->RemoveFromParent();
126 // static
127 bool Layer::UsingPictureLayer() {
128 return g_ui_impl_side_painting_status.Get().enabled;
131 Compositor* Layer::GetCompositor() {
132 return GetRoot(this)->compositor_;
135 float Layer::opacity() const {
136 return cc_layer_->opacity();
139 void Layer::SetCompositor(Compositor* compositor) {
140 // This function must only be called to set the compositor on the root layer,
141 // or to reset it.
142 DCHECK(!compositor || !compositor_);
143 DCHECK(!compositor || compositor->root_layer() == this);
144 DCHECK(!parent_);
145 compositor_ = compositor;
146 if (compositor) {
147 OnDeviceScaleFactorChanged(compositor->device_scale_factor());
148 SendPendingThreadedAnimations();
152 void Layer::Add(Layer* child) {
153 DCHECK(!child->compositor_);
154 if (child->parent_)
155 child->parent_->Remove(child);
156 child->parent_ = this;
157 children_.push_back(child);
158 cc_layer_->AddChild(child->cc_layer_);
159 child->OnDeviceScaleFactorChanged(device_scale_factor_);
160 if (GetCompositor())
161 child->SendPendingThreadedAnimations();
164 void Layer::Remove(Layer* child) {
165 // Current bounds are used to calculate offsets when layers are reparented.
166 // Stop (and complete) an ongoing animation to update the bounds immediately.
167 if (child->GetAnimator()) {
168 child->GetAnimator()->StopAnimatingProperty(
169 ui::LayerAnimationElement::BOUNDS);
171 std::vector<Layer*>::iterator i =
172 std::find(children_.begin(), children_.end(), child);
173 DCHECK(i != children_.end());
174 children_.erase(i);
175 child->parent_ = NULL;
176 child->cc_layer_->RemoveFromParent();
179 void Layer::StackAtTop(Layer* child) {
180 if (children_.size() <= 1 || child == children_.back())
181 return; // Already in front.
182 StackAbove(child, children_.back());
185 void Layer::StackAbove(Layer* child, Layer* other) {
186 StackRelativeTo(child, other, true);
189 void Layer::StackAtBottom(Layer* child) {
190 if (children_.size() <= 1 || child == children_.front())
191 return; // Already on bottom.
192 StackBelow(child, children_.front());
195 void Layer::StackBelow(Layer* child, Layer* other) {
196 StackRelativeTo(child, other, false);
199 bool Layer::Contains(const Layer* other) const {
200 for (const Layer* parent = other; parent; parent = parent->parent()) {
201 if (parent == this)
202 return true;
204 return false;
207 void Layer::SetAnimator(LayerAnimator* animator) {
208 if (animator)
209 animator->SetDelegate(this);
210 animator_ = animator;
213 LayerAnimator* Layer::GetAnimator() {
214 if (!animator_.get())
215 SetAnimator(LayerAnimator::CreateDefaultAnimator());
216 return animator_.get();
219 void Layer::SetTransform(const gfx::Transform& transform) {
220 GetAnimator()->SetTransform(transform);
223 gfx::Transform Layer::GetTargetTransform() const {
224 if (animator_.get() && animator_->IsAnimatingProperty(
225 LayerAnimationElement::TRANSFORM)) {
226 return animator_->GetTargetTransform();
228 return transform();
231 void Layer::SetBounds(const gfx::Rect& bounds) {
232 GetAnimator()->SetBounds(bounds);
235 gfx::Rect Layer::GetTargetBounds() const {
236 if (animator_.get() && animator_->IsAnimatingProperty(
237 LayerAnimationElement::BOUNDS)) {
238 return animator_->GetTargetBounds();
240 return bounds_;
243 void Layer::SetMasksToBounds(bool masks_to_bounds) {
244 cc_layer_->SetMasksToBounds(masks_to_bounds);
247 bool Layer::GetMasksToBounds() const {
248 return cc_layer_->masks_to_bounds();
251 void Layer::SetOpacity(float opacity) {
252 GetAnimator()->SetOpacity(opacity);
255 float Layer::GetCombinedOpacity() const {
256 float opacity = this->opacity();
257 Layer* current = this->parent_;
258 while (current) {
259 opacity *= current->opacity();
260 current = current->parent_;
262 return opacity;
265 void Layer::SetBackgroundBlur(int blur_radius) {
266 background_blur_radius_ = blur_radius;
268 SetLayerBackgroundFilters();
271 void Layer::SetLayerSaturation(float saturation) {
272 layer_saturation_ = saturation;
273 SetLayerFilters();
276 void Layer::SetLayerBrightness(float brightness) {
277 GetAnimator()->SetBrightness(brightness);
280 float Layer::GetTargetBrightness() const {
281 if (animator_.get() && animator_->IsAnimatingProperty(
282 LayerAnimationElement::BRIGHTNESS)) {
283 return animator_->GetTargetBrightness();
285 return layer_brightness();
288 void Layer::SetLayerGrayscale(float grayscale) {
289 GetAnimator()->SetGrayscale(grayscale);
292 float Layer::GetTargetGrayscale() const {
293 if (animator_.get() && animator_->IsAnimatingProperty(
294 LayerAnimationElement::GRAYSCALE)) {
295 return animator_->GetTargetGrayscale();
297 return layer_grayscale();
300 void Layer::SetLayerInverted(bool inverted) {
301 layer_inverted_ = inverted;
302 SetLayerFilters();
305 void Layer::SetMaskLayer(Layer* layer_mask) {
306 // The provided mask should not have a layer mask itself.
307 DCHECK(!layer_mask ||
308 (!layer_mask->layer_mask_layer() &&
309 layer_mask->children().empty() &&
310 !layer_mask->layer_mask_back_link_));
311 DCHECK(!layer_mask_back_link_);
312 if (layer_mask_ == layer_mask)
313 return;
314 // We need to de-reference the currently linked object so that no problem
315 // arises if the mask layer gets deleted before this object.
316 if (layer_mask_)
317 layer_mask_->layer_mask_back_link_ = NULL;
318 layer_mask_ = layer_mask;
319 cc_layer_->SetMaskLayer(
320 layer_mask ? layer_mask->cc_layer() : NULL);
321 // We need to reference the linked object so that it can properly break the
322 // link to us when it gets deleted.
323 if (layer_mask) {
324 layer_mask->layer_mask_back_link_ = this;
325 layer_mask->OnDeviceScaleFactorChanged(device_scale_factor_);
329 void Layer::SetBackgroundZoom(float zoom, int inset) {
330 zoom_ = zoom;
331 zoom_inset_ = inset;
333 SetLayerBackgroundFilters();
336 void Layer::SetAlphaShape(scoped_ptr<SkRegion> region) {
337 alpha_shape_ = region.Pass();
339 SetLayerFilters();
342 void Layer::SetLayerFilters() {
343 cc::FilterOperations filters;
344 if (layer_saturation_) {
345 filters.Append(cc::FilterOperation::CreateSaturateFilter(
346 layer_saturation_));
348 if (layer_grayscale_) {
349 filters.Append(cc::FilterOperation::CreateGrayscaleFilter(
350 layer_grayscale_));
352 if (layer_inverted_)
353 filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
354 // Brightness goes last, because the resulting colors neeed clamping, which
355 // cause further color matrix filters to be applied separately. In this order,
356 // they all can be combined in a single pass.
357 if (layer_brightness_) {
358 filters.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter(
359 layer_brightness_));
361 if (alpha_shape_) {
362 filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter(
363 *alpha_shape_, 1.f, 0.f));
366 cc_layer_->SetFilters(filters);
369 void Layer::SetLayerBackgroundFilters() {
370 cc::FilterOperations filters;
371 if (zoom_ != 1)
372 filters.Append(cc::FilterOperation::CreateZoomFilter(zoom_, zoom_inset_));
374 if (background_blur_radius_) {
375 filters.Append(cc::FilterOperation::CreateBlurFilter(
376 background_blur_radius_));
379 cc_layer_->SetBackgroundFilters(filters);
382 float Layer::GetTargetOpacity() const {
383 if (animator_.get() && animator_->IsAnimatingProperty(
384 LayerAnimationElement::OPACITY))
385 return animator_->GetTargetOpacity();
386 return opacity();
389 void Layer::SetVisible(bool visible) {
390 GetAnimator()->SetVisibility(visible);
393 bool Layer::GetTargetVisibility() const {
394 if (animator_.get() && animator_->IsAnimatingProperty(
395 LayerAnimationElement::VISIBILITY))
396 return animator_->GetTargetVisibility();
397 return visible_;
400 bool Layer::IsDrawn() const {
401 const Layer* layer = this;
402 while (layer && layer->visible_)
403 layer = layer->parent_;
404 return layer == NULL;
407 bool Layer::ShouldDraw() const {
408 return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f;
411 // static
412 void Layer::ConvertPointToLayer(const Layer* source,
413 const Layer* target,
414 gfx::Point* point) {
415 if (source == target)
416 return;
418 const Layer* root_layer = GetRoot(source);
419 CHECK_EQ(root_layer, GetRoot(target));
421 if (source != root_layer)
422 source->ConvertPointForAncestor(root_layer, point);
423 if (target != root_layer)
424 target->ConvertPointFromAncestor(root_layer, point);
427 bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor,
428 gfx::Transform* transform) const {
429 const Layer* p = this;
430 for (; p && p != ancestor; p = p->parent()) {
431 gfx::Transform translation;
432 translation.Translate(static_cast<float>(p->bounds().x()),
433 static_cast<float>(p->bounds().y()));
434 // Use target transform so that result will be correct once animation is
435 // finished.
436 if (!p->GetTargetTransform().IsIdentity())
437 transform->ConcatTransform(p->GetTargetTransform());
438 transform->ConcatTransform(translation);
440 return p == ancestor;
443 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
444 if (fills_bounds_opaquely_ == fills_bounds_opaquely)
445 return;
447 fills_bounds_opaquely_ = fills_bounds_opaquely;
449 cc_layer_->SetContentsOpaque(fills_bounds_opaquely);
452 void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) {
453 fills_bounds_completely_ = fills_bounds_completely;
456 void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
457 // Finish animations being handled by cc_layer_.
458 if (animator_.get()) {
459 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
460 animator_->StopAnimatingProperty(LayerAnimationElement::OPACITY);
463 if (texture_layer_.get())
464 texture_layer_->ClearClient();
465 // TODO(piman): delegated_renderer_layer_ cleanup.
467 cc_layer_->RemoveAllChildren();
468 if (cc_layer_->parent()) {
469 cc_layer_->parent()->ReplaceChild(cc_layer_, new_layer);
471 cc_layer_->SetLayerClient(NULL);
472 cc_layer_->RemoveLayerAnimationEventObserver(this);
473 new_layer->SetOpacity(cc_layer_->opacity());
474 new_layer->SetTransform(cc_layer_->transform());
475 new_layer->SetPosition(cc_layer_->position());
477 cc_layer_ = new_layer.get();
478 content_layer_ = NULL;
479 solid_color_layer_ = NULL;
480 texture_layer_ = NULL;
481 delegated_renderer_layer_ = NULL;
483 cc_layer_->AddLayerAnimationEventObserver(this);
484 for (size_t i = 0; i < children_.size(); ++i) {
485 DCHECK(children_[i]->cc_layer_);
486 cc_layer_->AddChild(children_[i]->cc_layer_);
488 cc_layer_->SetLayerClient(this);
489 cc_layer_->SetAnchorPoint(gfx::PointF());
490 cc_layer_->SetContentsOpaque(fills_bounds_opaquely_);
491 cc_layer_->SetForceRenderSurface(force_render_surface_);
492 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
493 cc_layer_->SetHideLayerAndSubtree(!visible_);
496 void Layer::SwitchCCLayerForTest() {
497 scoped_refptr<cc::Layer> new_layer;
498 if (Layer::UsingPictureLayer())
499 new_layer = cc::PictureLayer::Create(this);
500 else
501 new_layer = cc::ContentLayer::Create(this);
502 SwitchToLayer(new_layer);
503 content_layer_ = new_layer;
506 void Layer::SetTextureMailbox(
507 const cc::TextureMailbox& mailbox,
508 scoped_ptr<cc::SingleReleaseCallback> release_callback,
509 gfx::Size texture_size_in_dip) {
510 DCHECK_EQ(type_, LAYER_TEXTURED);
511 DCHECK(!solid_color_layer_.get());
512 DCHECK(mailbox.IsValid());
513 DCHECK(release_callback);
514 if (!texture_layer_) {
515 scoped_refptr<cc::TextureLayer> new_layer =
516 cc::TextureLayer::CreateForMailbox(this);
517 new_layer->SetFlipped(true);
518 SwitchToLayer(new_layer);
519 texture_layer_ = new_layer;
521 if (mailbox_release_callback_)
522 mailbox_release_callback_->Run(0, false);
523 mailbox_release_callback_ = release_callback.Pass();
524 mailbox_ = mailbox;
525 SetTextureSize(texture_size_in_dip);
528 void Layer::SetTextureSize(gfx::Size texture_size_in_dip) {
529 DCHECK(texture_layer_.get());
530 if (frame_size_in_dip_ == texture_size_in_dip)
531 return;
532 frame_size_in_dip_ = texture_size_in_dip;
533 RecomputeDrawsContentAndUVRect();
534 texture_layer_->SetNeedsDisplay();
537 void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider,
538 gfx::Size frame_size_in_dip) {
539 DCHECK_EQ(type_, LAYER_TEXTURED);
541 scoped_refptr<cc::DelegatedRendererLayer> new_layer =
542 cc::DelegatedRendererLayer::Create(frame_provider);
543 SwitchToLayer(new_layer);
544 delegated_renderer_layer_ = new_layer;
546 frame_size_in_dip_ = frame_size_in_dip;
547 RecomputeDrawsContentAndUVRect();
550 void Layer::SetShowPaintedContent() {
551 if (content_layer_.get())
552 return;
554 scoped_refptr<cc::Layer> new_layer;
555 if (Layer::UsingPictureLayer())
556 new_layer = cc::PictureLayer::Create(this);
557 else
558 new_layer = cc::ContentLayer::Create(this);
559 SwitchToLayer(new_layer);
560 content_layer_ = new_layer;
562 mailbox_ = cc::TextureMailbox();
563 if (mailbox_release_callback_) {
564 mailbox_release_callback_->Run(0, false);
565 mailbox_release_callback_.reset();
567 RecomputeDrawsContentAndUVRect();
570 void Layer::SetColor(SkColor color) { GetAnimator()->SetColor(color); }
572 bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) {
573 if (type_ == LAYER_SOLID_COLOR || (!delegate_ && !mailbox_.IsValid()))
574 return false;
576 damaged_region_.op(invalid_rect.x(),
577 invalid_rect.y(),
578 invalid_rect.right(),
579 invalid_rect.bottom(),
580 SkRegion::kUnion_Op);
581 ScheduleDraw();
582 return true;
585 void Layer::ScheduleDraw() {
586 Compositor* compositor = GetCompositor();
587 if (compositor)
588 compositor->ScheduleDraw();
591 void Layer::SendDamagedRects() {
592 if ((delegate_ || mailbox_.IsValid()) && !damaged_region_.isEmpty()) {
593 for (SkRegion::Iterator iter(damaged_region_); !iter.done(); iter.next()) {
594 const SkIRect& sk_damaged = iter.rect();
595 gfx::Rect damaged(
596 sk_damaged.x(),
597 sk_damaged.y(),
598 sk_damaged.width(),
599 sk_damaged.height());
600 cc_layer_->SetNeedsDisplayRect(damaged);
602 damaged_region_.setEmpty();
604 for (size_t i = 0; i < children_.size(); ++i)
605 children_[i]->SendDamagedRects();
608 void Layer::SuppressPaint() {
609 if (!delegate_)
610 return;
611 delegate_ = NULL;
612 for (size_t i = 0; i < children_.size(); ++i)
613 children_[i]->SuppressPaint();
616 void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) {
617 if (device_scale_factor_ == device_scale_factor)
618 return;
619 if (animator_.get())
620 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
621 device_scale_factor_ = device_scale_factor;
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);
633 void Layer::RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) {
634 cc_layer_->RequestCopyOfOutput(request.Pass());
637 void Layer::PaintContents(SkCanvas* sk_canvas,
638 const gfx::Rect& clip,
639 gfx::RectF* opaque,
640 ContentLayerClient::GraphicsContextStatus gc_status) {
641 TRACE_EVENT0("ui", "Layer::PaintContents");
642 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling(
643 sk_canvas, device_scale_factor_));
644 if (delegate_)
645 delegate_->OnPaintLayer(canvas.get());
648 bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; }
650 bool Layer::PrepareTextureMailbox(
651 cc::TextureMailbox* mailbox,
652 scoped_ptr<cc::SingleReleaseCallback>* release_callback,
653 bool use_shared_memory) {
654 if (!mailbox_release_callback_)
655 return false;
656 *mailbox = mailbox_;
657 *release_callback = mailbox_release_callback_.Pass();
658 return true;
661 void Layer::SetForceRenderSurface(bool force) {
662 if (force_render_surface_ == force)
663 return;
665 force_render_surface_ = force;
666 cc_layer_->SetForceRenderSurface(force_render_surface_);
669 class LayerDebugInfo : public base::debug::ConvertableToTraceFormat {
670 public:
671 explicit LayerDebugInfo(std::string name) : name_(name) { }
672 virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE {
673 base::DictionaryValue dictionary;
674 dictionary.SetString("layer_name", name_);
675 base::JSONWriter::Write(&dictionary, out);
678 private:
679 virtual ~LayerDebugInfo() { }
680 std::string name_;
683 scoped_refptr<base::debug::ConvertableToTraceFormat> Layer::TakeDebugInfo() {
684 return new LayerDebugInfo(name_);
687 void Layer::OnAnimationStarted(const cc::AnimationEvent& event) {
688 if (animator_.get())
689 animator_->OnThreadedAnimationStarted(event);
692 void 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());
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;
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);
711 child->cc_layer_->RemoveFromParent();
712 cc_layer_->InsertChild(child->cc_layer_, dest_i);
715 bool 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;
725 bool 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;
735 void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) {
736 if (bounds == bounds_)
737 return;
739 base::Closure closure;
740 if (delegate_)
741 closure = delegate_->PrepareForLayerBoundsChange();
742 bool was_move = bounds_.size() == bounds.size();
743 bounds_ = bounds;
745 RecomputeDrawsContentAndUVRect();
746 RecomputePosition();
748 if (!closure.is_null())
749 closure.Run();
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()));
762 void Layer::SetTransformFromAnimation(const gfx::Transform& transform) {
763 cc_layer_->SetTransform(transform);
766 void Layer::SetOpacityFromAnimation(float opacity) {
767 cc_layer_->SetOpacity(opacity);
768 ScheduleDraw();
771 void Layer::SetVisibilityFromAnimation(bool visible) {
772 if (visible_ == visible)
773 return;
775 visible_ = visible;
776 cc_layer_->SetHideLayerAndSubtree(!visible_);
779 void Layer::SetBrightnessFromAnimation(float brightness) {
780 layer_brightness_ = brightness;
781 SetLayerFilters();
784 void Layer::SetGrayscaleFromAnimation(float grayscale) {
785 layer_grayscale_ = grayscale;
786 SetLayerFilters();
789 void Layer::SetColorFromAnimation(SkColor color) {
790 DCHECK_EQ(type_, LAYER_SOLID_COLOR);
791 solid_color_layer_->SetBackgroundColor(color);
792 SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF);
795 void Layer::ScheduleDrawForAnimation() {
796 ScheduleDraw();
799 const gfx::Rect& Layer::GetBoundsForAnimation() const {
800 return bounds();
803 gfx::Transform Layer::GetTransformForAnimation() const {
804 return transform();
807 float Layer::GetOpacityForAnimation() const {
808 return opacity();
811 bool Layer::GetVisibilityForAnimation() const {
812 return visible();
815 float Layer::GetBrightnessForAnimation() const {
816 return layer_brightness();
819 float Layer::GetGrayscaleForAnimation() const {
820 return layer_grayscale();
823 SkColor Layer::GetColorForAnimation() const {
824 // WebColor is equivalent to SkColor, per WebColor.h.
825 // The NULL check is here since this is invoked regardless of whether we have
826 // been configured as LAYER_SOLID_COLOR.
827 return solid_color_layer_.get() ?
828 solid_color_layer_->background_color() : SK_ColorBLACK;
831 float Layer::GetDeviceScaleFactor() const {
832 return device_scale_factor_;
835 void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) {
836 DCHECK(cc_layer_);
837 // Until this layer has a compositor (and hence cc_layer_ has a
838 // LayerTreeHost), addAnimation will fail.
839 if (GetCompositor())
840 cc_layer_->AddAnimation(animation.Pass());
841 else
842 pending_threaded_animations_.push_back(animation.Pass());
845 namespace{
847 struct HasAnimationId {
848 HasAnimationId(int id): id_(id) {
851 bool operator()(cc::Animation* animation) const {
852 return animation->id() == id_;
855 private:
856 int id_;
861 void Layer::RemoveThreadedAnimation(int animation_id) {
862 DCHECK(cc_layer_);
863 if (pending_threaded_animations_.size() == 0) {
864 cc_layer_->RemoveAnimation(animation_id);
865 return;
868 pending_threaded_animations_.erase(
869 cc::remove_if(&pending_threaded_animations_,
870 pending_threaded_animations_.begin(),
871 pending_threaded_animations_.end(),
872 HasAnimationId(animation_id)),
873 pending_threaded_animations_.end());
876 void Layer::SendPendingThreadedAnimations() {
877 for (cc::ScopedPtrVector<cc::Animation>::iterator it =
878 pending_threaded_animations_.begin();
879 it != pending_threaded_animations_.end();
880 ++it)
881 cc_layer_->AddAnimation(pending_threaded_animations_.take(it));
883 pending_threaded_animations_.clear();
885 for (size_t i = 0; i < children_.size(); ++i)
886 children_[i]->SendPendingThreadedAnimations();
889 void Layer::CreateWebLayer() {
890 if (type_ == LAYER_SOLID_COLOR) {
891 solid_color_layer_ = cc::SolidColorLayer::Create();
892 cc_layer_ = solid_color_layer_.get();
893 } else {
894 if (Layer::UsingPictureLayer())
895 content_layer_ = cc::PictureLayer::Create(this);
896 else
897 content_layer_ = cc::ContentLayer::Create(this);
898 cc_layer_ = content_layer_.get();
900 cc_layer_->SetAnchorPoint(gfx::PointF());
901 cc_layer_->SetContentsOpaque(true);
902 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
903 cc_layer_->AddLayerAnimationEventObserver(this);
904 cc_layer_->SetLayerClient(this);
905 RecomputePosition();
908 gfx::Transform Layer::transform() const {
909 return cc_layer_->transform();
912 void Layer::RecomputeDrawsContentAndUVRect() {
913 DCHECK(cc_layer_);
914 gfx::Size size(bounds_.size());
915 if (texture_layer_.get()) {
916 size.SetToMin(frame_size_in_dip_);
917 gfx::PointF uv_top_left(0.f, 0.f);
918 gfx::PointF uv_bottom_right(
919 static_cast<float>(size.width()) / frame_size_in_dip_.width(),
920 static_cast<float>(size.height()) / frame_size_in_dip_.height());
921 texture_layer_->SetUV(uv_top_left, uv_bottom_right);
922 } else if (delegated_renderer_layer_.get()) {
923 size.SetToMin(frame_size_in_dip_);
924 delegated_renderer_layer_->SetDisplaySize(frame_size_in_dip_);
926 cc_layer_->SetBounds(size);
929 void Layer::RecomputePosition() {
930 cc_layer_->SetPosition(gfx::PointF(bounds_.x(), bounds_.y()));
933 } // namespace ui