Index: cc/trees/property_tree.cc |
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc |
index 1b0b5954a547fef475042fc8985caa199747098d..891ce85628624a141f631f89ceff4d9bcedc0216 100644 |
--- a/cc/trees/property_tree.cc |
+++ b/cc/trees/property_tree.cc |
@@ -1115,28 +1115,20 @@ ScrollTree::~ScrollTree() {} |
ScrollTree& ScrollTree::operator=(const ScrollTree& from) { |
PropertyTree::operator=(from); |
currently_scrolling_node_id_ = kInvalidNodeId; |
- // layer_id_to_scroll_offset_map_ is intentionally omitted in operator=, |
- // because we do not want to simply copy the map when property tree is |
- // propagating from pending to active. |
- // In the main to pending case, we do want to copy it, but this can be done by |
- // calling UpdateScrollOffsetMap after the assignment; |
- // In the other case, we want pending and active property trees to share the |
- // same map. |
+ // Maps for ScrollOffsets/SyncedScrollOffsets are intentionally ommitted here |
+ // since we can not directly copy them. Pushing of these updates from main |
+ // currently depends on Layer properties for scroll offset animation changes |
+ // (setting clobber_active_value for scroll offset animations interrupted on |
+ // the main thread) being pushed to impl first. |
return *this; |
} |
bool ScrollTree::operator==(const ScrollTree& other) const { |
- const ScrollTree::ScrollOffsetMap& other_scroll_offset_map = |
- other.scroll_offset_map(); |
- if (layer_id_to_scroll_offset_map_.size() != other_scroll_offset_map.size()) |
+ if (layer_id_to_scroll_offset_map_ != other.layer_id_to_scroll_offset_map_) |
+ return false; |
+ if (layer_id_to_synced_scroll_offset_map_ != |
+ other.layer_id_to_synced_scroll_offset_map_) |
return false; |
- |
- for (auto map_entry : layer_id_to_scroll_offset_map_) { |
- int key = map_entry.first; |
- if (other_scroll_offset_map.find(key) == other_scroll_offset_map.end() || |
- map_entry.second != layer_id_to_scroll_offset_map_.at(key)) |
- return false; |
- } |
bool is_currently_scrolling_node_equal = |
currently_scrolling_node_id_ == other.currently_scrolling_node_id_; |
@@ -1144,6 +1136,17 @@ bool ScrollTree::operator==(const ScrollTree& other) const { |
return PropertyTree::operator==(other) && is_currently_scrolling_node_equal; |
} |
+#if DCHECK_IS_ON() |
+void ScrollTree::CopyCompleteTreeState(const ScrollTree& other) { |
+ currently_scrolling_node_id_ = other.currently_scrolling_node_id_; |
+ layer_id_to_scrollbars_enabled_map_ = |
+ other.layer_id_to_scrollbars_enabled_map_; |
+ layer_id_to_scroll_offset_map_ = other.layer_id_to_scroll_offset_map_; |
+ layer_id_to_synced_scroll_offset_map_ = |
+ other.layer_id_to_synced_scroll_offset_map_; |
+} |
+#endif |
+ |
void ScrollTree::clear() { |
PropertyTree<ScrollNode>::clear(); |
@@ -1155,8 +1158,10 @@ void ScrollTree::clear() { |
#if DCHECK_IS_ON() |
ScrollTree tree; |
if (!property_trees()->is_main_thread) { |
+ DCHECK(layer_id_to_scroll_offset_map_.empty()); |
tree.currently_scrolling_node_id_ = currently_scrolling_node_id_; |
- tree.layer_id_to_scroll_offset_map_ = layer_id_to_scroll_offset_map_; |
+ tree.layer_id_to_synced_scroll_offset_map_ = |
+ layer_id_to_synced_scroll_offset_map_; |
} |
DCHECK(tree == *this); |
#endif |
@@ -1269,25 +1274,34 @@ gfx::Transform ScrollTree::ScreenSpaceTransform(int scroll_node_id) const { |
return screen_space_transform; |
} |
-SyncedScrollOffset* ScrollTree::synced_scroll_offset(int layer_id) { |
- if (layer_id_to_scroll_offset_map_.find(layer_id) == |
- layer_id_to_scroll_offset_map_.end()) { |
- layer_id_to_scroll_offset_map_[layer_id] = new SyncedScrollOffset; |
+SyncedScrollOffset* ScrollTree::GetOrCreateSyncedScrollOffset(int layer_id) { |
+ DCHECK(!property_trees()->is_main_thread); |
+ if (layer_id_to_synced_scroll_offset_map_.find(layer_id) == |
+ layer_id_to_synced_scroll_offset_map_.end()) { |
+ layer_id_to_synced_scroll_offset_map_[layer_id] = new SyncedScrollOffset; |
} |
- return layer_id_to_scroll_offset_map_[layer_id].get(); |
+ return layer_id_to_synced_scroll_offset_map_[layer_id].get(); |
} |
-const SyncedScrollOffset* ScrollTree::synced_scroll_offset(int layer_id) const { |
- if (layer_id_to_scroll_offset_map_.find(layer_id) == |
- layer_id_to_scroll_offset_map_.end()) { |
+const SyncedScrollOffset* ScrollTree::GetSyncedScrollOffset( |
+ int layer_id) const { |
+ DCHECK(!property_trees()->is_main_thread); |
+ if (layer_id_to_synced_scroll_offset_map_.find(layer_id) == |
+ layer_id_to_synced_scroll_offset_map_.end()) { |
return nullptr; |
} |
- return layer_id_to_scroll_offset_map_.at(layer_id).get(); |
+ return layer_id_to_synced_scroll_offset_map_.at(layer_id).get(); |
} |
const gfx::ScrollOffset ScrollTree::current_scroll_offset(int layer_id) const { |
- return synced_scroll_offset(layer_id) |
- ? synced_scroll_offset(layer_id)->Current( |
+ if (property_trees()->is_main_thread) { |
+ ScrollOffsetMap::const_iterator it = |
+ layer_id_to_scroll_offset_map_.find(layer_id); |
+ return it != layer_id_to_scroll_offset_map_.end() ? it->second |
+ : gfx::ScrollOffset(); |
+ } |
+ return GetSyncedScrollOffset(layer_id) |
+ ? GetSyncedScrollOffset(layer_id)->Current( |
property_trees()->is_active) |
: gfx::ScrollOffset(); |
} |
@@ -1311,7 +1325,8 @@ gfx::ScrollOffset ScrollTree::PullDeltaForMainThread( |
void ScrollTree::CollectScrollDeltas(ScrollAndScaleSet* scroll_info, |
int inner_viewport_layer_id) { |
- for (auto map_entry : layer_id_to_scroll_offset_map_) { |
+ DCHECK(!property_trees()->is_main_thread); |
+ for (auto map_entry : layer_id_to_synced_scroll_offset_map_) { |
gfx::ScrollOffset scroll_delta = |
PullDeltaForMainThread(map_entry.second.get()); |
@@ -1334,88 +1349,97 @@ void ScrollTree::CollectScrollDeltas(ScrollAndScaleSet* scroll_info, |
} |
void ScrollTree::CollectScrollDeltasForTesting() { |
- for (auto map_entry : layer_id_to_scroll_offset_map_) { |
+ for (auto map_entry : layer_id_to_synced_scroll_offset_map_) { |
PullDeltaForMainThread(map_entry.second.get()); |
} |
} |
-void ScrollTree::UpdateScrollOffsetMapEntry( |
- int key, |
- ScrollTree::ScrollOffsetMap* new_scroll_offset_map, |
- LayerTreeImpl* layer_tree_impl) { |
- bool changed = false; |
- // If we are pushing scroll offset from main to pending tree, we create a new |
- // instance of synced scroll offset; if we are pushing from pending to active, |
- // we reuse the pending tree's value in the map. |
- if (!property_trees()->is_active) { |
- changed = synced_scroll_offset(key)->PushFromMainThread( |
- new_scroll_offset_map->at(key)->PendingBase()); |
- |
- if (new_scroll_offset_map->at(key)->clobber_active_value()) { |
- synced_scroll_offset(key)->set_clobber_active_value(); |
- } |
- if (changed) { |
- layer_tree_impl->DidUpdateScrollOffset(key); |
- } |
- } else { |
- layer_id_to_scroll_offset_map_[key] = new_scroll_offset_map->at(key); |
- changed |= synced_scroll_offset(key)->PushPendingToActive(); |
- if (changed) { |
- layer_tree_impl->DidUpdateScrollOffset(key); |
- } |
+void ScrollTree::PushScrollUpdatesFromMainThread( |
+ PropertyTrees* main_property_trees, |
+ LayerTreeImpl* sync_tree) { |
+ DCHECK(!property_trees()->is_main_thread); |
+ const ScrollOffsetMap& main_scroll_offset_map = |
+ main_property_trees->scroll_tree.layer_id_to_scroll_offset_map_; |
+ |
+ // We first want to clear SyncedProperty instances for layers which were |
+ // destroyed or became non-scrollable on the main thread. |
+ for (auto map_entry = layer_id_to_synced_scroll_offset_map_.begin(); |
+ map_entry != layer_id_to_synced_scroll_offset_map_.end();) { |
+ int layer_id = map_entry->first; |
+ if (main_scroll_offset_map.find(layer_id) == main_scroll_offset_map.end()) |
+ map_entry = layer_id_to_synced_scroll_offset_map_.erase(map_entry); |
+ else |
+ map_entry++; |
} |
-} |
-void ScrollTree::UpdateScrollOffsetMap( |
- ScrollTree::ScrollOffsetMap* new_scroll_offset_map, |
- LayerTreeImpl* layer_tree_impl) { |
- if (layer_tree_impl && !layer_tree_impl->LayerListIsEmpty()) { |
- DCHECK(!property_trees()->is_main_thread); |
- for (auto map_entry = layer_id_to_scroll_offset_map_.begin(); |
- map_entry != layer_id_to_scroll_offset_map_.end();) { |
- int key = map_entry->first; |
- if (new_scroll_offset_map->find(key) != new_scroll_offset_map->end()) { |
- UpdateScrollOffsetMapEntry(key, new_scroll_offset_map, layer_tree_impl); |
- ++map_entry; |
- } else { |
- map_entry = layer_id_to_scroll_offset_map_.erase(map_entry); |
- } |
- } |
+ for (auto map_entry : main_scroll_offset_map) { |
+ int layer_id = map_entry.first; |
+ SyncedScrollOffset* synced_scroll_offset = |
+ GetOrCreateSyncedScrollOffset(layer_id); |
- for (auto& map_entry : *new_scroll_offset_map) { |
- int key = map_entry.first; |
- if (layer_id_to_scroll_offset_map_.find(key) == |
- layer_id_to_scroll_offset_map_.end()) |
- UpdateScrollOffsetMapEntry(key, new_scroll_offset_map, layer_tree_impl); |
- } |
- } |
-} |
+ bool changed = synced_scroll_offset->PushFromMainThread(map_entry.second); |
+ // If we are committing directly to the active tree, push pending to active |
+ // here. |
+ if (property_trees()->is_active) |
+ changed |= synced_scroll_offset->PushPendingToActive(); |
-ScrollTree::ScrollOffsetMap& ScrollTree::scroll_offset_map() { |
- return layer_id_to_scroll_offset_map_; |
+ if (changed) |
+ sync_tree->DidUpdateScrollOffset(layer_id); |
+ } |
} |
-const ScrollTree::ScrollOffsetMap& ScrollTree::scroll_offset_map() const { |
- return layer_id_to_scroll_offset_map_; |
+void ScrollTree::PushScrollUpdatesFromPendingTree( |
+ PropertyTrees* pending_property_trees, |
+ LayerTreeImpl* active_tree) { |
+ DCHECK(property_trees()->is_active); |
+ DCHECK(!pending_property_trees->is_main_thread); |
+ DCHECK(!pending_property_trees->is_active); |
+ |
+ // When pushing to the active tree, we can simply copy over the map from the |
+ // pending tree. The pending and active tree hold a reference to the same |
+ // SyncedProperty instances. |
+ layer_id_to_synced_scroll_offset_map_.clear(); |
+ for (auto map_entry : pending_property_trees->scroll_tree |
+ .layer_id_to_synced_scroll_offset_map_) { |
+ layer_id_to_synced_scroll_offset_map_[map_entry.first] = map_entry.second; |
+ if (map_entry.second->PushPendingToActive()) |
+ active_tree->DidUpdateScrollOffset(map_entry.first); |
+ } |
} |
void ScrollTree::ApplySentScrollDeltasFromAbortedCommit() { |
DCHECK(property_trees()->is_active); |
- for (auto& map_entry : layer_id_to_scroll_offset_map_) |
+ for (auto& map_entry : layer_id_to_synced_scroll_offset_map_) |
map_entry.second->AbortCommit(); |
} |
bool ScrollTree::SetBaseScrollOffset(int layer_id, |
const gfx::ScrollOffset& scroll_offset) { |
- return synced_scroll_offset(layer_id)->PushFromMainThread(scroll_offset); |
+ if (property_trees()->is_main_thread) { |
+ layer_id_to_scroll_offset_map_[layer_id] = scroll_offset; |
+ return true; |
+ } |
+ |
+ // Scroll offset updates on the impl thread should only be for layers which |
+ // were created on the main thread. But this method is called when we build |
+ // PropertyTrees on the impl thread from LayerTreeImpl. |
+ return GetOrCreateSyncedScrollOffset(layer_id)->PushFromMainThread( |
+ scroll_offset); |
} |
bool ScrollTree::SetScrollOffset(int layer_id, |
const gfx::ScrollOffset& scroll_offset) { |
- if (property_trees()->is_main_thread) |
- return synced_scroll_offset(layer_id)->PushFromMainThread(scroll_offset); |
- else if (property_trees()->is_active) |
- return synced_scroll_offset(layer_id)->SetCurrent(scroll_offset); |
+ if (property_trees()->is_main_thread) { |
+ if (layer_id_to_scroll_offset_map_[layer_id] == scroll_offset) |
+ return false; |
+ layer_id_to_scroll_offset_map_[layer_id] = scroll_offset; |
+ return true; |
+ } |
+ |
+ if (property_trees()->is_active) { |
+ return GetOrCreateSyncedScrollOffset(layer_id)->SetCurrent(scroll_offset); |
+ } |
+ |
return false; |
} |
@@ -1423,25 +1447,28 @@ bool ScrollTree::UpdateScrollOffsetBaseForTesting( |
int layer_id, |
const gfx::ScrollOffset& offset) { |
DCHECK(!property_trees()->is_main_thread); |
- bool changed = synced_scroll_offset(layer_id)->PushFromMainThread(offset); |
+ SyncedScrollOffset* synced_scroll_offset = |
+ GetOrCreateSyncedScrollOffset(layer_id); |
+ bool changed = synced_scroll_offset->PushFromMainThread(offset); |
if (property_trees()->is_active) |
- changed |= synced_scroll_offset(layer_id)->PushPendingToActive(); |
+ changed |= synced_scroll_offset->PushPendingToActive(); |
return changed; |
} |
bool ScrollTree::SetScrollOffsetDeltaForTesting(int layer_id, |
const gfx::Vector2dF& delta) { |
- return synced_scroll_offset(layer_id)->SetCurrent( |
- synced_scroll_offset(layer_id)->ActiveBase() + gfx::ScrollOffset(delta)); |
+ return GetOrCreateSyncedScrollOffset(layer_id)->SetCurrent( |
+ GetOrCreateSyncedScrollOffset(layer_id)->ActiveBase() + |
+ gfx::ScrollOffset(delta)); |
} |
const gfx::ScrollOffset ScrollTree::GetScrollOffsetBaseForTesting( |
int layer_id) const { |
DCHECK(!property_trees()->is_main_thread); |
- if (synced_scroll_offset(layer_id)) |
+ if (GetSyncedScrollOffset(layer_id)) |
return property_trees()->is_active |
- ? synced_scroll_offset(layer_id)->ActiveBase() |
- : synced_scroll_offset(layer_id)->PendingBase(); |
+ ? GetSyncedScrollOffset(layer_id)->ActiveBase() |
+ : GetSyncedScrollOffset(layer_id)->PendingBase(); |
else |
return gfx::ScrollOffset(); |
} |
@@ -1449,10 +1476,10 @@ const gfx::ScrollOffset ScrollTree::GetScrollOffsetBaseForTesting( |
const gfx::ScrollOffset ScrollTree::GetScrollOffsetDeltaForTesting( |
int layer_id) const { |
DCHECK(!property_trees()->is_main_thread); |
- if (synced_scroll_offset(layer_id)) |
+ if (GetSyncedScrollOffset(layer_id)) |
return property_trees()->is_active |
- ? synced_scroll_offset(layer_id)->Delta() |
- : synced_scroll_offset(layer_id)->PendingDelta().get(); |
+ ? GetSyncedScrollOffset(layer_id)->Delta() |
+ : GetSyncedScrollOffset(layer_id)->PendingDelta().get(); |
else |
return gfx::ScrollOffset(); |
} |
@@ -1601,12 +1628,7 @@ void PropertyTrees::clear() { |
tree.effect_tree = effect_tree; |
tree.clip_tree = clip_tree; |
tree.scroll_tree = scroll_tree; |
- // Scroll offset map and currently scrolling node id may not be copied |
- // during operator=. |
- ScrollTree::ScrollOffsetMap& map = tree.scroll_tree.scroll_offset_map(); |
- map = scroll_tree.scroll_offset_map(); |
- tree.scroll_tree.set_currently_scrolling_node( |
- scroll_tree.CurrentlyScrollingNodeId()); |
+ tree.scroll_tree.CopyCompleteTreeState(scroll_tree); |
tree.sequence_number = sequence_number; |
tree.is_main_thread = is_main_thread; |