Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / ui / compositor / layer.cc
blob3e61d40b95a2c02151bf44dd5418c2d74cc655c8
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/auto_reset.h"
10 #include "base/command_line.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 "base/trace_event/trace_event.h"
16 #include "cc/base/scoped_ptr_algorithm.h"
17 #include "cc/layers/content_layer.h"
18 #include "cc/layers/delegated_renderer_layer.h"
19 #include "cc/layers/nine_patch_layer.h"
20 #include "cc/layers/picture_layer.h"
21 #include "cc/layers/solid_color_layer.h"
22 #include "cc/layers/surface_layer.h"
23 #include "cc/layers/texture_layer.h"
24 #include "cc/output/copy_output_request.h"
25 #include "cc/output/delegated_frame_data.h"
26 #include "cc/output/filter_operation.h"
27 #include "cc/output/filter_operations.h"
28 #include "cc/resources/transferable_resource.h"
29 #include "ui/compositor/compositor_switches.h"
30 #include "ui/compositor/dip_util.h"
31 #include "ui/compositor/layer_animator.h"
32 #include "ui/compositor/paint_context.h"
33 #include "ui/gfx/animation/animation.h"
34 #include "ui/gfx/canvas.h"
35 #include "ui/gfx/display.h"
36 #include "ui/gfx/geometry/point3_f.h"
37 #include "ui/gfx/geometry/point_conversions.h"
38 #include "ui/gfx/geometry/size_conversions.h"
39 #include "ui/gfx/interpolated_transform.h"
41 namespace {
43 const ui::Layer* GetRoot(const ui::Layer* layer) {
44 while (layer->parent())
45 layer = layer->parent();
46 return layer;
49 struct UIImplSidePaintingStatus {
50 UIImplSidePaintingStatus()
51 : enabled(ui::IsUIImplSidePaintingEnabled()) {
53 bool enabled;
55 base::LazyInstance<UIImplSidePaintingStatus> g_ui_impl_side_painting_status =
56 LAZY_INSTANCE_INITIALIZER;
58 } // namespace
60 namespace ui {
62 Layer::Layer()
63 : type_(LAYER_TEXTURED),
64 compositor_(NULL),
65 parent_(NULL),
66 visible_(true),
67 force_render_surface_(false),
68 fills_bounds_opaquely_(true),
69 fills_bounds_completely_(false),
70 background_blur_radius_(0),
71 layer_saturation_(0.0f),
72 layer_brightness_(0.0f),
73 layer_grayscale_(0.0f),
74 layer_inverted_(false),
75 layer_mask_(NULL),
76 layer_mask_back_link_(NULL),
77 zoom_(1),
78 zoom_inset_(0),
79 delegate_(NULL),
80 owner_(NULL),
81 cc_layer_(NULL),
82 device_scale_factor_(1.0f) {
83 CreateCcLayer();
86 Layer::Layer(LayerType type)
87 : type_(type),
88 compositor_(NULL),
89 parent_(NULL),
90 visible_(true),
91 force_render_surface_(false),
92 fills_bounds_opaquely_(true),
93 fills_bounds_completely_(false),
94 background_blur_radius_(0),
95 layer_saturation_(0.0f),
96 layer_brightness_(0.0f),
97 layer_grayscale_(0.0f),
98 layer_inverted_(false),
99 layer_mask_(NULL),
100 layer_mask_back_link_(NULL),
101 zoom_(1),
102 zoom_inset_(0),
103 delegate_(NULL),
104 owner_(NULL),
105 cc_layer_(NULL),
106 device_scale_factor_(1.0f) {
107 CreateCcLayer();
110 Layer::~Layer() {
111 // Destroying the animator may cause observers to use the layer (and
112 // indirectly the WebLayer). Destroy the animator first so that the WebLayer
113 // is still around.
114 if (animator_.get())
115 animator_->SetDelegate(NULL);
116 animator_ = NULL;
117 if (compositor_)
118 compositor_->SetRootLayer(NULL);
119 if (parent_)
120 parent_->Remove(this);
121 if (layer_mask_)
122 SetMaskLayer(NULL);
123 if (layer_mask_back_link_)
124 layer_mask_back_link_->SetMaskLayer(NULL);
125 for (size_t i = 0; i < children_.size(); ++i)
126 children_[i]->parent_ = NULL;
127 cc_layer_->RemoveLayerAnimationEventObserver(this);
128 cc_layer_->RemoveFromParent();
131 // static
132 bool Layer::UsingPictureLayer() {
133 return g_ui_impl_side_painting_status.Get().enabled;
136 const Compositor* Layer::GetCompositor() const {
137 return GetRoot(this)->compositor_;
140 float Layer::opacity() const {
141 return cc_layer_->opacity();
144 void Layer::SetCompositor(Compositor* compositor) {
145 // This function must only be called to set the compositor on the root layer,
146 // or to reset it.
147 DCHECK(!compositor || !compositor_);
148 DCHECK(!compositor || compositor->root_layer() == this);
149 DCHECK(!parent_);
150 if (compositor_) {
151 RemoveAnimatorsInTreeFromCollection(
152 compositor_->layer_animator_collection());
154 compositor_ = compositor;
155 if (compositor) {
156 OnDeviceScaleFactorChanged(compositor->device_scale_factor());
157 SendPendingThreadedAnimations();
158 AddAnimatorsInTreeToCollection(compositor_->layer_animator_collection());
162 void Layer::Add(Layer* child) {
163 DCHECK(!child->compositor_);
164 if (child->parent_)
165 child->parent_->Remove(child);
166 child->parent_ = this;
167 children_.push_back(child);
168 cc_layer_->AddChild(child->cc_layer_);
169 child->OnDeviceScaleFactorChanged(device_scale_factor_);
170 if (GetCompositor())
171 child->SendPendingThreadedAnimations();
172 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
173 if (collection)
174 child->AddAnimatorsInTreeToCollection(collection);
177 void Layer::Remove(Layer* child) {
178 // Current bounds are used to calculate offsets when layers are reparented.
179 // Stop (and complete) an ongoing animation to update the bounds immediately.
180 LayerAnimator* child_animator = child->animator_.get();
181 if (child_animator)
182 child_animator->StopAnimatingProperty(ui::LayerAnimationElement::BOUNDS);
183 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
184 if (collection)
185 child->RemoveAnimatorsInTreeFromCollection(collection);
187 std::vector<Layer*>::iterator i =
188 std::find(children_.begin(), children_.end(), child);
189 DCHECK(i != children_.end());
190 children_.erase(i);
191 child->parent_ = NULL;
192 child->cc_layer_->RemoveFromParent();
195 void Layer::StackAtTop(Layer* child) {
196 if (children_.size() <= 1 || child == children_.back())
197 return; // Already in front.
198 StackAbove(child, children_.back());
201 void Layer::StackAbove(Layer* child, Layer* other) {
202 StackRelativeTo(child, other, true);
205 void Layer::StackAtBottom(Layer* child) {
206 if (children_.size() <= 1 || child == children_.front())
207 return; // Already on bottom.
208 StackBelow(child, children_.front());
211 void Layer::StackBelow(Layer* child, Layer* other) {
212 StackRelativeTo(child, other, false);
215 bool Layer::Contains(const Layer* other) const {
216 for (const Layer* parent = other; parent; parent = parent->parent()) {
217 if (parent == this)
218 return true;
220 return false;
223 void Layer::SetAnimator(LayerAnimator* animator) {
224 if (animator)
225 animator->SetDelegate(this);
226 animator_ = animator;
229 LayerAnimator* Layer::GetAnimator() {
230 if (!animator_.get())
231 SetAnimator(LayerAnimator::CreateDefaultAnimator());
232 return animator_.get();
235 void Layer::SetTransform(const gfx::Transform& transform) {
236 GetAnimator()->SetTransform(transform);
239 gfx::Transform Layer::GetTargetTransform() const {
240 if (animator_.get() && animator_->IsAnimatingProperty(
241 LayerAnimationElement::TRANSFORM)) {
242 return animator_->GetTargetTransform();
244 return transform();
247 void Layer::SetBounds(const gfx::Rect& bounds) {
248 GetAnimator()->SetBounds(bounds);
251 void Layer::SetSubpixelPositionOffset(const gfx::Vector2dF offset) {
252 subpixel_position_offset_ = offset;
253 RecomputePosition();
256 gfx::Rect Layer::GetTargetBounds() const {
257 if (animator_.get() && animator_->IsAnimatingProperty(
258 LayerAnimationElement::BOUNDS)) {
259 return animator_->GetTargetBounds();
261 return bounds_;
264 void Layer::SetMasksToBounds(bool masks_to_bounds) {
265 cc_layer_->SetMasksToBounds(masks_to_bounds);
268 bool Layer::GetMasksToBounds() const {
269 return cc_layer_->masks_to_bounds();
272 void Layer::SetOpacity(float opacity) {
273 GetAnimator()->SetOpacity(opacity);
276 float Layer::GetCombinedOpacity() const {
277 float opacity = this->opacity();
278 Layer* current = this->parent_;
279 while (current) {
280 opacity *= current->opacity();
281 current = current->parent_;
283 return opacity;
286 void Layer::SetBackgroundBlur(int blur_radius) {
287 background_blur_radius_ = blur_radius;
289 SetLayerBackgroundFilters();
292 void Layer::SetLayerSaturation(float saturation) {
293 layer_saturation_ = saturation;
294 SetLayerFilters();
297 void Layer::SetLayerBrightness(float brightness) {
298 GetAnimator()->SetBrightness(brightness);
301 float Layer::GetTargetBrightness() const {
302 if (animator_.get() && animator_->IsAnimatingProperty(
303 LayerAnimationElement::BRIGHTNESS)) {
304 return animator_->GetTargetBrightness();
306 return layer_brightness();
309 void Layer::SetLayerGrayscale(float grayscale) {
310 GetAnimator()->SetGrayscale(grayscale);
313 float Layer::GetTargetGrayscale() const {
314 if (animator_.get() && animator_->IsAnimatingProperty(
315 LayerAnimationElement::GRAYSCALE)) {
316 return animator_->GetTargetGrayscale();
318 return layer_grayscale();
321 void Layer::SetLayerInverted(bool inverted) {
322 layer_inverted_ = inverted;
323 SetLayerFilters();
326 void Layer::SetMaskLayer(Layer* layer_mask) {
327 // The provided mask should not have a layer mask itself.
328 DCHECK(!layer_mask ||
329 (!layer_mask->layer_mask_layer() &&
330 layer_mask->children().empty() &&
331 !layer_mask->layer_mask_back_link_));
332 DCHECK(!layer_mask_back_link_);
333 if (layer_mask_ == layer_mask)
334 return;
335 // We need to de-reference the currently linked object so that no problem
336 // arises if the mask layer gets deleted before this object.
337 if (layer_mask_)
338 layer_mask_->layer_mask_back_link_ = NULL;
339 layer_mask_ = layer_mask;
340 cc_layer_->SetMaskLayer(
341 layer_mask ? layer_mask->cc_layer() : NULL);
342 // We need to reference the linked object so that it can properly break the
343 // link to us when it gets deleted.
344 if (layer_mask) {
345 layer_mask->layer_mask_back_link_ = this;
346 layer_mask->OnDeviceScaleFactorChanged(device_scale_factor_);
350 void Layer::SetBackgroundZoom(float zoom, int inset) {
351 zoom_ = zoom;
352 zoom_inset_ = inset;
354 SetLayerBackgroundFilters();
357 void Layer::SetAlphaShape(scoped_ptr<SkRegion> region) {
358 alpha_shape_ = region.Pass();
360 SetLayerFilters();
363 void Layer::SetLayerFilters() {
364 cc::FilterOperations filters;
365 if (layer_saturation_) {
366 filters.Append(cc::FilterOperation::CreateSaturateFilter(
367 layer_saturation_));
369 if (layer_grayscale_) {
370 filters.Append(cc::FilterOperation::CreateGrayscaleFilter(
371 layer_grayscale_));
373 if (layer_inverted_)
374 filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
375 // Brightness goes last, because the resulting colors neeed clamping, which
376 // cause further color matrix filters to be applied separately. In this order,
377 // they all can be combined in a single pass.
378 if (layer_brightness_) {
379 filters.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter(
380 layer_brightness_));
382 if (alpha_shape_) {
383 filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter(
384 *alpha_shape_, 0.f, 0.f));
387 cc_layer_->SetFilters(filters);
390 void Layer::SetLayerBackgroundFilters() {
391 cc::FilterOperations filters;
392 if (zoom_ != 1)
393 filters.Append(cc::FilterOperation::CreateZoomFilter(zoom_, zoom_inset_));
395 if (background_blur_radius_) {
396 filters.Append(cc::FilterOperation::CreateBlurFilter(
397 background_blur_radius_));
400 cc_layer_->SetBackgroundFilters(filters);
403 float Layer::GetTargetOpacity() const {
404 if (animator_.get() && animator_->IsAnimatingProperty(
405 LayerAnimationElement::OPACITY))
406 return animator_->GetTargetOpacity();
407 return opacity();
410 void Layer::SetVisible(bool visible) {
411 GetAnimator()->SetVisibility(visible);
414 bool Layer::GetTargetVisibility() const {
415 if (animator_.get() && animator_->IsAnimatingProperty(
416 LayerAnimationElement::VISIBILITY))
417 return animator_->GetTargetVisibility();
418 return visible_;
421 bool Layer::IsDrawn() const {
422 const Layer* layer = this;
423 while (layer && layer->visible_)
424 layer = layer->parent_;
425 return layer == NULL;
428 bool Layer::ShouldDraw() const {
429 return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f;
432 // static
433 void Layer::ConvertPointToLayer(const Layer* source,
434 const Layer* target,
435 gfx::Point* point) {
436 if (source == target)
437 return;
439 const Layer* root_layer = GetRoot(source);
440 CHECK_EQ(root_layer, GetRoot(target));
442 if (source != root_layer)
443 source->ConvertPointForAncestor(root_layer, point);
444 if (target != root_layer)
445 target->ConvertPointFromAncestor(root_layer, point);
448 bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor,
449 gfx::Transform* transform) const {
450 const Layer* p = this;
451 for (; p && p != ancestor; p = p->parent()) {
452 gfx::Transform translation;
453 translation.Translate(static_cast<float>(p->bounds().x()),
454 static_cast<float>(p->bounds().y()));
455 // Use target transform so that result will be correct once animation is
456 // finished.
457 if (!p->GetTargetTransform().IsIdentity())
458 transform->ConcatTransform(p->GetTargetTransform());
459 transform->ConcatTransform(translation);
461 return p == ancestor;
464 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
465 if (fills_bounds_opaquely_ == fills_bounds_opaquely)
466 return;
468 fills_bounds_opaquely_ = fills_bounds_opaquely;
470 cc_layer_->SetContentsOpaque(fills_bounds_opaquely);
473 void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) {
474 fills_bounds_completely_ = fills_bounds_completely;
477 void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
478 // Finish animations being handled by cc_layer_.
479 if (animator_.get()) {
480 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
481 animator_->StopAnimatingProperty(LayerAnimationElement::OPACITY);
484 if (texture_layer_.get())
485 texture_layer_->ClearClient();
486 // TODO(piman): delegated_renderer_layer_ cleanup.
488 cc_layer_->RemoveAllChildren();
489 if (cc_layer_->parent()) {
490 cc_layer_->parent()->ReplaceChild(cc_layer_, new_layer);
492 cc_layer_->SetLayerClient(NULL);
493 cc_layer_->RemoveLayerAnimationEventObserver(this);
494 new_layer->SetOpacity(cc_layer_->opacity());
495 new_layer->SetTransform(cc_layer_->transform());
496 new_layer->SetPosition(cc_layer_->position());
497 new_layer->SetBackgroundColor(cc_layer_->background_color());
499 cc_layer_ = new_layer.get();
500 content_layer_ = NULL;
501 solid_color_layer_ = NULL;
502 texture_layer_ = NULL;
503 delegated_renderer_layer_ = NULL;
504 surface_layer_ = NULL;
506 cc_layer_->AddLayerAnimationEventObserver(this);
507 for (size_t i = 0; i < children_.size(); ++i) {
508 DCHECK(children_[i]->cc_layer_);
509 cc_layer_->AddChild(children_[i]->cc_layer_);
511 cc_layer_->SetLayerClient(this);
512 cc_layer_->SetTransformOrigin(gfx::Point3F());
513 cc_layer_->SetContentsOpaque(fills_bounds_opaquely_);
514 cc_layer_->SetForceRenderSurface(force_render_surface_);
515 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
516 cc_layer_->SetHideLayerAndSubtree(!visible_);
518 SetLayerFilters();
519 SetLayerBackgroundFilters();
522 void Layer::SwitchCCLayerForTest() {
523 scoped_refptr<cc::Layer> new_layer;
524 if (Layer::UsingPictureLayer())
525 new_layer = cc::PictureLayer::Create(this);
526 else
527 new_layer = cc::ContentLayer::Create(this);
528 SwitchToLayer(new_layer);
529 content_layer_ = new_layer;
532 void Layer::SetTextureMailbox(
533 const cc::TextureMailbox& mailbox,
534 scoped_ptr<cc::SingleReleaseCallback> release_callback,
535 gfx::Size texture_size_in_dip) {
536 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
537 DCHECK(mailbox.IsValid());
538 DCHECK(release_callback);
539 if (!texture_layer_.get()) {
540 scoped_refptr<cc::TextureLayer> new_layer =
541 cc::TextureLayer::CreateForMailbox(this);
542 new_layer->SetFlipped(true);
543 SwitchToLayer(new_layer);
544 texture_layer_ = new_layer;
545 // Reset the frame_size_in_dip_ so that SetTextureSize() will not early out,
546 // the frame_size_in_dip_ was for a previous (different) |texture_layer_|.
547 frame_size_in_dip_ = gfx::Size();
549 if (mailbox_release_callback_)
550 mailbox_release_callback_->Run(0, false);
551 mailbox_release_callback_ = release_callback.Pass();
552 mailbox_ = mailbox;
553 SetTextureSize(texture_size_in_dip);
556 void Layer::SetTextureSize(gfx::Size texture_size_in_dip) {
557 DCHECK(texture_layer_.get());
558 if (frame_size_in_dip_ == texture_size_in_dip)
559 return;
560 frame_size_in_dip_ = texture_size_in_dip;
561 RecomputeDrawsContentAndUVRect();
562 texture_layer_->SetNeedsDisplay();
565 void Layer::SetTextureFlipped(bool flipped) {
566 DCHECK(texture_layer_.get());
567 texture_layer_->SetFlipped(flipped);
570 bool Layer::TextureFlipped() const {
571 DCHECK(texture_layer_.get());
572 return texture_layer_->flipped();
575 void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider,
576 gfx::Size frame_size_in_dip) {
577 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
579 scoped_refptr<cc::DelegatedRendererLayer> new_layer =
580 cc::DelegatedRendererLayer::Create(frame_provider);
581 SwitchToLayer(new_layer);
582 delegated_renderer_layer_ = new_layer;
584 frame_size_in_dip_ = frame_size_in_dip;
585 RecomputeDrawsContentAndUVRect();
588 void Layer::SetShowSurface(
589 cc::SurfaceId surface_id,
590 const cc::SurfaceLayer::SatisfyCallback& satisfy_callback,
591 const cc::SurfaceLayer::RequireCallback& require_callback,
592 gfx::Size surface_size,
593 float scale,
594 gfx::Size frame_size_in_dip) {
595 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
597 scoped_refptr<cc::SurfaceLayer> new_layer =
598 cc::SurfaceLayer::Create(satisfy_callback, require_callback);
599 new_layer->SetSurfaceId(surface_id, scale, surface_size);
600 SwitchToLayer(new_layer);
601 surface_layer_ = new_layer;
603 frame_size_in_dip_ = frame_size_in_dip;
604 RecomputeDrawsContentAndUVRect();
607 void Layer::SetShowSolidColorContent() {
608 DCHECK_EQ(type_, LAYER_SOLID_COLOR);
610 if (solid_color_layer_.get())
611 return;
613 scoped_refptr<cc::SolidColorLayer> new_layer = cc::SolidColorLayer::Create();
614 SwitchToLayer(new_layer);
615 solid_color_layer_ = new_layer;
617 mailbox_ = cc::TextureMailbox();
618 if (mailbox_release_callback_) {
619 mailbox_release_callback_->Run(0, false);
620 mailbox_release_callback_.reset();
622 RecomputeDrawsContentAndUVRect();
625 void Layer::UpdateNinePatchLayerImage(const gfx::ImageSkia& image) {
626 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
627 nine_patch_layer_image_ = image;
628 SkBitmap bitmap = nine_patch_layer_image_.GetRepresentation(
629 device_scale_factor_).sk_bitmap();
630 SkBitmap bitmap_copy;
631 if (bitmap.isImmutable()) {
632 bitmap_copy = bitmap;
633 } else {
634 // UIResourceBitmap requires an immutable copy of the input |bitmap|.
635 bitmap.copyTo(&bitmap_copy);
636 bitmap_copy.setImmutable();
638 nine_patch_layer_->SetBitmap(bitmap_copy);
641 void Layer::UpdateNinePatchLayerAperture(const gfx::Rect& aperture_in_dip) {
642 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
643 nine_patch_layer_aperture_ = aperture_in_dip;
644 gfx::Rect aperture_in_pixel = ConvertRectToPixel(this, aperture_in_dip);
645 nine_patch_layer_->SetAperture(aperture_in_pixel);
648 void Layer::UpdateNinePatchLayerBorder(const gfx::Rect& border) {
649 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
650 nine_patch_layer_->SetBorder(border);
653 void Layer::SetColor(SkColor color) { GetAnimator()->SetColor(color); }
655 bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) {
656 if ((type_ == LAYER_SOLID_COLOR && !texture_layer_.get()) ||
657 type_ == LAYER_NINE_PATCH || (!delegate_ && !mailbox_.IsValid()))
658 return false;
660 damaged_region_.op(invalid_rect.x(),
661 invalid_rect.y(),
662 invalid_rect.right(),
663 invalid_rect.bottom(),
664 SkRegion::kUnion_Op);
665 ScheduleDraw();
666 return true;
669 void Layer::ScheduleDraw() {
670 Compositor* compositor = GetCompositor();
671 if (compositor)
672 compositor->ScheduleDraw();
675 void Layer::SendDamagedRects() {
676 if ((delegate_ || mailbox_.IsValid()) && !damaged_region_.isEmpty()) {
677 for (SkRegion::Iterator iter(damaged_region_); !iter.done(); iter.next()) {
678 const SkIRect& sk_damaged = iter.rect();
679 gfx::Rect damaged(
680 sk_damaged.x(),
681 sk_damaged.y(),
682 sk_damaged.width(),
683 sk_damaged.height());
684 cc_layer_->SetNeedsDisplayRect(damaged);
686 damaged_region_.setEmpty();
688 for (size_t i = 0; i < children_.size(); ++i)
689 children_[i]->SendDamagedRects();
692 void Layer::CompleteAllAnimations() {
693 typedef std::vector<scoped_refptr<LayerAnimator> > LayerAnimatorVector;
694 LayerAnimatorVector animators;
695 CollectAnimators(&animators);
696 for (LayerAnimatorVector::const_iterator it = animators.begin();
697 it != animators.end();
698 ++it) {
699 (*it)->StopAnimating();
703 void Layer::SuppressPaint() {
704 if (!delegate_)
705 return;
706 delegate_ = NULL;
707 for (size_t i = 0; i < children_.size(); ++i)
708 children_[i]->SuppressPaint();
711 void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) {
712 if (device_scale_factor_ == device_scale_factor)
713 return;
714 if (animator_.get())
715 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
716 device_scale_factor_ = device_scale_factor;
717 RecomputeDrawsContentAndUVRect();
718 RecomputePosition();
719 if (nine_patch_layer_) {
720 UpdateNinePatchLayerImage(nine_patch_layer_image_);
721 UpdateNinePatchLayerAperture(nine_patch_layer_aperture_);
723 SchedulePaint(gfx::Rect(bounds_.size()));
724 if (delegate_)
725 delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
726 for (size_t i = 0; i < children_.size(); ++i)
727 children_[i]->OnDeviceScaleFactorChanged(device_scale_factor);
728 if (layer_mask_)
729 layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor);
732 void Layer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {
733 DCHECK(delegated_renderer_layer_.get() || surface_layer_.get());
734 if (!delegate_)
735 return;
736 delegate_->OnDelegatedFrameDamage(damage_rect_in_dip);
739 void Layer::RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) {
740 cc_layer_->RequestCopyOfOutput(request.Pass());
743 void Layer::PaintContents(
744 SkCanvas* sk_canvas,
745 const gfx::Rect& clip,
746 ContentLayerClient::PaintingControlSetting painting_control) {
747 TRACE_EVENT1("ui", "Layer::PaintContents", "name", name_);
748 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling(
749 sk_canvas, device_scale_factor_));
750 if (delegate_)
751 delegate_->OnPaintLayer(PaintContext(canvas.get(), clip));
754 void Layer::PaintContentsToDisplayList(
755 cc::DisplayItemList* display_list,
756 const gfx::Rect& clip,
757 ContentLayerClient::PaintingControlSetting painting_control) {
758 TRACE_EVENT1("ui", "Layer::PaintContentsToDisplayList", "name", name_);
759 if (delegate_) {
760 // TODO(danakj): Save the invalidation on the layer and pass that down
761 // instead of the |clip| here. That will break everything until View
762 // early-outs emit cached display items instead of nothing.
763 gfx::Rect invalidation = clip;
764 DCHECK(clip.Contains(invalidation));
765 delegate_->OnPaintLayer(
766 PaintContext(display_list, device_scale_factor_, clip, invalidation));
770 bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; }
772 bool Layer::PrepareTextureMailbox(
773 cc::TextureMailbox* mailbox,
774 scoped_ptr<cc::SingleReleaseCallback>* release_callback,
775 bool use_shared_memory) {
776 if (!mailbox_release_callback_)
777 return false;
778 *mailbox = mailbox_;
779 *release_callback = mailbox_release_callback_.Pass();
780 return true;
783 void Layer::SetForceRenderSurface(bool force) {
784 if (force_render_surface_ == force)
785 return;
787 force_render_surface_ = force;
788 cc_layer_->SetForceRenderSurface(force_render_surface_);
791 class LayerDebugInfo : public base::trace_event::ConvertableToTraceFormat {
792 public:
793 explicit LayerDebugInfo(std::string name) : name_(name) { }
794 void AppendAsTraceFormat(std::string* out) const override {
795 base::DictionaryValue dictionary;
796 dictionary.SetString("layer_name", name_);
797 base::JSONWriter::Write(&dictionary, out);
800 private:
801 ~LayerDebugInfo() override {}
802 std::string name_;
805 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
806 Layer::TakeDebugInfo() {
807 return new LayerDebugInfo(name_);
810 void Layer::OnAnimationStarted(const cc::AnimationEvent& event) {
811 if (animator_.get())
812 animator_->OnThreadedAnimationStarted(event);
815 void Layer::CollectAnimators(
816 std::vector<scoped_refptr<LayerAnimator> >* animators) {
817 if (IsAnimating())
818 animators->push_back(animator_);
819 std::for_each(children_.begin(), children_.end(),
820 std::bind2nd(std::mem_fun(&Layer::CollectAnimators),
821 animators));
824 void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) {
825 DCHECK_NE(child, other);
826 DCHECK_EQ(this, child->parent());
827 DCHECK_EQ(this, other->parent());
829 const size_t child_i =
830 std::find(children_.begin(), children_.end(), child) - children_.begin();
831 const size_t other_i =
832 std::find(children_.begin(), children_.end(), other) - children_.begin();
833 if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i))
834 return;
836 const size_t dest_i =
837 above ?
838 (child_i < other_i ? other_i : other_i + 1) :
839 (child_i < other_i ? other_i - 1 : other_i);
840 children_.erase(children_.begin() + child_i);
841 children_.insert(children_.begin() + dest_i, child);
843 child->cc_layer_->RemoveFromParent();
844 cc_layer_->InsertChild(child->cc_layer_, dest_i);
847 bool Layer::ConvertPointForAncestor(const Layer* ancestor,
848 gfx::Point* point) const {
849 gfx::Transform transform;
850 bool result = GetTargetTransformRelativeTo(ancestor, &transform);
851 gfx::Point3F p(*point);
852 transform.TransformPoint(&p);
853 *point = gfx::ToFlooredPoint(p.AsPointF());
854 return result;
857 bool Layer::ConvertPointFromAncestor(const Layer* ancestor,
858 gfx::Point* point) const {
859 gfx::Transform transform;
860 bool result = GetTargetTransformRelativeTo(ancestor, &transform);
861 gfx::Point3F p(*point);
862 transform.TransformPointReverse(&p);
863 *point = gfx::ToFlooredPoint(p.AsPointF());
864 return result;
867 void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) {
868 if (bounds == bounds_)
869 return;
871 base::Closure closure;
872 if (delegate_)
873 closure = delegate_->PrepareForLayerBoundsChange();
874 bool was_move = bounds_.size() == bounds.size();
875 bounds_ = bounds;
877 RecomputeDrawsContentAndUVRect();
878 RecomputePosition();
880 if (!closure.is_null())
881 closure.Run();
883 if (was_move) {
884 // Don't schedule a draw if we're invisible. We'll schedule one
885 // automatically when we get visible.
886 if (IsDrawn())
887 ScheduleDraw();
888 } else {
889 // Always schedule a paint, even if we're invisible.
890 SchedulePaint(gfx::Rect(bounds.size()));
894 void Layer::SetTransformFromAnimation(const gfx::Transform& transform) {
895 cc_layer_->SetTransform(transform);
898 void Layer::SetOpacityFromAnimation(float opacity) {
899 cc_layer_->SetOpacity(opacity);
900 ScheduleDraw();
903 void Layer::SetVisibilityFromAnimation(bool visible) {
904 if (visible_ == visible)
905 return;
907 visible_ = visible;
908 cc_layer_->SetHideLayerAndSubtree(!visible_);
911 void Layer::SetBrightnessFromAnimation(float brightness) {
912 layer_brightness_ = brightness;
913 SetLayerFilters();
916 void Layer::SetGrayscaleFromAnimation(float grayscale) {
917 layer_grayscale_ = grayscale;
918 SetLayerFilters();
921 void Layer::SetColorFromAnimation(SkColor color) {
922 DCHECK_EQ(type_, LAYER_SOLID_COLOR);
923 cc_layer_->SetBackgroundColor(color);
924 SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF);
927 void Layer::ScheduleDrawForAnimation() {
928 ScheduleDraw();
931 const gfx::Rect& Layer::GetBoundsForAnimation() const {
932 return bounds();
935 gfx::Transform Layer::GetTransformForAnimation() const {
936 return transform();
939 float Layer::GetOpacityForAnimation() const {
940 return opacity();
943 bool Layer::GetVisibilityForAnimation() const {
944 return visible();
947 float Layer::GetBrightnessForAnimation() const {
948 return layer_brightness();
951 float Layer::GetGrayscaleForAnimation() const {
952 return layer_grayscale();
955 SkColor Layer::GetColorForAnimation() const {
956 // WebColor is equivalent to SkColor, per WebColor.h.
957 // The NULL check is here since this is invoked regardless of whether we have
958 // been configured as LAYER_SOLID_COLOR.
959 return solid_color_layer_.get() ?
960 solid_color_layer_->background_color() : SK_ColorBLACK;
963 float Layer::GetDeviceScaleFactor() const {
964 return device_scale_factor_;
967 void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) {
968 DCHECK(cc_layer_);
969 // Until this layer has a compositor (and hence cc_layer_ has a
970 // LayerTreeHost), addAnimation will fail.
971 if (GetCompositor())
972 cc_layer_->AddAnimation(animation.Pass());
973 else
974 pending_threaded_animations_.push_back(animation.Pass());
977 namespace{
979 struct HasAnimationId {
980 HasAnimationId(int id): id_(id) {
983 bool operator()(cc::Animation* animation) const {
984 return animation->id() == id_;
987 private:
988 int id_;
993 void Layer::RemoveThreadedAnimation(int animation_id) {
994 DCHECK(cc_layer_);
995 if (pending_threaded_animations_.size() == 0) {
996 cc_layer_->RemoveAnimation(animation_id);
997 return;
1000 pending_threaded_animations_.erase(
1001 cc::remove_if(&pending_threaded_animations_,
1002 pending_threaded_animations_.begin(),
1003 pending_threaded_animations_.end(),
1004 HasAnimationId(animation_id)),
1005 pending_threaded_animations_.end());
1008 LayerAnimatorCollection* Layer::GetLayerAnimatorCollection() {
1009 Compositor* compositor = GetCompositor();
1010 return compositor ? compositor->layer_animator_collection() : NULL;
1013 void Layer::SendPendingThreadedAnimations() {
1014 for (cc::ScopedPtrVector<cc::Animation>::iterator it =
1015 pending_threaded_animations_.begin();
1016 it != pending_threaded_animations_.end();
1017 ++it)
1018 cc_layer_->AddAnimation(pending_threaded_animations_.take(it));
1020 pending_threaded_animations_.clear();
1022 for (size_t i = 0; i < children_.size(); ++i)
1023 children_[i]->SendPendingThreadedAnimations();
1026 void Layer::CreateCcLayer() {
1027 if (type_ == LAYER_SOLID_COLOR) {
1028 solid_color_layer_ = cc::SolidColorLayer::Create();
1029 cc_layer_ = solid_color_layer_.get();
1030 } else if (type_ == LAYER_NINE_PATCH) {
1031 nine_patch_layer_ = cc::NinePatchLayer::Create();
1032 cc_layer_ = nine_patch_layer_.get();
1033 } else {
1034 if (Layer::UsingPictureLayer())
1035 content_layer_ = cc::PictureLayer::Create(this);
1036 else
1037 content_layer_ = cc::ContentLayer::Create(this);
1038 cc_layer_ = content_layer_.get();
1040 cc_layer_->SetTransformOrigin(gfx::Point3F());
1041 cc_layer_->SetContentsOpaque(true);
1042 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
1043 cc_layer_->AddLayerAnimationEventObserver(this);
1044 cc_layer_->SetLayerClient(this);
1045 RecomputePosition();
1048 gfx::Transform Layer::transform() const {
1049 return cc_layer_->transform();
1052 void Layer::RecomputeDrawsContentAndUVRect() {
1053 DCHECK(cc_layer_);
1054 gfx::Size size(bounds_.size());
1055 if (texture_layer_.get()) {
1056 size.SetToMin(frame_size_in_dip_);
1057 gfx::PointF uv_top_left(0.f, 0.f);
1058 gfx::PointF uv_bottom_right(
1059 static_cast<float>(size.width()) / frame_size_in_dip_.width(),
1060 static_cast<float>(size.height()) / frame_size_in_dip_.height());
1061 texture_layer_->SetUV(uv_top_left, uv_bottom_right);
1062 } else if (delegated_renderer_layer_.get() || surface_layer_.get()) {
1063 size.SetToMin(frame_size_in_dip_);
1065 cc_layer_->SetBounds(size);
1068 void Layer::RecomputePosition() {
1069 cc_layer_->SetPosition(bounds_.origin() + subpixel_position_offset_);
1072 void Layer::AddAnimatorsInTreeToCollection(
1073 LayerAnimatorCollection* collection) {
1074 DCHECK(collection);
1075 if (IsAnimating())
1076 animator_->AddToCollection(collection);
1077 std::for_each(
1078 children_.begin(),
1079 children_.end(),
1080 std::bind2nd(std::mem_fun(&Layer::AddAnimatorsInTreeToCollection),
1081 collection));
1084 void Layer::RemoveAnimatorsInTreeFromCollection(
1085 LayerAnimatorCollection* collection) {
1086 DCHECK(collection);
1087 if (IsAnimating())
1088 animator_->RemoveFromCollection(collection);
1089 std::for_each(
1090 children_.begin(),
1091 children_.end(),
1092 std::bind2nd(std::mem_fun(&Layer::RemoveAnimatorsInTreeFromCollection),
1093 collection));
1096 bool Layer::IsAnimating() const {
1097 return animator_.get() && animator_->is_animating();
1100 } // namespace ui