Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / compositor / layer.cc
blobf3551f7687babb3d1914b669ca8e32686491ddfb
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/compositor/layer.h"
7 #include <algorithm>
9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h"
11 #include "base/json/json_writer.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "cc/base/scoped_ptr_algorithm.h"
15 #include "cc/layers/content_layer.h"
16 #include "cc/layers/delegated_renderer_layer.h"
17 #include "cc/layers/nine_patch_layer.h"
18 #include "cc/layers/picture_layer.h"
19 #include "cc/layers/solid_color_layer.h"
20 #include "cc/layers/surface_layer.h"
21 #include "cc/layers/texture_layer.h"
22 #include "cc/output/copy_output_request.h"
23 #include "cc/output/delegated_frame_data.h"
24 #include "cc/output/filter_operation.h"
25 #include "cc/output/filter_operations.h"
26 #include "cc/resources/transferable_resource.h"
27 #include "ui/compositor/compositor_switches.h"
28 #include "ui/compositor/dip_util.h"
29 #include "ui/compositor/layer_animator.h"
30 #include "ui/gfx/animation/animation.h"
31 #include "ui/gfx/canvas.h"
32 #include "ui/gfx/display.h"
33 #include "ui/gfx/interpolated_transform.h"
34 #include "ui/gfx/point3_f.h"
35 #include "ui/gfx/point_conversions.h"
36 #include "ui/gfx/size_conversions.h"
38 namespace {
40 const ui::Layer* GetRoot(const ui::Layer* layer) {
41 while (layer->parent())
42 layer = layer->parent();
43 return layer;
46 struct UIImplSidePaintingStatus {
47 UIImplSidePaintingStatus()
48 : enabled(ui::IsUIImplSidePaintingEnabled()) {
50 bool enabled;
52 base::LazyInstance<UIImplSidePaintingStatus> g_ui_impl_side_painting_status =
53 LAZY_INSTANCE_INITIALIZER;
55 } // namespace
57 namespace ui {
59 Layer::Layer()
60 : type_(LAYER_TEXTURED),
61 compositor_(NULL),
62 parent_(NULL),
63 visible_(true),
64 force_render_surface_(false),
65 fills_bounds_opaquely_(true),
66 fills_bounds_completely_(false),
67 background_blur_radius_(0),
68 layer_saturation_(0.0f),
69 layer_brightness_(0.0f),
70 layer_grayscale_(0.0f),
71 layer_inverted_(false),
72 layer_mask_(NULL),
73 layer_mask_back_link_(NULL),
74 zoom_(1),
75 zoom_inset_(0),
76 delegate_(NULL),
77 owner_(NULL),
78 cc_layer_(NULL),
79 device_scale_factor_(1.0f) {
80 CreateWebLayer();
83 Layer::Layer(LayerType type)
84 : type_(type),
85 compositor_(NULL),
86 parent_(NULL),
87 visible_(true),
88 force_render_surface_(false),
89 fills_bounds_opaquely_(true),
90 fills_bounds_completely_(false),
91 background_blur_radius_(0),
92 layer_saturation_(0.0f),
93 layer_brightness_(0.0f),
94 layer_grayscale_(0.0f),
95 layer_inverted_(false),
96 layer_mask_(NULL),
97 layer_mask_back_link_(NULL),
98 zoom_(1),
99 zoom_inset_(0),
100 delegate_(NULL),
101 owner_(NULL),
102 cc_layer_(NULL),
103 device_scale_factor_(1.0f) {
104 CreateWebLayer();
107 Layer::~Layer() {
108 // Destroying the animator may cause observers to use the layer (and
109 // indirectly the WebLayer). Destroy the animator first so that the WebLayer
110 // is still around.
111 if (animator_.get())
112 animator_->SetDelegate(NULL);
113 animator_ = NULL;
114 if (compositor_)
115 compositor_->SetRootLayer(NULL);
116 if (parent_)
117 parent_->Remove(this);
118 if (layer_mask_)
119 SetMaskLayer(NULL);
120 if (layer_mask_back_link_)
121 layer_mask_back_link_->SetMaskLayer(NULL);
122 for (size_t i = 0; i < children_.size(); ++i)
123 children_[i]->parent_ = NULL;
124 cc_layer_->RemoveLayerAnimationEventObserver(this);
125 cc_layer_->RemoveFromParent();
128 // static
129 bool Layer::UsingPictureLayer() {
130 return g_ui_impl_side_painting_status.Get().enabled;
133 Compositor* Layer::GetCompositor() {
134 return GetRoot(this)->compositor_;
137 float Layer::opacity() const {
138 return cc_layer_->opacity();
141 void Layer::SetCompositor(Compositor* compositor) {
142 // This function must only be called to set the compositor on the root layer,
143 // or to reset it.
144 DCHECK(!compositor || !compositor_);
145 DCHECK(!compositor || compositor->root_layer() == this);
146 DCHECK(!parent_);
147 if (compositor_) {
148 RemoveAnimatorsInTreeFromCollection(
149 compositor_->layer_animator_collection());
151 compositor_ = compositor;
152 if (compositor) {
153 OnDeviceScaleFactorChanged(compositor->device_scale_factor());
154 SendPendingThreadedAnimations();
155 AddAnimatorsInTreeToCollection(compositor_->layer_animator_collection());
159 void Layer::Add(Layer* child) {
160 DCHECK(!child->compositor_);
161 if (child->parent_)
162 child->parent_->Remove(child);
163 child->parent_ = this;
164 children_.push_back(child);
165 cc_layer_->AddChild(child->cc_layer_);
166 child->OnDeviceScaleFactorChanged(device_scale_factor_);
167 if (GetCompositor())
168 child->SendPendingThreadedAnimations();
169 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
170 if (collection)
171 child->AddAnimatorsInTreeToCollection(collection);
174 void Layer::Remove(Layer* child) {
175 // Current bounds are used to calculate offsets when layers are reparented.
176 // Stop (and complete) an ongoing animation to update the bounds immediately.
177 LayerAnimator* child_animator = child->animator_.get();
178 if (child_animator)
179 child_animator->StopAnimatingProperty(ui::LayerAnimationElement::BOUNDS);
180 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
181 if (collection)
182 child->RemoveAnimatorsInTreeFromCollection(collection);
184 std::vector<Layer*>::iterator i =
185 std::find(children_.begin(), children_.end(), child);
186 DCHECK(i != children_.end());
187 children_.erase(i);
188 child->parent_ = NULL;
189 child->cc_layer_->RemoveFromParent();
192 void Layer::StackAtTop(Layer* child) {
193 if (children_.size() <= 1 || child == children_.back())
194 return; // Already in front.
195 StackAbove(child, children_.back());
198 void Layer::StackAbove(Layer* child, Layer* other) {
199 StackRelativeTo(child, other, true);
202 void Layer::StackAtBottom(Layer* child) {
203 if (children_.size() <= 1 || child == children_.front())
204 return; // Already on bottom.
205 StackBelow(child, children_.front());
208 void Layer::StackBelow(Layer* child, Layer* other) {
209 StackRelativeTo(child, other, false);
212 bool Layer::Contains(const Layer* other) const {
213 for (const Layer* parent = other; parent; parent = parent->parent()) {
214 if (parent == this)
215 return true;
217 return false;
220 void Layer::SetAnimator(LayerAnimator* animator) {
221 if (animator)
222 animator->SetDelegate(this);
223 animator_ = animator;
226 LayerAnimator* Layer::GetAnimator() {
227 if (!animator_.get())
228 SetAnimator(LayerAnimator::CreateDefaultAnimator());
229 return animator_.get();
232 void Layer::SetTransform(const gfx::Transform& transform) {
233 GetAnimator()->SetTransform(transform);
236 gfx::Transform Layer::GetTargetTransform() const {
237 if (animator_.get() && animator_->IsAnimatingProperty(
238 LayerAnimationElement::TRANSFORM)) {
239 return animator_->GetTargetTransform();
241 return transform();
244 void Layer::SetBounds(const gfx::Rect& bounds) {
245 GetAnimator()->SetBounds(bounds);
248 void Layer::SetSubpixelPositionOffset(const gfx::Vector2dF offset) {
249 subpixel_position_offset_ = offset;
250 RecomputePosition();
253 gfx::Rect Layer::GetTargetBounds() const {
254 if (animator_.get() && animator_->IsAnimatingProperty(
255 LayerAnimationElement::BOUNDS)) {
256 return animator_->GetTargetBounds();
258 return bounds_;
261 void Layer::SetMasksToBounds(bool masks_to_bounds) {
262 cc_layer_->SetMasksToBounds(masks_to_bounds);
265 bool Layer::GetMasksToBounds() const {
266 return cc_layer_->masks_to_bounds();
269 void Layer::SetOpacity(float opacity) {
270 GetAnimator()->SetOpacity(opacity);
273 float Layer::GetCombinedOpacity() const {
274 float opacity = this->opacity();
275 Layer* current = this->parent_;
276 while (current) {
277 opacity *= current->opacity();
278 current = current->parent_;
280 return opacity;
283 void Layer::SetBackgroundBlur(int blur_radius) {
284 background_blur_radius_ = blur_radius;
286 SetLayerBackgroundFilters();
289 void Layer::SetLayerSaturation(float saturation) {
290 layer_saturation_ = saturation;
291 SetLayerFilters();
294 void Layer::SetLayerBrightness(float brightness) {
295 GetAnimator()->SetBrightness(brightness);
298 float Layer::GetTargetBrightness() const {
299 if (animator_.get() && animator_->IsAnimatingProperty(
300 LayerAnimationElement::BRIGHTNESS)) {
301 return animator_->GetTargetBrightness();
303 return layer_brightness();
306 void Layer::SetLayerGrayscale(float grayscale) {
307 GetAnimator()->SetGrayscale(grayscale);
310 float Layer::GetTargetGrayscale() const {
311 if (animator_.get() && animator_->IsAnimatingProperty(
312 LayerAnimationElement::GRAYSCALE)) {
313 return animator_->GetTargetGrayscale();
315 return layer_grayscale();
318 void Layer::SetLayerInverted(bool inverted) {
319 layer_inverted_ = inverted;
320 SetLayerFilters();
323 void Layer::SetMaskLayer(Layer* layer_mask) {
324 // The provided mask should not have a layer mask itself.
325 DCHECK(!layer_mask ||
326 (!layer_mask->layer_mask_layer() &&
327 layer_mask->children().empty() &&
328 !layer_mask->layer_mask_back_link_));
329 DCHECK(!layer_mask_back_link_);
330 if (layer_mask_ == layer_mask)
331 return;
332 // We need to de-reference the currently linked object so that no problem
333 // arises if the mask layer gets deleted before this object.
334 if (layer_mask_)
335 layer_mask_->layer_mask_back_link_ = NULL;
336 layer_mask_ = layer_mask;
337 cc_layer_->SetMaskLayer(
338 layer_mask ? layer_mask->cc_layer() : NULL);
339 // We need to reference the linked object so that it can properly break the
340 // link to us when it gets deleted.
341 if (layer_mask) {
342 layer_mask->layer_mask_back_link_ = this;
343 layer_mask->OnDeviceScaleFactorChanged(device_scale_factor_);
347 void Layer::SetBackgroundZoom(float zoom, int inset) {
348 zoom_ = zoom;
349 zoom_inset_ = inset;
351 SetLayerBackgroundFilters();
354 void Layer::SetAlphaShape(scoped_ptr<SkRegion> region) {
355 alpha_shape_ = region.Pass();
357 SetLayerFilters();
360 void Layer::SetLayerFilters() {
361 cc::FilterOperations filters;
362 if (layer_saturation_) {
363 filters.Append(cc::FilterOperation::CreateSaturateFilter(
364 layer_saturation_));
366 if (layer_grayscale_) {
367 filters.Append(cc::FilterOperation::CreateGrayscaleFilter(
368 layer_grayscale_));
370 if (layer_inverted_)
371 filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
372 // Brightness goes last, because the resulting colors neeed clamping, which
373 // cause further color matrix filters to be applied separately. In this order,
374 // they all can be combined in a single pass.
375 if (layer_brightness_) {
376 filters.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter(
377 layer_brightness_));
379 if (alpha_shape_) {
380 filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter(
381 *alpha_shape_, 1.f, 0.f));
384 cc_layer_->SetFilters(filters);
387 void Layer::SetLayerBackgroundFilters() {
388 cc::FilterOperations filters;
389 if (zoom_ != 1)
390 filters.Append(cc::FilterOperation::CreateZoomFilter(zoom_, zoom_inset_));
392 if (background_blur_radius_) {
393 filters.Append(cc::FilterOperation::CreateBlurFilter(
394 background_blur_radius_));
397 cc_layer_->SetBackgroundFilters(filters);
400 float Layer::GetTargetOpacity() const {
401 if (animator_.get() && animator_->IsAnimatingProperty(
402 LayerAnimationElement::OPACITY))
403 return animator_->GetTargetOpacity();
404 return opacity();
407 void Layer::SetVisible(bool visible) {
408 GetAnimator()->SetVisibility(visible);
411 bool Layer::GetTargetVisibility() const {
412 if (animator_.get() && animator_->IsAnimatingProperty(
413 LayerAnimationElement::VISIBILITY))
414 return animator_->GetTargetVisibility();
415 return visible_;
418 bool Layer::IsDrawn() const {
419 const Layer* layer = this;
420 while (layer && layer->visible_)
421 layer = layer->parent_;
422 return layer == NULL;
425 bool Layer::ShouldDraw() const {
426 return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f;
429 // static
430 void Layer::ConvertPointToLayer(const Layer* source,
431 const Layer* target,
432 gfx::Point* point) {
433 if (source == target)
434 return;
436 const Layer* root_layer = GetRoot(source);
437 CHECK_EQ(root_layer, GetRoot(target));
439 if (source != root_layer)
440 source->ConvertPointForAncestor(root_layer, point);
441 if (target != root_layer)
442 target->ConvertPointFromAncestor(root_layer, point);
445 bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor,
446 gfx::Transform* transform) const {
447 const Layer* p = this;
448 for (; p && p != ancestor; p = p->parent()) {
449 gfx::Transform translation;
450 translation.Translate(static_cast<float>(p->bounds().x()),
451 static_cast<float>(p->bounds().y()));
452 // Use target transform so that result will be correct once animation is
453 // finished.
454 if (!p->GetTargetTransform().IsIdentity())
455 transform->ConcatTransform(p->GetTargetTransform());
456 transform->ConcatTransform(translation);
458 return p == ancestor;
461 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
462 if (fills_bounds_opaquely_ == fills_bounds_opaquely)
463 return;
465 fills_bounds_opaquely_ = fills_bounds_opaquely;
467 cc_layer_->SetContentsOpaque(fills_bounds_opaquely);
470 void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) {
471 fills_bounds_completely_ = fills_bounds_completely;
474 void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
475 // Finish animations being handled by cc_layer_.
476 if (animator_.get()) {
477 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
478 animator_->StopAnimatingProperty(LayerAnimationElement::OPACITY);
481 if (texture_layer_.get())
482 texture_layer_->ClearClient();
483 // TODO(piman): delegated_renderer_layer_ cleanup.
485 cc_layer_->RemoveAllChildren();
486 if (cc_layer_->parent()) {
487 cc_layer_->parent()->ReplaceChild(cc_layer_, new_layer);
489 cc_layer_->SetLayerClient(NULL);
490 cc_layer_->RemoveLayerAnimationEventObserver(this);
491 new_layer->SetOpacity(cc_layer_->opacity());
492 new_layer->SetTransform(cc_layer_->transform());
493 new_layer->SetPosition(cc_layer_->position());
495 cc_layer_ = new_layer.get();
496 content_layer_ = NULL;
497 solid_color_layer_ = NULL;
498 texture_layer_ = NULL;
499 delegated_renderer_layer_ = NULL;
500 surface_layer_ = NULL;
502 cc_layer_->AddLayerAnimationEventObserver(this);
503 for (size_t i = 0; i < children_.size(); ++i) {
504 DCHECK(children_[i]->cc_layer_);
505 cc_layer_->AddChild(children_[i]->cc_layer_);
507 cc_layer_->SetLayerClient(this);
508 cc_layer_->SetTransformOrigin(gfx::Point3F());
509 cc_layer_->SetContentsOpaque(fills_bounds_opaquely_);
510 cc_layer_->SetForceRenderSurface(force_render_surface_);
511 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
512 cc_layer_->SetHideLayerAndSubtree(!visible_);
515 void Layer::SwitchCCLayerForTest() {
516 scoped_refptr<cc::Layer> new_layer;
517 if (Layer::UsingPictureLayer())
518 new_layer = cc::PictureLayer::Create(this);
519 else
520 new_layer = cc::ContentLayer::Create(this);
521 SwitchToLayer(new_layer);
522 content_layer_ = new_layer;
525 void Layer::SetTextureMailbox(
526 const cc::TextureMailbox& mailbox,
527 scoped_ptr<cc::SingleReleaseCallback> release_callback,
528 gfx::Size texture_size_in_dip) {
529 DCHECK_EQ(type_, LAYER_TEXTURED);
530 DCHECK(!solid_color_layer_.get());
531 DCHECK(mailbox.IsValid());
532 DCHECK(release_callback);
533 if (!texture_layer_.get()) {
534 scoped_refptr<cc::TextureLayer> new_layer =
535 cc::TextureLayer::CreateForMailbox(this);
536 new_layer->SetFlipped(true);
537 SwitchToLayer(new_layer);
538 texture_layer_ = new_layer;
540 if (mailbox_release_callback_)
541 mailbox_release_callback_->Run(0, false);
542 mailbox_release_callback_ = release_callback.Pass();
543 mailbox_ = mailbox;
544 SetTextureSize(texture_size_in_dip);
547 void Layer::SetTextureSize(gfx::Size texture_size_in_dip) {
548 DCHECK(texture_layer_.get());
549 if (frame_size_in_dip_ == texture_size_in_dip)
550 return;
551 frame_size_in_dip_ = texture_size_in_dip;
552 RecomputeDrawsContentAndUVRect();
553 texture_layer_->SetNeedsDisplay();
556 void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider,
557 gfx::Size frame_size_in_dip) {
558 DCHECK_EQ(type_, LAYER_TEXTURED);
560 scoped_refptr<cc::DelegatedRendererLayer> new_layer =
561 cc::DelegatedRendererLayer::Create(frame_provider);
562 SwitchToLayer(new_layer);
563 delegated_renderer_layer_ = new_layer;
565 frame_size_in_dip_ = frame_size_in_dip;
566 RecomputeDrawsContentAndUVRect();
569 void Layer::SetShowSurface(cc::SurfaceId id, gfx::Size frame_size_in_dip) {
570 DCHECK_EQ(type_, LAYER_TEXTURED);
572 scoped_refptr<cc::SurfaceLayer> new_layer = cc::SurfaceLayer::Create();
573 new_layer->SetSurfaceId(id);
574 SwitchToLayer(new_layer);
575 surface_layer_ = new_layer;
577 frame_size_in_dip_ = frame_size_in_dip;
578 RecomputeDrawsContentAndUVRect();
581 void Layer::SetShowPaintedContent() {
582 if (content_layer_.get())
583 return;
585 scoped_refptr<cc::Layer> new_layer;
586 if (Layer::UsingPictureLayer())
587 new_layer = cc::PictureLayer::Create(this);
588 else
589 new_layer = cc::ContentLayer::Create(this);
590 SwitchToLayer(new_layer);
591 content_layer_ = new_layer;
593 mailbox_ = cc::TextureMailbox();
594 if (mailbox_release_callback_) {
595 mailbox_release_callback_->Run(0, false);
596 mailbox_release_callback_.reset();
598 RecomputeDrawsContentAndUVRect();
601 void Layer::UpdateNinePatchLayerBitmap(const SkBitmap& bitmap,
602 const gfx::Rect& aperture) {
603 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
604 SkBitmap bitmap_copy;
605 if (bitmap.isImmutable()) {
606 bitmap_copy = bitmap;
607 } else {
608 // UIResourceBitmap requires an immutable copy of the input |bitmap|.
609 bitmap.copyTo(&bitmap_copy);
610 bitmap_copy.setImmutable();
612 nine_patch_layer_->SetBitmap(bitmap_copy);
613 nine_patch_layer_->SetAperture(aperture);
616 void Layer::UpdateNinePatchLayerBorder(const gfx::Rect& border) {
617 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get());
618 nine_patch_layer_->SetBorder(border);
621 void Layer::SetColor(SkColor color) { GetAnimator()->SetColor(color); }
623 bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) {
624 if (type_ == LAYER_SOLID_COLOR ||
625 type_ == LAYER_NINE_PATCH ||
626 (!delegate_ && !mailbox_.IsValid()))
627 return false;
629 damaged_region_.op(invalid_rect.x(),
630 invalid_rect.y(),
631 invalid_rect.right(),
632 invalid_rect.bottom(),
633 SkRegion::kUnion_Op);
634 ScheduleDraw();
635 return true;
638 void Layer::ScheduleDraw() {
639 Compositor* compositor = GetCompositor();
640 if (compositor)
641 compositor->ScheduleDraw();
644 void Layer::SendDamagedRects() {
645 if ((delegate_ || mailbox_.IsValid()) && !damaged_region_.isEmpty()) {
646 for (SkRegion::Iterator iter(damaged_region_); !iter.done(); iter.next()) {
647 const SkIRect& sk_damaged = iter.rect();
648 gfx::Rect damaged(
649 sk_damaged.x(),
650 sk_damaged.y(),
651 sk_damaged.width(),
652 sk_damaged.height());
653 cc_layer_->SetNeedsDisplayRect(damaged);
655 damaged_region_.setEmpty();
657 for (size_t i = 0; i < children_.size(); ++i)
658 children_[i]->SendDamagedRects();
661 void Layer::CompleteAllAnimations() {
662 std::vector<scoped_refptr<LayerAnimator> > animators;
663 CollectAnimators(&animators);
664 std::for_each(animators.begin(), animators.end(),
665 std::mem_fun(&LayerAnimator::StopAnimating));
668 void Layer::SuppressPaint() {
669 if (!delegate_)
670 return;
671 delegate_ = NULL;
672 for (size_t i = 0; i < children_.size(); ++i)
673 children_[i]->SuppressPaint();
676 void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) {
677 if (device_scale_factor_ == device_scale_factor)
678 return;
679 if (animator_.get())
680 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM);
681 device_scale_factor_ = device_scale_factor;
682 RecomputeDrawsContentAndUVRect();
683 RecomputePosition();
684 SchedulePaint(gfx::Rect(bounds_.size()));
685 if (delegate_)
686 delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
687 for (size_t i = 0; i < children_.size(); ++i)
688 children_[i]->OnDeviceScaleFactorChanged(device_scale_factor);
689 if (layer_mask_)
690 layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor);
693 void Layer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {
694 DCHECK(delegated_renderer_layer_.get() || surface_layer_.get());
695 if (!delegate_)
696 return;
697 delegate_->OnDelegatedFrameDamage(damage_rect_in_dip);
700 void Layer::RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) {
701 cc_layer_->RequestCopyOfOutput(request.Pass());
704 void Layer::PaintContents(SkCanvas* sk_canvas,
705 const gfx::Rect& clip,
706 gfx::RectF* opaque,
707 ContentLayerClient::GraphicsContextStatus gc_status) {
708 TRACE_EVENT0("ui", "Layer::PaintContents");
709 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling(
710 sk_canvas, device_scale_factor_));
711 if (delegate_)
712 delegate_->OnPaintLayer(canvas.get());
715 bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; }
717 bool Layer::PrepareTextureMailbox(
718 cc::TextureMailbox* mailbox,
719 scoped_ptr<cc::SingleReleaseCallback>* release_callback,
720 bool use_shared_memory) {
721 if (!mailbox_release_callback_)
722 return false;
723 *mailbox = mailbox_;
724 *release_callback = mailbox_release_callback_.Pass();
725 return true;
728 void Layer::SetForceRenderSurface(bool force) {
729 if (force_render_surface_ == force)
730 return;
732 force_render_surface_ = force;
733 cc_layer_->SetForceRenderSurface(force_render_surface_);
736 class LayerDebugInfo : public base::debug::ConvertableToTraceFormat {
737 public:
738 explicit LayerDebugInfo(std::string name) : name_(name) { }
739 virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE {
740 base::DictionaryValue dictionary;
741 dictionary.SetString("layer_name", name_);
742 base::JSONWriter::Write(&dictionary, out);
745 private:
746 virtual ~LayerDebugInfo() { }
747 std::string name_;
750 scoped_refptr<base::debug::ConvertableToTraceFormat> Layer::TakeDebugInfo() {
751 return new LayerDebugInfo(name_);
754 void Layer::OnAnimationStarted(const cc::AnimationEvent& event) {
755 if (animator_.get())
756 animator_->OnThreadedAnimationStarted(event);
759 void Layer::CollectAnimators(
760 std::vector<scoped_refptr<LayerAnimator> >* animators) {
761 if (IsAnimating())
762 animators->push_back(animator_);
763 std::for_each(children_.begin(), children_.end(),
764 std::bind2nd(std::mem_fun(&Layer::CollectAnimators),
765 animators));
768 void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) {
769 DCHECK_NE(child, other);
770 DCHECK_EQ(this, child->parent());
771 DCHECK_EQ(this, other->parent());
773 const size_t child_i =
774 std::find(children_.begin(), children_.end(), child) - children_.begin();
775 const size_t other_i =
776 std::find(children_.begin(), children_.end(), other) - children_.begin();
777 if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i))
778 return;
780 const size_t dest_i =
781 above ?
782 (child_i < other_i ? other_i : other_i + 1) :
783 (child_i < other_i ? other_i - 1 : other_i);
784 children_.erase(children_.begin() + child_i);
785 children_.insert(children_.begin() + dest_i, child);
787 child->cc_layer_->RemoveFromParent();
788 cc_layer_->InsertChild(child->cc_layer_, dest_i);
791 bool Layer::ConvertPointForAncestor(const Layer* ancestor,
792 gfx::Point* point) const {
793 gfx::Transform transform;
794 bool result = GetTargetTransformRelativeTo(ancestor, &transform);
795 gfx::Point3F p(*point);
796 transform.TransformPoint(&p);
797 *point = gfx::ToFlooredPoint(p.AsPointF());
798 return result;
801 bool Layer::ConvertPointFromAncestor(const Layer* ancestor,
802 gfx::Point* point) const {
803 gfx::Transform transform;
804 bool result = GetTargetTransformRelativeTo(ancestor, &transform);
805 gfx::Point3F p(*point);
806 transform.TransformPointReverse(&p);
807 *point = gfx::ToFlooredPoint(p.AsPointF());
808 return result;
811 void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) {
812 if (bounds == bounds_)
813 return;
815 base::Closure closure;
816 if (delegate_)
817 closure = delegate_->PrepareForLayerBoundsChange();
818 bool was_move = bounds_.size() == bounds.size();
819 bounds_ = bounds;
821 RecomputeDrawsContentAndUVRect();
822 RecomputePosition();
824 if (!closure.is_null())
825 closure.Run();
827 if (was_move) {
828 // Don't schedule a draw if we're invisible. We'll schedule one
829 // automatically when we get visible.
830 if (IsDrawn())
831 ScheduleDraw();
832 } else {
833 // Always schedule a paint, even if we're invisible.
834 SchedulePaint(gfx::Rect(bounds.size()));
838 void Layer::SetTransformFromAnimation(const gfx::Transform& transform) {
839 cc_layer_->SetTransform(transform);
842 void Layer::SetOpacityFromAnimation(float opacity) {
843 cc_layer_->SetOpacity(opacity);
844 ScheduleDraw();
847 void Layer::SetVisibilityFromAnimation(bool visible) {
848 if (visible_ == visible)
849 return;
851 visible_ = visible;
852 cc_layer_->SetHideLayerAndSubtree(!visible_);
855 void Layer::SetBrightnessFromAnimation(float brightness) {
856 layer_brightness_ = brightness;
857 SetLayerFilters();
860 void Layer::SetGrayscaleFromAnimation(float grayscale) {
861 layer_grayscale_ = grayscale;
862 SetLayerFilters();
865 void Layer::SetColorFromAnimation(SkColor color) {
866 DCHECK_EQ(type_, LAYER_SOLID_COLOR);
867 solid_color_layer_->SetBackgroundColor(color);
868 SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF);
871 void Layer::ScheduleDrawForAnimation() {
872 ScheduleDraw();
875 const gfx::Rect& Layer::GetBoundsForAnimation() const {
876 return bounds();
879 gfx::Transform Layer::GetTransformForAnimation() const {
880 return transform();
883 float Layer::GetOpacityForAnimation() const {
884 return opacity();
887 bool Layer::GetVisibilityForAnimation() const {
888 return visible();
891 float Layer::GetBrightnessForAnimation() const {
892 return layer_brightness();
895 float Layer::GetGrayscaleForAnimation() const {
896 return layer_grayscale();
899 SkColor Layer::GetColorForAnimation() const {
900 // WebColor is equivalent to SkColor, per WebColor.h.
901 // The NULL check is here since this is invoked regardless of whether we have
902 // been configured as LAYER_SOLID_COLOR.
903 return solid_color_layer_.get() ?
904 solid_color_layer_->background_color() : SK_ColorBLACK;
907 float Layer::GetDeviceScaleFactor() const {
908 return device_scale_factor_;
911 void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) {
912 DCHECK(cc_layer_);
913 // Until this layer has a compositor (and hence cc_layer_ has a
914 // LayerTreeHost), addAnimation will fail.
915 if (GetCompositor())
916 cc_layer_->AddAnimation(animation.Pass());
917 else
918 pending_threaded_animations_.push_back(animation.Pass());
921 namespace{
923 struct HasAnimationId {
924 HasAnimationId(int id): id_(id) {
927 bool operator()(cc::Animation* animation) const {
928 return animation->id() == id_;
931 private:
932 int id_;
937 void Layer::RemoveThreadedAnimation(int animation_id) {
938 DCHECK(cc_layer_);
939 if (pending_threaded_animations_.size() == 0) {
940 cc_layer_->RemoveAnimation(animation_id);
941 return;
944 pending_threaded_animations_.erase(
945 cc::remove_if(&pending_threaded_animations_,
946 pending_threaded_animations_.begin(),
947 pending_threaded_animations_.end(),
948 HasAnimationId(animation_id)),
949 pending_threaded_animations_.end());
952 LayerAnimatorCollection* Layer::GetLayerAnimatorCollection() {
953 Compositor* compositor = GetCompositor();
954 return compositor ? compositor->layer_animator_collection() : NULL;
957 void Layer::SendPendingThreadedAnimations() {
958 for (cc::ScopedPtrVector<cc::Animation>::iterator it =
959 pending_threaded_animations_.begin();
960 it != pending_threaded_animations_.end();
961 ++it)
962 cc_layer_->AddAnimation(pending_threaded_animations_.take(it));
964 pending_threaded_animations_.clear();
966 for (size_t i = 0; i < children_.size(); ++i)
967 children_[i]->SendPendingThreadedAnimations();
970 void Layer::CreateWebLayer() {
971 if (type_ == LAYER_SOLID_COLOR) {
972 solid_color_layer_ = cc::SolidColorLayer::Create();
973 cc_layer_ = solid_color_layer_.get();
974 } else if (type_ == LAYER_NINE_PATCH) {
975 nine_patch_layer_ = cc::NinePatchLayer::Create();
976 cc_layer_ = nine_patch_layer_.get();
977 } else {
978 if (Layer::UsingPictureLayer())
979 content_layer_ = cc::PictureLayer::Create(this);
980 else
981 content_layer_ = cc::ContentLayer::Create(this);
982 cc_layer_ = content_layer_.get();
984 cc_layer_->SetTransformOrigin(gfx::Point3F());
985 cc_layer_->SetContentsOpaque(true);
986 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
987 cc_layer_->AddLayerAnimationEventObserver(this);
988 cc_layer_->SetLayerClient(this);
989 RecomputePosition();
992 gfx::Transform Layer::transform() const {
993 return cc_layer_->transform();
996 void Layer::RecomputeDrawsContentAndUVRect() {
997 DCHECK(cc_layer_);
998 gfx::Size size(bounds_.size());
999 if (texture_layer_.get()) {
1000 size.SetToMin(frame_size_in_dip_);
1001 gfx::PointF uv_top_left(0.f, 0.f);
1002 gfx::PointF uv_bottom_right(
1003 static_cast<float>(size.width()) / frame_size_in_dip_.width(),
1004 static_cast<float>(size.height()) / frame_size_in_dip_.height());
1005 texture_layer_->SetUV(uv_top_left, uv_bottom_right);
1006 } else if (delegated_renderer_layer_.get() || surface_layer_.get()) {
1007 size.SetToMin(frame_size_in_dip_);
1009 cc_layer_->SetBounds(size);
1012 void Layer::RecomputePosition() {
1013 cc_layer_->SetPosition(bounds_.origin() + subpixel_position_offset_);
1016 void Layer::AddAnimatorsInTreeToCollection(
1017 LayerAnimatorCollection* collection) {
1018 DCHECK(collection);
1019 if (IsAnimating())
1020 animator_->AddToCollection(collection);
1021 std::for_each(
1022 children_.begin(),
1023 children_.end(),
1024 std::bind2nd(std::mem_fun(&Layer::AddAnimatorsInTreeToCollection),
1025 collection));
1028 void Layer::RemoveAnimatorsInTreeFromCollection(
1029 LayerAnimatorCollection* collection) {
1030 DCHECK(collection);
1031 if (IsAnimating())
1032 animator_->RemoveFromCollection(collection);
1033 std::for_each(
1034 children_.begin(),
1035 children_.end(),
1036 std::bind2nd(std::mem_fun(&Layer::RemoveAnimatorsInTreeFromCollection),
1037 collection));
1040 bool Layer::IsAnimating() const {
1041 return animator_.get() && animator_->is_animating();
1044 } // namespace ui