Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / compositor / layer.cc
blob0c5543358f953af373914803cdbb84bcb7dd8305
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/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/playback/display_item_list_settings.h"
28 #include "cc/resources/transferable_resource.h"
29 #include "cc/trees/layer_tree_settings.h"
30 #include "ui/compositor/compositor_switches.h"
31 #include "ui/compositor/dip_util.h"
32 #include "ui/compositor/layer_animator.h"
33 #include "ui/compositor/paint_context.h"
34 #include "ui/gfx/animation/animation.h"
35 #include "ui/gfx/canvas.h"
36 #include "ui/gfx/display.h"
37 #include "ui/gfx/geometry/point3_f.h"
38 #include "ui/gfx/geometry/point_conversions.h"
39 #include "ui/gfx/geometry/size_conversions.h"
40 #include "ui/gfx/interpolated_transform.h"
42 namespace {
44 const ui::Layer* GetRoot(const ui::Layer* layer) {
45 while (layer->parent())
46 layer = layer->parent();
47 return layer;
50 base::LazyInstance<cc::LayerSettings> g_ui_layer_settings =
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 CreateCcLayer();
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 CreateCcLayer();
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;
123 cc_layer_->RemoveLayerAnimationEventObserver(this);
124 cc_layer_->RemoveFromParent();
127 // static
128 const cc::LayerSettings& Layer::UILayerSettings() {
129 return g_ui_layer_settings.Get();
132 // static
133 void Layer::InitializeUILayerSettings() {
134 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
135 if (command_line->HasSwitch(switches::kUIEnableCompositorAnimationTimelines))
136 g_ui_layer_settings.Get().use_compositor_animation_timelines = true;
139 const Compositor* Layer::GetCompositor() const {
140 return GetRoot(this)->compositor_;
143 float Layer::opacity() const {
144 return cc_layer_->opacity();
147 void Layer::SetCompositor(Compositor* compositor,
148 scoped_refptr<cc::Layer> root_layer) {
149 // This function must only be called to set the compositor on the root ui
150 // layer.
151 DCHECK(compositor);
152 DCHECK(!compositor_);
153 DCHECK(compositor->root_layer() == this);
154 DCHECK(!parent_);
156 compositor_ = compositor;
157 OnDeviceScaleFactorChanged(compositor->device_scale_factor());
158 AddAnimatorsInTreeToCollection(compositor_->layer_animator_collection());
160 root_layer->AddChild(cc_layer_);
161 SendPendingThreadedAnimations();
164 void Layer::ResetCompositor() {
165 DCHECK(!parent_);
166 if (compositor_)
167 RemoveAnimatorsInTreeFromCollection(
168 compositor_->layer_animator_collection());
169 compositor_ = nullptr;
172 void Layer::Add(Layer* child) {
173 DCHECK(!child->compositor_);
174 if (child->parent_)
175 child->parent_->Remove(child);
176 child->parent_ = this;
177 children_.push_back(child);
178 cc_layer_->AddChild(child->cc_layer_);
179 child->OnDeviceScaleFactorChanged(device_scale_factor_);
180 if (GetCompositor())
181 child->SendPendingThreadedAnimations();
182 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
183 if (collection)
184 child->AddAnimatorsInTreeToCollection(collection);
187 void Layer::Remove(Layer* child) {
188 // Current bounds are used to calculate offsets when layers are reparented.
189 // Stop (and complete) an ongoing animation to update the bounds immediately.
190 LayerAnimator* child_animator = child->animator_.get();
191 if (child_animator)
192 child_animator->StopAnimatingProperty(ui::LayerAnimationElement::BOUNDS);
193 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
194 if (collection)
195 child->RemoveAnimatorsInTreeFromCollection(collection);
197 std::vector<Layer*>::iterator i =
198 std::find(children_.begin(), children_.end(), child);
199 DCHECK(i != children_.end());
200 children_.erase(i);
201 child->parent_ = NULL;
202 child->cc_layer_->RemoveFromParent();
205 void Layer::StackAtTop(Layer* child) {
206 if (children_.size() <= 1 || child == children_.back())
207 return; // Already in front.
208 StackAbove(child, children_.back());
211 void Layer::StackAbove(Layer* child, Layer* other) {
212 StackRelativeTo(child, other, true);
215 void Layer::StackAtBottom(Layer* child) {
216 if (children_.size() <= 1 || child == children_.front())
217 return; // Already on bottom.
218 StackBelow(child, children_.front());
221 void Layer::StackBelow(Layer* child, Layer* other) {
222 StackRelativeTo(child, other, false);
225 bool Layer::Contains(const Layer* other) const {
226 for (const Layer* parent = other; parent; parent = parent->parent()) {
227 if (parent == this)
228 return true;
230 return false;
233 void Layer::SetAnimator(LayerAnimator* animator) {
234 if (animator)
235 animator->SetDelegate(this);
236 animator_ = animator;
239 LayerAnimator* Layer::GetAnimator() {
240 if (!animator_.get())
241 SetAnimator(LayerAnimator::CreateDefaultAnimator());
242 return animator_.get();
245 void Layer::SetTransform(const gfx::Transform& transform) {
246 GetAnimator()->SetTransform(transform);
249 gfx::Transform Layer::GetTargetTransform() const {
250 if (animator_.get() && animator_->IsAnimatingProperty(
251 LayerAnimationElement::TRANSFORM)) {
252 return animator_->GetTargetTransform();
254 return transform();
257 void Layer::SetBounds(const gfx::Rect& bounds) {
258 GetAnimator()->SetBounds(bounds);
261 void Layer::SetSubpixelPositionOffset(const gfx::Vector2dF& offset) {
262 subpixel_position_offset_ = offset;
263 RecomputePosition();
266 gfx::Rect Layer::GetTargetBounds() const {
267 if (animator_.get() && animator_->IsAnimatingProperty(
268 LayerAnimationElement::BOUNDS)) {
269 return animator_->GetTargetBounds();
271 return bounds_;
274 void Layer::SetMasksToBounds(bool masks_to_bounds) {
275 cc_layer_->SetMasksToBounds(masks_to_bounds);
278 bool Layer::GetMasksToBounds() const {
279 return cc_layer_->masks_to_bounds();
282 void Layer::SetOpacity(float opacity) {
283 GetAnimator()->SetOpacity(opacity);
286 float Layer::GetCombinedOpacity() const {
287 float opacity = this->opacity();
288 Layer* current = this->parent_;
289 while (current) {
290 opacity *= current->opacity();
291 current = current->parent_;
293 return opacity;
296 void Layer::SetBackgroundBlur(int blur_radius) {
297 background_blur_radius_ = blur_radius;
299 SetLayerBackgroundFilters();
302 void Layer::SetLayerSaturation(float saturation) {
303 layer_saturation_ = saturation;
304 SetLayerFilters();
307 void Layer::SetLayerBrightness(float brightness) {
308 GetAnimator()->SetBrightness(brightness);
311 float Layer::GetTargetBrightness() const {
312 if (animator_.get() && animator_->IsAnimatingProperty(
313 LayerAnimationElement::BRIGHTNESS)) {
314 return animator_->GetTargetBrightness();
316 return layer_brightness();
319 void Layer::SetLayerGrayscale(float grayscale) {
320 GetAnimator()->SetGrayscale(grayscale);
323 float Layer::GetTargetGrayscale() const {
324 if (animator_.get() && animator_->IsAnimatingProperty(
325 LayerAnimationElement::GRAYSCALE)) {
326 return animator_->GetTargetGrayscale();
328 return layer_grayscale();
331 void Layer::SetLayerInverted(bool inverted) {
332 layer_inverted_ = inverted;
333 SetLayerFilters();
336 void Layer::SetMaskLayer(Layer* layer_mask) {
337 // The provided mask should not have a layer mask itself.
338 DCHECK(!layer_mask ||
339 (!layer_mask->layer_mask_layer() &&
340 layer_mask->children().empty() &&
341 !layer_mask->layer_mask_back_link_));
342 DCHECK(!layer_mask_back_link_);
343 if (layer_mask_ == layer_mask)
344 return;
345 // We need to de-reference the currently linked object so that no problem
346 // arises if the mask layer gets deleted before this object.
347 if (layer_mask_)
348 layer_mask_->layer_mask_back_link_ = NULL;
349 layer_mask_ = layer_mask;
350 cc_layer_->SetMaskLayer(layer_mask ? layer_mask->cc_layer_ : NULL);
351 // We need to reference the linked object so that it can properly break the
352 // link to us when it gets deleted.
353 if (layer_mask) {
354 layer_mask->layer_mask_back_link_ = this;
355 layer_mask->OnDeviceScaleFactorChanged(device_scale_factor_);
359 void Layer::SetBackgroundZoom(float zoom, int inset) {
360 zoom_ = zoom;
361 zoom_inset_ = inset;
363 SetLayerBackgroundFilters();
366 void Layer::SetAlphaShape(scoped_ptr<SkRegion> region) {
367 alpha_shape_ = region.Pass();
369 SetLayerFilters();
372 void Layer::SetLayerFilters() {
373 cc::FilterOperations filters;
374 if (layer_saturation_) {
375 filters.Append(cc::FilterOperation::CreateSaturateFilter(
376 layer_saturation_));
378 if (layer_grayscale_) {
379 filters.Append(cc::FilterOperation::CreateGrayscaleFilter(
380 layer_grayscale_));
382 if (layer_inverted_)
383 filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
384 // Brightness goes last, because the resulting colors neeed clamping, which
385 // cause further color matrix filters to be applied separately. In this order,
386 // they all can be combined in a single pass.
387 if (layer_brightness_) {
388 filters.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter(
389 layer_brightness_));
391 if (alpha_shape_) {
392 filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter(
393 *alpha_shape_, 0.f, 0.f));
396 cc_layer_->SetFilters(filters);
399 void Layer::SetLayerBackgroundFilters() {
400 cc::FilterOperations filters;
401 if (zoom_ != 1)
402 filters.Append(cc::FilterOperation::CreateZoomFilter(zoom_, zoom_inset_));
404 if (background_blur_radius_) {
405 filters.Append(cc::FilterOperation::CreateBlurFilter(
406 background_blur_radius_));
409 cc_layer_->SetBackgroundFilters(filters);
412 float Layer::GetTargetOpacity() const {
413 if (animator_.get() && animator_->IsAnimatingProperty(
414 LayerAnimationElement::OPACITY))
415 return animator_->GetTargetOpacity();
416 return opacity();
419 void Layer::SetVisible(bool visible) {
420 GetAnimator()->SetVisibility(visible);
423 bool Layer::GetTargetVisibility() const {
424 if (animator_.get() && animator_->IsAnimatingProperty(
425 LayerAnimationElement::VISIBILITY))
426 return animator_->GetTargetVisibility();
427 return visible_;
430 bool Layer::IsDrawn() const {
431 const Layer* layer = this;
432 while (layer && layer->visible_)
433 layer = layer->parent_;
434 return layer == NULL;
437 bool Layer::ShouldDraw() const {
438 return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f;
441 // static
442 void Layer::ConvertPointToLayer(const Layer* source,
443 const Layer* target,
444 gfx::Point* point) {
445 if (source == target)
446 return;
448 const Layer* root_layer = GetRoot(source);
449 CHECK_EQ(root_layer, GetRoot(target));
451 if (source != root_layer)
452 source->ConvertPointForAncestor(root_layer, point);
453 if (target != root_layer)
454 target->ConvertPointFromAncestor(root_layer, point);
457 bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor,
458 gfx::Transform* transform) const {
459 const Layer* p = this;
460 for (; p && p != ancestor; p = p->parent()) {
461 gfx::Transform translation;
462 translation.Translate(static_cast<float>(p->bounds().x()),
463 static_cast<float>(p->bounds().y()));
464 // Use target transform so that result will be correct once animation is
465 // finished.
466 if (!p->GetTargetTransform().IsIdentity())
467 transform->ConcatTransform(p->GetTargetTransform());
468 transform->ConcatTransform(translation);
470 return p == ancestor;
473 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
474 if (fills_bounds_opaquely_ == fills_bounds_opaquely)
475 return;
477 fills_bounds_opaquely_ = fills_bounds_opaquely;
479 cc_layer_->SetContentsOpaque(fills_bounds_opaquely);
482 void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) {
483 fills_bounds_completely_ = fills_bounds_completely;
486 void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
487 // Finish animations being handled by cc_layer_.
488 if (animator_.get()) {
489 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
490 animator_->StopAnimatingProperty(LayerAnimationElement::OPACITY);
493 if (texture_layer_.get())
494 texture_layer_->ClearClient();
495 // TODO(piman): delegated_renderer_layer_ cleanup.
497 cc_layer_->RemoveAllChildren();
498 if (cc_layer_->parent()) {
499 cc_layer_->parent()->ReplaceChild(cc_layer_, new_layer);
501 cc_layer_->SetLayerClient(NULL);
502 cc_layer_->RemoveLayerAnimationEventObserver(this);
503 new_layer->SetOpacity(cc_layer_->opacity());
504 new_layer->SetTransform(cc_layer_->transform());
505 new_layer->SetPosition(cc_layer_->position());
506 new_layer->SetBackgroundColor(cc_layer_->background_color());
508 cc_layer_ = new_layer.get();
509 content_layer_ = NULL;
510 solid_color_layer_ = NULL;
511 texture_layer_ = NULL;
512 delegated_renderer_layer_ = NULL;
513 surface_layer_ = NULL;
515 cc_layer_->AddLayerAnimationEventObserver(this);
516 for (size_t i = 0; i < children_.size(); ++i) {
517 DCHECK(children_[i]->cc_layer_);
518 cc_layer_->AddChild(children_[i]->cc_layer_);
520 cc_layer_->SetLayerClient(this);
521 cc_layer_->SetTransformOrigin(gfx::Point3F());
522 cc_layer_->SetContentsOpaque(fills_bounds_opaquely_);
523 cc_layer_->SetForceRenderSurface(force_render_surface_);
524 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
525 cc_layer_->SetHideLayerAndSubtree(!visible_);
527 SetLayerFilters();
528 SetLayerBackgroundFilters();
531 void Layer::SwitchCCLayerForTest() {
532 scoped_refptr<cc::Layer> new_layer =
533 cc::PictureLayer::Create(UILayerSettings(), this);
534 SwitchToLayer(new_layer);
535 content_layer_ = new_layer;
538 void Layer::SetTextureMailbox(
539 const cc::TextureMailbox& mailbox,
540 scoped_ptr<cc::SingleReleaseCallback> release_callback,
541 gfx::Size texture_size_in_dip) {
542 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
543 DCHECK(mailbox.IsValid());
544 DCHECK(release_callback);
545 if (!texture_layer_.get()) {
546 scoped_refptr<cc::TextureLayer> new_layer =
547 cc::TextureLayer::CreateForMailbox(UILayerSettings(), this);
548 new_layer->SetFlipped(true);
549 SwitchToLayer(new_layer);
550 texture_layer_ = new_layer;
551 // Reset the frame_size_in_dip_ so that SetTextureSize() will not early out,
552 // the frame_size_in_dip_ was for a previous (different) |texture_layer_|.
553 frame_size_in_dip_ = gfx::Size();
555 if (mailbox_release_callback_)
556 mailbox_release_callback_->Run(0, false);
557 mailbox_release_callback_ = release_callback.Pass();
558 mailbox_ = mailbox;
559 SetTextureSize(texture_size_in_dip);
562 void Layer::SetTextureSize(gfx::Size texture_size_in_dip) {
563 DCHECK(texture_layer_.get());
564 if (frame_size_in_dip_ == texture_size_in_dip)
565 return;
566 frame_size_in_dip_ = texture_size_in_dip;
567 RecomputeDrawsContentAndUVRect();
568 texture_layer_->SetNeedsDisplay();
571 void Layer::SetTextureFlipped(bool flipped) {
572 DCHECK(texture_layer_.get());
573 texture_layer_->SetFlipped(flipped);
576 bool Layer::TextureFlipped() const {
577 DCHECK(texture_layer_.get());
578 return texture_layer_->flipped();
581 void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider,
582 gfx::Size frame_size_in_dip) {
583 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
585 scoped_refptr<cc::DelegatedRendererLayer> new_layer =
586 cc::DelegatedRendererLayer::Create(UILayerSettings(), frame_provider);
587 SwitchToLayer(new_layer);
588 delegated_renderer_layer_ = new_layer;
590 frame_size_in_dip_ = frame_size_in_dip;
591 RecomputeDrawsContentAndUVRect();
594 void Layer::SetShowSurface(
595 cc::SurfaceId surface_id,
596 const cc::SurfaceLayer::SatisfyCallback& satisfy_callback,
597 const cc::SurfaceLayer::RequireCallback& require_callback,
598 gfx::Size surface_size,
599 float scale,
600 gfx::Size frame_size_in_dip) {
601 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
603 scoped_refptr<cc::SurfaceLayer> new_layer = cc::SurfaceLayer::Create(
604 UILayerSettings(), satisfy_callback, require_callback);
605 new_layer->SetSurfaceId(surface_id, scale, surface_size);
606 SwitchToLayer(new_layer);
607 surface_layer_ = new_layer;
609 frame_size_in_dip_ = frame_size_in_dip;
610 RecomputeDrawsContentAndUVRect();
613 void Layer::SetShowSolidColorContent() {
614 DCHECK_EQ(type_, LAYER_SOLID_COLOR);
616 if (solid_color_layer_.get())
617 return;
619 scoped_refptr<cc::SolidColorLayer> new_layer =
620 cc::SolidColorLayer::Create(UILayerSettings());
621 SwitchToLayer(new_layer);
622 solid_color_layer_ = new_layer;
624 mailbox_ = cc::TextureMailbox();
625 if (mailbox_release_callback_) {
626 mailbox_release_callback_->Run(0, false);
627 mailbox_release_callback_.reset();
629 RecomputeDrawsContentAndUVRect();
632 void Layer::UpdateNinePatchLayerImage(const gfx::ImageSkia& image) {
633 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
634 nine_patch_layer_image_ = image;
635 SkBitmap bitmap = nine_patch_layer_image_.GetRepresentation(
636 device_scale_factor_).sk_bitmap();
637 SkBitmap bitmap_copy;
638 if (bitmap.isImmutable()) {
639 bitmap_copy = bitmap;
640 } else {
641 // UIResourceBitmap requires an immutable copy of the input |bitmap|.
642 bitmap.copyTo(&bitmap_copy);
643 bitmap_copy.setImmutable();
645 nine_patch_layer_->SetBitmap(bitmap_copy);
648 void Layer::UpdateNinePatchLayerAperture(const gfx::Rect& aperture_in_dip) {
649 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
650 nine_patch_layer_aperture_ = aperture_in_dip;
651 gfx::Rect aperture_in_pixel = ConvertRectToPixel(this, aperture_in_dip);
652 nine_patch_layer_->SetAperture(aperture_in_pixel);
655 void Layer::UpdateNinePatchLayerBorder(const gfx::Rect& border) {
656 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
657 nine_patch_layer_->SetBorder(border);
660 void Layer::SetColor(SkColor color) { GetAnimator()->SetColor(color); }
662 SkColor Layer::GetTargetColor() {
663 if (GetAnimator()->IsAnimatingProperty(LayerAnimationElement::COLOR))
664 return GetAnimator()->GetTargetColor();
665 return cc_layer_->background_color();
668 SkColor Layer::background_color() const {
669 return cc_layer_->background_color();
672 bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) {
673 if ((type_ == LAYER_SOLID_COLOR && !texture_layer_.get()) ||
674 type_ == LAYER_NINE_PATCH || (!delegate_ && !mailbox_.IsValid()))
675 return false;
677 damaged_region_.Union(invalid_rect);
678 ScheduleDraw();
679 return true;
682 void Layer::ScheduleDraw() {
683 Compositor* compositor = GetCompositor();
684 if (compositor)
685 compositor->ScheduleDraw();
688 void Layer::SendDamagedRects() {
689 if (damaged_region_.IsEmpty())
690 return;
691 if (!delegate_ && !mailbox_.IsValid())
692 return;
694 for (cc::Region::Iterator iter(damaged_region_); iter.has_rect(); iter.next())
695 cc_layer_->SetNeedsDisplayRect(iter.rect());
698 void Layer::ClearDamagedRects() {
699 damaged_region_.Clear();
702 void Layer::CompleteAllAnimations() {
703 typedef std::vector<scoped_refptr<LayerAnimator> > LayerAnimatorVector;
704 LayerAnimatorVector animators;
705 CollectAnimators(&animators);
706 for (LayerAnimatorVector::const_iterator it = animators.begin();
707 it != animators.end();
708 ++it) {
709 (*it)->StopAnimating();
713 void Layer::SuppressPaint() {
714 if (!delegate_)
715 return;
716 delegate_ = NULL;
717 for (size_t i = 0; i < children_.size(); ++i)
718 children_[i]->SuppressPaint();
721 void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) {
722 if (device_scale_factor_ == device_scale_factor)
723 return;
724 if (animator_.get())
725 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
726 device_scale_factor_ = device_scale_factor;
727 RecomputeDrawsContentAndUVRect();
728 RecomputePosition();
729 if (nine_patch_layer_) {
730 UpdateNinePatchLayerImage(nine_patch_layer_image_);
731 UpdateNinePatchLayerAperture(nine_patch_layer_aperture_);
733 SchedulePaint(gfx::Rect(bounds_.size()));
734 if (delegate_)
735 delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
736 for (size_t i = 0; i < children_.size(); ++i)
737 children_[i]->OnDeviceScaleFactorChanged(device_scale_factor);
738 if (layer_mask_)
739 layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor);
742 void Layer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {
743 DCHECK(delegated_renderer_layer_.get() || surface_layer_.get());
744 if (!delegate_)
745 return;
746 delegate_->OnDelegatedFrameDamage(damage_rect_in_dip);
749 void Layer::RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) {
750 cc_layer_->RequestCopyOfOutput(request.Pass());
753 void Layer::PaintContents(
754 SkCanvas* sk_canvas,
755 const gfx::Rect& clip,
756 ContentLayerClient::PaintingControlSetting painting_control) {
757 // The old non-slimming paint path is not used in ui::Compositor.
758 NOTREACHED();
761 scoped_refptr<cc::DisplayItemList> Layer::PaintContentsToDisplayList(
762 const gfx::Rect& clip,
763 ContentLayerClient::PaintingControlSetting painting_control) {
764 TRACE_EVENT1("ui", "Layer::PaintContentsToDisplayList", "name", name_);
765 gfx::Rect local_bounds(bounds().size());
766 gfx::Rect invalidation(
767 gfx::IntersectRects(damaged_region_.bounds(), local_bounds));
768 DCHECK(clip.Contains(invalidation));
769 ClearDamagedRects();
770 cc::DisplayItemListSettings settings;
771 settings.use_cached_picture = false;
772 scoped_refptr<cc::DisplayItemList> display_list =
773 cc::DisplayItemList::Create(clip, settings);
774 if (delegate_) {
775 delegate_->OnPaintLayer(
776 PaintContext(display_list.get(), device_scale_factor_, invalidation));
778 display_list->Finalize();
779 return display_list;
782 bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; }
784 size_t Layer::GetApproximateUnsharedMemoryUsage() const {
785 // Most of the "picture memory" is shared with the cc::DisplayItemList, so
786 // there's nothing significant to report here.
787 return 0;
790 bool Layer::PrepareTextureMailbox(
791 cc::TextureMailbox* mailbox,
792 scoped_ptr<cc::SingleReleaseCallback>* release_callback,
793 bool use_shared_memory) {
794 if (!mailbox_release_callback_)
795 return false;
796 *mailbox = mailbox_;
797 *release_callback = mailbox_release_callback_.Pass();
798 return true;
801 void Layer::SetForceRenderSurface(bool force) {
802 if (force_render_surface_ == force)
803 return;
805 force_render_surface_ = force;
806 cc_layer_->SetForceRenderSurface(force_render_surface_);
809 class LayerDebugInfo : public base::trace_event::ConvertableToTraceFormat {
810 public:
811 explicit LayerDebugInfo(std::string name) : name_(name) { }
812 void AppendAsTraceFormat(std::string* out) const override {
813 base::DictionaryValue dictionary;
814 dictionary.SetString("layer_name", name_);
815 base::JSONWriter::Write(dictionary, out);
818 private:
819 ~LayerDebugInfo() override {}
820 std::string name_;
823 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
824 Layer::TakeDebugInfo() {
825 return new LayerDebugInfo(name_);
828 void Layer::OnAnimationStarted(const cc::AnimationEvent& event) {
829 if (animator_.get())
830 animator_->OnThreadedAnimationStarted(event);
833 void Layer::CollectAnimators(
834 std::vector<scoped_refptr<LayerAnimator> >* animators) {
835 if (IsAnimating())
836 animators->push_back(animator_);
837 std::for_each(children_.begin(), children_.end(),
838 std::bind2nd(std::mem_fun(&Layer::CollectAnimators),
839 animators));
842 void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) {
843 DCHECK_NE(child, other);
844 DCHECK_EQ(this, child->parent());
845 DCHECK_EQ(this, other->parent());
847 const size_t child_i =
848 std::find(children_.begin(), children_.end(), child) - children_.begin();
849 const size_t other_i =
850 std::find(children_.begin(), children_.end(), other) - children_.begin();
851 if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i))
852 return;
854 const size_t dest_i =
855 above ?
856 (child_i < other_i ? other_i : other_i + 1) :
857 (child_i < other_i ? other_i - 1 : other_i);
858 children_.erase(children_.begin() + child_i);
859 children_.insert(children_.begin() + dest_i, child);
861 child->cc_layer_->RemoveFromParent();
862 cc_layer_->InsertChild(child->cc_layer_, dest_i);
865 bool Layer::ConvertPointForAncestor(const Layer* ancestor,
866 gfx::Point* point) const {
867 gfx::Transform transform;
868 bool result = GetTargetTransformRelativeTo(ancestor, &transform);
869 gfx::Point3F p(*point);
870 transform.TransformPoint(&p);
871 *point = gfx::ToFlooredPoint(p.AsPointF());
872 return result;
875 bool Layer::ConvertPointFromAncestor(const Layer* ancestor,
876 gfx::Point* point) const {
877 gfx::Transform transform;
878 bool result = GetTargetTransformRelativeTo(ancestor, &transform);
879 gfx::Point3F p(*point);
880 transform.TransformPointReverse(&p);
881 *point = gfx::ToFlooredPoint(p.AsPointF());
882 return result;
885 void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) {
886 if (bounds == bounds_)
887 return;
889 base::Closure closure;
890 if (delegate_)
891 closure = delegate_->PrepareForLayerBoundsChange();
892 bool was_move = bounds_.size() == bounds.size();
893 bounds_ = bounds;
895 RecomputeDrawsContentAndUVRect();
896 RecomputePosition();
898 if (!closure.is_null())
899 closure.Run();
901 if (was_move) {
902 // Don't schedule a draw if we're invisible. We'll schedule one
903 // automatically when we get visible.
904 if (IsDrawn())
905 ScheduleDraw();
906 } else {
907 // Always schedule a paint, even if we're invisible.
908 SchedulePaint(gfx::Rect(bounds.size()));
912 void Layer::SetTransformFromAnimation(const gfx::Transform& transform) {
913 cc_layer_->SetTransform(transform);
916 void Layer::SetOpacityFromAnimation(float opacity) {
917 cc_layer_->SetOpacity(opacity);
918 ScheduleDraw();
921 void Layer::SetVisibilityFromAnimation(bool visible) {
922 if (visible_ == visible)
923 return;
925 visible_ = visible;
926 cc_layer_->SetHideLayerAndSubtree(!visible_);
929 void Layer::SetBrightnessFromAnimation(float brightness) {
930 layer_brightness_ = brightness;
931 SetLayerFilters();
934 void Layer::SetGrayscaleFromAnimation(float grayscale) {
935 layer_grayscale_ = grayscale;
936 SetLayerFilters();
939 void Layer::SetColorFromAnimation(SkColor color) {
940 DCHECK_EQ(type_, LAYER_SOLID_COLOR);
941 cc_layer_->SetBackgroundColor(color);
942 SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF);
945 void Layer::ScheduleDrawForAnimation() {
946 ScheduleDraw();
949 const gfx::Rect& Layer::GetBoundsForAnimation() const {
950 return bounds();
953 gfx::Transform Layer::GetTransformForAnimation() const {
954 return transform();
957 float Layer::GetOpacityForAnimation() const {
958 return opacity();
961 bool Layer::GetVisibilityForAnimation() const {
962 return visible();
965 float Layer::GetBrightnessForAnimation() const {
966 return layer_brightness();
969 float Layer::GetGrayscaleForAnimation() const {
970 return layer_grayscale();
973 SkColor Layer::GetColorForAnimation() const {
974 // WebColor is equivalent to SkColor, per WebColor.h.
975 // The NULL check is here since this is invoked regardless of whether we have
976 // been configured as LAYER_SOLID_COLOR.
977 return solid_color_layer_.get() ?
978 solid_color_layer_->background_color() : SK_ColorBLACK;
981 float Layer::GetDeviceScaleFactor() const {
982 return device_scale_factor_;
985 void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) {
986 DCHECK(cc_layer_);
987 // Until this layer has a compositor (and hence cc_layer_ has a
988 // LayerTreeHost), addAnimation will fail.
989 if (GetCompositor())
990 cc_layer_->AddAnimation(animation.Pass());
991 else
992 pending_threaded_animations_.push_back(animation.Pass());
995 namespace{
997 struct HasAnimationId {
998 HasAnimationId(int id): id_(id) {
1001 bool operator()(cc::Animation* animation) const {
1002 return animation->id() == id_;
1005 private:
1006 int id_;
1011 void Layer::RemoveThreadedAnimation(int animation_id) {
1012 DCHECK(cc_layer_);
1013 if (pending_threaded_animations_.size() == 0) {
1014 cc_layer_->RemoveAnimation(animation_id);
1015 return;
1018 pending_threaded_animations_.erase(
1019 cc::remove_if(&pending_threaded_animations_,
1020 pending_threaded_animations_.begin(),
1021 pending_threaded_animations_.end(),
1022 HasAnimationId(animation_id)),
1023 pending_threaded_animations_.end());
1026 LayerAnimatorCollection* Layer::GetLayerAnimatorCollection() {
1027 Compositor* compositor = GetCompositor();
1028 return compositor ? compositor->layer_animator_collection() : NULL;
1031 void Layer::SendPendingThreadedAnimations() {
1032 for (cc::ScopedPtrVector<cc::Animation>::iterator it =
1033 pending_threaded_animations_.begin();
1034 it != pending_threaded_animations_.end();
1035 ++it)
1036 cc_layer_->AddAnimation(pending_threaded_animations_.take(it));
1038 pending_threaded_animations_.clear();
1040 for (size_t i = 0; i < children_.size(); ++i)
1041 children_[i]->SendPendingThreadedAnimations();
1044 void Layer::CreateCcLayer() {
1045 if (type_ == LAYER_SOLID_COLOR) {
1046 solid_color_layer_ = cc::SolidColorLayer::Create(UILayerSettings());
1047 cc_layer_ = solid_color_layer_.get();
1048 } else if (type_ == LAYER_NINE_PATCH) {
1049 nine_patch_layer_ = cc::NinePatchLayer::Create(UILayerSettings());
1050 cc_layer_ = nine_patch_layer_.get();
1051 } else {
1052 content_layer_ = cc::PictureLayer::Create(UILayerSettings(), this);
1053 cc_layer_ = content_layer_.get();
1055 cc_layer_->SetTransformOrigin(gfx::Point3F());
1056 cc_layer_->SetContentsOpaque(true);
1057 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
1058 cc_layer_->AddLayerAnimationEventObserver(this);
1059 cc_layer_->SetLayerClient(this);
1060 RecomputePosition();
1063 gfx::Transform Layer::transform() const {
1064 return cc_layer_->transform();
1067 void Layer::RecomputeDrawsContentAndUVRect() {
1068 DCHECK(cc_layer_);
1069 gfx::Size size(bounds_.size());
1070 if (texture_layer_.get()) {
1071 size.SetToMin(frame_size_in_dip_);
1072 gfx::PointF uv_top_left(0.f, 0.f);
1073 gfx::PointF uv_bottom_right(
1074 static_cast<float>(size.width()) / frame_size_in_dip_.width(),
1075 static_cast<float>(size.height()) / frame_size_in_dip_.height());
1076 texture_layer_->SetUV(uv_top_left, uv_bottom_right);
1077 } else if (delegated_renderer_layer_.get() || surface_layer_.get()) {
1078 size.SetToMin(frame_size_in_dip_);
1080 cc_layer_->SetBounds(size);
1083 void Layer::RecomputePosition() {
1084 cc_layer_->SetPosition(bounds_.origin() + subpixel_position_offset_);
1087 void Layer::AddAnimatorsInTreeToCollection(
1088 LayerAnimatorCollection* collection) {
1089 DCHECK(collection);
1090 if (IsAnimating())
1091 animator_->AddToCollection(collection);
1092 std::for_each(
1093 children_.begin(),
1094 children_.end(),
1095 std::bind2nd(std::mem_fun(&Layer::AddAnimatorsInTreeToCollection),
1096 collection));
1099 void Layer::RemoveAnimatorsInTreeFromCollection(
1100 LayerAnimatorCollection* collection) {
1101 DCHECK(collection);
1102 if (IsAnimating())
1103 animator_->RemoveFromCollection(collection);
1104 std::for_each(
1105 children_.begin(),
1106 children_.end(),
1107 std::bind2nd(std::mem_fun(&Layer::RemoveAnimatorsInTreeFromCollection),
1108 collection));
1111 bool Layer::IsAnimating() const {
1112 return animator_.get() && animator_->is_animating();
1115 } // namespace ui