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