Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / cc / layers / layer.cc
blob938449cb968e2e57ac3e792c1c4d9d6ddd1c548b
1 // Copyright 2010 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 "cc/layers/layer.h"
7 #include <algorithm>
9 #include "base/atomic_sequence_num.h"
10 #include "base/location.h"
11 #include "base/metrics/histogram.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/time/time.h"
14 #include "base/trace_event/trace_event.h"
15 #include "cc/animation/animation.h"
16 #include "cc/animation/animation_events.h"
17 #include "cc/animation/animation_registrar.h"
18 #include "cc/animation/keyframed_animation_curve.h"
19 #include "cc/animation/layer_animation_controller.h"
20 #include "cc/base/simple_enclosed_region.h"
21 #include "cc/debug/frame_viewer_instrumentation.h"
22 #include "cc/layers/layer_client.h"
23 #include "cc/layers/layer_impl.h"
24 #include "cc/layers/scrollbar_layer_interface.h"
25 #include "cc/output/copy_output_request.h"
26 #include "cc/output/copy_output_result.h"
27 #include "cc/trees/layer_tree_host.h"
28 #include "cc/trees/layer_tree_impl.h"
29 #include "third_party/skia/include/core/SkImageFilter.h"
30 #include "ui/gfx/geometry/rect_conversions.h"
31 #include "ui/gfx/geometry/vector2d_conversions.h"
33 namespace cc {
35 base::StaticAtomicSequenceNumber g_next_layer_id;
37 scoped_refptr<Layer> Layer::Create() {
38 return make_scoped_refptr(new Layer());
41 Layer::Layer()
42 : needs_push_properties_(false),
43 num_dependents_need_push_properties_(false),
44 stacking_order_changed_(false),
45 // Layer IDs start from 1.
46 layer_id_(g_next_layer_id.GetNext() + 1),
47 ignore_set_needs_commit_(false),
48 sorting_context_id_(0),
49 parent_(nullptr),
50 layer_tree_host_(nullptr),
51 scroll_clip_layer_id_(INVALID_ID),
52 num_descendants_that_draw_content_(0),
53 transform_tree_index_(-1),
54 opacity_tree_index_(-1),
55 clip_tree_index_(-1),
56 should_flatten_transform_from_property_tree_(false),
57 should_scroll_on_main_thread_(false),
58 have_wheel_event_handlers_(false),
59 have_scroll_event_handlers_(false),
60 user_scrollable_horizontal_(true),
61 user_scrollable_vertical_(true),
62 is_root_for_isolated_group_(false),
63 is_container_for_fixed_position_layers_(false),
64 is_drawable_(false),
65 draws_content_(false),
66 hide_layer_and_subtree_(false),
67 masks_to_bounds_(false),
68 contents_opaque_(false),
69 double_sided_(true),
70 should_flatten_transform_(true),
71 use_parent_backface_visibility_(false),
72 draw_checkerboard_for_missing_tiles_(false),
73 force_render_surface_(false),
74 transform_is_invertible_(true),
75 has_render_surface_(false),
76 scroll_blocks_on_(SCROLL_BLOCKS_ON_NONE),
77 background_color_(0),
78 opacity_(1.f),
79 blend_mode_(SkXfermode::kSrcOver_Mode),
80 scroll_parent_(nullptr),
81 clip_parent_(nullptr),
82 replica_layer_(nullptr),
83 raster_scale_(0.f),
84 client_(nullptr),
85 frame_timing_requests_dirty_(false) {
86 layer_animation_controller_ = LayerAnimationController::Create(layer_id_);
87 layer_animation_controller_->AddValueObserver(this);
88 layer_animation_controller_->set_value_provider(this);
91 Layer::~Layer() {
92 // Our parent should be holding a reference to us so there should be no
93 // way for us to be destroyed while we still have a parent.
94 DCHECK(!parent());
95 // Similarly we shouldn't have a layer tree host since it also keeps a
96 // reference to us.
97 DCHECK(!layer_tree_host());
99 layer_animation_controller_->RemoveValueObserver(this);
100 layer_animation_controller_->remove_value_provider(this);
102 RemoveFromScrollTree();
103 RemoveFromClipTree();
105 // Remove the parent reference from all children and dependents.
106 RemoveAllChildren();
107 if (mask_layer_.get()) {
108 DCHECK_EQ(this, mask_layer_->parent());
109 mask_layer_->RemoveFromParent();
111 if (replica_layer_.get()) {
112 DCHECK_EQ(this, replica_layer_->parent());
113 replica_layer_->RemoveFromParent();
117 void Layer::SetLayerTreeHost(LayerTreeHost* host) {
118 if (layer_tree_host_ == host)
119 return;
121 layer_tree_host_ = host;
123 // When changing hosts, the layer needs to commit its properties to the impl
124 // side for the new host.
125 SetNeedsPushProperties();
127 for (size_t i = 0; i < children_.size(); ++i)
128 children_[i]->SetLayerTreeHost(host);
130 if (mask_layer_.get())
131 mask_layer_->SetLayerTreeHost(host);
132 if (replica_layer_.get())
133 replica_layer_->SetLayerTreeHost(host);
135 if (host) {
136 layer_animation_controller_->SetAnimationRegistrar(
137 host->animation_registrar());
139 if (host->settings().layer_transforms_should_scale_layer_contents)
140 reset_raster_scale_to_unknown();
143 if (host && layer_animation_controller_->has_any_animation())
144 host->SetNeedsCommit();
147 void Layer::SetNeedsUpdate() {
148 if (layer_tree_host_ && !ignore_set_needs_commit_)
149 layer_tree_host_->SetNeedsUpdateLayers();
152 void Layer::SetNeedsCommit() {
153 if (!layer_tree_host_)
154 return;
156 SetNeedsPushProperties();
158 if (ignore_set_needs_commit_)
159 return;
161 layer_tree_host_->SetNeedsCommit();
164 void Layer::SetNeedsFullTreeSync() {
165 if (!layer_tree_host_)
166 return;
168 layer_tree_host_->SetNeedsFullTreeSync();
171 void Layer::SetNextCommitWaitsForActivation() {
172 if (!layer_tree_host_)
173 return;
175 layer_tree_host_->SetNextCommitWaitsForActivation();
178 void Layer::SetNeedsPushProperties() {
179 if (needs_push_properties_)
180 return;
181 if (!parent_should_know_need_push_properties() && parent_)
182 parent_->AddDependentNeedsPushProperties();
183 needs_push_properties_ = true;
186 void Layer::AddDependentNeedsPushProperties() {
187 DCHECK_GE(num_dependents_need_push_properties_, 0);
189 if (!parent_should_know_need_push_properties() && parent_)
190 parent_->AddDependentNeedsPushProperties();
192 num_dependents_need_push_properties_++;
195 void Layer::RemoveDependentNeedsPushProperties() {
196 num_dependents_need_push_properties_--;
197 DCHECK_GE(num_dependents_need_push_properties_, 0);
199 if (!parent_should_know_need_push_properties() && parent_)
200 parent_->RemoveDependentNeedsPushProperties();
203 bool Layer::IsPropertyChangeAllowed() const {
204 if (!layer_tree_host_)
205 return true;
207 if (!layer_tree_host_->settings().strict_layer_property_change_checking)
208 return true;
210 return !layer_tree_host_->in_paint_layer_contents();
213 gfx::Rect Layer::LayerRectToContentRect(const gfx::Rect& layer_rect) const {
214 gfx::Rect content_rect = gfx::ScaleToEnclosingRect(
215 layer_rect, contents_scale_x(), contents_scale_y());
216 // Intersect with content rect to avoid the extra pixel because for some
217 // values x and y, ceil((x / y) * y) may be x + 1.
218 content_rect.Intersect(gfx::Rect(content_bounds()));
219 return content_rect;
222 skia::RefPtr<SkPicture> Layer::GetPicture() const {
223 return skia::RefPtr<SkPicture>();
226 void Layer::SetParent(Layer* layer) {
227 DCHECK(!layer || !layer->HasAncestor(this));
229 if (parent_should_know_need_push_properties()) {
230 if (parent_)
231 parent_->RemoveDependentNeedsPushProperties();
232 if (layer)
233 layer->AddDependentNeedsPushProperties();
236 parent_ = layer;
237 SetLayerTreeHost(parent_ ? parent_->layer_tree_host() : nullptr);
239 if (!layer_tree_host_)
240 return;
241 const LayerTreeSettings& settings = layer_tree_host_->settings();
242 if (!settings.layer_transforms_should_scale_layer_contents)
243 return;
245 reset_raster_scale_to_unknown();
246 if (mask_layer_.get())
247 mask_layer_->reset_raster_scale_to_unknown();
248 if (replica_layer_.get() && replica_layer_->mask_layer_.get())
249 replica_layer_->mask_layer_->reset_raster_scale_to_unknown();
252 void Layer::AddChild(scoped_refptr<Layer> child) {
253 InsertChild(child, children_.size());
256 void Layer::InsertChild(scoped_refptr<Layer> child, size_t index) {
257 DCHECK(IsPropertyChangeAllowed());
258 child->RemoveFromParent();
259 AddDrawableDescendants(child->NumDescendantsThatDrawContent() +
260 (child->DrawsContent() ? 1 : 0));
261 child->SetParent(this);
262 child->stacking_order_changed_ = true;
264 index = std::min(index, children_.size());
265 children_.insert(children_.begin() + index, child);
266 SetNeedsFullTreeSync();
269 void Layer::RemoveFromParent() {
270 DCHECK(IsPropertyChangeAllowed());
271 if (parent_)
272 parent_->RemoveChildOrDependent(this);
275 void Layer::RemoveChildOrDependent(Layer* child) {
276 if (mask_layer_.get() == child) {
277 mask_layer_->SetParent(nullptr);
278 mask_layer_ = nullptr;
279 SetNeedsFullTreeSync();
280 return;
282 if (replica_layer_.get() == child) {
283 replica_layer_->SetParent(nullptr);
284 replica_layer_ = nullptr;
285 SetNeedsFullTreeSync();
286 return;
289 for (LayerList::iterator iter = children_.begin();
290 iter != children_.end();
291 ++iter) {
292 if (iter->get() != child)
293 continue;
295 child->SetParent(nullptr);
296 AddDrawableDescendants(-child->NumDescendantsThatDrawContent() -
297 (child->DrawsContent() ? 1 : 0));
298 children_.erase(iter);
299 SetNeedsFullTreeSync();
300 return;
304 void Layer::ReplaceChild(Layer* reference, scoped_refptr<Layer> new_layer) {
305 DCHECK(reference);
306 DCHECK_EQ(reference->parent(), this);
307 DCHECK(IsPropertyChangeAllowed());
309 if (reference == new_layer.get())
310 return;
312 int reference_index = IndexOfChild(reference);
313 if (reference_index == -1) {
314 NOTREACHED();
315 return;
318 reference->RemoveFromParent();
320 if (new_layer.get()) {
321 new_layer->RemoveFromParent();
322 InsertChild(new_layer, reference_index);
326 int Layer::IndexOfChild(const Layer* reference) {
327 for (size_t i = 0; i < children_.size(); ++i) {
328 if (children_[i].get() == reference)
329 return i;
331 return -1;
334 void Layer::SetBounds(const gfx::Size& size) {
335 DCHECK(IsPropertyChangeAllowed());
336 if (bounds() == size)
337 return;
339 bounds_ = size;
340 SetNeedsCommit();
343 Layer* Layer::RootLayer() {
344 Layer* layer = this;
345 while (layer->parent())
346 layer = layer->parent();
347 return layer;
350 void Layer::RemoveAllChildren() {
351 DCHECK(IsPropertyChangeAllowed());
352 while (children_.size()) {
353 Layer* layer = children_[0].get();
354 DCHECK_EQ(this, layer->parent());
355 layer->RemoveFromParent();
359 void Layer::SetChildren(const LayerList& children) {
360 DCHECK(IsPropertyChangeAllowed());
361 if (children == children_)
362 return;
364 RemoveAllChildren();
365 for (size_t i = 0; i < children.size(); ++i)
366 AddChild(children[i]);
369 bool Layer::HasAncestor(const Layer* ancestor) const {
370 for (const Layer* layer = parent(); layer; layer = layer->parent()) {
371 if (layer == ancestor)
372 return true;
374 return false;
377 void Layer::RequestCopyOfOutput(
378 scoped_ptr<CopyOutputRequest> request) {
379 DCHECK(IsPropertyChangeAllowed());
380 if (void* source = request->source()) {
381 auto it = std::find_if(
382 copy_requests_.begin(), copy_requests_.end(),
383 [source](const CopyOutputRequest* x) { return x->source() == source; });
384 if (it != copy_requests_.end())
385 copy_requests_.erase(it);
387 if (request->IsEmpty())
388 return;
389 copy_requests_.push_back(request.Pass());
390 SetNeedsCommit();
393 void Layer::SetBackgroundColor(SkColor background_color) {
394 DCHECK(IsPropertyChangeAllowed());
395 if (background_color_ == background_color)
396 return;
397 background_color_ = background_color;
398 SetNeedsCommit();
401 SkColor Layer::SafeOpaqueBackgroundColor() const {
402 SkColor color = background_color();
403 if (SkColorGetA(color) == 255 && !contents_opaque()) {
404 color = SK_ColorTRANSPARENT;
405 } else if (SkColorGetA(color) != 255 && contents_opaque()) {
406 for (const Layer* layer = parent(); layer;
407 layer = layer->parent()) {
408 color = layer->background_color();
409 if (SkColorGetA(color) == 255)
410 break;
412 if (SkColorGetA(color) != 255)
413 color = layer_tree_host_->background_color();
414 if (SkColorGetA(color) != 255)
415 color = SkColorSetA(color, 255);
417 return color;
420 void Layer::CalculateContentsScale(float ideal_contents_scale,
421 float* contents_scale_x,
422 float* contents_scale_y,
423 gfx::Size* content_bounds) {
424 DCHECK(layer_tree_host_);
426 *contents_scale_x = 1;
427 *contents_scale_y = 1;
428 *content_bounds = bounds();
431 void Layer::SetMasksToBounds(bool masks_to_bounds) {
432 DCHECK(IsPropertyChangeAllowed());
433 if (masks_to_bounds_ == masks_to_bounds)
434 return;
435 masks_to_bounds_ = masks_to_bounds;
436 SetNeedsCommit();
439 void Layer::SetMaskLayer(Layer* mask_layer) {
440 DCHECK(IsPropertyChangeAllowed());
441 if (mask_layer_.get() == mask_layer)
442 return;
443 if (mask_layer_.get()) {
444 DCHECK_EQ(this, mask_layer_->parent());
445 mask_layer_->RemoveFromParent();
447 mask_layer_ = mask_layer;
448 if (mask_layer_.get()) {
449 DCHECK(!mask_layer_->parent());
450 mask_layer_->RemoveFromParent();
451 mask_layer_->SetParent(this);
452 mask_layer_->SetIsMask(true);
454 SetNeedsFullTreeSync();
457 void Layer::SetReplicaLayer(Layer* layer) {
458 DCHECK(IsPropertyChangeAllowed());
459 if (replica_layer_.get() == layer)
460 return;
461 if (replica_layer_.get()) {
462 DCHECK_EQ(this, replica_layer_->parent());
463 replica_layer_->RemoveFromParent();
465 replica_layer_ = layer;
466 if (replica_layer_.get()) {
467 DCHECK(!replica_layer_->parent());
468 replica_layer_->RemoveFromParent();
469 replica_layer_->SetParent(this);
471 SetNeedsFullTreeSync();
474 void Layer::SetFilters(const FilterOperations& filters) {
475 DCHECK(IsPropertyChangeAllowed());
476 if (filters_ == filters)
477 return;
478 filters_ = filters;
479 SetNeedsCommit();
482 bool Layer::FilterIsAnimating() const {
483 return layer_animation_controller_->IsAnimatingProperty(Animation::FILTER);
486 void Layer::SetBackgroundFilters(const FilterOperations& filters) {
487 DCHECK(IsPropertyChangeAllowed());
488 if (background_filters_ == filters)
489 return;
490 background_filters_ = filters;
491 SetNeedsCommit();
494 void Layer::SetOpacity(float opacity) {
495 DCHECK(IsPropertyChangeAllowed());
496 if (opacity_ == opacity)
497 return;
498 opacity_ = opacity;
499 SetNeedsCommit();
502 bool Layer::OpacityIsAnimating() const {
503 return layer_animation_controller_->IsAnimatingProperty(Animation::OPACITY);
506 bool Layer::OpacityCanAnimateOnImplThread() const {
507 return false;
510 void Layer::SetBlendMode(SkXfermode::Mode blend_mode) {
511 DCHECK(IsPropertyChangeAllowed());
512 if (blend_mode_ == blend_mode)
513 return;
515 // Allowing only blend modes that are defined in the CSS Compositing standard:
516 // http://dev.w3.org/fxtf/compositing-1/#blending
517 switch (blend_mode) {
518 case SkXfermode::kSrcOver_Mode:
519 case SkXfermode::kScreen_Mode:
520 case SkXfermode::kOverlay_Mode:
521 case SkXfermode::kDarken_Mode:
522 case SkXfermode::kLighten_Mode:
523 case SkXfermode::kColorDodge_Mode:
524 case SkXfermode::kColorBurn_Mode:
525 case SkXfermode::kHardLight_Mode:
526 case SkXfermode::kSoftLight_Mode:
527 case SkXfermode::kDifference_Mode:
528 case SkXfermode::kExclusion_Mode:
529 case SkXfermode::kMultiply_Mode:
530 case SkXfermode::kHue_Mode:
531 case SkXfermode::kSaturation_Mode:
532 case SkXfermode::kColor_Mode:
533 case SkXfermode::kLuminosity_Mode:
534 // supported blend modes
535 break;
536 case SkXfermode::kClear_Mode:
537 case SkXfermode::kSrc_Mode:
538 case SkXfermode::kDst_Mode:
539 case SkXfermode::kDstOver_Mode:
540 case SkXfermode::kSrcIn_Mode:
541 case SkXfermode::kDstIn_Mode:
542 case SkXfermode::kSrcOut_Mode:
543 case SkXfermode::kDstOut_Mode:
544 case SkXfermode::kSrcATop_Mode:
545 case SkXfermode::kDstATop_Mode:
546 case SkXfermode::kXor_Mode:
547 case SkXfermode::kPlus_Mode:
548 case SkXfermode::kModulate_Mode:
549 // Porter Duff Compositing Operators are not yet supported
550 // http://dev.w3.org/fxtf/compositing-1/#porterduffcompositingoperators
551 NOTREACHED();
552 return;
555 blend_mode_ = blend_mode;
556 SetNeedsCommit();
559 void Layer::SetIsRootForIsolatedGroup(bool root) {
560 DCHECK(IsPropertyChangeAllowed());
561 if (is_root_for_isolated_group_ == root)
562 return;
563 is_root_for_isolated_group_ = root;
564 SetNeedsCommit();
567 void Layer::SetContentsOpaque(bool opaque) {
568 DCHECK(IsPropertyChangeAllowed());
569 if (contents_opaque_ == opaque)
570 return;
571 contents_opaque_ = opaque;
572 SetNeedsCommit();
575 void Layer::SetPosition(const gfx::PointF& position) {
576 DCHECK(IsPropertyChangeAllowed());
577 if (position_ == position)
578 return;
579 position_ = position;
580 SetNeedsCommit();
583 bool Layer::IsContainerForFixedPositionLayers() const {
584 if (!transform_.IsIdentityOrTranslation())
585 return true;
586 if (parent_ && !parent_->transform_.IsIdentityOrTranslation())
587 return true;
588 return is_container_for_fixed_position_layers_;
591 void Layer::SetTransform(const gfx::Transform& transform) {
592 DCHECK(IsPropertyChangeAllowed());
593 if (transform_ == transform)
594 return;
595 transform_ = transform;
596 transform_is_invertible_ = transform.IsInvertible();
597 SetNeedsCommit();
600 void Layer::SetTransformOrigin(const gfx::Point3F& transform_origin) {
601 DCHECK(IsPropertyChangeAllowed());
602 if (transform_origin_ == transform_origin)
603 return;
604 transform_origin_ = transform_origin;
605 SetNeedsCommit();
608 bool Layer::AnimationsPreserveAxisAlignment() const {
609 return layer_animation_controller_->AnimationsPreserveAxisAlignment();
612 bool Layer::TransformIsAnimating() const {
613 return layer_animation_controller_->IsAnimatingProperty(Animation::TRANSFORM);
616 void Layer::SetScrollParent(Layer* parent) {
617 DCHECK(IsPropertyChangeAllowed());
618 if (scroll_parent_ == parent)
619 return;
621 if (scroll_parent_)
622 scroll_parent_->RemoveScrollChild(this);
624 scroll_parent_ = parent;
626 if (scroll_parent_)
627 scroll_parent_->AddScrollChild(this);
629 SetNeedsCommit();
632 void Layer::AddScrollChild(Layer* child) {
633 if (!scroll_children_)
634 scroll_children_.reset(new std::set<Layer*>);
635 scroll_children_->insert(child);
636 SetNeedsCommit();
639 void Layer::RemoveScrollChild(Layer* child) {
640 scroll_children_->erase(child);
641 if (scroll_children_->empty())
642 scroll_children_ = nullptr;
643 SetNeedsCommit();
646 void Layer::SetClipParent(Layer* ancestor) {
647 DCHECK(IsPropertyChangeAllowed());
648 if (clip_parent_ == ancestor)
649 return;
651 if (clip_parent_)
652 clip_parent_->RemoveClipChild(this);
654 clip_parent_ = ancestor;
656 if (clip_parent_)
657 clip_parent_->AddClipChild(this);
659 SetNeedsCommit();
662 void Layer::AddClipChild(Layer* child) {
663 if (!clip_children_)
664 clip_children_.reset(new std::set<Layer*>);
665 clip_children_->insert(child);
666 SetNeedsCommit();
669 void Layer::RemoveClipChild(Layer* child) {
670 clip_children_->erase(child);
671 if (clip_children_->empty())
672 clip_children_ = nullptr;
673 SetNeedsCommit();
676 void Layer::SetScrollOffset(const gfx::ScrollOffset& scroll_offset) {
677 DCHECK(IsPropertyChangeAllowed());
679 if (scroll_offset_ == scroll_offset)
680 return;
681 scroll_offset_ = scroll_offset;
682 SetNeedsCommit();
685 void Layer::SetScrollCompensationAdjustment(
686 const gfx::Vector2dF& scroll_compensation_adjustment) {
687 if (scroll_compensation_adjustment_ == scroll_compensation_adjustment)
688 return;
689 scroll_compensation_adjustment_ = scroll_compensation_adjustment;
690 SetNeedsCommit();
693 gfx::Vector2dF Layer::ScrollCompensationAdjustment() const {
694 return scroll_compensation_adjustment_;
697 void Layer::SetScrollOffsetFromImplSide(
698 const gfx::ScrollOffset& scroll_offset) {
699 DCHECK(IsPropertyChangeAllowed());
700 // This function only gets called during a BeginMainFrame, so there
701 // is no need to call SetNeedsUpdate here.
702 DCHECK(layer_tree_host_ && layer_tree_host_->CommitRequested());
703 if (scroll_offset_ == scroll_offset)
704 return;
705 scroll_offset_ = scroll_offset;
706 SetNeedsPushProperties();
707 if (!did_scroll_callback_.is_null())
708 did_scroll_callback_.Run();
709 // The callback could potentially change the layer structure:
710 // "this" may have been destroyed during the process.
713 void Layer::SetScrollClipLayerId(int clip_layer_id) {
714 DCHECK(IsPropertyChangeAllowed());
715 if (scroll_clip_layer_id_ == clip_layer_id)
716 return;
717 scroll_clip_layer_id_ = clip_layer_id;
718 SetNeedsCommit();
721 void Layer::SetUserScrollable(bool horizontal, bool vertical) {
722 DCHECK(IsPropertyChangeAllowed());
723 if (user_scrollable_horizontal_ == horizontal &&
724 user_scrollable_vertical_ == vertical)
725 return;
726 user_scrollable_horizontal_ = horizontal;
727 user_scrollable_vertical_ = vertical;
728 SetNeedsCommit();
731 void Layer::SetShouldScrollOnMainThread(bool should_scroll_on_main_thread) {
732 DCHECK(IsPropertyChangeAllowed());
733 if (should_scroll_on_main_thread_ == should_scroll_on_main_thread)
734 return;
735 should_scroll_on_main_thread_ = should_scroll_on_main_thread;
736 SetNeedsCommit();
739 void Layer::SetHaveWheelEventHandlers(bool have_wheel_event_handlers) {
740 DCHECK(IsPropertyChangeAllowed());
741 if (have_wheel_event_handlers_ == have_wheel_event_handlers)
742 return;
743 have_wheel_event_handlers_ = have_wheel_event_handlers;
744 SetNeedsCommit();
747 void Layer::SetHaveScrollEventHandlers(bool have_scroll_event_handlers) {
748 DCHECK(IsPropertyChangeAllowed());
749 if (have_scroll_event_handlers_ == have_scroll_event_handlers)
750 return;
751 have_scroll_event_handlers_ = have_scroll_event_handlers;
752 SetNeedsCommit();
755 void Layer::SetNonFastScrollableRegion(const Region& region) {
756 DCHECK(IsPropertyChangeAllowed());
757 if (non_fast_scrollable_region_ == region)
758 return;
759 non_fast_scrollable_region_ = region;
760 SetNeedsCommit();
763 void Layer::SetTouchEventHandlerRegion(const Region& region) {
764 DCHECK(IsPropertyChangeAllowed());
765 if (touch_event_handler_region_ == region)
766 return;
767 touch_event_handler_region_ = region;
768 SetNeedsCommit();
771 void Layer::SetScrollBlocksOn(ScrollBlocksOn scroll_blocks_on) {
772 DCHECK(IsPropertyChangeAllowed());
773 if (scroll_blocks_on_ == scroll_blocks_on)
774 return;
775 scroll_blocks_on_ = scroll_blocks_on;
776 SetNeedsCommit();
779 void Layer::SetDrawCheckerboardForMissingTiles(bool checkerboard) {
780 DCHECK(IsPropertyChangeAllowed());
781 if (draw_checkerboard_for_missing_tiles_ == checkerboard)
782 return;
783 draw_checkerboard_for_missing_tiles_ = checkerboard;
784 SetNeedsCommit();
787 void Layer::SetForceRenderSurface(bool force) {
788 DCHECK(IsPropertyChangeAllowed());
789 if (force_render_surface_ == force)
790 return;
791 force_render_surface_ = force;
792 SetNeedsCommit();
795 void Layer::SetDoubleSided(bool double_sided) {
796 DCHECK(IsPropertyChangeAllowed());
797 if (double_sided_ == double_sided)
798 return;
799 double_sided_ = double_sided;
800 SetNeedsCommit();
803 void Layer::Set3dSortingContextId(int id) {
804 DCHECK(IsPropertyChangeAllowed());
805 if (id == sorting_context_id_)
806 return;
807 sorting_context_id_ = id;
808 SetNeedsCommit();
811 void Layer::SetShouldFlattenTransform(bool should_flatten) {
812 DCHECK(IsPropertyChangeAllowed());
813 if (should_flatten_transform_ == should_flatten)
814 return;
815 should_flatten_transform_ = should_flatten;
816 SetNeedsCommit();
819 void Layer::SetIsDrawable(bool is_drawable) {
820 DCHECK(IsPropertyChangeAllowed());
821 if (is_drawable_ == is_drawable)
822 return;
824 is_drawable_ = is_drawable;
825 UpdateDrawsContent(HasDrawableContent());
828 void Layer::SetHideLayerAndSubtree(bool hide) {
829 DCHECK(IsPropertyChangeAllowed());
830 if (hide_layer_and_subtree_ == hide)
831 return;
833 hide_layer_and_subtree_ = hide;
834 SetNeedsCommit();
837 void Layer::SetNeedsDisplayRect(const gfx::Rect& dirty_rect) {
838 if (dirty_rect.IsEmpty())
839 return;
841 SetNeedsPushProperties();
842 update_rect_.Union(dirty_rect);
844 if (DrawsContent())
845 SetNeedsUpdate();
848 bool Layer::DescendantIsFixedToContainerLayer() const {
849 for (size_t i = 0; i < children_.size(); ++i) {
850 if (children_[i]->position_constraint_.is_fixed_position() ||
851 children_[i]->DescendantIsFixedToContainerLayer())
852 return true;
854 return false;
857 void Layer::SetIsContainerForFixedPositionLayers(bool container) {
858 if (is_container_for_fixed_position_layers_ == container)
859 return;
860 is_container_for_fixed_position_layers_ = container;
862 if (layer_tree_host_ && layer_tree_host_->CommitRequested())
863 return;
865 // Only request a commit if we have a fixed positioned descendant.
866 if (DescendantIsFixedToContainerLayer())
867 SetNeedsCommit();
870 void Layer::SetPositionConstraint(const LayerPositionConstraint& constraint) {
871 DCHECK(IsPropertyChangeAllowed());
872 if (position_constraint_ == constraint)
873 return;
874 position_constraint_ = constraint;
875 SetNeedsCommit();
878 static void RunCopyCallbackOnMainThread(scoped_ptr<CopyOutputRequest> request,
879 scoped_ptr<CopyOutputResult> result) {
880 request->SendResult(result.Pass());
883 static void PostCopyCallbackToMainThread(
884 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
885 scoped_ptr<CopyOutputRequest> request,
886 scoped_ptr<CopyOutputResult> result) {
887 main_thread_task_runner->PostTask(FROM_HERE,
888 base::Bind(&RunCopyCallbackOnMainThread,
889 base::Passed(&request),
890 base::Passed(&result)));
893 void Layer::PushPropertiesTo(LayerImpl* layer) {
894 DCHECK(layer_tree_host_);
896 // If we did not SavePaintProperties() for the layer this frame, then push the
897 // real property values, not the paint property values.
898 bool use_paint_properties = paint_properties_.source_frame_number ==
899 layer_tree_host_->source_frame_number();
901 layer->SetTransformOrigin(transform_origin_);
902 layer->SetBackgroundColor(background_color_);
903 layer->SetBounds(use_paint_properties ? paint_properties_.bounds
904 : bounds_);
905 layer->SetContentBounds(content_bounds());
906 layer->SetContentsScale(contents_scale_x(), contents_scale_y());
908 if (frame_viewer_instrumentation::IsTracingLayerTreeSnapshots())
909 layer->SetDebugInfo(TakeDebugInfo());
911 layer->SetDoubleSided(double_sided_);
912 layer->SetDrawCheckerboardForMissingTiles(
913 draw_checkerboard_for_missing_tiles_);
914 layer->SetDrawsContent(DrawsContent());
915 layer->SetHideLayerAndSubtree(hide_layer_and_subtree_);
916 layer->SetHasRenderSurface(has_render_surface_ || layer->HasCopyRequest());
917 if (!layer->FilterIsAnimatingOnImplOnly() && !FilterIsAnimating())
918 layer->SetFilters(filters_);
919 DCHECK(!(FilterIsAnimating() && layer->FilterIsAnimatingOnImplOnly()));
920 layer->SetBackgroundFilters(background_filters());
921 layer->SetMasksToBounds(masks_to_bounds_);
922 layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
923 layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
924 layer->SetHaveScrollEventHandlers(have_scroll_event_handlers_);
925 layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
926 layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
927 layer->SetScrollBlocksOn(scroll_blocks_on_);
928 layer->SetContentsOpaque(contents_opaque_);
929 if (!layer->OpacityIsAnimatingOnImplOnly() && !OpacityIsAnimating())
930 layer->SetOpacity(opacity_);
931 DCHECK(!(OpacityIsAnimating() && layer->OpacityIsAnimatingOnImplOnly()));
932 layer->SetBlendMode(blend_mode_);
933 layer->SetIsRootForIsolatedGroup(is_root_for_isolated_group_);
934 layer->SetPosition(position_);
935 layer->SetIsContainerForFixedPositionLayers(
936 IsContainerForFixedPositionLayers());
937 layer->SetPositionConstraint(position_constraint_);
938 layer->SetShouldFlattenTransform(should_flatten_transform_);
939 layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
940 if (!layer->TransformIsAnimatingOnImplOnly() && !TransformIsAnimating())
941 layer->SetTransformAndInvertibility(transform_, transform_is_invertible_);
942 DCHECK(!(TransformIsAnimating() && layer->TransformIsAnimatingOnImplOnly()));
943 layer->Set3dSortingContextId(sorting_context_id_);
944 layer->SetNumDescendantsThatDrawContent(num_descendants_that_draw_content_);
946 layer->SetScrollClipLayer(scroll_clip_layer_id_);
947 layer->set_user_scrollable_horizontal(user_scrollable_horizontal_);
948 layer->set_user_scrollable_vertical(user_scrollable_vertical_);
950 LayerImpl* scroll_parent = nullptr;
951 if (scroll_parent_) {
952 scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id());
953 DCHECK(scroll_parent);
956 layer->SetScrollParent(scroll_parent);
957 if (scroll_children_) {
958 std::set<LayerImpl*>* scroll_children = new std::set<LayerImpl*>;
959 for (std::set<Layer*>::iterator it = scroll_children_->begin();
960 it != scroll_children_->end();
961 ++it) {
962 DCHECK_EQ((*it)->scroll_parent(), this);
963 LayerImpl* scroll_child =
964 layer->layer_tree_impl()->LayerById((*it)->id());
965 DCHECK(scroll_child);
966 scroll_children->insert(scroll_child);
968 layer->SetScrollChildren(scroll_children);
969 } else {
970 layer->SetScrollChildren(nullptr);
973 LayerImpl* clip_parent = nullptr;
974 if (clip_parent_) {
975 clip_parent =
976 layer->layer_tree_impl()->LayerById(clip_parent_->id());
977 DCHECK(clip_parent);
980 layer->SetClipParent(clip_parent);
981 if (clip_children_) {
982 std::set<LayerImpl*>* clip_children = new std::set<LayerImpl*>;
983 for (std::set<Layer*>::iterator it = clip_children_->begin();
984 it != clip_children_->end(); ++it) {
985 DCHECK_EQ((*it)->clip_parent(), this);
986 LayerImpl* clip_child = layer->layer_tree_impl()->LayerById((*it)->id());
987 DCHECK(clip_child);
988 clip_children->insert(clip_child);
990 layer->SetClipChildren(clip_children);
991 } else {
992 layer->SetClipChildren(nullptr);
995 // When a scroll offset animation is interrupted the new scroll position on
996 // the pending tree will clobber any impl-side scrolling occuring on the
997 // active tree. To do so, avoid scrolling the pending tree along with it
998 // instead of trying to undo that scrolling later.
999 if (layer_animation_controller_->scroll_offset_animation_was_interrupted())
1000 layer->PushScrollOffsetFromMainThreadAndClobberActiveValue(scroll_offset_);
1001 else
1002 layer->PushScrollOffsetFromMainThread(scroll_offset_);
1003 layer->SetScrollCompensationAdjustment(ScrollCompensationAdjustment());
1005 // Wrap the copy_requests_ in a PostTask to the main thread.
1006 ScopedPtrVector<CopyOutputRequest> main_thread_copy_requests;
1007 for (ScopedPtrVector<CopyOutputRequest>::iterator it = copy_requests_.begin();
1008 it != copy_requests_.end();
1009 ++it) {
1010 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner =
1011 layer_tree_host()->proxy()->MainThreadTaskRunner();
1012 scoped_ptr<CopyOutputRequest> original_request = copy_requests_.take(it);
1013 const CopyOutputRequest& original_request_ref = *original_request;
1014 scoped_ptr<CopyOutputRequest> main_thread_request =
1015 CopyOutputRequest::CreateRelayRequest(
1016 original_request_ref,
1017 base::Bind(&PostCopyCallbackToMainThread,
1018 main_thread_task_runner,
1019 base::Passed(&original_request)));
1020 main_thread_copy_requests.push_back(main_thread_request.Pass());
1022 copy_requests_.clear();
1023 layer->PassCopyRequests(&main_thread_copy_requests);
1025 // If the main thread commits multiple times before the impl thread actually
1026 // draws, then damage tracking will become incorrect if we simply clobber the
1027 // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
1028 // union) any update changes that have occurred on the main thread.
1029 update_rect_.Union(layer->update_rect());
1030 layer->SetUpdateRect(update_rect_);
1032 layer->SetStackingOrderChanged(stacking_order_changed_);
1034 layer_animation_controller_->PushAnimationUpdatesTo(
1035 layer->layer_animation_controller());
1037 if (frame_timing_requests_dirty_) {
1038 layer->PassFrameTimingRequests(&frame_timing_requests_);
1039 frame_timing_requests_dirty_ = false;
1042 // Reset any state that should be cleared for the next update.
1043 stacking_order_changed_ = false;
1044 update_rect_ = gfx::Rect();
1046 needs_push_properties_ = false;
1047 num_dependents_need_push_properties_ = 0;
1050 scoped_ptr<LayerImpl> Layer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
1051 return LayerImpl::Create(tree_impl, layer_id_,
1052 new LayerImpl::SyncedScrollOffset);
1055 bool Layer::DrawsContent() const {
1056 return draws_content_;
1059 bool Layer::HasDrawableContent() const {
1060 return is_drawable_;
1063 void Layer::UpdateDrawsContent(bool has_drawable_content) {
1064 bool draws_content = has_drawable_content;
1065 DCHECK(is_drawable_ || !has_drawable_content);
1066 if (draws_content == draws_content_)
1067 return;
1069 if (HasDelegatedContent()) {
1070 // Layers with delegated content need to be treated as if they have as
1071 // many children as the number of layers they own delegated quads for.
1072 // Since we don't know this number right now, we choose one that acts like
1073 // infinity for our purposes.
1074 AddDrawableDescendants(draws_content ? 1000 : -1000);
1077 if (parent())
1078 parent()->AddDrawableDescendants(draws_content ? 1 : -1);
1080 draws_content_ = draws_content;
1081 SetNeedsCommit();
1084 int Layer::NumDescendantsThatDrawContent() const {
1085 return num_descendants_that_draw_content_;
1088 void Layer::SavePaintProperties() {
1089 DCHECK(layer_tree_host_);
1091 // TODO(reveman): Save all layer properties that we depend on not
1092 // changing until PushProperties() has been called. crbug.com/231016
1093 paint_properties_.bounds = bounds_;
1094 paint_properties_.source_frame_number =
1095 layer_tree_host_->source_frame_number();
1098 bool Layer::Update(ResourceUpdateQueue* queue,
1099 const OcclusionTracker<Layer>* occlusion) {
1100 DCHECK(layer_tree_host_);
1101 DCHECK_EQ(layer_tree_host_->source_frame_number(),
1102 paint_properties_.source_frame_number) <<
1103 "SavePaintProperties must be called for any layer that is painted.";
1104 return false;
1107 bool Layer::NeedMoreUpdates() {
1108 return false;
1111 bool Layer::IsSuitableForGpuRasterization() const {
1112 return true;
1115 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
1116 Layer::TakeDebugInfo() {
1117 if (client_)
1118 return client_->TakeDebugInfo();
1119 else
1120 return nullptr;
1123 void Layer::SetHasRenderSurface(bool has_render_surface) {
1124 if (has_render_surface_ == has_render_surface)
1125 return;
1126 has_render_surface_ = has_render_surface;
1127 // We do not need SetNeedsCommit here, since this is only ever called
1128 // during a commit, from CalculateDrawProperties.
1129 SetNeedsPushProperties();
1132 void Layer::CreateRenderSurface() {
1133 DCHECK(!render_surface_);
1134 render_surface_ = make_scoped_ptr(new RenderSurface(this));
1137 void Layer::ClearRenderSurface() {
1138 render_surface_ = nullptr;
1141 void Layer::ClearRenderSurfaceLayerList() {
1142 if (render_surface_)
1143 render_surface_->ClearLayerLists();
1146 gfx::ScrollOffset Layer::ScrollOffsetForAnimation() const {
1147 return CurrentScrollOffset();
1150 // On<Property>Animated is called due to an ongoing accelerated animation.
1151 // Since this animation is also being run on the compositor thread, there
1152 // is no need to request a commit to push this value over, so the value is
1153 // set directly rather than by calling Set<Property>.
1154 void Layer::OnFilterAnimated(const FilterOperations& filters) {
1155 filters_ = filters;
1158 void Layer::OnOpacityAnimated(float opacity) {
1159 opacity_ = opacity;
1162 void Layer::OnTransformAnimated(const gfx::Transform& transform) {
1163 if (transform_ == transform)
1164 return;
1165 transform_ = transform;
1166 transform_is_invertible_ = transform.IsInvertible();
1169 void Layer::OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) {
1170 // Do nothing. Scroll deltas will be sent from the compositor thread back
1171 // to the main thread in the same manner as during non-animated
1172 // compositor-driven scrolling.
1175 void Layer::OnAnimationWaitingForDeletion() {
1176 // Animations are only deleted during PushProperties.
1177 SetNeedsPushProperties();
1180 bool Layer::IsActive() const {
1181 return true;
1184 bool Layer::AddAnimation(scoped_ptr <Animation> animation) {
1185 if (!layer_animation_controller_->animation_registrar())
1186 return false;
1188 if (animation->target_property() == Animation::SCROLL_OFFSET &&
1189 !layer_animation_controller_->animation_registrar()
1190 ->supports_scroll_animations())
1191 return false;
1193 UMA_HISTOGRAM_BOOLEAN("Renderer.AnimationAddedToOrphanLayer",
1194 !layer_tree_host_);
1195 layer_animation_controller_->AddAnimation(animation.Pass());
1196 SetNeedsCommit();
1197 return true;
1200 void Layer::PauseAnimation(int animation_id, double time_offset) {
1201 layer_animation_controller_->PauseAnimation(
1202 animation_id, base::TimeDelta::FromSecondsD(time_offset));
1203 SetNeedsCommit();
1206 void Layer::RemoveAnimation(int animation_id) {
1207 layer_animation_controller_->RemoveAnimation(animation_id);
1208 SetNeedsCommit();
1211 void Layer::RemoveAnimation(int animation_id,
1212 Animation::TargetProperty property) {
1213 layer_animation_controller_->RemoveAnimation(animation_id, property);
1214 SetNeedsCommit();
1217 void Layer::SetLayerAnimationControllerForTest(
1218 scoped_refptr<LayerAnimationController> controller) {
1219 layer_animation_controller_->RemoveValueObserver(this);
1220 layer_animation_controller_ = controller;
1221 layer_animation_controller_->AddValueObserver(this);
1222 SetNeedsCommit();
1225 bool Layer::HasActiveAnimation() const {
1226 return layer_animation_controller_->HasActiveAnimation();
1229 void Layer::AddLayerAnimationEventObserver(
1230 LayerAnimationEventObserver* animation_observer) {
1231 layer_animation_controller_->AddEventObserver(animation_observer);
1234 void Layer::RemoveLayerAnimationEventObserver(
1235 LayerAnimationEventObserver* animation_observer) {
1236 layer_animation_controller_->RemoveEventObserver(animation_observer);
1239 SimpleEnclosedRegion Layer::VisibleContentOpaqueRegion() const {
1240 if (contents_opaque())
1241 return SimpleEnclosedRegion(visible_content_rect());
1242 return SimpleEnclosedRegion();
1245 ScrollbarLayerInterface* Layer::ToScrollbarLayer() {
1246 return nullptr;
1249 RenderingStatsInstrumentation* Layer::rendering_stats_instrumentation() const {
1250 return layer_tree_host_->rendering_stats_instrumentation();
1253 void Layer::RemoveFromScrollTree() {
1254 if (scroll_children_.get()) {
1255 std::set<Layer*> copy = *scroll_children_;
1256 for (std::set<Layer*>::iterator it = copy.begin(); it != copy.end(); ++it)
1257 (*it)->SetScrollParent(nullptr);
1260 DCHECK(!scroll_children_);
1261 SetScrollParent(nullptr);
1264 void Layer::RemoveFromClipTree() {
1265 if (clip_children_.get()) {
1266 std::set<Layer*> copy = *clip_children_;
1267 for (std::set<Layer*>::iterator it = copy.begin(); it != copy.end(); ++it)
1268 (*it)->SetClipParent(nullptr);
1271 DCHECK(!clip_children_);
1272 SetClipParent(nullptr);
1275 void Layer::AddDrawableDescendants(int num) {
1276 DCHECK_GE(num_descendants_that_draw_content_, 0);
1277 DCHECK_GE(num_descendants_that_draw_content_ + num, 0);
1278 if (num == 0)
1279 return;
1280 num_descendants_that_draw_content_ += num;
1281 SetNeedsCommit();
1282 if (parent())
1283 parent()->AddDrawableDescendants(num);
1286 void Layer::RunMicroBenchmark(MicroBenchmark* benchmark) {
1287 benchmark->RunOnLayer(this);
1290 bool Layer::HasDelegatedContent() const {
1291 return false;
1294 gfx::Transform Layer::screen_space_transform_from_property_trees(
1295 const TransformTree& tree) const {
1296 gfx::Transform xform(1, 0, 0, 1, offset_to_transform_parent().x(),
1297 offset_to_transform_parent().y());
1298 if (transform_tree_index() >= 0) {
1299 gfx::Transform ssxform = tree.Node(transform_tree_index())->data.to_screen;
1300 xform.ConcatTransform(ssxform);
1301 if (should_flatten_transform_from_property_tree_)
1302 xform.FlattenTo2d();
1304 xform.Scale(1.0 / contents_scale_x(), 1.0 / contents_scale_y());
1305 return xform;
1308 gfx::Transform Layer::draw_transform_from_property_trees(
1309 const TransformTree& tree) const {
1310 const TransformNode* node = tree.Node(transform_tree_index());
1311 // TODO(vollick): ultimately we'll need to find this information (whether or
1312 // not we establish a render surface) somewhere other than the layer.
1313 const TransformNode* target_node =
1314 has_render_surface_ ? node : tree.Node(node->data.content_target_id);
1316 gfx::Transform xform;
1317 const bool owns_non_root_surface = parent() && render_surface();
1318 if (!owns_non_root_surface) {
1319 // If you're not the root, or you don't own a surface, you need to apply
1320 // your local offset.
1321 xform = node->data.to_target;
1322 if (should_flatten_transform_from_property_tree_)
1323 xform.FlattenTo2d();
1324 xform.Translate(offset_to_transform_parent().x(),
1325 offset_to_transform_parent().y());
1326 // A fixed-position layer does not necessarily have the same render target
1327 // as its transform node. In particular, its transform node may be an
1328 // ancestor of its render target's transform node. For example, given layer
1329 // tree R->S->F, suppose F is fixed and S owns a render surface (e.g., say S
1330 // has opacity 0.9 and both S and F draw content). Then F's transform node
1331 // is the root node, so the target space transform from that node is defined
1332 // with respect to the root render surface. But F will render to S's
1333 // surface, so must apply a change of basis transform to the target space
1334 // transform from its transform node.
1335 if (position_constraint_.is_fixed_position()) {
1336 gfx::Transform tree_target_to_render_target;
1337 tree.ComputeTransform(node->data.content_target_id,
1338 render_target()->transform_tree_index(),
1339 &tree_target_to_render_target);
1340 xform.ConcatTransform(tree_target_to_render_target);
1342 } else {
1343 // Surfaces need to apply their sublayer scale.
1344 xform.Scale(target_node->data.sublayer_scale.x(),
1345 target_node->data.sublayer_scale.y());
1347 xform.Scale(1.0 / contents_scale_x(), 1.0 / contents_scale_y());
1348 return xform;
1351 float Layer::DrawOpacityFromPropertyTrees(const OpacityTree& tree) const {
1352 if (!render_target())
1353 return 0.f;
1355 const OpacityNode* target_node =
1356 tree.Node(render_target()->opacity_tree_index());
1357 const OpacityNode* node = tree.Node(opacity_tree_index());
1358 if (node == target_node)
1359 return 1.f;
1361 float draw_opacity = 1.f;
1362 while (node != target_node) {
1363 draw_opacity *= node->data;
1364 node = tree.parent(node);
1366 return draw_opacity;
1369 void Layer::SetFrameTimingRequests(
1370 const std::vector<FrameTimingRequest>& requests) {
1371 frame_timing_requests_ = requests;
1372 frame_timing_requests_dirty_ = true;
1373 SetNeedsCommit();
1376 void Layer::DidBeginTracing() {
1377 // We'll be dumping layer trees as part of trace, so make sure
1378 // PushPropertiesTo() propagates layer debug info to the impl
1379 // side -- otherwise this won't happen for the the layers that
1380 // remain unchanged since tracing started.
1381 SetNeedsPushProperties();
1384 } // namespace cc