ui: Remove non-slimming paint code paths.
[chromium-blink-merge.git] / ui / compositor / layer.cc
blobe79f9a855bae013394cc8eb8e93d5e1113800ec6
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/resources/transferable_resource.h"
28 #include "cc/trees/layer_tree_settings.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 base::LazyInstance<cc::LayerSettings> g_ui_layer_settings =
50 LAZY_INSTANCE_INITIALIZER;
52 } // namespace
54 namespace ui {
56 Layer::Layer()
57 : type_(LAYER_TEXTURED),
58 compositor_(NULL),
59 parent_(NULL),
60 visible_(true),
61 force_render_surface_(false),
62 fills_bounds_opaquely_(true),
63 fills_bounds_completely_(false),
64 background_blur_radius_(0),
65 layer_saturation_(0.0f),
66 layer_brightness_(0.0f),
67 layer_grayscale_(0.0f),
68 layer_inverted_(false),
69 layer_mask_(NULL),
70 layer_mask_back_link_(NULL),
71 zoom_(1),
72 zoom_inset_(0),
73 delegate_(NULL),
74 owner_(NULL),
75 cc_layer_(NULL),
76 device_scale_factor_(1.0f) {
77 CreateCcLayer();
80 Layer::Layer(LayerType type)
81 : type_(type),
82 compositor_(NULL),
83 parent_(NULL),
84 visible_(true),
85 force_render_surface_(false),
86 fills_bounds_opaquely_(true),
87 fills_bounds_completely_(false),
88 background_blur_radius_(0),
89 layer_saturation_(0.0f),
90 layer_brightness_(0.0f),
91 layer_grayscale_(0.0f),
92 layer_inverted_(false),
93 layer_mask_(NULL),
94 layer_mask_back_link_(NULL),
95 zoom_(1),
96 zoom_inset_(0),
97 delegate_(NULL),
98 owner_(NULL),
99 cc_layer_(NULL),
100 device_scale_factor_(1.0f) {
101 CreateCcLayer();
104 Layer::~Layer() {
105 // Destroying the animator may cause observers to use the layer (and
106 // indirectly the WebLayer). Destroy the animator first so that the WebLayer
107 // is still around.
108 if (animator_.get())
109 animator_->SetDelegate(NULL);
110 animator_ = NULL;
111 if (compositor_)
112 compositor_->SetRootLayer(NULL);
113 if (parent_)
114 parent_->Remove(this);
115 if (layer_mask_)
116 SetMaskLayer(NULL);
117 if (layer_mask_back_link_)
118 layer_mask_back_link_->SetMaskLayer(NULL);
119 for (size_t i = 0; i < children_.size(); ++i)
120 children_[i]->parent_ = NULL;
122 cc_layer_->RemoveLayerAnimationEventObserver(this);
123 cc_layer_->RemoveFromParent();
126 // static
127 const cc::LayerSettings& Layer::UILayerSettings() {
128 return g_ui_layer_settings.Get();
131 // static
132 void Layer::InitializeUILayerSettings() {
133 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
134 if (command_line->HasSwitch(switches::kUIEnableCompositorAnimationTimelines))
135 g_ui_layer_settings.Get().use_compositor_animation_timelines = true;
138 const Compositor* Layer::GetCompositor() const {
139 return GetRoot(this)->compositor_;
142 float Layer::opacity() const {
143 return cc_layer_->opacity();
146 void Layer::SetCompositor(Compositor* compositor,
147 scoped_refptr<cc::Layer> root_layer) {
148 // This function must only be called to set the compositor on the root ui
149 // layer.
150 DCHECK(compositor);
151 DCHECK(!compositor_);
152 DCHECK(compositor->root_layer() == this);
153 DCHECK(!parent_);
155 compositor_ = compositor;
156 OnDeviceScaleFactorChanged(compositor->device_scale_factor());
157 AddAnimatorsInTreeToCollection(compositor_->layer_animator_collection());
159 root_layer->AddChild(cc_layer_);
160 SendPendingThreadedAnimations();
163 void Layer::ResetCompositor() {
164 DCHECK(!parent_);
165 if (compositor_)
166 RemoveAnimatorsInTreeFromCollection(
167 compositor_->layer_animator_collection());
168 compositor_ = nullptr;
171 void Layer::Add(Layer* child) {
172 DCHECK(!child->compositor_);
173 if (child->parent_)
174 child->parent_->Remove(child);
175 child->parent_ = this;
176 children_.push_back(child);
177 cc_layer_->AddChild(child->cc_layer_);
178 child->OnDeviceScaleFactorChanged(device_scale_factor_);
179 if (GetCompositor())
180 child->SendPendingThreadedAnimations();
181 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
182 if (collection)
183 child->AddAnimatorsInTreeToCollection(collection);
186 void Layer::Remove(Layer* child) {
187 // Current bounds are used to calculate offsets when layers are reparented.
188 // Stop (and complete) an ongoing animation to update the bounds immediately.
189 LayerAnimator* child_animator = child->animator_.get();
190 if (child_animator)
191 child_animator->StopAnimatingProperty(ui::LayerAnimationElement::BOUNDS);
192 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
193 if (collection)
194 child->RemoveAnimatorsInTreeFromCollection(collection);
196 std::vector<Layer*>::iterator i =
197 std::find(children_.begin(), children_.end(), child);
198 DCHECK(i != children_.end());
199 children_.erase(i);
200 child->parent_ = NULL;
201 child->cc_layer_->RemoveFromParent();
204 void Layer::StackAtTop(Layer* child) {
205 if (children_.size() <= 1 || child == children_.back())
206 return; // Already in front.
207 StackAbove(child, children_.back());
210 void Layer::StackAbove(Layer* child, Layer* other) {
211 StackRelativeTo(child, other, true);
214 void Layer::StackAtBottom(Layer* child) {
215 if (children_.size() <= 1 || child == children_.front())
216 return; // Already on bottom.
217 StackBelow(child, children_.front());
220 void Layer::StackBelow(Layer* child, Layer* other) {
221 StackRelativeTo(child, other, false);
224 bool Layer::Contains(const Layer* other) const {
225 for (const Layer* parent = other; parent; parent = parent->parent()) {
226 if (parent == this)
227 return true;
229 return false;
232 void Layer::SetAnimator(LayerAnimator* animator) {
233 if (animator)
234 animator->SetDelegate(this);
235 animator_ = animator;
238 LayerAnimator* Layer::GetAnimator() {
239 if (!animator_.get())
240 SetAnimator(LayerAnimator::CreateDefaultAnimator());
241 return animator_.get();
244 void Layer::SetTransform(const gfx::Transform& transform) {
245 GetAnimator()->SetTransform(transform);
248 gfx::Transform Layer::GetTargetTransform() const {
249 if (animator_.get() && animator_->IsAnimatingProperty(
250 LayerAnimationElement::TRANSFORM)) {
251 return animator_->GetTargetTransform();
253 return transform();
256 void Layer::SetBounds(const gfx::Rect& bounds) {
257 GetAnimator()->SetBounds(bounds);
260 void Layer::SetSubpixelPositionOffset(const gfx::Vector2dF& offset) {
261 subpixel_position_offset_ = offset;
262 RecomputePosition();
265 gfx::Rect Layer::GetTargetBounds() const {
266 if (animator_.get() && animator_->IsAnimatingProperty(
267 LayerAnimationElement::BOUNDS)) {
268 return animator_->GetTargetBounds();
270 return bounds_;
273 void Layer::SetMasksToBounds(bool masks_to_bounds) {
274 cc_layer_->SetMasksToBounds(masks_to_bounds);
277 bool Layer::GetMasksToBounds() const {
278 return cc_layer_->masks_to_bounds();
281 void Layer::SetOpacity(float opacity) {
282 GetAnimator()->SetOpacity(opacity);
285 float Layer::GetCombinedOpacity() const {
286 float opacity = this->opacity();
287 Layer* current = this->parent_;
288 while (current) {
289 opacity *= current->opacity();
290 current = current->parent_;
292 return opacity;
295 void Layer::SetBackgroundBlur(int blur_radius) {
296 background_blur_radius_ = blur_radius;
298 SetLayerBackgroundFilters();
301 void Layer::SetLayerSaturation(float saturation) {
302 layer_saturation_ = saturation;
303 SetLayerFilters();
306 void Layer::SetLayerBrightness(float brightness) {
307 GetAnimator()->SetBrightness(brightness);
310 float Layer::GetTargetBrightness() const {
311 if (animator_.get() && animator_->IsAnimatingProperty(
312 LayerAnimationElement::BRIGHTNESS)) {
313 return animator_->GetTargetBrightness();
315 return layer_brightness();
318 void Layer::SetLayerGrayscale(float grayscale) {
319 GetAnimator()->SetGrayscale(grayscale);
322 float Layer::GetTargetGrayscale() const {
323 if (animator_.get() && animator_->IsAnimatingProperty(
324 LayerAnimationElement::GRAYSCALE)) {
325 return animator_->GetTargetGrayscale();
327 return layer_grayscale();
330 void Layer::SetLayerInverted(bool inverted) {
331 layer_inverted_ = inverted;
332 SetLayerFilters();
335 void Layer::SetMaskLayer(Layer* layer_mask) {
336 // The provided mask should not have a layer mask itself.
337 DCHECK(!layer_mask ||
338 (!layer_mask->layer_mask_layer() &&
339 layer_mask->children().empty() &&
340 !layer_mask->layer_mask_back_link_));
341 DCHECK(!layer_mask_back_link_);
342 if (layer_mask_ == layer_mask)
343 return;
344 // We need to de-reference the currently linked object so that no problem
345 // arises if the mask layer gets deleted before this object.
346 if (layer_mask_)
347 layer_mask_->layer_mask_back_link_ = NULL;
348 layer_mask_ = layer_mask;
349 cc_layer_->SetMaskLayer(layer_mask ? layer_mask->cc_layer_ : NULL);
350 // We need to reference the linked object so that it can properly break the
351 // link to us when it gets deleted.
352 if (layer_mask) {
353 layer_mask->layer_mask_back_link_ = this;
354 layer_mask->OnDeviceScaleFactorChanged(device_scale_factor_);
358 void Layer::SetBackgroundZoom(float zoom, int inset) {
359 zoom_ = zoom;
360 zoom_inset_ = inset;
362 SetLayerBackgroundFilters();
365 void Layer::SetAlphaShape(scoped_ptr<SkRegion> region) {
366 alpha_shape_ = region.Pass();
368 SetLayerFilters();
371 void Layer::SetLayerFilters() {
372 cc::FilterOperations filters;
373 if (layer_saturation_) {
374 filters.Append(cc::FilterOperation::CreateSaturateFilter(
375 layer_saturation_));
377 if (layer_grayscale_) {
378 filters.Append(cc::FilterOperation::CreateGrayscaleFilter(
379 layer_grayscale_));
381 if (layer_inverted_)
382 filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
383 // Brightness goes last, because the resulting colors neeed clamping, which
384 // cause further color matrix filters to be applied separately. In this order,
385 // they all can be combined in a single pass.
386 if (layer_brightness_) {
387 filters.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter(
388 layer_brightness_));
390 if (alpha_shape_) {
391 filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter(
392 *alpha_shape_, 0.f, 0.f));
395 cc_layer_->SetFilters(filters);
398 void Layer::SetLayerBackgroundFilters() {
399 cc::FilterOperations filters;
400 if (zoom_ != 1)
401 filters.Append(cc::FilterOperation::CreateZoomFilter(zoom_, zoom_inset_));
403 if (background_blur_radius_) {
404 filters.Append(cc::FilterOperation::CreateBlurFilter(
405 background_blur_radius_));
408 cc_layer_->SetBackgroundFilters(filters);
411 float Layer::GetTargetOpacity() const {
412 if (animator_.get() && animator_->IsAnimatingProperty(
413 LayerAnimationElement::OPACITY))
414 return animator_->GetTargetOpacity();
415 return opacity();
418 void Layer::SetVisible(bool visible) {
419 GetAnimator()->SetVisibility(visible);
422 bool Layer::GetTargetVisibility() const {
423 if (animator_.get() && animator_->IsAnimatingProperty(
424 LayerAnimationElement::VISIBILITY))
425 return animator_->GetTargetVisibility();
426 return visible_;
429 bool Layer::IsDrawn() const {
430 const Layer* layer = this;
431 while (layer && layer->visible_)
432 layer = layer->parent_;
433 return layer == NULL;
436 bool Layer::ShouldDraw() const {
437 return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f;
440 // static
441 void Layer::ConvertPointToLayer(const Layer* source,
442 const Layer* target,
443 gfx::Point* point) {
444 if (source == target)
445 return;
447 const Layer* root_layer = GetRoot(source);
448 CHECK_EQ(root_layer, GetRoot(target));
450 if (source != root_layer)
451 source->ConvertPointForAncestor(root_layer, point);
452 if (target != root_layer)
453 target->ConvertPointFromAncestor(root_layer, point);
456 bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor,
457 gfx::Transform* transform) const {
458 const Layer* p = this;
459 for (; p && p != ancestor; p = p->parent()) {
460 gfx::Transform translation;
461 translation.Translate(static_cast<float>(p->bounds().x()),
462 static_cast<float>(p->bounds().y()));
463 // Use target transform so that result will be correct once animation is
464 // finished.
465 if (!p->GetTargetTransform().IsIdentity())
466 transform->ConcatTransform(p->GetTargetTransform());
467 transform->ConcatTransform(translation);
469 return p == ancestor;
472 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
473 if (fills_bounds_opaquely_ == fills_bounds_opaquely)
474 return;
476 fills_bounds_opaquely_ = fills_bounds_opaquely;
478 cc_layer_->SetContentsOpaque(fills_bounds_opaquely);
481 void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) {
482 fills_bounds_completely_ = fills_bounds_completely;
485 void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
486 // Finish animations being handled by cc_layer_.
487 if (animator_.get()) {
488 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
489 animator_->StopAnimatingProperty(LayerAnimationElement::OPACITY);
492 if (texture_layer_.get())
493 texture_layer_->ClearClient();
494 // TODO(piman): delegated_renderer_layer_ cleanup.
496 cc_layer_->RemoveAllChildren();
497 if (cc_layer_->parent()) {
498 cc_layer_->parent()->ReplaceChild(cc_layer_, new_layer);
500 cc_layer_->SetLayerClient(NULL);
501 cc_layer_->RemoveLayerAnimationEventObserver(this);
502 new_layer->SetOpacity(cc_layer_->opacity());
503 new_layer->SetTransform(cc_layer_->transform());
504 new_layer->SetPosition(cc_layer_->position());
505 new_layer->SetBackgroundColor(cc_layer_->background_color());
507 cc_layer_ = new_layer.get();
508 content_layer_ = NULL;
509 solid_color_layer_ = NULL;
510 texture_layer_ = NULL;
511 delegated_renderer_layer_ = NULL;
512 surface_layer_ = NULL;
514 cc_layer_->AddLayerAnimationEventObserver(this);
515 for (size_t i = 0; i < children_.size(); ++i) {
516 DCHECK(children_[i]->cc_layer_);
517 cc_layer_->AddChild(children_[i]->cc_layer_);
519 cc_layer_->SetLayerClient(this);
520 cc_layer_->SetTransformOrigin(gfx::Point3F());
521 cc_layer_->SetContentsOpaque(fills_bounds_opaquely_);
522 cc_layer_->SetForceRenderSurface(force_render_surface_);
523 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
524 cc_layer_->SetHideLayerAndSubtree(!visible_);
526 SetLayerFilters();
527 SetLayerBackgroundFilters();
530 void Layer::SwitchCCLayerForTest() {
531 scoped_refptr<cc::Layer> new_layer =
532 cc::PictureLayer::Create(UILayerSettings(), this);
533 SwitchToLayer(new_layer);
534 content_layer_ = new_layer;
537 void Layer::SetTextureMailbox(
538 const cc::TextureMailbox& mailbox,
539 scoped_ptr<cc::SingleReleaseCallback> release_callback,
540 gfx::Size texture_size_in_dip) {
541 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
542 DCHECK(mailbox.IsValid());
543 DCHECK(release_callback);
544 if (!texture_layer_.get()) {
545 scoped_refptr<cc::TextureLayer> new_layer =
546 cc::TextureLayer::CreateForMailbox(UILayerSettings(), this);
547 new_layer->SetFlipped(true);
548 SwitchToLayer(new_layer);
549 texture_layer_ = new_layer;
550 // Reset the frame_size_in_dip_ so that SetTextureSize() will not early out,
551 // the frame_size_in_dip_ was for a previous (different) |texture_layer_|.
552 frame_size_in_dip_ = gfx::Size();
554 if (mailbox_release_callback_)
555 mailbox_release_callback_->Run(0, false);
556 mailbox_release_callback_ = release_callback.Pass();
557 mailbox_ = mailbox;
558 SetTextureSize(texture_size_in_dip);
561 void Layer::SetTextureSize(gfx::Size texture_size_in_dip) {
562 DCHECK(texture_layer_.get());
563 if (frame_size_in_dip_ == texture_size_in_dip)
564 return;
565 frame_size_in_dip_ = texture_size_in_dip;
566 RecomputeDrawsContentAndUVRect();
567 texture_layer_->SetNeedsDisplay();
570 void Layer::SetTextureFlipped(bool flipped) {
571 DCHECK(texture_layer_.get());
572 texture_layer_->SetFlipped(flipped);
575 bool Layer::TextureFlipped() const {
576 DCHECK(texture_layer_.get());
577 return texture_layer_->flipped();
580 void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider,
581 gfx::Size frame_size_in_dip) {
582 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
584 scoped_refptr<cc::DelegatedRendererLayer> new_layer =
585 cc::DelegatedRendererLayer::Create(UILayerSettings(), frame_provider);
586 SwitchToLayer(new_layer);
587 delegated_renderer_layer_ = new_layer;
589 frame_size_in_dip_ = frame_size_in_dip;
590 RecomputeDrawsContentAndUVRect();
593 void Layer::SetShowSurface(
594 cc::SurfaceId surface_id,
595 const cc::SurfaceLayer::SatisfyCallback& satisfy_callback,
596 const cc::SurfaceLayer::RequireCallback& require_callback,
597 gfx::Size surface_size,
598 float scale,
599 gfx::Size frame_size_in_dip) {
600 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
602 scoped_refptr<cc::SurfaceLayer> new_layer = cc::SurfaceLayer::Create(
603 UILayerSettings(), satisfy_callback, require_callback);
604 new_layer->SetSurfaceId(surface_id, scale, surface_size);
605 SwitchToLayer(new_layer);
606 surface_layer_ = new_layer;
608 frame_size_in_dip_ = frame_size_in_dip;
609 RecomputeDrawsContentAndUVRect();
612 void Layer::SetShowSolidColorContent() {
613 DCHECK_EQ(type_, LAYER_SOLID_COLOR);
615 if (solid_color_layer_.get())
616 return;
618 scoped_refptr<cc::SolidColorLayer> new_layer =
619 cc::SolidColorLayer::Create(UILayerSettings());
620 SwitchToLayer(new_layer);
621 solid_color_layer_ = new_layer;
623 mailbox_ = cc::TextureMailbox();
624 if (mailbox_release_callback_) {
625 mailbox_release_callback_->Run(0, false);
626 mailbox_release_callback_.reset();
628 RecomputeDrawsContentAndUVRect();
631 void Layer::UpdateNinePatchLayerImage(const gfx::ImageSkia& image) {
632 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
633 nine_patch_layer_image_ = image;
634 SkBitmap bitmap = nine_patch_layer_image_.GetRepresentation(
635 device_scale_factor_).sk_bitmap();
636 SkBitmap bitmap_copy;
637 if (bitmap.isImmutable()) {
638 bitmap_copy = bitmap;
639 } else {
640 // UIResourceBitmap requires an immutable copy of the input |bitmap|.
641 bitmap.copyTo(&bitmap_copy);
642 bitmap_copy.setImmutable();
644 nine_patch_layer_->SetBitmap(bitmap_copy);
647 void Layer::UpdateNinePatchLayerAperture(const gfx::Rect& aperture_in_dip) {
648 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
649 nine_patch_layer_aperture_ = aperture_in_dip;
650 gfx::Rect aperture_in_pixel = ConvertRectToPixel(this, aperture_in_dip);
651 nine_patch_layer_->SetAperture(aperture_in_pixel);
654 void Layer::UpdateNinePatchLayerBorder(const gfx::Rect& border) {
655 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
656 nine_patch_layer_->SetBorder(border);
659 void Layer::SetColor(SkColor color) { GetAnimator()->SetColor(color); }
661 SkColor Layer::GetTargetColor() {
662 if (GetAnimator()->IsAnimatingProperty(LayerAnimationElement::COLOR))
663 return GetAnimator()->GetTargetColor();
664 return cc_layer_->background_color();
667 SkColor Layer::background_color() const {
668 return cc_layer_->background_color();
671 bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) {
672 if ((type_ == LAYER_SOLID_COLOR && !texture_layer_.get()) ||
673 type_ == LAYER_NINE_PATCH || (!delegate_ && !mailbox_.IsValid()))
674 return false;
676 damaged_region_.Union(invalid_rect);
677 ScheduleDraw();
678 return true;
681 void Layer::ScheduleDraw() {
682 Compositor* compositor = GetCompositor();
683 if (compositor)
684 compositor->ScheduleDraw();
687 void Layer::SendDamagedRects() {
688 if (damaged_region_.IsEmpty())
689 return;
690 if (!delegate_ && !mailbox_.IsValid())
691 return;
693 for (cc::Region::Iterator iter(damaged_region_); iter.has_rect(); iter.next())
694 cc_layer_->SetNeedsDisplayRect(iter.rect());
697 void Layer::ClearDamagedRects() {
698 damaged_region_.Clear();
701 void Layer::CompleteAllAnimations() {
702 typedef std::vector<scoped_refptr<LayerAnimator> > LayerAnimatorVector;
703 LayerAnimatorVector animators;
704 CollectAnimators(&animators);
705 for (LayerAnimatorVector::const_iterator it = animators.begin();
706 it != animators.end();
707 ++it) {
708 (*it)->StopAnimating();
712 void Layer::SuppressPaint() {
713 if (!delegate_)
714 return;
715 delegate_ = NULL;
716 for (size_t i = 0; i < children_.size(); ++i)
717 children_[i]->SuppressPaint();
720 void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) {
721 if (device_scale_factor_ == device_scale_factor)
722 return;
723 if (animator_.get())
724 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
725 device_scale_factor_ = device_scale_factor;
726 RecomputeDrawsContentAndUVRect();
727 RecomputePosition();
728 if (nine_patch_layer_) {
729 UpdateNinePatchLayerImage(nine_patch_layer_image_);
730 UpdateNinePatchLayerAperture(nine_patch_layer_aperture_);
732 SchedulePaint(gfx::Rect(bounds_.size()));
733 if (delegate_)
734 delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
735 for (size_t i = 0; i < children_.size(); ++i)
736 children_[i]->OnDeviceScaleFactorChanged(device_scale_factor);
737 if (layer_mask_)
738 layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor);
741 void Layer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {
742 DCHECK(delegated_renderer_layer_.get() || surface_layer_.get());
743 if (!delegate_)
744 return;
745 delegate_->OnDelegatedFrameDamage(damage_rect_in_dip);
748 void Layer::RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) {
749 cc_layer_->RequestCopyOfOutput(request.Pass());
752 void Layer::PaintContents(
753 SkCanvas* sk_canvas,
754 const gfx::Rect& clip,
755 ContentLayerClient::PaintingControlSetting painting_control) {
756 // The old non-slimming paint path is not used in ui::Compositor.
757 NOTREACHED();
760 scoped_refptr<cc::DisplayItemList> Layer::PaintContentsToDisplayList(
761 const gfx::Rect& clip,
762 ContentLayerClient::PaintingControlSetting painting_control) {
763 TRACE_EVENT1("ui", "Layer::PaintContentsToDisplayList", "name", name_);
764 gfx::Rect local_bounds(bounds().size());
765 gfx::Rect invalidation(
766 gfx::IntersectRects(damaged_region_.bounds(), local_bounds));
767 DCHECK(clip.Contains(invalidation));
768 ClearDamagedRects();
769 const bool use_cached_picture = false;
770 scoped_refptr<cc::DisplayItemList> display_list =
771 cc::DisplayItemList::Create(clip, use_cached_picture);
772 if (delegate_) {
773 delegate_->OnPaintLayer(PaintContext(
774 display_list.get(), device_scale_factor_, clip, invalidation));
776 display_list->Finalize();
777 return display_list;
780 bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; }
782 bool Layer::PrepareTextureMailbox(
783 cc::TextureMailbox* mailbox,
784 scoped_ptr<cc::SingleReleaseCallback>* release_callback,
785 bool use_shared_memory) {
786 if (!mailbox_release_callback_)
787 return false;
788 *mailbox = mailbox_;
789 *release_callback = mailbox_release_callback_.Pass();
790 return true;
793 void Layer::SetForceRenderSurface(bool force) {
794 if (force_render_surface_ == force)
795 return;
797 force_render_surface_ = force;
798 cc_layer_->SetForceRenderSurface(force_render_surface_);
801 class LayerDebugInfo : public base::trace_event::ConvertableToTraceFormat {
802 public:
803 explicit LayerDebugInfo(std::string name) : name_(name) { }
804 void AppendAsTraceFormat(std::string* out) const override {
805 base::DictionaryValue dictionary;
806 dictionary.SetString("layer_name", name_);
807 base::JSONWriter::Write(dictionary, out);
810 private:
811 ~LayerDebugInfo() override {}
812 std::string name_;
815 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
816 Layer::TakeDebugInfo() {
817 return new LayerDebugInfo(name_);
820 void Layer::OnAnimationStarted(const cc::AnimationEvent& event) {
821 if (animator_.get())
822 animator_->OnThreadedAnimationStarted(event);
825 void Layer::CollectAnimators(
826 std::vector<scoped_refptr<LayerAnimator> >* animators) {
827 if (IsAnimating())
828 animators->push_back(animator_);
829 std::for_each(children_.begin(), children_.end(),
830 std::bind2nd(std::mem_fun(&Layer::CollectAnimators),
831 animators));
834 void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) {
835 DCHECK_NE(child, other);
836 DCHECK_EQ(this, child->parent());
837 DCHECK_EQ(this, other->parent());
839 const size_t child_i =
840 std::find(children_.begin(), children_.end(), child) - children_.begin();
841 const size_t other_i =
842 std::find(children_.begin(), children_.end(), other) - children_.begin();
843 if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i))
844 return;
846 const size_t dest_i =
847 above ?
848 (child_i < other_i ? other_i : other_i + 1) :
849 (child_i < other_i ? other_i - 1 : other_i);
850 children_.erase(children_.begin() + child_i);
851 children_.insert(children_.begin() + dest_i, child);
853 child->cc_layer_->RemoveFromParent();
854 cc_layer_->InsertChild(child->cc_layer_, dest_i);
857 bool Layer::ConvertPointForAncestor(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.TransformPoint(&p);
863 *point = gfx::ToFlooredPoint(p.AsPointF());
864 return result;
867 bool Layer::ConvertPointFromAncestor(const Layer* ancestor,
868 gfx::Point* point) const {
869 gfx::Transform transform;
870 bool result = GetTargetTransformRelativeTo(ancestor, &transform);
871 gfx::Point3F p(*point);
872 transform.TransformPointReverse(&p);
873 *point = gfx::ToFlooredPoint(p.AsPointF());
874 return result;
877 void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) {
878 if (bounds == bounds_)
879 return;
881 base::Closure closure;
882 if (delegate_)
883 closure = delegate_->PrepareForLayerBoundsChange();
884 bool was_move = bounds_.size() == bounds.size();
885 bounds_ = bounds;
887 RecomputeDrawsContentAndUVRect();
888 RecomputePosition();
890 if (!closure.is_null())
891 closure.Run();
893 if (was_move) {
894 // Don't schedule a draw if we're invisible. We'll schedule one
895 // automatically when we get visible.
896 if (IsDrawn())
897 ScheduleDraw();
898 } else {
899 // Always schedule a paint, even if we're invisible.
900 SchedulePaint(gfx::Rect(bounds.size()));
904 void Layer::SetTransformFromAnimation(const gfx::Transform& transform) {
905 cc_layer_->SetTransform(transform);
908 void Layer::SetOpacityFromAnimation(float opacity) {
909 cc_layer_->SetOpacity(opacity);
910 ScheduleDraw();
913 void Layer::SetVisibilityFromAnimation(bool visible) {
914 if (visible_ == visible)
915 return;
917 visible_ = visible;
918 cc_layer_->SetHideLayerAndSubtree(!visible_);
921 void Layer::SetBrightnessFromAnimation(float brightness) {
922 layer_brightness_ = brightness;
923 SetLayerFilters();
926 void Layer::SetGrayscaleFromAnimation(float grayscale) {
927 layer_grayscale_ = grayscale;
928 SetLayerFilters();
931 void Layer::SetColorFromAnimation(SkColor color) {
932 DCHECK_EQ(type_, LAYER_SOLID_COLOR);
933 cc_layer_->SetBackgroundColor(color);
934 SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF);
937 void Layer::ScheduleDrawForAnimation() {
938 ScheduleDraw();
941 const gfx::Rect& Layer::GetBoundsForAnimation() const {
942 return bounds();
945 gfx::Transform Layer::GetTransformForAnimation() const {
946 return transform();
949 float Layer::GetOpacityForAnimation() const {
950 return opacity();
953 bool Layer::GetVisibilityForAnimation() const {
954 return visible();
957 float Layer::GetBrightnessForAnimation() const {
958 return layer_brightness();
961 float Layer::GetGrayscaleForAnimation() const {
962 return layer_grayscale();
965 SkColor Layer::GetColorForAnimation() const {
966 // WebColor is equivalent to SkColor, per WebColor.h.
967 // The NULL check is here since this is invoked regardless of whether we have
968 // been configured as LAYER_SOLID_COLOR.
969 return solid_color_layer_.get() ?
970 solid_color_layer_->background_color() : SK_ColorBLACK;
973 float Layer::GetDeviceScaleFactor() const {
974 return device_scale_factor_;
977 void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) {
978 DCHECK(cc_layer_);
979 // Until this layer has a compositor (and hence cc_layer_ has a
980 // LayerTreeHost), addAnimation will fail.
981 if (GetCompositor())
982 cc_layer_->AddAnimation(animation.Pass());
983 else
984 pending_threaded_animations_.push_back(animation.Pass());
987 namespace{
989 struct HasAnimationId {
990 HasAnimationId(int id): id_(id) {
993 bool operator()(cc::Animation* animation) const {
994 return animation->id() == id_;
997 private:
998 int id_;
1003 void Layer::RemoveThreadedAnimation(int animation_id) {
1004 DCHECK(cc_layer_);
1005 if (pending_threaded_animations_.size() == 0) {
1006 cc_layer_->RemoveAnimation(animation_id);
1007 return;
1010 pending_threaded_animations_.erase(
1011 cc::remove_if(&pending_threaded_animations_,
1012 pending_threaded_animations_.begin(),
1013 pending_threaded_animations_.end(),
1014 HasAnimationId(animation_id)),
1015 pending_threaded_animations_.end());
1018 LayerAnimatorCollection* Layer::GetLayerAnimatorCollection() {
1019 Compositor* compositor = GetCompositor();
1020 return compositor ? compositor->layer_animator_collection() : NULL;
1023 void Layer::SendPendingThreadedAnimations() {
1024 for (cc::ScopedPtrVector<cc::Animation>::iterator it =
1025 pending_threaded_animations_.begin();
1026 it != pending_threaded_animations_.end();
1027 ++it)
1028 cc_layer_->AddAnimation(pending_threaded_animations_.take(it));
1030 pending_threaded_animations_.clear();
1032 for (size_t i = 0; i < children_.size(); ++i)
1033 children_[i]->SendPendingThreadedAnimations();
1036 void Layer::CreateCcLayer() {
1037 if (type_ == LAYER_SOLID_COLOR) {
1038 solid_color_layer_ = cc::SolidColorLayer::Create(UILayerSettings());
1039 cc_layer_ = solid_color_layer_.get();
1040 } else if (type_ == LAYER_NINE_PATCH) {
1041 nine_patch_layer_ = cc::NinePatchLayer::Create(UILayerSettings());
1042 cc_layer_ = nine_patch_layer_.get();
1043 } else {
1044 content_layer_ = cc::PictureLayer::Create(UILayerSettings(), this);
1045 cc_layer_ = content_layer_.get();
1047 cc_layer_->SetTransformOrigin(gfx::Point3F());
1048 cc_layer_->SetContentsOpaque(true);
1049 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
1050 cc_layer_->AddLayerAnimationEventObserver(this);
1051 cc_layer_->SetLayerClient(this);
1052 RecomputePosition();
1055 gfx::Transform Layer::transform() const {
1056 return cc_layer_->transform();
1059 void Layer::RecomputeDrawsContentAndUVRect() {
1060 DCHECK(cc_layer_);
1061 gfx::Size size(bounds_.size());
1062 if (texture_layer_.get()) {
1063 size.SetToMin(frame_size_in_dip_);
1064 gfx::PointF uv_top_left(0.f, 0.f);
1065 gfx::PointF uv_bottom_right(
1066 static_cast<float>(size.width()) / frame_size_in_dip_.width(),
1067 static_cast<float>(size.height()) / frame_size_in_dip_.height());
1068 texture_layer_->SetUV(uv_top_left, uv_bottom_right);
1069 } else if (delegated_renderer_layer_.get() || surface_layer_.get()) {
1070 size.SetToMin(frame_size_in_dip_);
1072 cc_layer_->SetBounds(size);
1075 void Layer::RecomputePosition() {
1076 cc_layer_->SetPosition(bounds_.origin() + subpixel_position_offset_);
1079 void Layer::AddAnimatorsInTreeToCollection(
1080 LayerAnimatorCollection* collection) {
1081 DCHECK(collection);
1082 if (IsAnimating())
1083 animator_->AddToCollection(collection);
1084 std::for_each(
1085 children_.begin(),
1086 children_.end(),
1087 std::bind2nd(std::mem_fun(&Layer::AddAnimatorsInTreeToCollection),
1088 collection));
1091 void Layer::RemoveAnimatorsInTreeFromCollection(
1092 LayerAnimatorCollection* collection) {
1093 DCHECK(collection);
1094 if (IsAnimating())
1095 animator_->RemoveFromCollection(collection);
1096 std::for_each(
1097 children_.begin(),
1098 children_.end(),
1099 std::bind2nd(std::mem_fun(&Layer::RemoveAnimatorsInTreeFromCollection),
1100 collection));
1103 bool Layer::IsAnimating() const {
1104 return animator_.get() && animator_->is_animating();
1107 } // namespace ui