Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / ui / compositor / layer.cc
blobf7871b8602d7775c86be28365e2dc0cd794836c9
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/lazy_instance.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "cc/base/scoped_ptr_algorithm.h"
16 #include "cc/layers/content_layer.h"
17 #include "cc/layers/delegated_renderer_layer.h"
18 #include "cc/layers/nine_patch_layer.h"
19 #include "cc/layers/picture_layer.h"
20 #include "cc/layers/solid_color_layer.h"
21 #include "cc/layers/surface_layer.h"
22 #include "cc/layers/texture_layer.h"
23 #include "cc/output/copy_output_request.h"
24 #include "cc/output/delegated_frame_data.h"
25 #include "cc/output/filter_operation.h"
26 #include "cc/output/filter_operations.h"
27 #include "cc/resources/transferable_resource.h"
28 #include "ui/compositor/compositor_switches.h"
29 #include "ui/compositor/dip_util.h"
30 #include "ui/compositor/layer_animator.h"
31 #include "ui/gfx/animation/animation.h"
32 #include "ui/gfx/canvas.h"
33 #include "ui/gfx/display.h"
34 #include "ui/gfx/interpolated_transform.h"
35 #include "ui/gfx/point3_f.h"
36 #include "ui/gfx/point_conversions.h"
37 #include "ui/gfx/size_conversions.h"
39 namespace {
41 const ui::Layer* GetRoot(const ui::Layer* layer) {
42 while (layer->parent())
43 layer = layer->parent();
44 return layer;
47 struct UIImplSidePaintingStatus {
48 UIImplSidePaintingStatus()
49 : enabled(ui::IsUIImplSidePaintingEnabled()) {
51 bool enabled;
53 base::LazyInstance<UIImplSidePaintingStatus> g_ui_impl_side_painting_status =
54 LAZY_INSTANCE_INITIALIZER;
56 } // namespace
58 namespace ui {
60 Layer::Layer()
61 : type_(LAYER_TEXTURED),
62 compositor_(NULL),
63 parent_(NULL),
64 visible_(true),
65 force_render_surface_(false),
66 fills_bounds_opaquely_(true),
67 fills_bounds_completely_(false),
68 background_blur_radius_(0),
69 layer_saturation_(0.0f),
70 layer_brightness_(0.0f),
71 layer_grayscale_(0.0f),
72 layer_inverted_(false),
73 layer_mask_(NULL),
74 layer_mask_back_link_(NULL),
75 zoom_(1),
76 zoom_inset_(0),
77 delegate_(NULL),
78 owner_(NULL),
79 cc_layer_(NULL),
80 device_scale_factor_(1.0f) {
81 CreateCcLayer();
84 Layer::Layer(LayerType type)
85 : type_(type),
86 compositor_(NULL),
87 parent_(NULL),
88 visible_(true),
89 force_render_surface_(false),
90 fills_bounds_opaquely_(true),
91 fills_bounds_completely_(false),
92 background_blur_radius_(0),
93 layer_saturation_(0.0f),
94 layer_brightness_(0.0f),
95 layer_grayscale_(0.0f),
96 layer_inverted_(false),
97 layer_mask_(NULL),
98 layer_mask_back_link_(NULL),
99 zoom_(1),
100 zoom_inset_(0),
101 delegate_(NULL),
102 owner_(NULL),
103 cc_layer_(NULL),
104 device_scale_factor_(1.0f) {
105 CreateCcLayer();
108 Layer::~Layer() {
109 // Destroying the animator may cause observers to use the layer (and
110 // indirectly the WebLayer). Destroy the animator first so that the WebLayer
111 // is still around.
112 if (animator_.get())
113 animator_->SetDelegate(NULL);
114 animator_ = NULL;
115 if (compositor_)
116 compositor_->SetRootLayer(NULL);
117 if (parent_)
118 parent_->Remove(this);
119 if (layer_mask_)
120 SetMaskLayer(NULL);
121 if (layer_mask_back_link_)
122 layer_mask_back_link_->SetMaskLayer(NULL);
123 for (size_t i = 0; i < children_.size(); ++i)
124 children_[i]->parent_ = NULL;
125 cc_layer_->RemoveLayerAnimationEventObserver(this);
126 cc_layer_->RemoveFromParent();
129 // static
130 bool Layer::UsingPictureLayer() {
131 return g_ui_impl_side_painting_status.Get().enabled;
134 const Compositor* Layer::GetCompositor() const {
135 return GetRoot(this)->compositor_;
138 float Layer::opacity() const {
139 return cc_layer_->opacity();
142 void Layer::SetCompositor(Compositor* compositor) {
143 // This function must only be called to set the compositor on the root layer,
144 // or to reset it.
145 DCHECK(!compositor || !compositor_);
146 DCHECK(!compositor || compositor->root_layer() == this);
147 DCHECK(!parent_);
148 if (compositor_) {
149 RemoveAnimatorsInTreeFromCollection(
150 compositor_->layer_animator_collection());
152 compositor_ = compositor;
153 if (compositor) {
154 OnDeviceScaleFactorChanged(compositor->device_scale_factor());
155 SendPendingThreadedAnimations();
156 AddAnimatorsInTreeToCollection(compositor_->layer_animator_collection());
160 void Layer::Add(Layer* child) {
161 DCHECK(!child->compositor_);
162 if (child->parent_)
163 child->parent_->Remove(child);
164 child->parent_ = this;
165 children_.push_back(child);
166 cc_layer_->AddChild(child->cc_layer_);
167 child->OnDeviceScaleFactorChanged(device_scale_factor_);
168 if (GetCompositor())
169 child->SendPendingThreadedAnimations();
170 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
171 if (collection)
172 child->AddAnimatorsInTreeToCollection(collection);
175 void Layer::Remove(Layer* child) {
176 // Current bounds are used to calculate offsets when layers are reparented.
177 // Stop (and complete) an ongoing animation to update the bounds immediately.
178 LayerAnimator* child_animator = child->animator_.get();
179 if (child_animator)
180 child_animator->StopAnimatingProperty(ui::LayerAnimationElement::BOUNDS);
181 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
182 if (collection)
183 child->RemoveAnimatorsInTreeFromCollection(collection);
185 std::vector<Layer*>::iterator i =
186 std::find(children_.begin(), children_.end(), child);
187 DCHECK(i != children_.end());
188 children_.erase(i);
189 child->parent_ = NULL;
190 child->cc_layer_->RemoveFromParent();
193 void Layer::StackAtTop(Layer* child) {
194 if (children_.size() <= 1 || child == children_.back())
195 return; // Already in front.
196 StackAbove(child, children_.back());
199 void Layer::StackAbove(Layer* child, Layer* other) {
200 StackRelativeTo(child, other, true);
203 void Layer::StackAtBottom(Layer* child) {
204 if (children_.size() <= 1 || child == children_.front())
205 return; // Already on bottom.
206 StackBelow(child, children_.front());
209 void Layer::StackBelow(Layer* child, Layer* other) {
210 StackRelativeTo(child, other, false);
213 bool Layer::Contains(const Layer* other) const {
214 for (const Layer* parent = other; parent; parent = parent->parent()) {
215 if (parent == this)
216 return true;
218 return false;
221 void Layer::SetAnimator(LayerAnimator* animator) {
222 if (animator)
223 animator->SetDelegate(this);
224 animator_ = animator;
227 LayerAnimator* Layer::GetAnimator() {
228 if (!animator_.get())
229 SetAnimator(LayerAnimator::CreateDefaultAnimator());
230 return animator_.get();
233 void Layer::SetTransform(const gfx::Transform& transform) {
234 GetAnimator()->SetTransform(transform);
237 gfx::Transform Layer::GetTargetTransform() const {
238 if (animator_.get() && animator_->IsAnimatingProperty(
239 LayerAnimationElement::TRANSFORM)) {
240 return animator_->GetTargetTransform();
242 return transform();
245 void Layer::SetBounds(const gfx::Rect& bounds) {
246 GetAnimator()->SetBounds(bounds);
249 void Layer::SetSubpixelPositionOffset(const gfx::Vector2dF offset) {
250 subpixel_position_offset_ = offset;
251 RecomputePosition();
254 gfx::Rect Layer::GetTargetBounds() const {
255 if (animator_.get() && animator_->IsAnimatingProperty(
256 LayerAnimationElement::BOUNDS)) {
257 return animator_->GetTargetBounds();
259 return bounds_;
262 void Layer::SetMasksToBounds(bool masks_to_bounds) {
263 cc_layer_->SetMasksToBounds(masks_to_bounds);
266 bool Layer::GetMasksToBounds() const {
267 return cc_layer_->masks_to_bounds();
270 void Layer::SetOpacity(float opacity) {
271 GetAnimator()->SetOpacity(opacity);
274 float Layer::GetCombinedOpacity() const {
275 float opacity = this->opacity();
276 Layer* current = this->parent_;
277 while (current) {
278 opacity *= current->opacity();
279 current = current->parent_;
281 return opacity;
284 void Layer::SetBackgroundBlur(int blur_radius) {
285 background_blur_radius_ = blur_radius;
287 SetLayerBackgroundFilters();
290 void Layer::SetLayerSaturation(float saturation) {
291 layer_saturation_ = saturation;
292 SetLayerFilters();
295 void Layer::SetLayerBrightness(float brightness) {
296 GetAnimator()->SetBrightness(brightness);
299 float Layer::GetTargetBrightness() const {
300 if (animator_.get() && animator_->IsAnimatingProperty(
301 LayerAnimationElement::BRIGHTNESS)) {
302 return animator_->GetTargetBrightness();
304 return layer_brightness();
307 void Layer::SetLayerGrayscale(float grayscale) {
308 GetAnimator()->SetGrayscale(grayscale);
311 float Layer::GetTargetGrayscale() const {
312 if (animator_.get() && animator_->IsAnimatingProperty(
313 LayerAnimationElement::GRAYSCALE)) {
314 return animator_->GetTargetGrayscale();
316 return layer_grayscale();
319 void Layer::SetLayerInverted(bool inverted) {
320 layer_inverted_ = inverted;
321 SetLayerFilters();
324 void Layer::SetMaskLayer(Layer* layer_mask) {
325 // The provided mask should not have a layer mask itself.
326 DCHECK(!layer_mask ||
327 (!layer_mask->layer_mask_layer() &&
328 layer_mask->children().empty() &&
329 !layer_mask->layer_mask_back_link_));
330 DCHECK(!layer_mask_back_link_);
331 if (layer_mask_ == layer_mask)
332 return;
333 // We need to de-reference the currently linked object so that no problem
334 // arises if the mask layer gets deleted before this object.
335 if (layer_mask_)
336 layer_mask_->layer_mask_back_link_ = NULL;
337 layer_mask_ = layer_mask;
338 cc_layer_->SetMaskLayer(
339 layer_mask ? layer_mask->cc_layer() : NULL);
340 // We need to reference the linked object so that it can properly break the
341 // link to us when it gets deleted.
342 if (layer_mask) {
343 layer_mask->layer_mask_back_link_ = this;
344 layer_mask->OnDeviceScaleFactorChanged(device_scale_factor_);
348 void Layer::SetBackgroundZoom(float zoom, int inset) {
349 zoom_ = zoom;
350 zoom_inset_ = inset;
352 SetLayerBackgroundFilters();
355 void Layer::SetAlphaShape(scoped_ptr<SkRegion> region) {
356 alpha_shape_ = region.Pass();
358 SetLayerFilters();
361 void Layer::SetLayerFilters() {
362 cc::FilterOperations filters;
363 if (layer_saturation_) {
364 filters.Append(cc::FilterOperation::CreateSaturateFilter(
365 layer_saturation_));
367 if (layer_grayscale_) {
368 filters.Append(cc::FilterOperation::CreateGrayscaleFilter(
369 layer_grayscale_));
371 if (layer_inverted_)
372 filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
373 // Brightness goes last, because the resulting colors neeed clamping, which
374 // cause further color matrix filters to be applied separately. In this order,
375 // they all can be combined in a single pass.
376 if (layer_brightness_) {
377 filters.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter(
378 layer_brightness_));
380 if (alpha_shape_) {
381 filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter(
382 *alpha_shape_, 0.f, 0.f));
385 cc_layer_->SetFilters(filters);
388 void Layer::SetLayerBackgroundFilters() {
389 cc::FilterOperations filters;
390 if (zoom_ != 1)
391 filters.Append(cc::FilterOperation::CreateZoomFilter(zoom_, zoom_inset_));
393 if (background_blur_radius_) {
394 filters.Append(cc::FilterOperation::CreateBlurFilter(
395 background_blur_radius_));
398 cc_layer_->SetBackgroundFilters(filters);
401 float Layer::GetTargetOpacity() const {
402 if (animator_.get() && animator_->IsAnimatingProperty(
403 LayerAnimationElement::OPACITY))
404 return animator_->GetTargetOpacity();
405 return opacity();
408 void Layer::SetVisible(bool visible) {
409 GetAnimator()->SetVisibility(visible);
412 bool Layer::GetTargetVisibility() const {
413 if (animator_.get() && animator_->IsAnimatingProperty(
414 LayerAnimationElement::VISIBILITY))
415 return animator_->GetTargetVisibility();
416 return visible_;
419 bool Layer::IsDrawn() const {
420 const Layer* layer = this;
421 while (layer && layer->visible_)
422 layer = layer->parent_;
423 return layer == NULL;
426 bool Layer::ShouldDraw() const {
427 return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f;
430 // static
431 void Layer::ConvertPointToLayer(const Layer* source,
432 const Layer* target,
433 gfx::Point* point) {
434 if (source == target)
435 return;
437 const Layer* root_layer = GetRoot(source);
438 CHECK_EQ(root_layer, GetRoot(target));
440 if (source != root_layer)
441 source->ConvertPointForAncestor(root_layer, point);
442 if (target != root_layer)
443 target->ConvertPointFromAncestor(root_layer, point);
446 bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor,
447 gfx::Transform* transform) const {
448 const Layer* p = this;
449 for (; p && p != ancestor; p = p->parent()) {
450 gfx::Transform translation;
451 translation.Translate(static_cast<float>(p->bounds().x()),
452 static_cast<float>(p->bounds().y()));
453 // Use target transform so that result will be correct once animation is
454 // finished.
455 if (!p->GetTargetTransform().IsIdentity())
456 transform->ConcatTransform(p->GetTargetTransform());
457 transform->ConcatTransform(translation);
459 return p == ancestor;
462 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
463 if (fills_bounds_opaquely_ == fills_bounds_opaquely)
464 return;
466 fills_bounds_opaquely_ = fills_bounds_opaquely;
468 cc_layer_->SetContentsOpaque(fills_bounds_opaquely);
471 void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) {
472 fills_bounds_completely_ = fills_bounds_completely;
475 void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
476 // Finish animations being handled by cc_layer_.
477 if (animator_.get()) {
478 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
479 animator_->StopAnimatingProperty(LayerAnimationElement::OPACITY);
482 if (texture_layer_.get())
483 texture_layer_->ClearClient();
484 // TODO(piman): delegated_renderer_layer_ cleanup.
486 cc_layer_->RemoveAllChildren();
487 if (cc_layer_->parent()) {
488 cc_layer_->parent()->ReplaceChild(cc_layer_, new_layer);
490 cc_layer_->SetLayerClient(NULL);
491 cc_layer_->RemoveLayerAnimationEventObserver(this);
492 new_layer->SetOpacity(cc_layer_->opacity());
493 new_layer->SetTransform(cc_layer_->transform());
494 new_layer->SetPosition(cc_layer_->position());
495 new_layer->SetBackgroundColor(cc_layer_->background_color());
497 cc_layer_ = new_layer.get();
498 content_layer_ = NULL;
499 solid_color_layer_ = NULL;
500 texture_layer_ = NULL;
501 delegated_renderer_layer_ = NULL;
502 surface_layer_ = NULL;
504 cc_layer_->AddLayerAnimationEventObserver(this);
505 for (size_t i = 0; i < children_.size(); ++i) {
506 DCHECK(children_[i]->cc_layer_);
507 cc_layer_->AddChild(children_[i]->cc_layer_);
509 cc_layer_->SetLayerClient(this);
510 cc_layer_->SetTransformOrigin(gfx::Point3F());
511 cc_layer_->SetContentsOpaque(fills_bounds_opaquely_);
512 cc_layer_->SetForceRenderSurface(force_render_surface_);
513 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
514 cc_layer_->SetHideLayerAndSubtree(!visible_);
516 SetLayerFilters();
517 SetLayerBackgroundFilters();
520 void Layer::SwitchCCLayerForTest() {
521 scoped_refptr<cc::Layer> new_layer;
522 if (Layer::UsingPictureLayer())
523 new_layer = cc::PictureLayer::Create(this);
524 else
525 new_layer = cc::ContentLayer::Create(this);
526 SwitchToLayer(new_layer);
527 content_layer_ = new_layer;
530 void Layer::SetTextureMailbox(
531 const cc::TextureMailbox& mailbox,
532 scoped_ptr<cc::SingleReleaseCallback> release_callback,
533 gfx::Size texture_size_in_dip) {
534 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
535 DCHECK(mailbox.IsValid());
536 DCHECK(release_callback);
537 if (!texture_layer_.get()) {
538 scoped_refptr<cc::TextureLayer> new_layer =
539 cc::TextureLayer::CreateForMailbox(this);
540 new_layer->SetFlipped(true);
541 SwitchToLayer(new_layer);
542 texture_layer_ = new_layer;
544 if (mailbox_release_callback_)
545 mailbox_release_callback_->Run(0, false);
546 mailbox_release_callback_ = release_callback.Pass();
547 mailbox_ = mailbox;
548 SetTextureSize(texture_size_in_dip);
551 void Layer::SetTextureSize(gfx::Size texture_size_in_dip) {
552 DCHECK(texture_layer_.get());
553 if (frame_size_in_dip_ == texture_size_in_dip)
554 return;
555 frame_size_in_dip_ = texture_size_in_dip;
556 RecomputeDrawsContentAndUVRect();
557 texture_layer_->SetNeedsDisplay();
560 void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider,
561 gfx::Size frame_size_in_dip) {
562 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
564 scoped_refptr<cc::DelegatedRendererLayer> new_layer =
565 cc::DelegatedRendererLayer::Create(frame_provider);
566 SwitchToLayer(new_layer);
567 delegated_renderer_layer_ = new_layer;
569 frame_size_in_dip_ = frame_size_in_dip;
570 RecomputeDrawsContentAndUVRect();
573 void Layer::SetShowSurface(
574 cc::SurfaceId surface_id,
575 const cc::SurfaceLayer::SatisfyCallback& satisfy_callback,
576 const cc::SurfaceLayer::RequireCallback& require_callback,
577 gfx::Size surface_size,
578 float scale,
579 gfx::Size frame_size_in_dip) {
580 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
582 scoped_refptr<cc::SurfaceLayer> new_layer =
583 cc::SurfaceLayer::Create(satisfy_callback, require_callback);
584 new_layer->SetSurfaceId(surface_id, scale, surface_size);
585 SwitchToLayer(new_layer);
586 surface_layer_ = new_layer;
588 frame_size_in_dip_ = frame_size_in_dip;
589 RecomputeDrawsContentAndUVRect();
592 void Layer::SetShowSolidColorContent() {
593 DCHECK_EQ(type_, LAYER_SOLID_COLOR);
595 if (solid_color_layer_.get())
596 return;
598 scoped_refptr<cc::SolidColorLayer> new_layer = cc::SolidColorLayer::Create();
599 SwitchToLayer(new_layer);
600 solid_color_layer_ = new_layer;
602 mailbox_ = cc::TextureMailbox();
603 if (mailbox_release_callback_) {
604 mailbox_release_callback_->Run(0, false);
605 mailbox_release_callback_.reset();
607 RecomputeDrawsContentAndUVRect();
610 void Layer::UpdateNinePatchLayerBitmap(const SkBitmap& bitmap) {
611 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
612 SkBitmap bitmap_copy;
613 if (bitmap.isImmutable()) {
614 bitmap_copy = bitmap;
615 } else {
616 // UIResourceBitmap requires an immutable copy of the input |bitmap|.
617 bitmap.copyTo(&bitmap_copy);
618 bitmap_copy.setImmutable();
620 nine_patch_layer_->SetBitmap(bitmap_copy);
623 void Layer::UpdateNinePatchLayerAperture(const gfx::Rect& aperture) {
624 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
625 nine_patch_layer_->SetAperture(aperture);
628 void Layer::UpdateNinePatchLayerBorder(const gfx::Rect& border) {
629 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
630 nine_patch_layer_->SetBorder(border);
633 void Layer::SetColor(SkColor color) { GetAnimator()->SetColor(color); }
635 bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) {
636 if ((type_ == LAYER_SOLID_COLOR && !texture_layer_.get()) ||
637 type_ == LAYER_NINE_PATCH || (!delegate_ && !mailbox_.IsValid()))
638 return false;
640 damaged_region_.op(invalid_rect.x(),
641 invalid_rect.y(),
642 invalid_rect.right(),
643 invalid_rect.bottom(),
644 SkRegion::kUnion_Op);
645 ScheduleDraw();
646 return true;
649 void Layer::ScheduleDraw() {
650 Compositor* compositor = GetCompositor();
651 if (compositor)
652 compositor->ScheduleDraw();
655 void Layer::SendDamagedRects() {
656 if ((delegate_ || mailbox_.IsValid()) && !damaged_region_.isEmpty()) {
657 for (SkRegion::Iterator iter(damaged_region_); !iter.done(); iter.next()) {
658 const SkIRect& sk_damaged = iter.rect();
659 gfx::Rect damaged(
660 sk_damaged.x(),
661 sk_damaged.y(),
662 sk_damaged.width(),
663 sk_damaged.height());
664 cc_layer_->SetNeedsDisplayRect(damaged);
666 damaged_region_.setEmpty();
668 for (size_t i = 0; i < children_.size(); ++i)
669 children_[i]->SendDamagedRects();
672 void Layer::CompleteAllAnimations() {
673 typedef std::vector<scoped_refptr<LayerAnimator> > LayerAnimatorVector;
674 LayerAnimatorVector animators;
675 CollectAnimators(&animators);
676 for (LayerAnimatorVector::const_iterator it = animators.begin();
677 it != animators.end();
678 ++it) {
679 (*it)->StopAnimating();
683 void Layer::SuppressPaint() {
684 if (!delegate_)
685 return;
686 delegate_ = NULL;
687 for (size_t i = 0; i < children_.size(); ++i)
688 children_[i]->SuppressPaint();
691 void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) {
692 if (device_scale_factor_ == device_scale_factor)
693 return;
694 if (animator_.get())
695 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
696 device_scale_factor_ = device_scale_factor;
697 RecomputeDrawsContentAndUVRect();
698 RecomputePosition();
699 SchedulePaint(gfx::Rect(bounds_.size()));
700 if (delegate_)
701 delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
702 for (size_t i = 0; i < children_.size(); ++i)
703 children_[i]->OnDeviceScaleFactorChanged(device_scale_factor);
704 if (layer_mask_)
705 layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor);
708 void Layer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {
709 DCHECK(delegated_renderer_layer_.get() || surface_layer_.get());
710 if (!delegate_)
711 return;
712 delegate_->OnDelegatedFrameDamage(damage_rect_in_dip);
715 void Layer::RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) {
716 cc_layer_->RequestCopyOfOutput(request.Pass());
719 void Layer::PaintContents(SkCanvas* sk_canvas,
720 const gfx::Rect& clip,
721 ContentLayerClient::GraphicsContextStatus gc_status) {
722 TRACE_EVENT0("ui", "Layer::PaintContents");
723 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling(
724 sk_canvas, device_scale_factor_));
725 if (delegate_)
726 delegate_->OnPaintLayer(canvas.get());
729 bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; }
731 bool Layer::PrepareTextureMailbox(
732 cc::TextureMailbox* mailbox,
733 scoped_ptr<cc::SingleReleaseCallback>* release_callback,
734 bool use_shared_memory) {
735 if (!mailbox_release_callback_)
736 return false;
737 *mailbox = mailbox_;
738 *release_callback = mailbox_release_callback_.Pass();
739 return true;
742 void Layer::SetForceRenderSurface(bool force) {
743 if (force_render_surface_ == force)
744 return;
746 force_render_surface_ = force;
747 cc_layer_->SetForceRenderSurface(force_render_surface_);
750 class LayerDebugInfo : public base::debug::ConvertableToTraceFormat {
751 public:
752 explicit LayerDebugInfo(std::string name) : name_(name) { }
753 void AppendAsTraceFormat(std::string* out) const override {
754 base::DictionaryValue dictionary;
755 dictionary.SetString("layer_name", name_);
756 base::JSONWriter::Write(&dictionary, out);
759 private:
760 ~LayerDebugInfo() override {}
761 std::string name_;
764 scoped_refptr<base::debug::ConvertableToTraceFormat> Layer::TakeDebugInfo() {
765 return new LayerDebugInfo(name_);
768 void Layer::OnAnimationStarted(const cc::AnimationEvent& event) {
769 if (animator_.get())
770 animator_->OnThreadedAnimationStarted(event);
773 void Layer::CollectAnimators(
774 std::vector<scoped_refptr<LayerAnimator> >* animators) {
775 if (IsAnimating())
776 animators->push_back(animator_);
777 std::for_each(children_.begin(), children_.end(),
778 std::bind2nd(std::mem_fun(&Layer::CollectAnimators),
779 animators));
782 void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) {
783 DCHECK_NE(child, other);
784 DCHECK_EQ(this, child->parent());
785 DCHECK_EQ(this, other->parent());
787 const size_t child_i =
788 std::find(children_.begin(), children_.end(), child) - children_.begin();
789 const size_t other_i =
790 std::find(children_.begin(), children_.end(), other) - children_.begin();
791 if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i))
792 return;
794 const size_t dest_i =
795 above ?
796 (child_i < other_i ? other_i : other_i + 1) :
797 (child_i < other_i ? other_i - 1 : other_i);
798 children_.erase(children_.begin() + child_i);
799 children_.insert(children_.begin() + dest_i, child);
801 child->cc_layer_->RemoveFromParent();
802 cc_layer_->InsertChild(child->cc_layer_, dest_i);
805 bool Layer::ConvertPointForAncestor(const Layer* ancestor,
806 gfx::Point* point) const {
807 gfx::Transform transform;
808 bool result = GetTargetTransformRelativeTo(ancestor, &transform);
809 gfx::Point3F p(*point);
810 transform.TransformPoint(&p);
811 *point = gfx::ToFlooredPoint(p.AsPointF());
812 return result;
815 bool Layer::ConvertPointFromAncestor(const Layer* ancestor,
816 gfx::Point* point) const {
817 gfx::Transform transform;
818 bool result = GetTargetTransformRelativeTo(ancestor, &transform);
819 gfx::Point3F p(*point);
820 transform.TransformPointReverse(&p);
821 *point = gfx::ToFlooredPoint(p.AsPointF());
822 return result;
825 void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) {
826 if (bounds == bounds_)
827 return;
829 base::Closure closure;
830 if (delegate_)
831 closure = delegate_->PrepareForLayerBoundsChange();
832 bool was_move = bounds_.size() == bounds.size();
833 bounds_ = bounds;
835 RecomputeDrawsContentAndUVRect();
836 RecomputePosition();
838 if (!closure.is_null())
839 closure.Run();
841 if (was_move) {
842 // Don't schedule a draw if we're invisible. We'll schedule one
843 // automatically when we get visible.
844 if (IsDrawn())
845 ScheduleDraw();
846 } else {
847 // Always schedule a paint, even if we're invisible.
848 SchedulePaint(gfx::Rect(bounds.size()));
852 void Layer::SetTransformFromAnimation(const gfx::Transform& transform) {
853 cc_layer_->SetTransform(transform);
856 void Layer::SetOpacityFromAnimation(float opacity) {
857 cc_layer_->SetOpacity(opacity);
858 ScheduleDraw();
861 void Layer::SetVisibilityFromAnimation(bool visible) {
862 if (visible_ == visible)
863 return;
865 visible_ = visible;
866 cc_layer_->SetHideLayerAndSubtree(!visible_);
869 void Layer::SetBrightnessFromAnimation(float brightness) {
870 layer_brightness_ = brightness;
871 SetLayerFilters();
874 void Layer::SetGrayscaleFromAnimation(float grayscale) {
875 layer_grayscale_ = grayscale;
876 SetLayerFilters();
879 void Layer::SetColorFromAnimation(SkColor color) {
880 DCHECK_EQ(type_, LAYER_SOLID_COLOR);
881 cc_layer_->SetBackgroundColor(color);
882 SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF);
885 void Layer::ScheduleDrawForAnimation() {
886 ScheduleDraw();
889 const gfx::Rect& Layer::GetBoundsForAnimation() const {
890 return bounds();
893 gfx::Transform Layer::GetTransformForAnimation() const {
894 return transform();
897 float Layer::GetOpacityForAnimation() const {
898 return opacity();
901 bool Layer::GetVisibilityForAnimation() const {
902 return visible();
905 float Layer::GetBrightnessForAnimation() const {
906 return layer_brightness();
909 float Layer::GetGrayscaleForAnimation() const {
910 return layer_grayscale();
913 SkColor Layer::GetColorForAnimation() const {
914 // WebColor is equivalent to SkColor, per WebColor.h.
915 // The NULL check is here since this is invoked regardless of whether we have
916 // been configured as LAYER_SOLID_COLOR.
917 return solid_color_layer_.get() ?
918 solid_color_layer_->background_color() : SK_ColorBLACK;
921 float Layer::GetDeviceScaleFactor() const {
922 return device_scale_factor_;
925 void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) {
926 DCHECK(cc_layer_);
927 // Until this layer has a compositor (and hence cc_layer_ has a
928 // LayerTreeHost), addAnimation will fail.
929 if (GetCompositor())
930 cc_layer_->AddAnimation(animation.Pass());
931 else
932 pending_threaded_animations_.push_back(animation.Pass());
935 namespace{
937 struct HasAnimationId {
938 HasAnimationId(int id): id_(id) {
941 bool operator()(cc::Animation* animation) const {
942 return animation->id() == id_;
945 private:
946 int id_;
951 void Layer::RemoveThreadedAnimation(int animation_id) {
952 DCHECK(cc_layer_);
953 if (pending_threaded_animations_.size() == 0) {
954 cc_layer_->RemoveAnimation(animation_id);
955 return;
958 pending_threaded_animations_.erase(
959 cc::remove_if(&pending_threaded_animations_,
960 pending_threaded_animations_.begin(),
961 pending_threaded_animations_.end(),
962 HasAnimationId(animation_id)),
963 pending_threaded_animations_.end());
966 LayerAnimatorCollection* Layer::GetLayerAnimatorCollection() {
967 Compositor* compositor = GetCompositor();
968 return compositor ? compositor->layer_animator_collection() : NULL;
971 void Layer::SendPendingThreadedAnimations() {
972 for (cc::ScopedPtrVector<cc::Animation>::iterator it =
973 pending_threaded_animations_.begin();
974 it != pending_threaded_animations_.end();
975 ++it)
976 cc_layer_->AddAnimation(pending_threaded_animations_.take(it));
978 pending_threaded_animations_.clear();
980 for (size_t i = 0; i < children_.size(); ++i)
981 children_[i]->SendPendingThreadedAnimations();
984 void Layer::CreateCcLayer() {
985 if (type_ == LAYER_SOLID_COLOR) {
986 solid_color_layer_ = cc::SolidColorLayer::Create();
987 cc_layer_ = solid_color_layer_.get();
988 } else if (type_ == LAYER_NINE_PATCH) {
989 nine_patch_layer_ = cc::NinePatchLayer::Create();
990 cc_layer_ = nine_patch_layer_.get();
991 } else {
992 if (Layer::UsingPictureLayer())
993 content_layer_ = cc::PictureLayer::Create(this);
994 else
995 content_layer_ = cc::ContentLayer::Create(this);
996 cc_layer_ = content_layer_.get();
998 cc_layer_->SetTransformOrigin(gfx::Point3F());
999 cc_layer_->SetContentsOpaque(true);
1000 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
1001 cc_layer_->AddLayerAnimationEventObserver(this);
1002 cc_layer_->SetLayerClient(this);
1003 RecomputePosition();
1006 gfx::Transform Layer::transform() const {
1007 return cc_layer_->transform();
1010 void Layer::RecomputeDrawsContentAndUVRect() {
1011 DCHECK(cc_layer_);
1012 gfx::Size size(bounds_.size());
1013 if (texture_layer_.get()) {
1014 size.SetToMin(frame_size_in_dip_);
1015 gfx::PointF uv_top_left(0.f, 0.f);
1016 gfx::PointF uv_bottom_right(
1017 static_cast<float>(size.width()) / frame_size_in_dip_.width(),
1018 static_cast<float>(size.height()) / frame_size_in_dip_.height());
1019 texture_layer_->SetUV(uv_top_left, uv_bottom_right);
1020 } else if (delegated_renderer_layer_.get() || surface_layer_.get()) {
1021 size.SetToMin(frame_size_in_dip_);
1023 cc_layer_->SetBounds(size);
1026 void Layer::RecomputePosition() {
1027 cc_layer_->SetPosition(bounds_.origin() + subpixel_position_offset_);
1030 void Layer::AddAnimatorsInTreeToCollection(
1031 LayerAnimatorCollection* collection) {
1032 DCHECK(collection);
1033 if (IsAnimating())
1034 animator_->AddToCollection(collection);
1035 std::for_each(
1036 children_.begin(),
1037 children_.end(),
1038 std::bind2nd(std::mem_fun(&Layer::AddAnimatorsInTreeToCollection),
1039 collection));
1042 void Layer::RemoveAnimatorsInTreeFromCollection(
1043 LayerAnimatorCollection* collection) {
1044 DCHECK(collection);
1045 if (IsAnimating())
1046 animator_->RemoveFromCollection(collection);
1047 std::for_each(
1048 children_.begin(),
1049 children_.end(),
1050 std::bind2nd(std::mem_fun(&Layer::RemoveAnimatorsInTreeFromCollection),
1051 collection));
1054 bool Layer::IsAnimating() const {
1055 return animator_.get() && animator_->is_animating();
1058 } // namespace ui