| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 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. | |
| 4 | |
| 5 #include "cc/trees/layer_tree.h" | |
| 6 | |
| 7 #include "base/auto_reset.h" | |
| 8 #include "base/time/time.h" | |
| 9 #include "cc/input/page_scale_animation.h" | |
| 10 #include "cc/layers/heads_up_display_layer.h" | |
| 11 #include "cc/layers/heads_up_display_layer_impl.h" | |
| 12 #include "cc/layers/layer.h" | |
| 13 #include "cc/trees/layer_tree_host.h" | |
| 14 #include "cc/trees/layer_tree_host_common.h" | |
| 15 #include "cc/trees/layer_tree_impl.h" | |
| 16 #include "cc/trees/mutator_host.h" | |
| 17 #include "cc/trees/property_tree_builder.h" | |
| 18 | |
| 19 namespace cc { | |
| 20 | |
| 21 LayerTree::LayerTree(MutatorHost* mutator_host, LayerTreeHost* layer_tree_host) | |
| 22 : event_listener_properties_(), | |
| 23 mutator_host_(mutator_host), | |
| 24 layer_tree_host_(layer_tree_host) { | |
| 25 DCHECK(mutator_host_); | |
| 26 DCHECK(layer_tree_host_); | |
| 27 mutator_host_->SetMutatorHostClient(this); | |
| 28 } | |
| 29 | |
| 30 LayerTree::~LayerTree() { | |
| 31 mutator_host_->SetMutatorHostClient(nullptr); | |
| 32 | |
| 33 // We must clear any pointers into the layer tree prior to destroying it. | |
| 34 RegisterViewportLayers(nullptr, nullptr, nullptr, nullptr); | |
| 35 | |
| 36 if (root_layer_) { | |
| 37 root_layer_->SetLayerTreeHost(nullptr); | |
| 38 | |
| 39 // The root layer must be destroyed before the layer tree. We've made a | |
| 40 // contract with our animation controllers that the animation_host will | |
| 41 // outlive them, and we must make good. | |
| 42 root_layer_ = nullptr; | |
| 43 } | |
| 44 } | |
| 45 | |
| 46 void LayerTree::SetRootLayer(scoped_refptr<Layer> root_layer) { | |
| 47 if (root_layer_.get() == root_layer.get()) | |
| 48 return; | |
| 49 | |
| 50 if (root_layer_.get()) | |
| 51 root_layer_->SetLayerTreeHost(nullptr); | |
| 52 root_layer_ = root_layer; | |
| 53 if (root_layer_.get()) { | |
| 54 DCHECK(!root_layer_->parent()); | |
| 55 root_layer_->SetLayerTreeHost(layer_tree_host_); | |
| 56 } | |
| 57 | |
| 58 if (hud_layer_.get()) | |
| 59 hud_layer_->RemoveFromParent(); | |
| 60 | |
| 61 // Reset gpu rasterization tracking. | |
| 62 // This flag is sticky until a new tree comes along. | |
| 63 layer_tree_host_->ResetGpuRasterizationTracking(); | |
| 64 | |
| 65 SetNeedsFullTreeSync(); | |
| 66 } | |
| 67 | |
| 68 void LayerTree::RegisterViewportLayers( | |
| 69 scoped_refptr<Layer> overscroll_elasticity_layer, | |
| 70 scoped_refptr<Layer> page_scale_layer, | |
| 71 scoped_refptr<Layer> inner_viewport_scroll_layer, | |
| 72 scoped_refptr<Layer> outer_viewport_scroll_layer) { | |
| 73 DCHECK(!inner_viewport_scroll_layer || | |
| 74 inner_viewport_scroll_layer != outer_viewport_scroll_layer); | |
| 75 overscroll_elasticity_layer_ = overscroll_elasticity_layer; | |
| 76 page_scale_layer_ = page_scale_layer; | |
| 77 inner_viewport_scroll_layer_ = inner_viewport_scroll_layer; | |
| 78 outer_viewport_scroll_layer_ = outer_viewport_scroll_layer; | |
| 79 } | |
| 80 | |
| 81 void LayerTree::RegisterSelection(const LayerSelection& selection) { | |
| 82 if (selection_ == selection) | |
| 83 return; | |
| 84 | |
| 85 selection_ = selection; | |
| 86 SetNeedsCommit(); | |
| 87 } | |
| 88 | |
| 89 void LayerTree::SetHaveScrollEventHandlers(bool have_event_handlers) { | |
| 90 if (have_scroll_event_handlers_ == have_event_handlers) | |
| 91 return; | |
| 92 | |
| 93 have_scroll_event_handlers_ = have_event_handlers; | |
| 94 SetNeedsCommit(); | |
| 95 } | |
| 96 | |
| 97 void LayerTree::SetEventListenerProperties(EventListenerClass event_class, | |
| 98 EventListenerProperties properties) { | |
| 99 const size_t index = static_cast<size_t>(event_class); | |
| 100 if (event_listener_properties_[index] == properties) | |
| 101 return; | |
| 102 | |
| 103 event_listener_properties_[index] = properties; | |
| 104 SetNeedsCommit(); | |
| 105 } | |
| 106 | |
| 107 void LayerTree::SetViewportSize(const gfx::Size& device_viewport_size) { | |
| 108 if (device_viewport_size_ == device_viewport_size) | |
| 109 return; | |
| 110 | |
| 111 device_viewport_size_ = device_viewport_size; | |
| 112 | |
| 113 SetPropertyTreesNeedRebuild(); | |
| 114 SetNeedsCommit(); | |
| 115 } | |
| 116 | |
| 117 void LayerTree::SetBrowserControlsHeight(float height, bool shrink) { | |
| 118 if (top_controls_height_ == height && | |
| 119 browser_controls_shrink_blink_size_ == shrink) | |
| 120 return; | |
| 121 | |
| 122 top_controls_height_ = height; | |
| 123 browser_controls_shrink_blink_size_ = shrink; | |
| 124 SetNeedsCommit(); | |
| 125 } | |
| 126 | |
| 127 void LayerTree::SetBrowserControlsShownRatio(float ratio) { | |
| 128 if (top_controls_shown_ratio_ == ratio) | |
| 129 return; | |
| 130 | |
| 131 top_controls_shown_ratio_ = ratio; | |
| 132 SetNeedsCommit(); | |
| 133 } | |
| 134 | |
| 135 void LayerTree::SetBottomControlsHeight(float height) { | |
| 136 if (bottom_controls_height_ == height) | |
| 137 return; | |
| 138 | |
| 139 bottom_controls_height_ = height; | |
| 140 SetNeedsCommit(); | |
| 141 } | |
| 142 | |
| 143 void LayerTree::SetPageScaleFactorAndLimits(float page_scale_factor, | |
| 144 float min_page_scale_factor, | |
| 145 float max_page_scale_factor) { | |
| 146 if (page_scale_factor_ == page_scale_factor && | |
| 147 min_page_scale_factor_ == min_page_scale_factor && | |
| 148 max_page_scale_factor_ == max_page_scale_factor) | |
| 149 return; | |
| 150 | |
| 151 page_scale_factor_ = page_scale_factor; | |
| 152 min_page_scale_factor_ = min_page_scale_factor; | |
| 153 max_page_scale_factor_ = max_page_scale_factor; | |
| 154 SetPropertyTreesNeedRebuild(); | |
| 155 SetNeedsCommit(); | |
| 156 } | |
| 157 | |
| 158 void LayerTree::StartPageScaleAnimation(const gfx::Vector2d& target_offset, | |
| 159 bool use_anchor, | |
| 160 float scale, | |
| 161 base::TimeDelta duration) { | |
| 162 pending_page_scale_animation_.reset(new PendingPageScaleAnimation( | |
| 163 target_offset, use_anchor, scale, duration)); | |
| 164 | |
| 165 SetNeedsCommit(); | |
| 166 } | |
| 167 | |
| 168 bool LayerTree::HasPendingPageScaleAnimation() const { | |
| 169 return !!pending_page_scale_animation_.get(); | |
| 170 } | |
| 171 | |
| 172 void LayerTree::SetDeviceScaleFactor(float device_scale_factor) { | |
| 173 if (device_scale_factor_ == device_scale_factor) | |
| 174 return; | |
| 175 device_scale_factor_ = device_scale_factor; | |
| 176 | |
| 177 property_trees_.needs_rebuild = true; | |
| 178 SetNeedsCommit(); | |
| 179 } | |
| 180 | |
| 181 void LayerTree::SetPaintedDeviceScaleFactor(float painted_device_scale_factor) { | |
| 182 if (painted_device_scale_factor_ == painted_device_scale_factor) | |
| 183 return; | |
| 184 painted_device_scale_factor_ = painted_device_scale_factor; | |
| 185 | |
| 186 SetNeedsCommit(); | |
| 187 } | |
| 188 | |
| 189 void LayerTree::SetDeviceColorSpace(const gfx::ColorSpace& device_color_space) { | |
| 190 if (device_color_space_ == device_color_space) | |
| 191 return; | |
| 192 device_color_space_ = device_color_space; | |
| 193 LayerTreeHostCommon::CallFunctionForEveryLayer( | |
| 194 this, [](Layer* layer) { layer->SetNeedsDisplay(); }); | |
| 195 } | |
| 196 | |
| 197 void LayerTree::RegisterLayer(Layer* layer) { | |
| 198 DCHECK(!LayerById(layer->id())); | |
| 199 DCHECK(!in_paint_layer_contents_); | |
| 200 layer_id_map_[layer->id()] = layer; | |
| 201 if (layer->element_id()) { | |
| 202 mutator_host_->RegisterElement(layer->element_id(), | |
| 203 ElementListType::ACTIVE); | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 void LayerTree::UnregisterLayer(Layer* layer) { | |
| 208 DCHECK(LayerById(layer->id())); | |
| 209 DCHECK(!in_paint_layer_contents_); | |
| 210 if (layer->element_id()) { | |
| 211 mutator_host_->UnregisterElement(layer->element_id(), | |
| 212 ElementListType::ACTIVE); | |
| 213 } | |
| 214 RemoveLayerShouldPushProperties(layer); | |
| 215 layer_id_map_.erase(layer->id()); | |
| 216 } | |
| 217 | |
| 218 Layer* LayerTree::LayerById(int id) const { | |
| 219 LayerIdMap::const_iterator iter = layer_id_map_.find(id); | |
| 220 return iter != layer_id_map_.end() ? iter->second : nullptr; | |
| 221 } | |
| 222 | |
| 223 size_t LayerTree::NumLayers() const { | |
| 224 return layer_id_map_.size(); | |
| 225 } | |
| 226 | |
| 227 bool LayerTree::UpdateLayers(const LayerList& update_layer_list, | |
| 228 bool* content_is_suitable_for_gpu) { | |
| 229 base::AutoReset<bool> painting(&in_paint_layer_contents_, true); | |
| 230 bool did_paint_content = false; | |
| 231 for (const auto& layer : update_layer_list) { | |
| 232 did_paint_content |= layer->Update(); | |
| 233 *content_is_suitable_for_gpu &= layer->IsSuitableForGpuRasterization(); | |
| 234 } | |
| 235 return did_paint_content; | |
| 236 } | |
| 237 | |
| 238 void LayerTree::AddLayerShouldPushProperties(Layer* layer) { | |
| 239 layers_that_should_push_properties_.insert(layer); | |
| 240 } | |
| 241 | |
| 242 void LayerTree::RemoveLayerShouldPushProperties(Layer* layer) { | |
| 243 layers_that_should_push_properties_.erase(layer); | |
| 244 } | |
| 245 | |
| 246 std::unordered_set<Layer*>& LayerTree::LayersThatShouldPushProperties() { | |
| 247 return layers_that_should_push_properties_; | |
| 248 } | |
| 249 | |
| 250 bool LayerTree::LayerNeedsPushPropertiesForTesting(Layer* layer) const { | |
| 251 return layers_that_should_push_properties_.find(layer) != | |
| 252 layers_that_should_push_properties_.end(); | |
| 253 } | |
| 254 | |
| 255 void LayerTree::SetNeedsMetaInfoRecomputation(bool needs_recomputation) { | |
| 256 needs_meta_info_recomputation_ = needs_recomputation; | |
| 257 } | |
| 258 | |
| 259 void LayerTree::SetPageScaleFromImplSide(float page_scale) { | |
| 260 DCHECK(layer_tree_host_->CommitRequested()); | |
| 261 page_scale_factor_ = page_scale; | |
| 262 SetPropertyTreesNeedRebuild(); | |
| 263 } | |
| 264 | |
| 265 void LayerTree::SetElasticOverscrollFromImplSide( | |
| 266 gfx::Vector2dF elastic_overscroll) { | |
| 267 DCHECK(layer_tree_host_->CommitRequested()); | |
| 268 elastic_overscroll_ = elastic_overscroll; | |
| 269 } | |
| 270 | |
| 271 void LayerTree::UpdateHudLayer(bool show_hud_info) { | |
| 272 if (show_hud_info) { | |
| 273 if (!hud_layer_.get()) { | |
| 274 hud_layer_ = HeadsUpDisplayLayer::Create(); | |
| 275 } | |
| 276 | |
| 277 if (root_layer_.get() && !hud_layer_->parent()) | |
| 278 root_layer_->AddChild(hud_layer_); | |
| 279 } else if (hud_layer_.get()) { | |
| 280 hud_layer_->RemoveFromParent(); | |
| 281 hud_layer_ = nullptr; | |
| 282 } | |
| 283 } | |
| 284 | |
| 285 void LayerTree::SetNeedsFullTreeSync() { | |
| 286 needs_full_tree_sync_ = true; | |
| 287 needs_meta_info_recomputation_ = true; | |
| 288 | |
| 289 property_trees_.needs_rebuild = true; | |
| 290 SetNeedsCommit(); | |
| 291 } | |
| 292 | |
| 293 void LayerTree::SetNeedsCommit() { | |
| 294 layer_tree_host_->SetNeedsCommit(); | |
| 295 } | |
| 296 | |
| 297 const LayerTreeSettings& LayerTree::GetSettings() const { | |
| 298 return layer_tree_host_->GetSettings(); | |
| 299 } | |
| 300 | |
| 301 void LayerTree::SetPropertyTreesNeedRebuild() { | |
| 302 property_trees_.needs_rebuild = true; | |
| 303 layer_tree_host_->SetNeedsUpdateLayers(); | |
| 304 } | |
| 305 | |
| 306 void LayerTree::PushPropertiesTo(LayerTreeImpl* tree_impl) { | |
| 307 tree_impl->set_needs_full_tree_sync(needs_full_tree_sync_); | |
| 308 needs_full_tree_sync_ = false; | |
| 309 | |
| 310 if (hud_layer_.get()) { | |
| 311 LayerImpl* hud_impl = tree_impl->LayerById(hud_layer_->id()); | |
| 312 tree_impl->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(hud_impl)); | |
| 313 } else { | |
| 314 tree_impl->set_hud_layer(nullptr); | |
| 315 } | |
| 316 | |
| 317 tree_impl->set_background_color(background_color_); | |
| 318 tree_impl->set_has_transparent_background(has_transparent_background_); | |
| 319 tree_impl->set_have_scroll_event_handlers(have_scroll_event_handlers_); | |
| 320 tree_impl->set_event_listener_properties( | |
| 321 EventListenerClass::kTouchStartOrMove, | |
| 322 event_listener_properties(EventListenerClass::kTouchStartOrMove)); | |
| 323 tree_impl->set_event_listener_properties( | |
| 324 EventListenerClass::kMouseWheel, | |
| 325 event_listener_properties(EventListenerClass::kMouseWheel)); | |
| 326 tree_impl->set_event_listener_properties( | |
| 327 EventListenerClass::kTouchEndOrCancel, | |
| 328 event_listener_properties(EventListenerClass::kTouchEndOrCancel)); | |
| 329 | |
| 330 if (page_scale_layer_ && inner_viewport_scroll_layer_) { | |
| 331 tree_impl->SetViewportLayersFromIds( | |
| 332 overscroll_elasticity_layer_ ? overscroll_elasticity_layer_->id() | |
| 333 : Layer::INVALID_ID, | |
| 334 page_scale_layer_->id(), inner_viewport_scroll_layer_->id(), | |
| 335 outer_viewport_scroll_layer_ ? outer_viewport_scroll_layer_->id() | |
| 336 : Layer::INVALID_ID); | |
| 337 DCHECK(inner_viewport_scroll_layer_->IsContainerForFixedPositionLayers()); | |
| 338 } else { | |
| 339 tree_impl->ClearViewportLayers(); | |
| 340 } | |
| 341 | |
| 342 tree_impl->RegisterSelection(selection_); | |
| 343 | |
| 344 bool property_trees_changed_on_active_tree = | |
| 345 tree_impl->IsActiveTree() && tree_impl->property_trees()->changed; | |
| 346 // Property trees may store damage status. We preserve the sync tree damage | |
| 347 // status by pushing the damage status from sync tree property trees to main | |
| 348 // thread property trees or by moving it onto the layers. | |
| 349 if (root_layer_ && property_trees_changed_on_active_tree) { | |
| 350 if (property_trees_.sequence_number == | |
| 351 tree_impl->property_trees()->sequence_number) | |
| 352 tree_impl->property_trees()->PushChangeTrackingTo(&property_trees_); | |
| 353 else | |
| 354 tree_impl->MoveChangeTrackingToLayers(); | |
| 355 } | |
| 356 // Setting property trees must happen before pushing the page scale. | |
| 357 tree_impl->SetPropertyTrees(&property_trees_); | |
| 358 | |
| 359 tree_impl->PushPageScaleFromMainThread( | |
| 360 page_scale_factor_, min_page_scale_factor_, max_page_scale_factor_); | |
| 361 | |
| 362 tree_impl->set_browser_controls_shrink_blink_size( | |
| 363 browser_controls_shrink_blink_size_); | |
| 364 tree_impl->set_top_controls_height(top_controls_height_); | |
| 365 tree_impl->set_bottom_controls_height(bottom_controls_height_); | |
| 366 tree_impl->PushBrowserControlsFromMainThread(top_controls_shown_ratio_); | |
| 367 tree_impl->elastic_overscroll()->PushFromMainThread(elastic_overscroll_); | |
| 368 if (tree_impl->IsActiveTree()) | |
| 369 tree_impl->elastic_overscroll()->PushPendingToActive(); | |
| 370 | |
| 371 tree_impl->set_painted_device_scale_factor(painted_device_scale_factor_); | |
| 372 | |
| 373 tree_impl->SetDeviceColorSpace(device_color_space_); | |
| 374 | |
| 375 if (pending_page_scale_animation_) { | |
| 376 tree_impl->SetPendingPageScaleAnimation( | |
| 377 std::move(pending_page_scale_animation_)); | |
| 378 } | |
| 379 | |
| 380 DCHECK(!tree_impl->ViewportSizeInvalid()); | |
| 381 | |
| 382 tree_impl->set_has_ever_been_drawn(false); | |
| 383 } | |
| 384 | |
| 385 Layer* LayerTree::LayerByElementId(ElementId element_id) const { | |
| 386 ElementLayersMap::const_iterator iter = element_layers_map_.find(element_id); | |
| 387 return iter != element_layers_map_.end() ? iter->second : nullptr; | |
| 388 } | |
| 389 | |
| 390 void LayerTree::RegisterElement(ElementId element_id, | |
| 391 ElementListType list_type, | |
| 392 Layer* layer) { | |
| 393 if (layer->element_id()) { | |
| 394 element_layers_map_[layer->element_id()] = layer; | |
| 395 } | |
| 396 | |
| 397 mutator_host_->RegisterElement(element_id, list_type); | |
| 398 } | |
| 399 | |
| 400 void LayerTree::UnregisterElement(ElementId element_id, | |
| 401 ElementListType list_type, | |
| 402 Layer* layer) { | |
| 403 mutator_host_->UnregisterElement(element_id, list_type); | |
| 404 | |
| 405 if (layer->element_id()) { | |
| 406 element_layers_map_.erase(layer->element_id()); | |
| 407 } | |
| 408 } | |
| 409 | |
| 410 static void SetElementIdForTesting(Layer* layer) { | |
| 411 layer->SetElementId(LayerIdToElementIdForTesting(layer->id())); | |
| 412 } | |
| 413 | |
| 414 void LayerTree::SetElementIdsForTesting() { | |
| 415 LayerTreeHostCommon::CallFunctionForEveryLayer(this, SetElementIdForTesting); | |
| 416 } | |
| 417 | |
| 418 void LayerTree::BuildPropertyTreesForTesting() { | |
| 419 PropertyTreeBuilder::PreCalculateMetaInformation(root_layer()); | |
| 420 gfx::Transform identity_transform; | |
| 421 PropertyTreeBuilder::BuildPropertyTrees( | |
| 422 root_layer(), page_scale_layer(), inner_viewport_scroll_layer(), | |
| 423 outer_viewport_scroll_layer(), overscroll_elasticity_layer(), | |
| 424 elastic_overscroll(), page_scale_factor(), device_scale_factor(), | |
| 425 gfx::Rect(device_viewport_size()), identity_transform, property_trees()); | |
| 426 } | |
| 427 | |
| 428 bool LayerTree::IsElementInList(ElementId element_id, | |
| 429 ElementListType list_type) const { | |
| 430 return list_type == ElementListType::ACTIVE && LayerByElementId(element_id); | |
| 431 } | |
| 432 | |
| 433 void LayerTree::SetMutatorsNeedCommit() { | |
| 434 layer_tree_host_->SetNeedsCommit(); | |
| 435 } | |
| 436 | |
| 437 void LayerTree::SetMutatorsNeedRebuildPropertyTrees() { | |
| 438 property_trees_.needs_rebuild = true; | |
| 439 } | |
| 440 | |
| 441 void LayerTree::SetElementFilterMutated(ElementId element_id, | |
| 442 ElementListType list_type, | |
| 443 const FilterOperations& filters) { | |
| 444 Layer* layer = LayerByElementId(element_id); | |
| 445 DCHECK(layer); | |
| 446 layer->OnFilterAnimated(filters); | |
| 447 } | |
| 448 | |
| 449 void LayerTree::SetElementOpacityMutated(ElementId element_id, | |
| 450 ElementListType list_type, | |
| 451 float opacity) { | |
| 452 Layer* layer = LayerByElementId(element_id); | |
| 453 DCHECK(layer); | |
| 454 layer->OnOpacityAnimated(opacity); | |
| 455 } | |
| 456 | |
| 457 void LayerTree::SetElementTransformMutated(ElementId element_id, | |
| 458 ElementListType list_type, | |
| 459 const gfx::Transform& transform) { | |
| 460 Layer* layer = LayerByElementId(element_id); | |
| 461 DCHECK(layer); | |
| 462 layer->OnTransformAnimated(transform); | |
| 463 } | |
| 464 | |
| 465 void LayerTree::SetElementScrollOffsetMutated( | |
| 466 ElementId element_id, | |
| 467 ElementListType list_type, | |
| 468 const gfx::ScrollOffset& scroll_offset) { | |
| 469 Layer* layer = LayerByElementId(element_id); | |
| 470 DCHECK(layer); | |
| 471 layer->OnScrollOffsetAnimated(scroll_offset); | |
| 472 } | |
| 473 | |
| 474 void LayerTree::ElementIsAnimatingChanged(ElementId element_id, | |
| 475 ElementListType list_type, | |
| 476 const PropertyAnimationState& mask, | |
| 477 const PropertyAnimationState& state) { | |
| 478 Layer* layer = LayerByElementId(element_id); | |
| 479 if (layer) | |
| 480 layer->OnIsAnimatingChanged(mask, state); | |
| 481 } | |
| 482 | |
| 483 gfx::ScrollOffset LayerTree::GetScrollOffsetForAnimation( | |
| 484 ElementId element_id) const { | |
| 485 Layer* layer = LayerByElementId(element_id); | |
| 486 DCHECK(layer); | |
| 487 return layer->ScrollOffsetForAnimation(); | |
| 488 } | |
| 489 | |
| 490 LayerListIterator<Layer> LayerTree::begin() const { | |
| 491 return LayerListIterator<Layer>(root_layer_.get()); | |
| 492 } | |
| 493 | |
| 494 LayerListIterator<Layer> LayerTree::end() const { | |
| 495 return LayerListIterator<Layer>(nullptr); | |
| 496 } | |
| 497 | |
| 498 LayerListReverseIterator<Layer> LayerTree::rbegin() { | |
| 499 return LayerListReverseIterator<Layer>(root_layer_.get()); | |
| 500 } | |
| 501 | |
| 502 LayerListReverseIterator<Layer> LayerTree::rend() { | |
| 503 return LayerListReverseIterator<Layer>(nullptr); | |
| 504 } | |
| 505 | |
| 506 void LayerTree::SetNeedsDisplayOnAllLayers() { | |
| 507 for (auto* layer : *this) | |
| 508 layer->SetNeedsDisplay(); | |
| 509 } | |
| 510 | |
| 511 } // namespace cc | |
| OLD | NEW |