| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 | 167 |
| 168 #if DCHECK_IS_ON() | 168 #if DCHECK_IS_ON() |
| 169 TransformTree tree; | 169 TransformTree tree; |
| 170 // TODO(jaydasika) : Move tests that expect source_to_parent_updates_allowed | 170 // TODO(jaydasika) : Move tests that expect source_to_parent_updates_allowed |
| 171 // to be true on impl thread to main thread and set it to is_main_thread here. | 171 // to be true on impl thread to main thread and set it to is_main_thread here. |
| 172 tree.source_to_parent_updates_allowed_ = source_to_parent_updates_allowed_; | 172 tree.source_to_parent_updates_allowed_ = source_to_parent_updates_allowed_; |
| 173 DCHECK(tree == *this); | 173 DCHECK(tree == *this); |
| 174 #endif | 174 #endif |
| 175 } | 175 } |
| 176 | 176 |
| 177 void TransformTree::set_needs_update(bool needs_update) { |
| 178 if (needs_update && !needs_update_) |
| 179 property_trees()->UpdateCachedNumber(); |
| 180 needs_update_ = needs_update; |
| 181 } |
| 182 |
| 177 bool TransformTree::ComputeTransform(int source_id, | 183 bool TransformTree::ComputeTransform(int source_id, |
| 178 int dest_id, | 184 int dest_id, |
| 179 gfx::Transform* transform) const { | 185 gfx::Transform* transform) const { |
| 180 transform->MakeIdentity(); | 186 transform->MakeIdentity(); |
| 181 | 187 |
| 182 if (source_id == dest_id) | 188 if (source_id == dest_id) |
| 183 return true; | 189 return true; |
| 184 | 190 |
| 185 if (source_id > dest_id) { | 191 if (source_id > dest_id) { |
| 186 CombineTransformsBetween(source_id, dest_id, transform); | 192 CombineTransformsBetween(source_id, dest_id, transform); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 TransformNode* node = Node(id); | 263 TransformNode* node = Node(id); |
| 258 node->transform_changed = false; | 264 node->transform_changed = false; |
| 259 } | 265 } |
| 260 } | 266 } |
| 261 | 267 |
| 262 void TransformTree::UpdateTransforms(int id) { | 268 void TransformTree::UpdateTransforms(int id) { |
| 263 TransformNode* node = Node(id); | 269 TransformNode* node = Node(id); |
| 264 TransformNode* parent_node = parent(node); | 270 TransformNode* parent_node = parent(node); |
| 265 TransformNode* target_node = Node(TargetId(id)); | 271 TransformNode* target_node = Node(TargetId(id)); |
| 266 TransformNode* source_node = Node(node->source_node_id); | 272 TransformNode* source_node = Node(node->source_node_id); |
| 267 property_trees()->UpdateCachedNumber(); | |
| 268 // TODO(flackr): Only dirty when scroll offset changes. | 273 // TODO(flackr): Only dirty when scroll offset changes. |
| 269 if (node->sticky_position_constraint_id >= 0 || | 274 if (node->sticky_position_constraint_id >= 0 || |
| 270 node->needs_local_transform_update || NeedsSourceToParentUpdate(node)) { | 275 node->needs_local_transform_update || NeedsSourceToParentUpdate(node)) { |
| 271 UpdateLocalTransform(node); | 276 UpdateLocalTransform(node); |
| 272 } else { | 277 } else { |
| 273 UndoSnapping(node); | 278 UndoSnapping(node); |
| 274 } | 279 } |
| 275 UpdateScreenSpaceTransform(node, parent_node, target_node); | 280 UpdateScreenSpaceTransform(node, parent_node, target_node); |
| 276 UpdateSurfaceContentsScale(node); | 281 UpdateSurfaceContentsScale(node); |
| 277 UpdateAnimationProperties(node, parent_node); | 282 UpdateAnimationProperties(node, parent_node); |
| 278 UpdateSnapping(node); | 283 UpdateSnapping(node); |
| 279 UpdateTargetSpaceTransform(node, target_node); | |
| 280 UpdateNodeAndAncestorsHaveIntegerTranslations(node, parent_node); | 284 UpdateNodeAndAncestorsHaveIntegerTranslations(node, parent_node); |
| 281 UpdateTransformChanged(node, parent_node, source_node); | 285 UpdateTransformChanged(node, parent_node, source_node); |
| 282 UpdateNodeAndAncestorsAreAnimatedOrInvertible(node, parent_node); | 286 UpdateNodeAndAncestorsAreAnimatedOrInvertible(node, parent_node); |
| 283 } | 287 } |
| 284 | 288 |
| 285 bool TransformTree::IsDescendant(int desc_id, int source_id) const { | 289 bool TransformTree::IsDescendant(int desc_id, int source_id) const { |
| 286 while (desc_id != source_id) { | 290 while (desc_id != source_id) { |
| 287 if (desc_id == kInvalidNodeId) | 291 if (desc_id == kInvalidNodeId) |
| 288 return false; | 292 return false; |
| 289 desc_id = Node(desc_id)->parent_id; | 293 desc_id = Node(desc_id)->parent_id; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 // surface contents scale baked in, but we need to compute an unscaled | 330 // surface contents scale baked in, but we need to compute an unscaled |
| 327 // transform. | 331 // transform. |
| 328 std::vector<int> source_to_destination; | 332 std::vector<int> source_to_destination; |
| 329 source_to_destination.push_back(current->id); | 333 source_to_destination.push_back(current->id); |
| 330 current = parent(current); | 334 current = parent(current); |
| 331 bool destination_has_non_zero_surface_contents_scale = | 335 bool destination_has_non_zero_surface_contents_scale = |
| 332 dest->surface_contents_scale.x() != 0.f && | 336 dest->surface_contents_scale.x() != 0.f && |
| 333 dest->surface_contents_scale.y() != 0.f; | 337 dest->surface_contents_scale.y() != 0.f; |
| 334 DCHECK(destination_has_non_zero_surface_contents_scale || | 338 DCHECK(destination_has_non_zero_surface_contents_scale || |
| 335 !dest->ancestors_are_invertible); | 339 !dest->ancestors_are_invertible); |
| 336 for (; current && current->id > dest_id; current = parent(current)) { | 340 for (; current && current->id > dest_id; current = parent(current)) |
| 337 if (destination_has_non_zero_surface_contents_scale && | |
| 338 TargetId(current->id) == dest_id && | |
| 339 ContentTargetId(current->id) == dest_id) | |
| 340 break; | |
| 341 source_to_destination.push_back(current->id); | 341 source_to_destination.push_back(current->id); |
| 342 } | |
| 343 | 342 |
| 344 gfx::Transform combined_transform; | 343 gfx::Transform combined_transform; |
| 345 if (current->id > dest_id) { | 344 if (current->id > dest_id) { |
| 346 // TODO(sunxd): Instead of using target space transform, only use to_parent | |
| 347 // here when we fully implement computing draw transforms on demand. | |
| 348 combined_transform = ToTarget(current->id, kInvalidNodeId); | |
| 349 // The stored target space transform has surface contents scale baked in, | 345 // The stored target space transform has surface contents scale baked in, |
| 350 // but we need the unscaled transform. | 346 // but we need the unscaled transform. |
| 351 combined_transform.matrix().postScale( | 347 combined_transform.matrix().postScale( |
| 352 1.0f / dest->surface_contents_scale.x(), | 348 1.0f / dest->surface_contents_scale.x(), |
| 353 1.0f / dest->surface_contents_scale.y(), 1.0f); | 349 1.0f / dest->surface_contents_scale.y(), 1.0f); |
| 354 } else if (current->id < dest_id) { | 350 } else if (current->id < dest_id) { |
| 355 // We have reached the lowest common ancestor of the source and destination | 351 // We have reached the lowest common ancestor of the source and destination |
| 356 // nodes. This case can occur when we are transforming between a node | 352 // nodes. This case can occur when we are transforming between a node |
| 357 // corresponding to a fixed-position layer (or its descendant) and the node | 353 // corresponding to a fixed-position layer (or its descendant) and the node |
| 358 // corresponding to the layer's render target. For example, consider the | 354 // corresponding to the layer's render target. For example, consider the |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 } | 756 } |
| 761 | 757 |
| 762 bool TransformTree::HasNodesAffectedByInnerViewportBoundsDelta() const { | 758 bool TransformTree::HasNodesAffectedByInnerViewportBoundsDelta() const { |
| 763 return !nodes_affected_by_inner_viewport_bounds_delta_.empty(); | 759 return !nodes_affected_by_inner_viewport_bounds_delta_.empty(); |
| 764 } | 760 } |
| 765 | 761 |
| 766 bool TransformTree::HasNodesAffectedByOuterViewportBoundsDelta() const { | 762 bool TransformTree::HasNodesAffectedByOuterViewportBoundsDelta() const { |
| 767 return !nodes_affected_by_outer_viewport_bounds_delta_.empty(); | 763 return !nodes_affected_by_outer_viewport_bounds_delta_.empty(); |
| 768 } | 764 } |
| 769 | 765 |
| 770 const gfx::Transform& TransformTree::FromTarget(int node_id, | 766 gfx::Transform TransformTree::FromTarget(int node_id, int effect_id) const { |
| 771 int effect_id) const { | 767 gfx::Transform from_target; |
| 772 DCHECK(static_cast<int>(cached_data_.size()) > node_id); | 768 property_trees()->GetFromTarget(node_id, effect_id, &from_target); |
| 773 if (effect_id != kInvalidNodeId && | 769 return from_target; |
| 774 property_trees()->verify_transform_tree_calculations) { | |
| 775 const gfx::Transform& transform = | |
| 776 property_trees()->GetDrawTransforms(node_id, effect_id).from_target; | |
| 777 CHECK(transform.ApproximatelyEqual(cached_data_[node_id].from_target)); | |
| 778 } | |
| 779 return cached_data_[node_id].from_target; | |
| 780 } | 770 } |
| 781 | 771 |
| 782 void TransformTree::SetFromTarget(int node_id, | 772 void TransformTree::SetFromTarget(int node_id, |
| 783 const gfx::Transform& transform) { | 773 const gfx::Transform& transform) { |
| 784 DCHECK(static_cast<int>(cached_data_.size()) > node_id); | 774 DCHECK(static_cast<int>(cached_data_.size()) > node_id); |
| 785 cached_data_[node_id].from_target = transform; | 775 cached_data_[node_id].from_target = transform; |
| 786 } | 776 } |
| 787 | 777 |
| 788 const gfx::Transform& TransformTree::ToTarget(int node_id, | 778 gfx::Transform TransformTree::ToTarget(int node_id, int effect_id) const { |
| 789 int effect_id) const { | 779 gfx::Transform to_target; |
| 790 DCHECK(static_cast<int>(cached_data_.size()) > node_id); | 780 property_trees()->GetToTarget(node_id, effect_id, &to_target); |
| 791 if (effect_id != kInvalidNodeId && | 781 return to_target; |
| 792 property_trees()->verify_transform_tree_calculations) { | |
| 793 const gfx::Transform& transform = | |
| 794 property_trees()->GetDrawTransforms(node_id, effect_id).to_target; | |
| 795 if (property_trees()->non_root_surfaces_enabled) | |
| 796 CHECK(transform.ApproximatelyEqual(cached_data_[node_id].to_target)); | |
| 797 else | |
| 798 CHECK(transform.ApproximatelyEqual(cached_data_[node_id].to_screen)); | |
| 799 } | |
| 800 return cached_data_[node_id].to_target; | |
| 801 } | 782 } |
| 802 | 783 |
| 803 void TransformTree::SetToTarget(int node_id, const gfx::Transform& transform) { | 784 void TransformTree::SetToTarget(int node_id, const gfx::Transform& transform) { |
| 804 DCHECK(static_cast<int>(cached_data_.size()) > node_id); | 785 DCHECK(static_cast<int>(cached_data_.size()) > node_id); |
| 805 cached_data_[node_id].to_target = transform; | 786 cached_data_[node_id].to_target = transform; |
| 806 } | 787 } |
| 807 | 788 |
| 808 const gfx::Transform& TransformTree::FromScreen(int node_id) const { | 789 const gfx::Transform& TransformTree::FromScreen(int node_id) const { |
| 809 DCHECK(static_cast<int>(cached_data_.size()) > node_id); | 790 DCHECK(static_cast<int>(cached_data_.size()) > node_id); |
| 810 return cached_data_[node_id].from_screen; | 791 return cached_data_[node_id].from_screen; |
| (...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1746 | 1727 |
| 1747 PropertyTreesCachedData::~PropertyTreesCachedData() {} | 1728 PropertyTreesCachedData::~PropertyTreesCachedData() {} |
| 1748 | 1729 |
| 1749 PropertyTrees::PropertyTrees() | 1730 PropertyTrees::PropertyTrees() |
| 1750 : needs_rebuild(true), | 1731 : needs_rebuild(true), |
| 1751 non_root_surfaces_enabled(true), | 1732 non_root_surfaces_enabled(true), |
| 1752 changed(false), | 1733 changed(false), |
| 1753 full_tree_damaged(false), | 1734 full_tree_damaged(false), |
| 1754 sequence_number(0), | 1735 sequence_number(0), |
| 1755 is_main_thread(true), | 1736 is_main_thread(true), |
| 1756 is_active(false), | 1737 is_active(false) { |
| 1757 verify_transform_tree_calculations(false) { | |
| 1758 transform_tree.SetPropertyTrees(this); | 1738 transform_tree.SetPropertyTrees(this); |
| 1759 effect_tree.SetPropertyTrees(this); | 1739 effect_tree.SetPropertyTrees(this); |
| 1760 clip_tree.SetPropertyTrees(this); | 1740 clip_tree.SetPropertyTrees(this); |
| 1761 scroll_tree.SetPropertyTrees(this); | 1741 scroll_tree.SetPropertyTrees(this); |
| 1762 } | 1742 } |
| 1763 | 1743 |
| 1764 PropertyTrees::~PropertyTrees() {} | 1744 PropertyTrees::~PropertyTrees() {} |
| 1765 | 1745 |
| 1766 bool PropertyTrees::operator==(const PropertyTrees& other) const { | 1746 bool PropertyTrees::operator==(const PropertyTrees& other) const { |
| 1767 return transform_tree == other.transform_tree && | 1747 return transform_tree == other.transform_tree && |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1792 from.always_use_active_tree_opacity_effect_ids; | 1772 from.always_use_active_tree_opacity_effect_ids; |
| 1793 clip_id_to_index_map = from.clip_id_to_index_map; | 1773 clip_id_to_index_map = from.clip_id_to_index_map; |
| 1794 scroll_id_to_index_map = from.scroll_id_to_index_map; | 1774 scroll_id_to_index_map = from.scroll_id_to_index_map; |
| 1795 needs_rebuild = from.needs_rebuild; | 1775 needs_rebuild = from.needs_rebuild; |
| 1796 changed = from.changed; | 1776 changed = from.changed; |
| 1797 full_tree_damaged = from.full_tree_damaged; | 1777 full_tree_damaged = from.full_tree_damaged; |
| 1798 non_root_surfaces_enabled = from.non_root_surfaces_enabled; | 1778 non_root_surfaces_enabled = from.non_root_surfaces_enabled; |
| 1799 sequence_number = from.sequence_number; | 1779 sequence_number = from.sequence_number; |
| 1800 is_main_thread = from.is_main_thread; | 1780 is_main_thread = from.is_main_thread; |
| 1801 is_active = from.is_active; | 1781 is_active = from.is_active; |
| 1802 verify_transform_tree_calculations = from.verify_transform_tree_calculations; | |
| 1803 inner_viewport_container_bounds_delta_ = | 1782 inner_viewport_container_bounds_delta_ = |
| 1804 from.inner_viewport_container_bounds_delta(); | 1783 from.inner_viewport_container_bounds_delta(); |
| 1805 outer_viewport_container_bounds_delta_ = | 1784 outer_viewport_container_bounds_delta_ = |
| 1806 from.outer_viewport_container_bounds_delta(); | 1785 from.outer_viewport_container_bounds_delta(); |
| 1807 inner_viewport_scroll_bounds_delta_ = | 1786 inner_viewport_scroll_bounds_delta_ = |
| 1808 from.inner_viewport_scroll_bounds_delta(); | 1787 from.inner_viewport_scroll_bounds_delta(); |
| 1809 transform_tree.SetPropertyTrees(this); | 1788 transform_tree.SetPropertyTrees(this); |
| 1810 effect_tree.SetPropertyTrees(this); | 1789 effect_tree.SetPropertyTrees(this); |
| 1811 clip_tree.SetPropertyTrees(this); | 1790 clip_tree.SetPropertyTrees(this); |
| 1812 scroll_tree.SetPropertyTrees(this); | 1791 scroll_tree.SetPropertyTrees(this); |
| 1813 ResetCachedData(); | 1792 ResetCachedData(); |
| 1814 return *this; | 1793 return *this; |
| 1815 } | 1794 } |
| 1816 | 1795 |
| 1817 void PropertyTrees::ToProtobuf(proto::PropertyTrees* proto) const { | 1796 void PropertyTrees::ToProtobuf(proto::PropertyTrees* proto) const { |
| 1818 // TODO(khushalsagar): Add support for sending diffs when serializaing | 1797 // TODO(khushalsagar): Add support for sending diffs when serializaing |
| 1819 // property trees. See crbug/555370. | 1798 // property trees. See crbug/555370. |
| 1820 transform_tree.ToProtobuf(proto->mutable_transform_tree()); | 1799 transform_tree.ToProtobuf(proto->mutable_transform_tree()); |
| 1821 effect_tree.ToProtobuf(proto->mutable_effect_tree()); | 1800 effect_tree.ToProtobuf(proto->mutable_effect_tree()); |
| 1822 clip_tree.ToProtobuf(proto->mutable_clip_tree()); | 1801 clip_tree.ToProtobuf(proto->mutable_clip_tree()); |
| 1823 scroll_tree.ToProtobuf(proto->mutable_scroll_tree()); | 1802 scroll_tree.ToProtobuf(proto->mutable_scroll_tree()); |
| 1824 proto->set_needs_rebuild(needs_rebuild); | 1803 proto->set_needs_rebuild(needs_rebuild); |
| 1825 proto->set_changed(changed); | 1804 proto->set_changed(changed); |
| 1826 proto->set_full_tree_damaged(full_tree_damaged); | 1805 proto->set_full_tree_damaged(full_tree_damaged); |
| 1827 proto->set_non_root_surfaces_enabled(non_root_surfaces_enabled); | 1806 proto->set_non_root_surfaces_enabled(non_root_surfaces_enabled); |
| 1828 proto->set_is_main_thread(is_main_thread); | 1807 proto->set_is_main_thread(is_main_thread); |
| 1829 proto->set_is_active(is_active); | 1808 proto->set_is_active(is_active); |
| 1830 proto->set_verify_transform_tree_calculations( | |
| 1831 verify_transform_tree_calculations); | |
| 1832 | 1809 |
| 1833 // TODO(khushalsagar): Consider using the sequence number to decide if | 1810 // TODO(khushalsagar): Consider using the sequence number to decide if |
| 1834 // property trees need to be serialized again for a commit. See crbug/555370. | 1811 // property trees need to be serialized again for a commit. See crbug/555370. |
| 1835 proto->set_sequence_number(sequence_number); | 1812 proto->set_sequence_number(sequence_number); |
| 1836 | 1813 |
| 1837 for (auto i : always_use_active_tree_opacity_effect_ids) | 1814 for (auto i : always_use_active_tree_opacity_effect_ids) |
| 1838 proto->add_always_use_active_tree_opacity_effect_ids(i); | 1815 proto->add_always_use_active_tree_opacity_effect_ids(i); |
| 1839 } | 1816 } |
| 1840 | 1817 |
| 1841 // static | 1818 // static |
| 1842 void PropertyTrees::FromProtobuf(const proto::PropertyTrees& proto) { | 1819 void PropertyTrees::FromProtobuf(const proto::PropertyTrees& proto) { |
| 1843 transform_tree.FromProtobuf(proto.transform_tree(), | 1820 transform_tree.FromProtobuf(proto.transform_tree(), |
| 1844 &transform_id_to_index_map); | 1821 &transform_id_to_index_map); |
| 1845 effect_tree.FromProtobuf(proto.effect_tree(), &effect_id_to_index_map); | 1822 effect_tree.FromProtobuf(proto.effect_tree(), &effect_id_to_index_map); |
| 1846 clip_tree.FromProtobuf(proto.clip_tree(), &clip_id_to_index_map); | 1823 clip_tree.FromProtobuf(proto.clip_tree(), &clip_id_to_index_map); |
| 1847 scroll_tree.FromProtobuf(proto.scroll_tree(), &scroll_id_to_index_map); | 1824 scroll_tree.FromProtobuf(proto.scroll_tree(), &scroll_id_to_index_map); |
| 1848 | 1825 |
| 1849 needs_rebuild = proto.needs_rebuild(); | 1826 needs_rebuild = proto.needs_rebuild(); |
| 1850 changed = proto.changed(); | 1827 changed = proto.changed(); |
| 1851 full_tree_damaged = proto.full_tree_damaged(); | 1828 full_tree_damaged = proto.full_tree_damaged(); |
| 1852 non_root_surfaces_enabled = proto.non_root_surfaces_enabled(); | 1829 non_root_surfaces_enabled = proto.non_root_surfaces_enabled(); |
| 1853 sequence_number = proto.sequence_number(); | 1830 sequence_number = proto.sequence_number(); |
| 1854 is_main_thread = proto.is_main_thread(); | 1831 is_main_thread = proto.is_main_thread(); |
| 1855 is_active = proto.is_active(); | 1832 is_active = proto.is_active(); |
| 1856 verify_transform_tree_calculations = | |
| 1857 proto.verify_transform_tree_calculations(); | |
| 1858 | 1833 |
| 1859 transform_tree.SetPropertyTrees(this); | 1834 transform_tree.SetPropertyTrees(this); |
| 1860 effect_tree.SetPropertyTrees(this); | 1835 effect_tree.SetPropertyTrees(this); |
| 1861 clip_tree.SetPropertyTrees(this); | 1836 clip_tree.SetPropertyTrees(this); |
| 1862 scroll_tree.SetPropertyTrees(this); | 1837 scroll_tree.SetPropertyTrees(this); |
| 1863 for (auto i : proto.always_use_active_tree_opacity_effect_ids()) | 1838 for (auto i : proto.always_use_active_tree_opacity_effect_ids()) |
| 1864 always_use_active_tree_opacity_effect_ids.push_back(i); | 1839 always_use_active_tree_opacity_effect_ids.push_back(i); |
| 1865 } | 1840 } |
| 1866 | 1841 |
| 1867 void PropertyTrees::clear() { | 1842 void PropertyTrees::clear() { |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2075 !node->has_only_translation_animations || ancestor_is_animating_scale; | 2050 !node->has_only_translation_animations || ancestor_is_animating_scale; |
| 2076 | 2051 |
| 2077 // Once we've failed to compute a maximum animated scale at an ancestor, we | 2052 // Once we've failed to compute a maximum animated scale at an ancestor, we |
| 2078 // continue to fail. | 2053 // continue to fail. |
| 2079 bool failed_at_ancestor = | 2054 bool failed_at_ancestor = |
| 2080 ancestor_is_animating_scale && ancestor_maximum_target_scale == 0.f; | 2055 ancestor_is_animating_scale && ancestor_maximum_target_scale == 0.f; |
| 2081 | 2056 |
| 2082 // Computing maximum animated scale in the presence of non-scale/translation | 2057 // Computing maximum animated scale in the presence of non-scale/translation |
| 2083 // transforms isn't supported. | 2058 // transforms isn't supported. |
| 2084 bool failed_for_non_scale_or_translation = | 2059 bool failed_for_non_scale_or_translation = |
| 2085 !transform_tree.Node(transform_node_id) | 2060 !node->to_parent.IsScaleOrTranslation(); |
| 2086 ->to_parent.IsScaleOrTranslation(); | |
| 2087 | 2061 |
| 2088 // We don't attempt to accumulate animation scale from multiple nodes with | 2062 // We don't attempt to accumulate animation scale from multiple nodes with |
| 2089 // scale animations, because of the risk of significant overestimation. For | 2063 // scale animations, because of the risk of significant overestimation. For |
| 2090 // example, one node might be increasing scale from 1 to 10 at the same time | 2064 // example, one node might be increasing scale from 1 to 10 at the same time |
| 2091 // as another node is decreasing scale from 10 to 1. Naively combining these | 2065 // as another node is decreasing scale from 10 to 1. Naively combining these |
| 2092 // scales would produce a scale of 100. | 2066 // scales would produce a scale of 100. |
| 2093 bool failed_for_multiple_scale_animations = | 2067 bool failed_for_multiple_scale_animations = |
| 2094 ancestor_is_animating_scale && !node->has_only_translation_animations; | 2068 ancestor_is_animating_scale && !node->has_only_translation_animations; |
| 2095 | 2069 |
| 2096 if (failed_at_ancestor || failed_for_non_scale_or_translation || | 2070 if (failed_at_ancestor || failed_for_non_scale_or_translation || |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2181 float maximum_animation_scale, | 2155 float maximum_animation_scale, |
| 2182 float starting_animation_scale) { | 2156 float starting_animation_scale) { |
| 2183 cached_data_.animation_scales[transform_id] | 2157 cached_data_.animation_scales[transform_id] |
| 2184 .combined_maximum_animation_target_scale = maximum_animation_scale; | 2158 .combined_maximum_animation_target_scale = maximum_animation_scale; |
| 2185 cached_data_.animation_scales[transform_id] | 2159 cached_data_.animation_scales[transform_id] |
| 2186 .combined_starting_animation_scale = starting_animation_scale; | 2160 .combined_starting_animation_scale = starting_animation_scale; |
| 2187 cached_data_.animation_scales[transform_id].update_number = | 2161 cached_data_.animation_scales[transform_id].update_number = |
| 2188 cached_data_.property_tree_update_number; | 2162 cached_data_.property_tree_update_number; |
| 2189 } | 2163 } |
| 2190 | 2164 |
| 2191 const DrawTransforms& PropertyTrees::GetDrawTransforms(int transform_id, | 2165 bool PropertyTrees::GetToTarget(int transform_id, |
| 2192 int effect_id) const { | 2166 int effect_id, |
| 2193 if (cached_data_.draw_transforms[effect_id][transform_id].update_number != | 2167 gfx::Transform* to_target) const { |
| 2194 cached_data_.property_tree_update_number) { | 2168 DrawTransforms& transforms = GetDrawTransforms(transform_id, effect_id); |
| 2195 gfx::Transform target_space_transform; | 2169 if (transforms.to_valid) { |
| 2196 gfx::Transform from_target; | 2170 *to_target = transforms.to_target; |
| 2197 const TransformNode* transform_node = transform_tree.Node(transform_id); | 2171 return true; |
| 2198 const EffectNode* effect_node = effect_tree.Node(effect_id); | 2172 } else if (!transforms.might_be_invertible) { |
| 2199 const TransformNode* dest_node = | 2173 return false; |
| 2200 transform_tree.Node(effect_node->transform_id); | 2174 } else { |
| 2201 DCHECK(effect_id == effect_tree.kRootNodeId || | 2175 transforms.might_be_invertible = |
| 2202 effect_node->has_render_surface); | 2176 transforms.from_target.GetInverse(to_target); |
| 2203 bool already_computed_inverse = false; | 2177 transforms.to_valid = transforms.might_be_invertible; |
| 2204 if (transform_id == effect_node->transform_id) { | 2178 transforms.to_target = *to_target; |
| 2205 target_space_transform.Scale(effect_node->surface_contents_scale.x(), | 2179 return transforms.to_valid; |
| 2206 effect_node->surface_contents_scale.y()); | 2180 } |
| 2207 } else if (!dest_node || (dest_node->ancestors_are_invertible && | 2181 } |
| 2208 dest_node->node_and_ancestors_are_flat)) { | 2182 |
| 2209 // Compute transform from transform_id to effect_node->transform using | 2183 bool PropertyTrees::GetFromTarget(int transform_id, |
| 2210 // screen space transforms. | 2184 int effect_id, |
| 2211 target_space_transform.ConcatTransform( | 2185 gfx::Transform* from_target) const { |
| 2212 transform_tree.ToScreen(transform_id)); | 2186 DrawTransforms& transforms = GetDrawTransforms(transform_id, effect_id); |
| 2213 if (dest_node) | 2187 if (transforms.from_valid) { |
| 2214 target_space_transform.ConcatTransform( | 2188 *from_target = transforms.from_target; |
| 2215 transform_tree.FromScreen(dest_node->id)); | 2189 return true; |
| 2216 if (dest_node->needs_surface_contents_scale) | 2190 } else if (!transforms.might_be_invertible) { |
| 2217 target_space_transform.matrix().postScale( | 2191 return false; |
| 2218 dest_node->surface_contents_scale.x(), | 2192 } else { |
| 2219 dest_node->surface_contents_scale.y(), 1.f); | 2193 transforms.might_be_invertible = |
| 2220 } else if (transform_node->id > dest_node->id) { | 2194 transforms.to_target.GetInverse(from_target); |
| 2221 target_space_transform = | 2195 transforms.from_valid = transforms.might_be_invertible; |
| 2222 GetDrawTransforms(transform_node->parent_id, effect_id).to_target; | 2196 transforms.from_target = *from_target; |
| 2223 if (transform_node->flattens_inherited_transform) | 2197 return transforms.from_valid; |
| 2224 target_space_transform.FlattenTo2d(); | 2198 } |
| 2225 target_space_transform.PreconcatTransform(transform_node->to_parent); | 2199 } |
| 2226 } else { | 2200 |
| 2227 const TransformNode* current = dest_node; | 2201 DrawTransformData& PropertyTrees::FetchDrawTransformsDataFromCache( |
| 2228 std::vector<int> source_to_destination; | 2202 int transform_id, |
| 2229 source_to_destination.push_back(current->id); | 2203 int dest_id) const { |
| 2230 current = transform_tree.parent(current); | 2204 for (auto& transform_data : cached_data_.draw_transforms[transform_id]) { |
| 2231 for (; current && current->id > transform_node->id; | 2205 // We initialize draw_transforms with 1 element vectors when |
| 2232 current = transform_tree.parent(current)) { | 2206 // ResetCachedData, so if we hit a -1 target id, it means it's the first |
| 2233 source_to_destination.push_back(current->id); | 2207 // time we compute draw transforms after reset. |
| 2234 } | 2208 if (transform_data.target_id == dest_id || transform_data.target_id == -1) { |
| 2235 DCHECK_EQ(current, transform_node); | 2209 return transform_data; |
| 2236 gfx::Transform combined_transform; | |
| 2237 size_t source_to_destination_size = source_to_destination.size(); | |
| 2238 for (size_t i = 0; i < source_to_destination_size; ++i) { | |
| 2239 size_t index = source_to_destination_size - 1 - i; | |
| 2240 const TransformNode* node = | |
| 2241 transform_tree.Node(source_to_destination[index]); | |
| 2242 if (node->flattens_inherited_transform) | |
| 2243 combined_transform.FlattenTo2d(); | |
| 2244 combined_transform.PreconcatTransform(node->to_parent); | |
| 2245 } | |
| 2246 if (effect_node->surface_contents_scale.x() != 0.f && | |
| 2247 effect_node->surface_contents_scale.y() != 0.f) | |
| 2248 combined_transform.Scale( | |
| 2249 1.0f / effect_node->surface_contents_scale.x(), | |
| 2250 1.0f / effect_node->surface_contents_scale.y()); | |
| 2251 cached_data_.draw_transforms[effect_id][transform_id] | |
| 2252 .transforms.invertible = | |
| 2253 combined_transform.GetInverse(&target_space_transform); | |
| 2254 from_target = combined_transform; | |
| 2255 already_computed_inverse = true; | |
| 2256 } | 2210 } |
| 2257 if (!already_computed_inverse) { | |
| 2258 cached_data_.draw_transforms[effect_id][transform_id] | |
| 2259 .transforms.invertible = | |
| 2260 target_space_transform.GetInverse(&from_target); | |
| 2261 } | |
| 2262 cached_data_.draw_transforms[effect_id][transform_id].update_number = | |
| 2263 cached_data_.property_tree_update_number; | |
| 2264 cached_data_.draw_transforms[effect_id][transform_id] | |
| 2265 .transforms.from_target = from_target; | |
| 2266 cached_data_.draw_transforms[effect_id][transform_id].transforms.to_target = | |
| 2267 target_space_transform; | |
| 2268 } | 2211 } |
| 2269 return cached_data_.draw_transforms[effect_id][transform_id].transforms; | 2212 // Add an entry to the cache. |
| 2213 cached_data_.draw_transforms[transform_id].push_back(DrawTransformData()); |
| 2214 DrawTransformData& data = cached_data_.draw_transforms[transform_id].back(); |
| 2215 data.update_number = -1; |
| 2216 data.target_id = dest_id; |
| 2217 return data; |
| 2218 } |
| 2219 |
| 2220 DrawTransforms& PropertyTrees::GetDrawTransforms(int transform_id, |
| 2221 int effect_id) const { |
| 2222 const EffectNode* effect_node = effect_tree.Node(effect_id); |
| 2223 int dest_id = effect_node->transform_id; |
| 2224 |
| 2225 DrawTransformData& data = |
| 2226 FetchDrawTransformsDataFromCache(transform_id, dest_id); |
| 2227 |
| 2228 DCHECK(data.update_number != cached_data_.property_tree_update_number || |
| 2229 data.target_id != -1); |
| 2230 if (data.update_number == cached_data_.property_tree_update_number) |
| 2231 return data.transforms; |
| 2232 |
| 2233 // Cache miss. |
| 2234 gfx::Transform target_space_transform; |
| 2235 gfx::Transform from_target; |
| 2236 bool already_computed_inverse = false; |
| 2237 if (transform_id == dest_id) { |
| 2238 target_space_transform.Scale(effect_node->surface_contents_scale.x(), |
| 2239 effect_node->surface_contents_scale.y()); |
| 2240 data.transforms.to_valid = true; |
| 2241 data.transforms.from_valid = false; |
| 2242 } else if (transform_id > dest_id) { |
| 2243 transform_tree.CombineTransformsBetween(transform_id, dest_id, |
| 2244 &target_space_transform); |
| 2245 if (dest_id != TransformTree::kRootNodeId) |
| 2246 target_space_transform.matrix().postScale( |
| 2247 effect_node->surface_contents_scale.x(), |
| 2248 effect_node->surface_contents_scale.y(), 1.f); |
| 2249 data.transforms.to_valid = true; |
| 2250 data.transforms.from_valid = false; |
| 2251 data.transforms.might_be_invertible = true; |
| 2252 } else { |
| 2253 gfx::Transform combined_transform; |
| 2254 transform_tree.CombineTransformsBetween(dest_id, transform_id, |
| 2255 &combined_transform); |
| 2256 if (effect_node->surface_contents_scale.x() != 0.f && |
| 2257 effect_node->surface_contents_scale.y() != 0.f) |
| 2258 combined_transform.Scale(1.0f / effect_node->surface_contents_scale.x(), |
| 2259 1.0f / effect_node->surface_contents_scale.y()); |
| 2260 bool invertible = combined_transform.GetInverse(&target_space_transform); |
| 2261 data.transforms.might_be_invertible = invertible; |
| 2262 data.transforms.to_valid = invertible; |
| 2263 data.transforms.from_valid = true; |
| 2264 from_target = combined_transform; |
| 2265 already_computed_inverse = true; |
| 2266 } |
| 2267 |
| 2268 if (!already_computed_inverse) |
| 2269 data.transforms.to_valid = true; |
| 2270 data.update_number = cached_data_.property_tree_update_number; |
| 2271 data.target_id = dest_id; |
| 2272 data.transforms.from_target = from_target; |
| 2273 data.transforms.to_target = target_space_transform; |
| 2274 return data.transforms; |
| 2270 } | 2275 } |
| 2271 | 2276 |
| 2272 void PropertyTrees::ResetCachedData() { | 2277 void PropertyTrees::ResetCachedData() { |
| 2273 cached_data_.property_tree_update_number = 0; | 2278 cached_data_.property_tree_update_number = 0; |
| 2274 cached_data_.animation_scales = std::vector<AnimationScaleData>( | 2279 cached_data_.animation_scales = std::vector<AnimationScaleData>( |
| 2275 transform_tree.nodes().size(), AnimationScaleData()); | 2280 transform_tree.nodes().size(), AnimationScaleData()); |
| 2276 cached_data_.draw_transforms = | 2281 cached_data_.draw_transforms = std::vector<std::vector<DrawTransformData>>( |
| 2277 std::vector<std::unordered_map<int, DrawTransformData>>( | 2282 transform_tree.nodes().size(), std::vector<DrawTransformData>(1)); |
| 2278 effect_tree.nodes().size(), | |
| 2279 std::unordered_map<int, DrawTransformData>()); | |
| 2280 } | 2283 } |
| 2281 | 2284 |
| 2282 void PropertyTrees::UpdateCachedNumber() { | 2285 void PropertyTrees::UpdateCachedNumber() { |
| 2283 cached_data_.property_tree_update_number++; | 2286 cached_data_.property_tree_update_number++; |
| 2284 } | 2287 } |
| 2285 | 2288 |
| 2286 gfx::Transform PropertyTrees::ToScreenSpaceTransformWithoutSurfaceContentsScale( | 2289 gfx::Transform PropertyTrees::ToScreenSpaceTransformWithoutSurfaceContentsScale( |
| 2287 int transform_id, | 2290 int transform_id, |
| 2288 int effect_id) const { | 2291 int effect_id) const { |
| 2289 DCHECK_GT(transform_id, 0); | 2292 DCHECK_GT(transform_id, 0); |
| 2290 if (transform_id == 1) { | 2293 if (transform_id == 1) { |
| 2291 return gfx::Transform(); | 2294 return gfx::Transform(); |
| 2292 } | 2295 } |
| 2293 gfx::Transform screen_space_transform = transform_tree.ToScreen(transform_id); | 2296 gfx::Transform screen_space_transform = transform_tree.ToScreen(transform_id); |
| 2294 const EffectNode* effect_node = effect_tree.Node(effect_id); | 2297 const EffectNode* effect_node = effect_tree.Node(effect_id); |
| 2295 | 2298 |
| 2296 if (effect_node->surface_contents_scale.x() != 0.0 && | 2299 if (effect_node->surface_contents_scale.x() != 0.0 && |
| 2297 effect_node->surface_contents_scale.y() != 0.0) | 2300 effect_node->surface_contents_scale.y() != 0.0) |
| 2298 screen_space_transform.Scale(1.0 / effect_node->surface_contents_scale.x(), | 2301 screen_space_transform.Scale(1.0 / effect_node->surface_contents_scale.x(), |
| 2299 1.0 / effect_node->surface_contents_scale.y()); | 2302 1.0 / effect_node->surface_contents_scale.y()); |
| 2300 return screen_space_transform; | 2303 return screen_space_transform; |
| 2301 } | 2304 } |
| 2302 | 2305 |
| 2303 bool PropertyTrees::ComputeTransformToTarget(int transform_id, | 2306 bool PropertyTrees::ComputeTransformToTarget(int transform_id, |
| 2304 int effect_id, | 2307 int effect_id, |
| 2305 gfx::Transform* transform) const { | 2308 gfx::Transform* transform) const { |
| 2306 transform->MakeIdentity(); | 2309 transform->MakeIdentity(); |
| 2307 | |
| 2308 if (transform_id == TransformTree::kInvalidNodeId) | 2310 if (transform_id == TransformTree::kInvalidNodeId) |
| 2309 return true; | 2311 return true; |
| 2310 | 2312 |
| 2311 int target_transform_id; | |
| 2312 const EffectNode* effect_node = effect_tree.Node(effect_id); | 2313 const EffectNode* effect_node = effect_tree.Node(effect_id); |
| 2313 if (effect_id == EffectTree::kInvalidNodeId) { | |
| 2314 // This can happen when PaintArtifactCompositor builds property trees as | |
| 2315 // it doesn't set effect ids on clip nodes. We want to compute transform | |
| 2316 // to the root in this case. | |
| 2317 target_transform_id = TransformTree::kRootNodeId; | |
| 2318 } else { | |
| 2319 DCHECK(effect_node->has_render_surface || | |
| 2320 effect_node->id == EffectTree::kRootNodeId); | |
| 2321 target_transform_id = effect_node->transform_id; | |
| 2322 } | |
| 2323 | 2314 |
| 2324 bool success = transform_tree.ComputeTransform( | 2315 bool success = true; |
| 2325 transform_id, target_transform_id, transform); | 2316 success = GetToTarget(transform_id, effect_id, transform); |
| 2326 if (verify_transform_tree_calculations) { | 2317 if (effect_node->surface_contents_scale.x() != 0.f && |
| 2327 gfx::Transform to_target; | 2318 effect_node->surface_contents_scale.y() != 0.f) |
| 2328 to_target.ConcatTransform( | 2319 transform->matrix().postScale( |
| 2329 GetDrawTransforms(transform_id, effect_id).to_target); | 2320 1.0f / effect_node->surface_contents_scale.x(), |
| 2330 if (effect_node->surface_contents_scale.x() != 0.f && | 2321 1.0f / effect_node->surface_contents_scale.y(), 1.0f); |
| 2331 effect_node->surface_contents_scale.y() != 0.f) | |
| 2332 to_target.matrix().postScale( | |
| 2333 1.0f / effect_node->surface_contents_scale.x(), | |
| 2334 1.0f / effect_node->surface_contents_scale.y(), 1.0f); | |
| 2335 DCHECK(to_target.ApproximatelyEqual(*transform)); | |
| 2336 } | |
| 2337 return success; | 2322 return success; |
| 2338 } | 2323 } |
| 2339 | 2324 |
| 2340 bool PropertyTrees::ComputeTransformFromTarget( | 2325 bool PropertyTrees::ComputeTransformFromTarget( |
| 2341 int transform_id, | 2326 int transform_id, |
| 2342 int effect_id, | 2327 int effect_id, |
| 2343 gfx::Transform* transform) const { | 2328 gfx::Transform* transform) const { |
| 2344 transform->MakeIdentity(); | 2329 transform->MakeIdentity(); |
| 2345 | |
| 2346 if (transform_id == TransformTree::kInvalidNodeId) | 2330 if (transform_id == TransformTree::kInvalidNodeId) |
| 2347 return true; | 2331 return true; |
| 2348 | 2332 |
| 2349 int target_transform_id; | |
| 2350 const EffectNode* effect_node = effect_tree.Node(effect_id); | 2333 const EffectNode* effect_node = effect_tree.Node(effect_id); |
| 2351 if (effect_id == EffectTree::kInvalidNodeId) { | |
| 2352 // This can happen when PaintArtifactCompositor builds property trees as | |
| 2353 // it doesn't set effect ids on clip nodes. We want to compute transform | |
| 2354 // to the root in this case. | |
| 2355 target_transform_id = TransformTree::kRootNodeId; | |
| 2356 } else { | |
| 2357 DCHECK(effect_node->has_render_surface || | |
| 2358 effect_node->id == EffectTree::kRootNodeId); | |
| 2359 target_transform_id = effect_node->transform_id; | |
| 2360 } | |
| 2361 | 2334 |
| 2362 bool success = transform_tree.ComputeTransform(target_transform_id, | 2335 bool success = GetFromTarget(transform_id, effect_id, transform); |
| 2363 transform_id, transform); | 2336 transform->Scale(effect_node->surface_contents_scale.x(), |
| 2364 if (verify_transform_tree_calculations) { | 2337 effect_node->surface_contents_scale.y()); |
| 2365 auto draw_transforms = GetDrawTransforms(transform_id, effect_id); | |
| 2366 gfx::Transform from_target; | |
| 2367 from_target.ConcatTransform(draw_transforms.from_target); | |
| 2368 from_target.Scale(effect_node->surface_contents_scale.x(), | |
| 2369 effect_node->surface_contents_scale.y()); | |
| 2370 DCHECK(from_target.ApproximatelyEqual(*transform) || | |
| 2371 !draw_transforms.invertible); | |
| 2372 } | |
| 2373 return success; | 2338 return success; |
| 2374 } | 2339 } |
| 2375 | 2340 |
| 2376 } // namespace cc | 2341 } // namespace cc |
| OLD | NEW |