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"
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"
40 const ui::Layer
* GetRoot(const ui::Layer
* layer
) {
41 while (layer
->parent())
42 layer
= layer
->parent();
46 struct UIImplSidePaintingStatus
{
47 UIImplSidePaintingStatus()
48 : enabled(ui::IsUIImplSidePaintingEnabled()) {
52 base::LazyInstance
<UIImplSidePaintingStatus
> g_ui_impl_side_painting_status
=
53 LAZY_INSTANCE_INITIALIZER
;
60 : type_(LAYER_TEXTURED
),
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),
73 layer_mask_back_link_(NULL
),
79 device_scale_factor_(1.0f
) {
83 Layer::Layer(LayerType type
)
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),
97 layer_mask_back_link_(NULL
),
103 device_scale_factor_(1.0f
) {
108 // Destroying the animator may cause observers to use the layer (and
109 // indirectly the WebLayer). Destroy the animator first so that the WebLayer
112 animator_
->SetDelegate(NULL
);
115 compositor_
->SetRootLayer(NULL
);
117 parent_
->Remove(this);
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();
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,
144 DCHECK(!compositor
|| !compositor_
);
145 DCHECK(!compositor
|| compositor
->root_layer() == this);
148 RemoveAnimatorsInTreeFromCollection(
149 compositor_
->layer_animator_collection());
151 compositor_
= 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_
);
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_
);
168 child
->SendPendingThreadedAnimations();
169 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
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_
;
179 child_animator
->StopAnimatingProperty(ui::LayerAnimationElement::BOUNDS
);
180 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
182 child
->RemoveAnimatorsInTreeFromCollection(collection
);
184 std::vector
<Layer
*>::iterator i
=
185 std::find(children_
.begin(), children_
.end(), child
);
186 DCHECK(i
!= children_
.end());
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()) {
220 void Layer::SetAnimator(LayerAnimator
* 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();
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
;
253 gfx::Rect
Layer::GetTargetBounds() const {
254 if (animator_
.get() && animator_
->IsAnimatingProperty(
255 LayerAnimationElement::BOUNDS
)) {
256 return animator_
->GetTargetBounds();
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_
;
277 opacity
*= current
->opacity();
278 current
= current
->parent_
;
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
;
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
;
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
)
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.
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.
342 layer_mask
->layer_mask_back_link_
= this;
343 layer_mask
->OnDeviceScaleFactorChanged(device_scale_factor_
);
347 void Layer::SetBackgroundZoom(float zoom
, int inset
) {
351 SetLayerBackgroundFilters();
354 void Layer::SetAlphaShape(scoped_ptr
<SkRegion
> region
) {
355 alpha_shape_
= region
.Pass();
360 void Layer::SetLayerFilters() {
361 cc::FilterOperations filters
;
362 if (layer_saturation_
) {
363 filters
.Append(cc::FilterOperation::CreateSaturateFilter(
366 if (layer_grayscale_
) {
367 filters
.Append(cc::FilterOperation::CreateGrayscaleFilter(
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(
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
;
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();
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();
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
;
430 void Layer::ConvertPointToLayer(const Layer
* source
,
433 if (source
== target
)
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
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
)
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);
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_
) {
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();
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
)
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())
585 scoped_refptr
<cc::Layer
> new_layer
;
586 if (Layer::UsingPictureLayer())
587 new_layer
= cc::PictureLayer::Create(this);
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
;
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()))
629 damaged_region_
.op(invalid_rect
.x(),
631 invalid_rect
.right(),
632 invalid_rect
.bottom(),
633 SkRegion::kUnion_Op
);
638 void Layer::ScheduleDraw() {
639 Compositor
* compositor
= GetCompositor();
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();
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() {
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
)
680 animator_
->StopAnimatingProperty(LayerAnimationElement::TRANSFORM
);
681 device_scale_factor_
= device_scale_factor
;
682 RecomputeDrawsContentAndUVRect();
684 SchedulePaint(gfx::Rect(bounds_
.size()));
686 delegate_
->OnDeviceScaleFactorChanged(device_scale_factor
);
687 for (size_t i
= 0; i
< children_
.size(); ++i
)
688 children_
[i
]->OnDeviceScaleFactorChanged(device_scale_factor
);
690 layer_mask_
->OnDeviceScaleFactorChanged(device_scale_factor
);
693 void Layer::RequestCopyOfOutput(scoped_ptr
<cc::CopyOutputRequest
> request
) {
694 cc_layer_
->RequestCopyOfOutput(request
.Pass());
697 void Layer::PaintContents(SkCanvas
* sk_canvas
,
698 const gfx::Rect
& clip
,
700 ContentLayerClient::GraphicsContextStatus gc_status
) {
701 TRACE_EVENT0("ui", "Layer::PaintContents");
702 scoped_ptr
<gfx::Canvas
> canvas(gfx::Canvas::CreateCanvasWithoutScaling(
703 sk_canvas
, device_scale_factor_
));
705 delegate_
->OnPaintLayer(canvas
.get());
708 bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_
; }
710 bool Layer::PrepareTextureMailbox(
711 cc::TextureMailbox
* mailbox
,
712 scoped_ptr
<cc::SingleReleaseCallback
>* release_callback
,
713 bool use_shared_memory
) {
714 if (!mailbox_release_callback_
)
717 *release_callback
= mailbox_release_callback_
.Pass();
721 void Layer::SetForceRenderSurface(bool force
) {
722 if (force_render_surface_
== force
)
725 force_render_surface_
= force
;
726 cc_layer_
->SetForceRenderSurface(force_render_surface_
);
729 class LayerDebugInfo
: public base::debug::ConvertableToTraceFormat
{
731 explicit LayerDebugInfo(std::string name
) : name_(name
) { }
732 virtual void AppendAsTraceFormat(std::string
* out
) const OVERRIDE
{
733 base::DictionaryValue dictionary
;
734 dictionary
.SetString("layer_name", name_
);
735 base::JSONWriter::Write(&dictionary
, out
);
739 virtual ~LayerDebugInfo() { }
743 scoped_refptr
<base::debug::ConvertableToTraceFormat
> Layer::TakeDebugInfo() {
744 return new LayerDebugInfo(name_
);
747 void Layer::OnAnimationStarted(const cc::AnimationEvent
& event
) {
749 animator_
->OnThreadedAnimationStarted(event
);
752 void Layer::CollectAnimators(
753 std::vector
<scoped_refptr
<LayerAnimator
> >* animators
) {
755 animators
->push_back(animator_
);
756 std::for_each(children_
.begin(), children_
.end(),
757 std::bind2nd(std::mem_fun(&Layer::CollectAnimators
),
761 void Layer::StackRelativeTo(Layer
* child
, Layer
* other
, bool above
) {
762 DCHECK_NE(child
, other
);
763 DCHECK_EQ(this, child
->parent());
764 DCHECK_EQ(this, other
->parent());
766 const size_t child_i
=
767 std::find(children_
.begin(), children_
.end(), child
) - children_
.begin();
768 const size_t other_i
=
769 std::find(children_
.begin(), children_
.end(), other
) - children_
.begin();
770 if ((above
&& child_i
== other_i
+ 1) || (!above
&& child_i
+ 1 == other_i
))
773 const size_t dest_i
=
775 (child_i
< other_i
? other_i
: other_i
+ 1) :
776 (child_i
< other_i
? other_i
- 1 : other_i
);
777 children_
.erase(children_
.begin() + child_i
);
778 children_
.insert(children_
.begin() + dest_i
, child
);
780 child
->cc_layer_
->RemoveFromParent();
781 cc_layer_
->InsertChild(child
->cc_layer_
, dest_i
);
784 bool Layer::ConvertPointForAncestor(const Layer
* ancestor
,
785 gfx::Point
* point
) const {
786 gfx::Transform transform
;
787 bool result
= GetTargetTransformRelativeTo(ancestor
, &transform
);
788 gfx::Point3F
p(*point
);
789 transform
.TransformPoint(&p
);
790 *point
= gfx::ToFlooredPoint(p
.AsPointF());
794 bool Layer::ConvertPointFromAncestor(const Layer
* ancestor
,
795 gfx::Point
* point
) const {
796 gfx::Transform transform
;
797 bool result
= GetTargetTransformRelativeTo(ancestor
, &transform
);
798 gfx::Point3F
p(*point
);
799 transform
.TransformPointReverse(&p
);
800 *point
= gfx::ToFlooredPoint(p
.AsPointF());
804 void Layer::SetBoundsFromAnimation(const gfx::Rect
& bounds
) {
805 if (bounds
== bounds_
)
808 base::Closure closure
;
810 closure
= delegate_
->PrepareForLayerBoundsChange();
811 bool was_move
= bounds_
.size() == bounds
.size();
814 RecomputeDrawsContentAndUVRect();
817 if (!closure
.is_null())
821 // Don't schedule a draw if we're invisible. We'll schedule one
822 // automatically when we get visible.
826 // Always schedule a paint, even if we're invisible.
827 SchedulePaint(gfx::Rect(bounds
.size()));
831 void Layer::SetTransformFromAnimation(const gfx::Transform
& transform
) {
832 cc_layer_
->SetTransform(transform
);
835 void Layer::SetOpacityFromAnimation(float opacity
) {
836 cc_layer_
->SetOpacity(opacity
);
840 void Layer::SetVisibilityFromAnimation(bool visible
) {
841 if (visible_
== visible
)
845 cc_layer_
->SetHideLayerAndSubtree(!visible_
);
848 void Layer::SetBrightnessFromAnimation(float brightness
) {
849 layer_brightness_
= brightness
;
853 void Layer::SetGrayscaleFromAnimation(float grayscale
) {
854 layer_grayscale_
= grayscale
;
858 void Layer::SetColorFromAnimation(SkColor color
) {
859 DCHECK_EQ(type_
, LAYER_SOLID_COLOR
);
860 solid_color_layer_
->SetBackgroundColor(color
);
861 SetFillsBoundsOpaquely(SkColorGetA(color
) == 0xFF);
864 void Layer::ScheduleDrawForAnimation() {
868 const gfx::Rect
& Layer::GetBoundsForAnimation() const {
872 gfx::Transform
Layer::GetTransformForAnimation() const {
876 float Layer::GetOpacityForAnimation() const {
880 bool Layer::GetVisibilityForAnimation() const {
884 float Layer::GetBrightnessForAnimation() const {
885 return layer_brightness();
888 float Layer::GetGrayscaleForAnimation() const {
889 return layer_grayscale();
892 SkColor
Layer::GetColorForAnimation() const {
893 // WebColor is equivalent to SkColor, per WebColor.h.
894 // The NULL check is here since this is invoked regardless of whether we have
895 // been configured as LAYER_SOLID_COLOR.
896 return solid_color_layer_
.get() ?
897 solid_color_layer_
->background_color() : SK_ColorBLACK
;
900 float Layer::GetDeviceScaleFactor() const {
901 return device_scale_factor_
;
904 void Layer::AddThreadedAnimation(scoped_ptr
<cc::Animation
> animation
) {
906 // Until this layer has a compositor (and hence cc_layer_ has a
907 // LayerTreeHost), addAnimation will fail.
909 cc_layer_
->AddAnimation(animation
.Pass());
911 pending_threaded_animations_
.push_back(animation
.Pass());
916 struct HasAnimationId
{
917 HasAnimationId(int id
): id_(id
) {
920 bool operator()(cc::Animation
* animation
) const {
921 return animation
->id() == id_
;
930 void Layer::RemoveThreadedAnimation(int animation_id
) {
932 if (pending_threaded_animations_
.size() == 0) {
933 cc_layer_
->RemoveAnimation(animation_id
);
937 pending_threaded_animations_
.erase(
938 cc::remove_if(&pending_threaded_animations_
,
939 pending_threaded_animations_
.begin(),
940 pending_threaded_animations_
.end(),
941 HasAnimationId(animation_id
)),
942 pending_threaded_animations_
.end());
945 LayerAnimatorCollection
* Layer::GetLayerAnimatorCollection() {
946 Compositor
* compositor
= GetCompositor();
947 return compositor
? compositor
->layer_animator_collection() : NULL
;
950 void Layer::SendPendingThreadedAnimations() {
951 for (cc::ScopedPtrVector
<cc::Animation
>::iterator it
=
952 pending_threaded_animations_
.begin();
953 it
!= pending_threaded_animations_
.end();
955 cc_layer_
->AddAnimation(pending_threaded_animations_
.take(it
));
957 pending_threaded_animations_
.clear();
959 for (size_t i
= 0; i
< children_
.size(); ++i
)
960 children_
[i
]->SendPendingThreadedAnimations();
963 void Layer::CreateWebLayer() {
964 if (type_
== LAYER_SOLID_COLOR
) {
965 solid_color_layer_
= cc::SolidColorLayer::Create();
966 cc_layer_
= solid_color_layer_
.get();
967 } else if (type_
== LAYER_NINE_PATCH
) {
968 nine_patch_layer_
= cc::NinePatchLayer::Create();
969 cc_layer_
= nine_patch_layer_
.get();
971 if (Layer::UsingPictureLayer())
972 content_layer_
= cc::PictureLayer::Create(this);
974 content_layer_
= cc::ContentLayer::Create(this);
975 cc_layer_
= content_layer_
.get();
977 cc_layer_
->SetTransformOrigin(gfx::Point3F());
978 cc_layer_
->SetContentsOpaque(true);
979 cc_layer_
->SetIsDrawable(type_
!= LAYER_NOT_DRAWN
);
980 cc_layer_
->AddLayerAnimationEventObserver(this);
981 cc_layer_
->SetLayerClient(this);
985 gfx::Transform
Layer::transform() const {
986 return cc_layer_
->transform();
989 void Layer::RecomputeDrawsContentAndUVRect() {
991 gfx::Size
size(bounds_
.size());
992 if (texture_layer_
.get()) {
993 size
.SetToMin(frame_size_in_dip_
);
994 gfx::PointF
uv_top_left(0.f
, 0.f
);
995 gfx::PointF
uv_bottom_right(
996 static_cast<float>(size
.width()) / frame_size_in_dip_
.width(),
997 static_cast<float>(size
.height()) / frame_size_in_dip_
.height());
998 texture_layer_
->SetUV(uv_top_left
, uv_bottom_right
);
999 } else if (delegated_renderer_layer_
.get() || surface_layer_
.get()) {
1000 size
.SetToMin(frame_size_in_dip_
);
1002 cc_layer_
->SetBounds(size
);
1005 void Layer::RecomputePosition() {
1006 cc_layer_
->SetPosition(bounds_
.origin() + subpixel_position_offset_
);
1009 void Layer::AddAnimatorsInTreeToCollection(
1010 LayerAnimatorCollection
* collection
) {
1013 animator_
->AddToCollection(collection
);
1017 std::bind2nd(std::mem_fun(&Layer::AddAnimatorsInTreeToCollection
),
1021 void Layer::RemoveAnimatorsInTreeFromCollection(
1022 LayerAnimatorCollection
* collection
) {
1025 animator_
->RemoveFromCollection(collection
);
1029 std::bind2nd(std::mem_fun(&Layer::RemoveAnimatorsInTreeFromCollection
),
1033 bool Layer::IsAnimating() const {
1034 return animator_
&& animator_
->is_animating();