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/picture_layer.h"
18 #include "cc/layers/solid_color_layer.h"
19 #include "cc/layers/texture_layer.h"
20 #include "cc/output/copy_output_request.h"
21 #include "cc/output/delegated_frame_data.h"
22 #include "cc/output/filter_operation.h"
23 #include "cc/output/filter_operations.h"
24 #include "cc/resources/transferable_resource.h"
25 #include "ui/compositor/compositor_switches.h"
26 #include "ui/compositor/dip_util.h"
27 #include "ui/compositor/layer_animator.h"
28 #include "ui/gfx/animation/animation.h"
29 #include "ui/gfx/canvas.h"
30 #include "ui/gfx/display.h"
31 #include "ui/gfx/interpolated_transform.h"
32 #include "ui/gfx/point3_f.h"
33 #include "ui/gfx/point_conversions.h"
34 #include "ui/gfx/size_conversions.h"
38 const ui::Layer
* GetRoot(const ui::Layer
* layer
) {
39 while (layer
->parent())
40 layer
= layer
->parent();
44 struct UIImplSidePaintingStatus
{
45 UIImplSidePaintingStatus()
46 : enabled(ui::IsUIImplSidePaintingEnabled()) {
50 base::LazyInstance
<UIImplSidePaintingStatus
> g_ui_impl_side_painting_status
=
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
;
122 cc_layer_
->RemoveLayerAnimationEventObserver(this);
123 cc_layer_
->RemoveFromParent();
127 bool Layer::UsingPictureLayer() {
128 return g_ui_impl_side_painting_status
.Get().enabled
;
131 Compositor
* Layer::GetCompositor() {
132 return GetRoot(this)->compositor_
;
135 float Layer::opacity() const {
136 return cc_layer_
->opacity();
139 void Layer::SetCompositor(Compositor
* compositor
) {
140 // This function must only be called to set the compositor on the root layer,
142 DCHECK(!compositor
|| !compositor_
);
143 DCHECK(!compositor
|| compositor
->root_layer() == this);
145 compositor_
= compositor
;
147 OnDeviceScaleFactorChanged(compositor
->device_scale_factor());
148 SendPendingThreadedAnimations();
152 void Layer::Add(Layer
* child
) {
153 DCHECK(!child
->compositor_
);
155 child
->parent_
->Remove(child
);
156 child
->parent_
= this;
157 children_
.push_back(child
);
158 cc_layer_
->AddChild(child
->cc_layer_
);
159 child
->OnDeviceScaleFactorChanged(device_scale_factor_
);
161 child
->SendPendingThreadedAnimations();
164 void Layer::Remove(Layer
* child
) {
165 // Current bounds are used to calculate offsets when layers are reparented.
166 // Stop (and complete) an ongoing animation to update the bounds immediately.
167 if (child
->GetAnimator()) {
168 child
->GetAnimator()->StopAnimatingProperty(
169 ui::LayerAnimationElement::BOUNDS
);
171 std::vector
<Layer
*>::iterator i
=
172 std::find(children_
.begin(), children_
.end(), child
);
173 DCHECK(i
!= children_
.end());
175 child
->parent_
= NULL
;
176 child
->cc_layer_
->RemoveFromParent();
179 void Layer::StackAtTop(Layer
* child
) {
180 if (children_
.size() <= 1 || child
== children_
.back())
181 return; // Already in front.
182 StackAbove(child
, children_
.back());
185 void Layer::StackAbove(Layer
* child
, Layer
* other
) {
186 StackRelativeTo(child
, other
, true);
189 void Layer::StackAtBottom(Layer
* child
) {
190 if (children_
.size() <= 1 || child
== children_
.front())
191 return; // Already on bottom.
192 StackBelow(child
, children_
.front());
195 void Layer::StackBelow(Layer
* child
, Layer
* other
) {
196 StackRelativeTo(child
, other
, false);
199 bool Layer::Contains(const Layer
* other
) const {
200 for (const Layer
* parent
= other
; parent
; parent
= parent
->parent()) {
207 void Layer::SetAnimator(LayerAnimator
* animator
) {
209 animator
->SetDelegate(this);
210 animator_
= animator
;
213 LayerAnimator
* Layer::GetAnimator() {
214 if (!animator_
.get())
215 SetAnimator(LayerAnimator::CreateDefaultAnimator());
216 return animator_
.get();
219 void Layer::SetTransform(const gfx::Transform
& transform
) {
220 GetAnimator()->SetTransform(transform
);
223 gfx::Transform
Layer::GetTargetTransform() const {
224 if (animator_
.get() && animator_
->IsAnimatingProperty(
225 LayerAnimationElement::TRANSFORM
)) {
226 return animator_
->GetTargetTransform();
231 void Layer::SetBounds(const gfx::Rect
& bounds
) {
232 GetAnimator()->SetBounds(bounds
);
235 gfx::Rect
Layer::GetTargetBounds() const {
236 if (animator_
.get() && animator_
->IsAnimatingProperty(
237 LayerAnimationElement::BOUNDS
)) {
238 return animator_
->GetTargetBounds();
243 void Layer::SetMasksToBounds(bool masks_to_bounds
) {
244 cc_layer_
->SetMasksToBounds(masks_to_bounds
);
247 bool Layer::GetMasksToBounds() const {
248 return cc_layer_
->masks_to_bounds();
251 void Layer::SetOpacity(float opacity
) {
252 GetAnimator()->SetOpacity(opacity
);
255 float Layer::GetCombinedOpacity() const {
256 float opacity
= this->opacity();
257 Layer
* current
= this->parent_
;
259 opacity
*= current
->opacity();
260 current
= current
->parent_
;
265 void Layer::SetBackgroundBlur(int blur_radius
) {
266 background_blur_radius_
= blur_radius
;
268 SetLayerBackgroundFilters();
271 void Layer::SetLayerSaturation(float saturation
) {
272 layer_saturation_
= saturation
;
276 void Layer::SetLayerBrightness(float brightness
) {
277 GetAnimator()->SetBrightness(brightness
);
280 float Layer::GetTargetBrightness() const {
281 if (animator_
.get() && animator_
->IsAnimatingProperty(
282 LayerAnimationElement::BRIGHTNESS
)) {
283 return animator_
->GetTargetBrightness();
285 return layer_brightness();
288 void Layer::SetLayerGrayscale(float grayscale
) {
289 GetAnimator()->SetGrayscale(grayscale
);
292 float Layer::GetTargetGrayscale() const {
293 if (animator_
.get() && animator_
->IsAnimatingProperty(
294 LayerAnimationElement::GRAYSCALE
)) {
295 return animator_
->GetTargetGrayscale();
297 return layer_grayscale();
300 void Layer::SetLayerInverted(bool inverted
) {
301 layer_inverted_
= inverted
;
305 void Layer::SetMaskLayer(Layer
* layer_mask
) {
306 // The provided mask should not have a layer mask itself.
307 DCHECK(!layer_mask
||
308 (!layer_mask
->layer_mask_layer() &&
309 layer_mask
->children().empty() &&
310 !layer_mask
->layer_mask_back_link_
));
311 DCHECK(!layer_mask_back_link_
);
312 if (layer_mask_
== layer_mask
)
314 // We need to de-reference the currently linked object so that no problem
315 // arises if the mask layer gets deleted before this object.
317 layer_mask_
->layer_mask_back_link_
= NULL
;
318 layer_mask_
= layer_mask
;
319 cc_layer_
->SetMaskLayer(
320 layer_mask
? layer_mask
->cc_layer() : NULL
);
321 // We need to reference the linked object so that it can properly break the
322 // link to us when it gets deleted.
324 layer_mask
->layer_mask_back_link_
= this;
325 layer_mask
->OnDeviceScaleFactorChanged(device_scale_factor_
);
329 void Layer::SetBackgroundZoom(float zoom
, int inset
) {
333 SetLayerBackgroundFilters();
336 void Layer::SetAlphaShape(scoped_ptr
<SkRegion
> region
) {
337 alpha_shape_
= region
.Pass();
342 void Layer::SetLayerFilters() {
343 cc::FilterOperations filters
;
344 if (layer_saturation_
) {
345 filters
.Append(cc::FilterOperation::CreateSaturateFilter(
348 if (layer_grayscale_
) {
349 filters
.Append(cc::FilterOperation::CreateGrayscaleFilter(
353 filters
.Append(cc::FilterOperation::CreateInvertFilter(1.0));
354 // Brightness goes last, because the resulting colors neeed clamping, which
355 // cause further color matrix filters to be applied separately. In this order,
356 // they all can be combined in a single pass.
357 if (layer_brightness_
) {
358 filters
.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter(
362 filters
.Append(cc::FilterOperation::CreateAlphaThresholdFilter(
363 *alpha_shape_
, 1.f
, 0.f
));
366 cc_layer_
->SetFilters(filters
);
369 void Layer::SetLayerBackgroundFilters() {
370 cc::FilterOperations filters
;
372 filters
.Append(cc::FilterOperation::CreateZoomFilter(zoom_
, zoom_inset_
));
374 if (background_blur_radius_
) {
375 filters
.Append(cc::FilterOperation::CreateBlurFilter(
376 background_blur_radius_
));
379 cc_layer_
->SetBackgroundFilters(filters
);
382 float Layer::GetTargetOpacity() const {
383 if (animator_
.get() && animator_
->IsAnimatingProperty(
384 LayerAnimationElement::OPACITY
))
385 return animator_
->GetTargetOpacity();
389 void Layer::SetVisible(bool visible
) {
390 GetAnimator()->SetVisibility(visible
);
393 bool Layer::GetTargetVisibility() const {
394 if (animator_
.get() && animator_
->IsAnimatingProperty(
395 LayerAnimationElement::VISIBILITY
))
396 return animator_
->GetTargetVisibility();
400 bool Layer::IsDrawn() const {
401 const Layer
* layer
= this;
402 while (layer
&& layer
->visible_
)
403 layer
= layer
->parent_
;
404 return layer
== NULL
;
407 bool Layer::ShouldDraw() const {
408 return type_
!= LAYER_NOT_DRAWN
&& GetCombinedOpacity() > 0.0f
;
412 void Layer::ConvertPointToLayer(const Layer
* source
,
415 if (source
== target
)
418 const Layer
* root_layer
= GetRoot(source
);
419 CHECK_EQ(root_layer
, GetRoot(target
));
421 if (source
!= root_layer
)
422 source
->ConvertPointForAncestor(root_layer
, point
);
423 if (target
!= root_layer
)
424 target
->ConvertPointFromAncestor(root_layer
, point
);
427 bool Layer::GetTargetTransformRelativeTo(const Layer
* ancestor
,
428 gfx::Transform
* transform
) const {
429 const Layer
* p
= this;
430 for (; p
&& p
!= ancestor
; p
= p
->parent()) {
431 gfx::Transform translation
;
432 translation
.Translate(static_cast<float>(p
->bounds().x()),
433 static_cast<float>(p
->bounds().y()));
434 // Use target transform so that result will be correct once animation is
436 if (!p
->GetTargetTransform().IsIdentity())
437 transform
->ConcatTransform(p
->GetTargetTransform());
438 transform
->ConcatTransform(translation
);
440 return p
== ancestor
;
443 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely
) {
444 if (fills_bounds_opaquely_
== fills_bounds_opaquely
)
447 fills_bounds_opaquely_
= fills_bounds_opaquely
;
449 cc_layer_
->SetContentsOpaque(fills_bounds_opaquely
);
452 void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely
) {
453 fills_bounds_completely_
= fills_bounds_completely
;
456 void Layer::SwitchToLayer(scoped_refptr
<cc::Layer
> new_layer
) {
457 // Finish animations being handled by cc_layer_.
458 if (animator_
.get()) {
459 animator_
->StopAnimatingProperty(LayerAnimationElement::TRANSFORM
);
460 animator_
->StopAnimatingProperty(LayerAnimationElement::OPACITY
);
463 if (texture_layer_
.get())
464 texture_layer_
->ClearClient();
465 // TODO(piman): delegated_renderer_layer_ cleanup.
467 cc_layer_
->RemoveAllChildren();
468 if (cc_layer_
->parent()) {
469 cc_layer_
->parent()->ReplaceChild(cc_layer_
, new_layer
);
471 cc_layer_
->SetLayerClient(NULL
);
472 cc_layer_
->RemoveLayerAnimationEventObserver(this);
473 new_layer
->SetOpacity(cc_layer_
->opacity());
474 new_layer
->SetTransform(cc_layer_
->transform());
475 new_layer
->SetPosition(cc_layer_
->position());
477 cc_layer_
= new_layer
.get();
478 content_layer_
= NULL
;
479 solid_color_layer_
= NULL
;
480 texture_layer_
= NULL
;
481 delegated_renderer_layer_
= NULL
;
483 cc_layer_
->AddLayerAnimationEventObserver(this);
484 for (size_t i
= 0; i
< children_
.size(); ++i
) {
485 DCHECK(children_
[i
]->cc_layer_
);
486 cc_layer_
->AddChild(children_
[i
]->cc_layer_
);
488 cc_layer_
->SetLayerClient(this);
489 cc_layer_
->SetAnchorPoint(gfx::PointF());
490 cc_layer_
->SetContentsOpaque(fills_bounds_opaquely_
);
491 cc_layer_
->SetForceRenderSurface(force_render_surface_
);
492 cc_layer_
->SetIsDrawable(type_
!= LAYER_NOT_DRAWN
);
493 cc_layer_
->SetHideLayerAndSubtree(!visible_
);
496 void Layer::SwitchCCLayerForTest() {
497 scoped_refptr
<cc::Layer
> new_layer
;
498 if (Layer::UsingPictureLayer())
499 new_layer
= cc::PictureLayer::Create(this);
501 new_layer
= cc::ContentLayer::Create(this);
502 SwitchToLayer(new_layer
);
503 content_layer_
= new_layer
;
506 void Layer::SetTextureMailbox(
507 const cc::TextureMailbox
& mailbox
,
508 scoped_ptr
<cc::SingleReleaseCallback
> release_callback
,
509 gfx::Size texture_size_in_dip
) {
510 DCHECK_EQ(type_
, LAYER_TEXTURED
);
511 DCHECK(!solid_color_layer_
.get());
512 DCHECK(mailbox
.IsValid());
513 DCHECK(release_callback
);
514 if (!texture_layer_
) {
515 scoped_refptr
<cc::TextureLayer
> new_layer
=
516 cc::TextureLayer::CreateForMailbox(this);
517 new_layer
->SetFlipped(true);
518 SwitchToLayer(new_layer
);
519 texture_layer_
= new_layer
;
521 if (mailbox_release_callback_
)
522 mailbox_release_callback_
->Run(0, false);
523 mailbox_release_callback_
= release_callback
.Pass();
525 SetTextureSize(texture_size_in_dip
);
528 void Layer::SetTextureSize(gfx::Size texture_size_in_dip
) {
529 DCHECK(texture_layer_
.get());
530 if (frame_size_in_dip_
== texture_size_in_dip
)
532 frame_size_in_dip_
= texture_size_in_dip
;
533 RecomputeDrawsContentAndUVRect();
534 texture_layer_
->SetNeedsDisplay();
537 void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider
* frame_provider
,
538 gfx::Size frame_size_in_dip
) {
539 DCHECK_EQ(type_
, LAYER_TEXTURED
);
541 scoped_refptr
<cc::DelegatedRendererLayer
> new_layer
=
542 cc::DelegatedRendererLayer::Create(frame_provider
);
543 SwitchToLayer(new_layer
);
544 delegated_renderer_layer_
= new_layer
;
546 frame_size_in_dip_
= frame_size_in_dip
;
547 RecomputeDrawsContentAndUVRect();
550 void Layer::SetShowPaintedContent() {
551 if (content_layer_
.get())
554 scoped_refptr
<cc::Layer
> new_layer
;
555 if (Layer::UsingPictureLayer())
556 new_layer
= cc::PictureLayer::Create(this);
558 new_layer
= cc::ContentLayer::Create(this);
559 SwitchToLayer(new_layer
);
560 content_layer_
= new_layer
;
562 mailbox_
= cc::TextureMailbox();
563 if (mailbox_release_callback_
) {
564 mailbox_release_callback_
->Run(0, false);
565 mailbox_release_callback_
.reset();
567 RecomputeDrawsContentAndUVRect();
570 void Layer::SetColor(SkColor color
) { GetAnimator()->SetColor(color
); }
572 bool Layer::SchedulePaint(const gfx::Rect
& invalid_rect
) {
573 if (type_
== LAYER_SOLID_COLOR
|| (!delegate_
&& !mailbox_
.IsValid()))
576 damaged_region_
.op(invalid_rect
.x(),
578 invalid_rect
.right(),
579 invalid_rect
.bottom(),
580 SkRegion::kUnion_Op
);
585 void Layer::ScheduleDraw() {
586 Compositor
* compositor
= GetCompositor();
588 compositor
->ScheduleDraw();
591 void Layer::SendDamagedRects() {
592 if ((delegate_
|| mailbox_
.IsValid()) && !damaged_region_
.isEmpty()) {
593 for (SkRegion::Iterator
iter(damaged_region_
); !iter
.done(); iter
.next()) {
594 const SkIRect
& sk_damaged
= iter
.rect();
599 sk_damaged
.height());
600 cc_layer_
->SetNeedsDisplayRect(damaged
);
602 damaged_region_
.setEmpty();
604 for (size_t i
= 0; i
< children_
.size(); ++i
)
605 children_
[i
]->SendDamagedRects();
608 void Layer::SuppressPaint() {
612 for (size_t i
= 0; i
< children_
.size(); ++i
)
613 children_
[i
]->SuppressPaint();
616 void Layer::OnDeviceScaleFactorChanged(float device_scale_factor
) {
617 if (device_scale_factor_
== device_scale_factor
)
620 animator_
->StopAnimatingProperty(LayerAnimationElement::TRANSFORM
);
621 device_scale_factor_
= device_scale_factor
;
622 RecomputeDrawsContentAndUVRect();
624 SchedulePaint(gfx::Rect(bounds_
.size()));
626 delegate_
->OnDeviceScaleFactorChanged(device_scale_factor
);
627 for (size_t i
= 0; i
< children_
.size(); ++i
)
628 children_
[i
]->OnDeviceScaleFactorChanged(device_scale_factor
);
630 layer_mask_
->OnDeviceScaleFactorChanged(device_scale_factor
);
633 void Layer::RequestCopyOfOutput(scoped_ptr
<cc::CopyOutputRequest
> request
) {
634 cc_layer_
->RequestCopyOfOutput(request
.Pass());
637 void Layer::PaintContents(SkCanvas
* sk_canvas
,
638 const gfx::Rect
& clip
,
640 ContentLayerClient::GraphicsContextStatus gc_status
) {
641 TRACE_EVENT0("ui", "Layer::PaintContents");
642 scoped_ptr
<gfx::Canvas
> canvas(gfx::Canvas::CreateCanvasWithoutScaling(
643 sk_canvas
, device_scale_factor_
));
645 delegate_
->OnPaintLayer(canvas
.get());
648 bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_
; }
650 bool Layer::PrepareTextureMailbox(
651 cc::TextureMailbox
* mailbox
,
652 scoped_ptr
<cc::SingleReleaseCallback
>* release_callback
,
653 bool use_shared_memory
) {
654 if (!mailbox_release_callback_
)
657 *release_callback
= mailbox_release_callback_
.Pass();
661 void Layer::SetForceRenderSurface(bool force
) {
662 if (force_render_surface_
== force
)
665 force_render_surface_
= force
;
666 cc_layer_
->SetForceRenderSurface(force_render_surface_
);
669 class LayerDebugInfo
: public base::debug::ConvertableToTraceFormat
{
671 explicit LayerDebugInfo(std::string name
) : name_(name
) { }
672 virtual void AppendAsTraceFormat(std::string
* out
) const OVERRIDE
{
673 base::DictionaryValue dictionary
;
674 dictionary
.SetString("layer_name", name_
);
675 base::JSONWriter::Write(&dictionary
, out
);
679 virtual ~LayerDebugInfo() { }
683 scoped_refptr
<base::debug::ConvertableToTraceFormat
> Layer::TakeDebugInfo() {
684 return new LayerDebugInfo(name_
);
687 void Layer::OnAnimationStarted(const cc::AnimationEvent
& event
) {
689 animator_
->OnThreadedAnimationStarted(event
);
692 void Layer::StackRelativeTo(Layer
* child
, Layer
* other
, bool above
) {
693 DCHECK_NE(child
, other
);
694 DCHECK_EQ(this, child
->parent());
695 DCHECK_EQ(this, other
->parent());
697 const size_t child_i
=
698 std::find(children_
.begin(), children_
.end(), child
) - children_
.begin();
699 const size_t other_i
=
700 std::find(children_
.begin(), children_
.end(), other
) - children_
.begin();
701 if ((above
&& child_i
== other_i
+ 1) || (!above
&& child_i
+ 1 == other_i
))
704 const size_t dest_i
=
706 (child_i
< other_i
? other_i
: other_i
+ 1) :
707 (child_i
< other_i
? other_i
- 1 : other_i
);
708 children_
.erase(children_
.begin() + child_i
);
709 children_
.insert(children_
.begin() + dest_i
, child
);
711 child
->cc_layer_
->RemoveFromParent();
712 cc_layer_
->InsertChild(child
->cc_layer_
, dest_i
);
715 bool Layer::ConvertPointForAncestor(const Layer
* ancestor
,
716 gfx::Point
* point
) const {
717 gfx::Transform transform
;
718 bool result
= GetTargetTransformRelativeTo(ancestor
, &transform
);
719 gfx::Point3F
p(*point
);
720 transform
.TransformPoint(&p
);
721 *point
= gfx::ToFlooredPoint(p
.AsPointF());
725 bool Layer::ConvertPointFromAncestor(const Layer
* ancestor
,
726 gfx::Point
* point
) const {
727 gfx::Transform transform
;
728 bool result
= GetTargetTransformRelativeTo(ancestor
, &transform
);
729 gfx::Point3F
p(*point
);
730 transform
.TransformPointReverse(&p
);
731 *point
= gfx::ToFlooredPoint(p
.AsPointF());
735 void Layer::SetBoundsFromAnimation(const gfx::Rect
& bounds
) {
736 if (bounds
== bounds_
)
739 base::Closure closure
;
741 closure
= delegate_
->PrepareForLayerBoundsChange();
742 bool was_move
= bounds_
.size() == bounds
.size();
745 RecomputeDrawsContentAndUVRect();
748 if (!closure
.is_null())
752 // Don't schedule a draw if we're invisible. We'll schedule one
753 // automatically when we get visible.
757 // Always schedule a paint, even if we're invisible.
758 SchedulePaint(gfx::Rect(bounds
.size()));
762 void Layer::SetTransformFromAnimation(const gfx::Transform
& transform
) {
763 cc_layer_
->SetTransform(transform
);
766 void Layer::SetOpacityFromAnimation(float opacity
) {
767 cc_layer_
->SetOpacity(opacity
);
771 void Layer::SetVisibilityFromAnimation(bool visible
) {
772 if (visible_
== visible
)
776 cc_layer_
->SetHideLayerAndSubtree(!visible_
);
779 void Layer::SetBrightnessFromAnimation(float brightness
) {
780 layer_brightness_
= brightness
;
784 void Layer::SetGrayscaleFromAnimation(float grayscale
) {
785 layer_grayscale_
= grayscale
;
789 void Layer::SetColorFromAnimation(SkColor color
) {
790 DCHECK_EQ(type_
, LAYER_SOLID_COLOR
);
791 solid_color_layer_
->SetBackgroundColor(color
);
792 SetFillsBoundsOpaquely(SkColorGetA(color
) == 0xFF);
795 void Layer::ScheduleDrawForAnimation() {
799 const gfx::Rect
& Layer::GetBoundsForAnimation() const {
803 gfx::Transform
Layer::GetTransformForAnimation() const {
807 float Layer::GetOpacityForAnimation() const {
811 bool Layer::GetVisibilityForAnimation() const {
815 float Layer::GetBrightnessForAnimation() const {
816 return layer_brightness();
819 float Layer::GetGrayscaleForAnimation() const {
820 return layer_grayscale();
823 SkColor
Layer::GetColorForAnimation() const {
824 // WebColor is equivalent to SkColor, per WebColor.h.
825 // The NULL check is here since this is invoked regardless of whether we have
826 // been configured as LAYER_SOLID_COLOR.
827 return solid_color_layer_
.get() ?
828 solid_color_layer_
->background_color() : SK_ColorBLACK
;
831 float Layer::GetDeviceScaleFactor() const {
832 return device_scale_factor_
;
835 void Layer::AddThreadedAnimation(scoped_ptr
<cc::Animation
> animation
) {
837 // Until this layer has a compositor (and hence cc_layer_ has a
838 // LayerTreeHost), addAnimation will fail.
840 cc_layer_
->AddAnimation(animation
.Pass());
842 pending_threaded_animations_
.push_back(animation
.Pass());
847 struct HasAnimationId
{
848 HasAnimationId(int id
): id_(id
) {
851 bool operator()(cc::Animation
* animation
) const {
852 return animation
->id() == id_
;
861 void Layer::RemoveThreadedAnimation(int animation_id
) {
863 if (pending_threaded_animations_
.size() == 0) {
864 cc_layer_
->RemoveAnimation(animation_id
);
868 pending_threaded_animations_
.erase(
869 cc::remove_if(&pending_threaded_animations_
,
870 pending_threaded_animations_
.begin(),
871 pending_threaded_animations_
.end(),
872 HasAnimationId(animation_id
)),
873 pending_threaded_animations_
.end());
876 void Layer::SendPendingThreadedAnimations() {
877 for (cc::ScopedPtrVector
<cc::Animation
>::iterator it
=
878 pending_threaded_animations_
.begin();
879 it
!= pending_threaded_animations_
.end();
881 cc_layer_
->AddAnimation(pending_threaded_animations_
.take(it
));
883 pending_threaded_animations_
.clear();
885 for (size_t i
= 0; i
< children_
.size(); ++i
)
886 children_
[i
]->SendPendingThreadedAnimations();
889 void Layer::CreateWebLayer() {
890 if (type_
== LAYER_SOLID_COLOR
) {
891 solid_color_layer_
= cc::SolidColorLayer::Create();
892 cc_layer_
= solid_color_layer_
.get();
894 if (Layer::UsingPictureLayer())
895 content_layer_
= cc::PictureLayer::Create(this);
897 content_layer_
= cc::ContentLayer::Create(this);
898 cc_layer_
= content_layer_
.get();
900 cc_layer_
->SetAnchorPoint(gfx::PointF());
901 cc_layer_
->SetContentsOpaque(true);
902 cc_layer_
->SetIsDrawable(type_
!= LAYER_NOT_DRAWN
);
903 cc_layer_
->AddLayerAnimationEventObserver(this);
904 cc_layer_
->SetLayerClient(this);
908 gfx::Transform
Layer::transform() const {
909 return cc_layer_
->transform();
912 void Layer::RecomputeDrawsContentAndUVRect() {
914 gfx::Size
size(bounds_
.size());
915 if (texture_layer_
.get()) {
916 size
.SetToMin(frame_size_in_dip_
);
917 gfx::PointF
uv_top_left(0.f
, 0.f
);
918 gfx::PointF
uv_bottom_right(
919 static_cast<float>(size
.width()) / frame_size_in_dip_
.width(),
920 static_cast<float>(size
.height()) / frame_size_in_dip_
.height());
921 texture_layer_
->SetUV(uv_top_left
, uv_bottom_right
);
922 } else if (delegated_renderer_layer_
.get()) {
923 size
.SetToMin(frame_size_in_dip_
);
924 delegated_renderer_layer_
->SetDisplaySize(frame_size_in_dip_
);
926 cc_layer_
->SetBounds(size
);
929 void Layer::RecomputePosition() {
930 cc_layer_
->SetPosition(gfx::PointF(bounds_
.x(), bounds_
.y()));