blob: b6ce2d29d2bedf48488deb58cda10e2095b125ff [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/trees/layer_tree.h"
#include "base/auto_reset.h"
#include "base/time/time.h"
#include "cc/animation/animation_host.h"
#include "cc/input/page_scale_animation.h"
#include "cc/layers/heads_up_display_layer.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_proto_converter.h"
#include "cc/proto/gfx_conversions.h"
#include "cc/proto/layer_tree.pb.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/property_tree_builder.h"
namespace cc {
namespace {
Layer* UpdateAndGetLayer(Layer* current_layer,
int layer_id,
LayerTree* layer_tree) {
if (layer_id == Layer::INVALID_ID) {
if (current_layer)
current_layer->SetLayerTreeHost(nullptr);
return nullptr;
}
Layer* layer = layer_tree->LayerById(layer_id);
DCHECK(layer);
if (current_layer && current_layer != layer)
current_layer->SetLayerTreeHost(nullptr);
return layer;
}
} // namespace
LayerTree::Inputs::Inputs()
: top_controls_height(0.f),
top_controls_shown_ratio(0.f),
top_controls_shrink_blink_size(false),
bottom_controls_height(0.f),
device_scale_factor(1.f),
painted_device_scale_factor(1.f),
page_scale_factor(1.f),
min_page_scale_factor(1.f),
max_page_scale_factor(1.f),
background_color(SK_ColorWHITE),
has_transparent_background(false),
have_scroll_event_handlers(false),
event_listener_properties() {}
LayerTree::Inputs::~Inputs() = default;
LayerTree::LayerTree(std::unique_ptr<AnimationHost> animation_host,
LayerTreeHost* layer_tree_host)
: needs_full_tree_sync_(true),
needs_meta_info_recomputation_(true),
in_paint_layer_contents_(false),
animation_host_(std::move(animation_host)),
layer_tree_host_(layer_tree_host) {
DCHECK(animation_host_);
DCHECK(layer_tree_host_);
animation_host_->SetMutatorHostClient(this);
}
LayerTree::~LayerTree() {
animation_host_->SetMutatorHostClient(nullptr);
// We must clear any pointers into the layer tree prior to destroying it.
RegisterViewportLayers(nullptr, nullptr, nullptr, nullptr);
if (inputs_.root_layer) {
inputs_.root_layer->SetLayerTreeHost(nullptr);
// The root layer must be destroyed before the layer tree. We've made a
// contract with our animation controllers that the animation_host will
// outlive them, and we must make good.
inputs_.root_layer = nullptr;
}
}
void LayerTree::SetRootLayer(scoped_refptr<Layer> root_layer) {
if (inputs_.root_layer.get() == root_layer.get())
return;
if (inputs_.root_layer.get())
inputs_.root_layer->SetLayerTreeHost(nullptr);
inputs_.root_layer = root_layer;
if (inputs_.root_layer.get()) {
DCHECK(!inputs_.root_layer->parent());
inputs_.root_layer->SetLayerTreeHost(layer_tree_host_);
}
if (hud_layer_.get())
hud_layer_->RemoveFromParent();
// Reset gpu rasterization tracking.
// This flag is sticky until a new tree comes along.
layer_tree_host_->ResetGpuRasterizationTracking();
SetNeedsFullTreeSync();
}
void LayerTree::RegisterViewportLayers(
scoped_refptr<Layer> overscroll_elasticity_layer,
scoped_refptr<Layer> page_scale_layer,
scoped_refptr<Layer> inner_viewport_scroll_layer,
scoped_refptr<Layer> outer_viewport_scroll_layer) {
DCHECK(!inner_viewport_scroll_layer ||
inner_viewport_scroll_layer != outer_viewport_scroll_layer);
inputs_.overscroll_elasticity_layer = overscroll_elasticity_layer;
inputs_.page_scale_layer = page_scale_layer;
inputs_.inner_viewport_scroll_layer = inner_viewport_scroll_layer;
inputs_.outer_viewport_scroll_layer = outer_viewport_scroll_layer;
}
void LayerTree::RegisterSelection(const LayerSelection& selection) {
if (inputs_.selection == selection)
return;
inputs_.selection = selection;
SetNeedsCommit();
}
void LayerTree::SetHaveScrollEventHandlers(bool have_event_handlers) {
if (inputs_.have_scroll_event_handlers == have_event_handlers)
return;
inputs_.have_scroll_event_handlers = have_event_handlers;
SetNeedsCommit();
}
void LayerTree::SetEventListenerProperties(EventListenerClass event_class,
EventListenerProperties properties) {
const size_t index = static_cast<size_t>(event_class);
if (inputs_.event_listener_properties[index] == properties)
return;
inputs_.event_listener_properties[index] = properties;
SetNeedsCommit();
}
void LayerTree::SetViewportSize(const gfx::Size& device_viewport_size) {
if (inputs_.device_viewport_size == device_viewport_size)
return;
inputs_.device_viewport_size = device_viewport_size;
SetPropertyTreesNeedRebuild();
SetNeedsCommit();
}
void LayerTree::SetTopControlsHeight(float height, bool shrink) {
if (inputs_.top_controls_height == height &&
inputs_.top_controls_shrink_blink_size == shrink)
return;
inputs_.top_controls_height = height;
inputs_.top_controls_shrink_blink_size = shrink;
SetNeedsCommit();
}
void LayerTree::SetTopControlsShownRatio(float ratio) {
if (inputs_.top_controls_shown_ratio == ratio)
return;
inputs_.top_controls_shown_ratio = ratio;
SetNeedsCommit();
}
void LayerTree::SetBottomControlsHeight(float height) {
if (inputs_.bottom_controls_height == height)
return;
inputs_.bottom_controls_height = height;
SetNeedsCommit();
}
void LayerTree::SetPageScaleFactorAndLimits(float page_scale_factor,
float min_page_scale_factor,
float max_page_scale_factor) {
if (inputs_.page_scale_factor == page_scale_factor &&
inputs_.min_page_scale_factor == min_page_scale_factor &&
inputs_.max_page_scale_factor == max_page_scale_factor)
return;
inputs_.page_scale_factor = page_scale_factor;
inputs_.min_page_scale_factor = min_page_scale_factor;
inputs_.max_page_scale_factor = max_page_scale_factor;
SetPropertyTreesNeedRebuild();
SetNeedsCommit();
}
void LayerTree::StartPageScaleAnimation(const gfx::Vector2d& target_offset,
bool use_anchor,
float scale,
base::TimeDelta duration) {
inputs_.pending_page_scale_animation.reset(new PendingPageScaleAnimation(
target_offset, use_anchor, scale, duration));
SetNeedsCommit();
}
bool LayerTree::HasPendingPageScaleAnimation() const {
return !!inputs_.pending_page_scale_animation.get();
}
void LayerTree::SetDeviceScaleFactor(float device_scale_factor) {
if (inputs_.device_scale_factor == device_scale_factor)
return;
inputs_.device_scale_factor = device_scale_factor;
property_trees_.needs_rebuild = true;
SetNeedsCommit();
}
void LayerTree::SetPaintedDeviceScaleFactor(float painted_device_scale_factor) {
if (inputs_.painted_device_scale_factor == painted_device_scale_factor)
return;
inputs_.painted_device_scale_factor = painted_device_scale_factor;
SetNeedsCommit();
}
void LayerTree::SetDeviceColorSpace(const gfx::ColorSpace& device_color_space) {
if (inputs_.device_color_space == device_color_space)
return;
inputs_.device_color_space = device_color_space;
LayerTreeHostCommon::CallFunctionForEveryLayer(
this, [](Layer* layer) { layer->SetNeedsDisplay(); });
}
void LayerTree::RegisterLayer(Layer* layer) {
DCHECK(!LayerById(layer->id()));
DCHECK(!in_paint_layer_contents_);
layer_id_map_[layer->id()] = layer;
if (layer->element_id()) {
animation_host_->RegisterElement(layer->element_id(),
ElementListType::ACTIVE);
}
}
void LayerTree::UnregisterLayer(Layer* layer) {
DCHECK(LayerById(layer->id()));
DCHECK(!in_paint_layer_contents_);
if (layer->element_id()) {
animation_host_->UnregisterElement(layer->element_id(),
ElementListType::ACTIVE);
}
RemoveLayerShouldPushProperties(layer);
layer_id_map_.erase(layer->id());
}
Layer* LayerTree::LayerById(int id) const {
LayerIdMap::const_iterator iter = layer_id_map_.find(id);
return iter != layer_id_map_.end() ? iter->second : nullptr;
}
bool LayerTree::UpdateLayers(const LayerList& update_layer_list,
bool* content_is_suitable_for_gpu) {
base::AutoReset<bool> painting(&in_paint_layer_contents_, true);
bool did_paint_content = false;
for (const auto& layer : update_layer_list) {
did_paint_content |= layer->Update();
*content_is_suitable_for_gpu &= layer->IsSuitableForGpuRasterization();
}
return did_paint_content;
}
void LayerTree::AddLayerShouldPushProperties(Layer* layer) {
layers_that_should_push_properties_.insert(layer);
}
void LayerTree::RemoveLayerShouldPushProperties(Layer* layer) {
layers_that_should_push_properties_.erase(layer);
}
std::unordered_set<Layer*>& LayerTree::LayersThatShouldPushProperties() {
return layers_that_should_push_properties_;
}
bool LayerTree::LayerNeedsPushPropertiesForTesting(Layer* layer) const {
return layers_that_should_push_properties_.find(layer) !=
layers_that_should_push_properties_.end();
}
void LayerTree::SetNeedsMetaInfoRecomputation(bool needs_recomputation) {
needs_meta_info_recomputation_ = needs_recomputation;
}
void LayerTree::SetPageScaleFromImplSide(float page_scale) {
DCHECK(layer_tree_host_->CommitRequested());
inputs_.page_scale_factor = page_scale;
SetPropertyTreesNeedRebuild();
}
void LayerTree::SetElasticOverscrollFromImplSide(
gfx::Vector2dF elastic_overscroll) {
DCHECK(layer_tree_host_->CommitRequested());
elastic_overscroll_ = elastic_overscroll;
}
void LayerTree::UpdateHudLayer(bool show_hud_info) {
if (show_hud_info) {
if (!hud_layer_.get()) {
hud_layer_ = HeadsUpDisplayLayer::Create();
}
if (inputs_.root_layer.get() && !hud_layer_->parent())
inputs_.root_layer->AddChild(hud_layer_);
} else if (hud_layer_.get()) {
hud_layer_->RemoveFromParent();
hud_layer_ = nullptr;
}
}
void LayerTree::SetNeedsFullTreeSync() {
needs_full_tree_sync_ = true;
needs_meta_info_recomputation_ = true;
property_trees_.needs_rebuild = true;
SetNeedsCommit();
}
void LayerTree::SetNeedsCommit() {
layer_tree_host_->SetNeedsCommit();
}
const LayerTreeSettings& LayerTree::GetSettings() const {
return layer_tree_host_->GetSettings();
}
void LayerTree::SetPropertyTreesNeedRebuild() {
property_trees_.needs_rebuild = true;
layer_tree_host_->SetNeedsUpdateLayers();
}
void LayerTree::PushPropertiesTo(LayerTreeImpl* tree_impl) {
tree_impl->set_needs_full_tree_sync(needs_full_tree_sync_);
needs_full_tree_sync_ = false;
if (hud_layer_.get()) {
LayerImpl* hud_impl = tree_impl->LayerById(hud_layer_->id());
tree_impl->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(hud_impl));
} else {
tree_impl->set_hud_layer(nullptr);
}
tree_impl->set_background_color(inputs_.background_color);
tree_impl->set_has_transparent_background(inputs_.has_transparent_background);
tree_impl->set_have_scroll_event_handlers(inputs_.have_scroll_event_handlers);
tree_impl->set_event_listener_properties(
EventListenerClass::kTouchStartOrMove,
event_listener_properties(EventListenerClass::kTouchStartOrMove));
tree_impl->set_event_listener_properties(
EventListenerClass::kMouseWheel,
event_listener_properties(EventListenerClass::kMouseWheel));
tree_impl->set_event_listener_properties(
EventListenerClass::kTouchEndOrCancel,
event_listener_properties(EventListenerClass::kTouchEndOrCancel));
if (inputs_.page_scale_layer && inputs_.inner_viewport_scroll_layer) {
tree_impl->SetViewportLayersFromIds(
inputs_.overscroll_elasticity_layer
? inputs_.overscroll_elasticity_layer->id()
: Layer::INVALID_ID,
inputs_.page_scale_layer->id(),
inputs_.inner_viewport_scroll_layer->id(),
inputs_.outer_viewport_scroll_layer
? inputs_.outer_viewport_scroll_layer->id()
: Layer::INVALID_ID);
DCHECK(inputs_.inner_viewport_scroll_layer
->IsContainerForFixedPositionLayers());
} else {
tree_impl->ClearViewportLayers();
}
tree_impl->RegisterSelection(inputs_.selection);
bool property_trees_changed_on_active_tree =
tree_impl->IsActiveTree() && tree_impl->property_trees()->changed;
// Property trees may store damage status. We preserve the sync tree damage
// status by pushing the damage status from sync tree property trees to main
// thread property trees or by moving it onto the layers.
if (inputs_.root_layer && property_trees_changed_on_active_tree) {
if (property_trees_.sequence_number ==
tree_impl->property_trees()->sequence_number)
tree_impl->property_trees()->PushChangeTrackingTo(&property_trees_);
else
tree_impl->MoveChangeTrackingToLayers();
}
// Setting property trees must happen before pushing the page scale.
tree_impl->SetPropertyTrees(&property_trees_);
tree_impl->PushPageScaleFromMainThread(inputs_.page_scale_factor,
inputs_.min_page_scale_factor,
inputs_.max_page_scale_factor);
tree_impl->set_top_controls_shrink_blink_size(
inputs_.top_controls_shrink_blink_size);
tree_impl->set_top_controls_height(inputs_.top_controls_height);
tree_impl->set_bottom_controls_height(inputs_.bottom_controls_height);
tree_impl->PushTopControlsFromMainThread(inputs_.top_controls_shown_ratio);
tree_impl->elastic_overscroll()->PushFromMainThread(elastic_overscroll_);
if (tree_impl->IsActiveTree())
tree_impl->elastic_overscroll()->PushPendingToActive();
tree_impl->set_painted_device_scale_factor(
inputs_.painted_device_scale_factor);
tree_impl->SetDeviceColorSpace(inputs_.device_color_space);
if (inputs_.pending_page_scale_animation) {
tree_impl->SetPendingPageScaleAnimation(
std::move(inputs_.pending_page_scale_animation));
}
DCHECK(!tree_impl->ViewportSizeInvalid());
tree_impl->set_has_ever_been_drawn(false);
}
void LayerTree::ToProtobuf(proto::LayerTree* proto) {
LayerProtoConverter::SerializeLayerHierarchy(inputs_.root_layer,
proto->mutable_root_layer());
for (auto* layer : layers_that_should_push_properties_) {
proto->add_layers_that_should_push_properties(layer->id());
}
proto->set_in_paint_layer_contents(in_paint_layer_contents());
proto->set_needs_full_tree_sync(needs_full_tree_sync_);
proto->set_needs_meta_info_recomputation(needs_meta_info_recomputation_);
proto->set_hud_layer_id(hud_layer_ ? hud_layer_->id() : Layer::INVALID_ID);
// Viewport layers.
proto->set_overscroll_elasticity_layer_id(
inputs_.overscroll_elasticity_layer
? inputs_.overscroll_elasticity_layer->id()
: Layer::INVALID_ID);
proto->set_page_scale_layer_id(inputs_.page_scale_layer
? inputs_.page_scale_layer->id()
: Layer::INVALID_ID);
proto->set_inner_viewport_scroll_layer_id(
inputs_.inner_viewport_scroll_layer
? inputs_.inner_viewport_scroll_layer->id()
: Layer::INVALID_ID);
proto->set_outer_viewport_scroll_layer_id(
inputs_.outer_viewport_scroll_layer
? inputs_.outer_viewport_scroll_layer->id()
: Layer::INVALID_ID);
SizeToProto(inputs_.device_viewport_size,
proto->mutable_device_viewport_size());
proto->set_top_controls_shrink_blink_size(
inputs_.top_controls_shrink_blink_size);
proto->set_top_controls_height(inputs_.top_controls_height);
proto->set_top_controls_shown_ratio(inputs_.top_controls_shown_ratio);
proto->set_device_scale_factor(inputs_.device_scale_factor);
proto->set_painted_device_scale_factor(inputs_.painted_device_scale_factor);
proto->set_page_scale_factor(inputs_.page_scale_factor);
proto->set_min_page_scale_factor(inputs_.min_page_scale_factor);
proto->set_max_page_scale_factor(inputs_.max_page_scale_factor);
proto->set_background_color(inputs_.background_color);
proto->set_has_transparent_background(inputs_.has_transparent_background);
proto->set_have_scroll_event_handlers(inputs_.have_scroll_event_handlers);
proto->set_wheel_event_listener_properties(static_cast<uint32_t>(
event_listener_properties(EventListenerClass::kMouseWheel)));
proto->set_touch_start_or_move_event_listener_properties(
static_cast<uint32_t>(
event_listener_properties(EventListenerClass::kTouchStartOrMove)));
proto->set_touch_end_or_cancel_event_listener_properties(
static_cast<uint32_t>(
event_listener_properties(EventListenerClass::kTouchEndOrCancel)));
LayerSelectionToProtobuf(inputs_.selection, proto->mutable_selection());
property_trees_.ToProtobuf(proto->mutable_property_trees());
Vector2dFToProto(elastic_overscroll_, proto->mutable_elastic_overscroll());
}
void LayerTree::FromProtobuf(const proto::LayerTree& proto) {
// Layer hierarchy.
scoped_refptr<Layer> new_root_layer =
LayerProtoConverter::DeserializeLayerHierarchy(
inputs_.root_layer, proto.root_layer(), layer_tree_host_);
if (inputs_.root_layer != new_root_layer) {
inputs_.root_layer = new_root_layer;
}
for (auto layer_id : proto.layers_that_should_push_properties()) {
AddLayerShouldPushProperties(layer_id_map_[layer_id]);
}
in_paint_layer_contents_ = proto.in_paint_layer_contents();
needs_full_tree_sync_ = proto.needs_full_tree_sync();
needs_meta_info_recomputation_ = proto.needs_meta_info_recomputation();
inputs_.overscroll_elasticity_layer =
UpdateAndGetLayer(inputs_.overscroll_elasticity_layer.get(),
proto.overscroll_elasticity_layer_id(), this);
inputs_.page_scale_layer = UpdateAndGetLayer(
inputs_.page_scale_layer.get(), proto.page_scale_layer_id(), this);
inputs_.inner_viewport_scroll_layer =
UpdateAndGetLayer(inputs_.inner_viewport_scroll_layer.get(),
proto.inner_viewport_scroll_layer_id(), this);
inputs_.outer_viewport_scroll_layer =
UpdateAndGetLayer(inputs_.outer_viewport_scroll_layer.get(),
proto.outer_viewport_scroll_layer_id(), this);
inputs_.device_viewport_size = ProtoToSize(proto.device_viewport_size());
inputs_.top_controls_shrink_blink_size =
proto.top_controls_shrink_blink_size();
inputs_.top_controls_height = proto.top_controls_height();
inputs_.top_controls_shown_ratio = proto.top_controls_shown_ratio();
inputs_.device_scale_factor = proto.device_scale_factor();
inputs_.painted_device_scale_factor = proto.painted_device_scale_factor();
inputs_.page_scale_factor = proto.page_scale_factor();
inputs_.min_page_scale_factor = proto.min_page_scale_factor();
inputs_.max_page_scale_factor = proto.max_page_scale_factor();
inputs_.background_color = proto.background_color();
inputs_.has_transparent_background = proto.has_transparent_background();
inputs_.have_scroll_event_handlers = proto.have_scroll_event_handlers();
inputs_.event_listener_properties[static_cast<size_t>(
EventListenerClass::kMouseWheel)] =
static_cast<EventListenerProperties>(
proto.wheel_event_listener_properties());
inputs_.event_listener_properties[static_cast<size_t>(
EventListenerClass::kTouchStartOrMove)] =
static_cast<EventListenerProperties>(
proto.touch_start_or_move_event_listener_properties());
inputs_.event_listener_properties[static_cast<size_t>(
EventListenerClass::kTouchEndOrCancel)] =
static_cast<EventListenerProperties>(
proto.touch_end_or_cancel_event_listener_properties());
hud_layer_ = static_cast<HeadsUpDisplayLayer*>(
UpdateAndGetLayer(hud_layer_.get(), proto.hud_layer_id(), this));
LayerSelectionFromProtobuf(&inputs_.selection, proto.selection());
elastic_overscroll_ = ProtoToVector2dF(proto.elastic_overscroll());
// It is required to create new PropertyTrees before deserializing it.
property_trees_ = PropertyTrees();
property_trees_.FromProtobuf(proto.property_trees());
// Forcefully override the sequence number of all layers in the tree to have
// a valid sequence number. Changing the sequence number for a layer does not
// need a commit, so the value will become out of date for layers that are not
// updated for other reasons. All layers that at this point are part of the
// layer tree are valid, so it is OK that they have a valid sequence number.
int seq_num = property_trees_.sequence_number;
LayerTreeHostCommon::CallFunctionForEveryLayer(this, [seq_num](Layer* layer) {
layer->set_property_tree_sequence_number(seq_num);
});
}
Layer* LayerTree::LayerByElementId(ElementId element_id) const {
ElementLayersMap::const_iterator iter = element_layers_map_.find(element_id);
return iter != element_layers_map_.end() ? iter->second : nullptr;
}
void LayerTree::RegisterElement(ElementId element_id,
ElementListType list_type,
Layer* layer) {
if (layer->element_id()) {
element_layers_map_[layer->element_id()] = layer;
}
animation_host_->RegisterElement(element_id, list_type);
}
void LayerTree::UnregisterElement(ElementId element_id,
ElementListType list_type,
Layer* layer) {
animation_host_->UnregisterElement(element_id, list_type);
if (layer->element_id()) {
element_layers_map_.erase(layer->element_id());
}
}
static void SetElementIdForTesting(Layer* layer) {
layer->SetElementId(LayerIdToElementIdForTesting(layer->id()));
}
void LayerTree::SetElementIdsForTesting() {
LayerTreeHostCommon::CallFunctionForEveryLayer(this, SetElementIdForTesting);
}
void LayerTree::BuildPropertyTreesForTesting() {
PropertyTreeBuilder::PreCalculateMetaInformation(root_layer());
gfx::Transform identity_transform;
PropertyTreeBuilder::BuildPropertyTrees(
root_layer(), page_scale_layer(), inner_viewport_scroll_layer(),
outer_viewport_scroll_layer(), overscroll_elasticity_layer(),
elastic_overscroll(), page_scale_factor(), device_scale_factor(),
gfx::Rect(device_viewport_size()), identity_transform, property_trees());
}
bool LayerTree::IsElementInList(ElementId element_id,
ElementListType list_type) const {
return list_type == ElementListType::ACTIVE && LayerByElementId(element_id);
}
void LayerTree::SetMutatorsNeedCommit() {
layer_tree_host_->SetNeedsCommit();
}
void LayerTree::SetMutatorsNeedRebuildPropertyTrees() {
property_trees_.needs_rebuild = true;
}
void LayerTree::SetElementFilterMutated(ElementId element_id,
ElementListType list_type,
const FilterOperations& filters) {
Layer* layer = LayerByElementId(element_id);
DCHECK(layer);
layer->OnFilterAnimated(filters);
}
void LayerTree::SetElementOpacityMutated(ElementId element_id,
ElementListType list_type,
float opacity) {
Layer* layer = LayerByElementId(element_id);
DCHECK(layer);
layer->OnOpacityAnimated(opacity);
}
void LayerTree::SetElementTransformMutated(ElementId element_id,
ElementListType list_type,
const gfx::Transform& transform) {
Layer* layer = LayerByElementId(element_id);
DCHECK(layer);
layer->OnTransformAnimated(transform);
}
void LayerTree::SetElementScrollOffsetMutated(
ElementId element_id,
ElementListType list_type,
const gfx::ScrollOffset& scroll_offset) {
Layer* layer = LayerByElementId(element_id);
DCHECK(layer);
layer->OnScrollOffsetAnimated(scroll_offset);
}
void LayerTree::ElementTransformIsAnimatingChanged(
ElementId element_id,
ElementListType list_type,
AnimationChangeType change_type,
bool is_animating) {
Layer* layer = LayerByElementId(element_id);
if (layer) {
switch (change_type) {
case AnimationChangeType::POTENTIAL:
layer->OnTransformIsPotentiallyAnimatingChanged(is_animating);
break;
case AnimationChangeType::RUNNING:
layer->OnTransformIsCurrentlyAnimatingChanged(is_animating);
break;
case AnimationChangeType::BOTH:
layer->OnTransformIsPotentiallyAnimatingChanged(is_animating);
layer->OnTransformIsCurrentlyAnimatingChanged(is_animating);
break;
}
}
}
void LayerTree::ElementOpacityIsAnimatingChanged(
ElementId element_id,
ElementListType list_type,
AnimationChangeType change_type,
bool is_animating) {
Layer* layer = LayerByElementId(element_id);
if (layer) {
switch (change_type) {
case AnimationChangeType::POTENTIAL:
layer->OnOpacityIsPotentiallyAnimatingChanged(is_animating);
break;
case AnimationChangeType::RUNNING:
layer->OnOpacityIsCurrentlyAnimatingChanged(is_animating);
break;
case AnimationChangeType::BOTH:
layer->OnOpacityIsPotentiallyAnimatingChanged(is_animating);
layer->OnOpacityIsCurrentlyAnimatingChanged(is_animating);
break;
}
}
}
void LayerTree::ElementFilterIsAnimatingChanged(ElementId element_id,
ElementListType list_type,
AnimationChangeType change_type,
bool is_animating) {
Layer* layer = LayerByElementId(element_id);
if (layer) {
switch (change_type) {
case AnimationChangeType::POTENTIAL:
layer->OnFilterIsPotentiallyAnimatingChanged(is_animating);
break;
case AnimationChangeType::RUNNING:
layer->OnFilterIsCurrentlyAnimatingChanged(is_animating);
break;
case AnimationChangeType::BOTH:
layer->OnFilterIsPotentiallyAnimatingChanged(is_animating);
layer->OnFilterIsCurrentlyAnimatingChanged(is_animating);
break;
}
}
}
gfx::ScrollOffset LayerTree::GetScrollOffsetForAnimation(
ElementId element_id) const {
Layer* layer = LayerByElementId(element_id);
DCHECK(layer);
return layer->ScrollOffsetForAnimation();
}
LayerListIterator<Layer> LayerTree::begin() const {
return LayerListIterator<Layer>(inputs_.root_layer.get());
}
LayerListIterator<Layer> LayerTree::end() const {
return LayerListIterator<Layer>(nullptr);
}
LayerListReverseIterator<Layer> LayerTree::rbegin() {
return LayerListReverseIterator<Layer>(inputs_.root_layer.get());
}
LayerListReverseIterator<Layer> LayerTree::rend() {
return LayerListReverseIterator<Layer>(nullptr);
}
void LayerTree::SetNeedsDisplayOnAllLayers() {
for (auto* layer : *this)
layer->SetNeedsDisplay();
}
} // namespace cc