| 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 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 | 152 |
| 153 #if DCHECK_IS_ON() | 153 #if DCHECK_IS_ON() |
| 154 TransformTree tree; | 154 TransformTree tree; |
| 155 // TODO(jaydasika) : Move tests that expect source_to_parent_updates_allowed | 155 // TODO(jaydasika) : Move tests that expect source_to_parent_updates_allowed |
| 156 // to be true on impl thread to main thread and set it to is_main_thread here. | 156 // to be true on impl thread to main thread and set it to is_main_thread here. |
| 157 tree.source_to_parent_updates_allowed_ = source_to_parent_updates_allowed_; | 157 tree.source_to_parent_updates_allowed_ = source_to_parent_updates_allowed_; |
| 158 DCHECK(tree == *this); | 158 DCHECK(tree == *this); |
| 159 #endif | 159 #endif |
| 160 } | 160 } |
| 161 | 161 |
| 162 bool TransformTree::ComputeTransform(int source_id, | |
| 163 int dest_id, | |
| 164 gfx::Transform* transform) const { | |
| 165 transform->MakeIdentity(); | |
| 166 | |
| 167 if (source_id == dest_id) | |
| 168 return true; | |
| 169 | |
| 170 if (source_id > dest_id) { | |
| 171 CombineTransformsBetween(source_id, dest_id, transform); | |
| 172 return true; | |
| 173 } | |
| 174 | |
| 175 return CombineInversesBetween(source_id, dest_id, transform); | |
| 176 } | |
| 177 | |
| 178 bool TransformTree::ComputeTranslation(int source_id, | 162 bool TransformTree::ComputeTranslation(int source_id, |
| 179 int dest_id, | 163 int dest_id, |
| 180 gfx::Transform* transform) const { | 164 gfx::Transform* transform) const { |
| 181 transform->MakeIdentity(); | 165 transform->MakeIdentity(); |
| 182 if (source_id == dest_id) | 166 if (source_id == dest_id) |
| 183 return true; | 167 return true; |
| 184 | 168 |
| 185 const TransformNode* dest = Node(dest_id); | 169 const TransformNode* dest = Node(dest_id); |
| 186 if (!dest->ancestors_are_invertible) | 170 if (!dest->ancestors_are_invertible) |
| 187 return false; | 171 return false; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 TransformNode* source_node = Node(node->source_node_id); | 235 TransformNode* source_node = Node(node->source_node_id); |
| 252 property_trees()->UpdateCachedNumber(); | 236 property_trees()->UpdateCachedNumber(); |
| 253 if (node->needs_local_transform_update || NeedsSourceToParentUpdate(node)) | 237 if (node->needs_local_transform_update || NeedsSourceToParentUpdate(node)) |
| 254 UpdateLocalTransform(node); | 238 UpdateLocalTransform(node); |
| 255 else | 239 else |
| 256 UndoSnapping(node); | 240 UndoSnapping(node); |
| 257 UpdateScreenSpaceTransform(node, parent_node, target_node); | 241 UpdateScreenSpaceTransform(node, parent_node, target_node); |
| 258 UpdateSurfaceContentsScale(node); | 242 UpdateSurfaceContentsScale(node); |
| 259 UpdateAnimationProperties(node, parent_node); | 243 UpdateAnimationProperties(node, parent_node); |
| 260 UpdateSnapping(node); | 244 UpdateSnapping(node); |
| 261 UpdateTargetSpaceTransform(node, target_node); | |
| 262 UpdateNodeAndAncestorsHaveIntegerTranslations(node, parent_node); | 245 UpdateNodeAndAncestorsHaveIntegerTranslations(node, parent_node); |
| 263 UpdateTransformChanged(node, parent_node, source_node); | 246 UpdateTransformChanged(node, parent_node, source_node); |
| 264 UpdateNodeAndAncestorsAreAnimatedOrInvertible(node, parent_node); | 247 UpdateNodeAndAncestorsAreAnimatedOrInvertible(node, parent_node); |
| 265 } | 248 } |
| 266 | 249 |
| 267 bool TransformTree::IsDescendant(int desc_id, int source_id) const { | 250 bool TransformTree::IsDescendant(int desc_id, int source_id) const { |
| 268 while (desc_id != source_id) { | 251 while (desc_id != source_id) { |
| 269 if (desc_id == kInvalidNodeId) | 252 if (desc_id == kInvalidNodeId) |
| 270 return false; | 253 return false; |
| 271 desc_id = Node(desc_id)->parent_id; | 254 desc_id = Node(desc_id)->parent_id; |
| 272 } | 255 } |
| 273 return true; | 256 return true; |
| 274 } | 257 } |
| 275 | 258 |
| 276 void TransformTree::CombineTransformsBetween(int source_id, | |
| 277 int dest_id, | |
| 278 gfx::Transform* transform) const { | |
| 279 DCHECK(source_id > dest_id); | |
| 280 const TransformNode* current = Node(source_id); | |
| 281 const TransformNode* dest = Node(dest_id); | |
| 282 // Combine transforms to and from the screen when possible. Since flattening | |
| 283 // is a non-linear operation, we cannot use this approach when there is | |
| 284 // non-trivial flattening between the source and destination nodes. For | |
| 285 // example, consider the tree R->A->B->C, where B flattens its inherited | |
| 286 // transform, and A has a non-flat transform. Suppose C is the source and A is | |
| 287 // the destination. The expected result is C * B. But C's to_screen | |
| 288 // transform is C * B * flattened(A * R), and A's from_screen transform is | |
| 289 // R^{-1} * A^{-1}. If at least one of A and R isn't flat, the inverse of | |
| 290 // flattened(A * R) won't be R^{-1} * A{-1}, so multiplying C's to_screen and | |
| 291 // A's from_screen will not produce the correct result. | |
| 292 if (!dest || | |
| 293 (dest->ancestors_are_invertible && dest->node_and_ancestors_are_flat)) { | |
| 294 transform->ConcatTransform(ToScreen(current->id)); | |
| 295 if (dest) | |
| 296 transform->ConcatTransform(FromScreen(dest->id)); | |
| 297 return; | |
| 298 } | |
| 299 | |
| 300 // Flattening is defined in a way that requires it to be applied while | |
| 301 // traversing downward in the tree. We first identify nodes that are on the | |
| 302 // path from the source to the destination (this is traversing upward), and | |
| 303 // then we visit these nodes in reverse order, flattening as needed. We | |
| 304 // early-out if we get to a node whose target node is the destination, since | |
| 305 // we can then re-use the target space transform stored at that node. However, | |
| 306 // we cannot re-use a stored target space transform if the destination has a | |
| 307 // zero surface contents scale, since stored target space transforms have | |
| 308 // surface contents scale baked in, but we need to compute an unscaled | |
| 309 // transform. | |
| 310 std::vector<int> source_to_destination; | |
| 311 source_to_destination.push_back(current->id); | |
| 312 current = parent(current); | |
| 313 bool destination_has_non_zero_surface_contents_scale = | |
| 314 dest->surface_contents_scale.x() != 0.f && | |
| 315 dest->surface_contents_scale.y() != 0.f; | |
| 316 DCHECK(destination_has_non_zero_surface_contents_scale || | |
| 317 !dest->ancestors_are_invertible); | |
| 318 for (; current && current->id > dest_id; current = parent(current)) { | |
| 319 if (destination_has_non_zero_surface_contents_scale && | |
| 320 TargetId(current->id) == dest_id && | |
| 321 ContentTargetId(current->id) == dest_id) | |
| 322 break; | |
| 323 source_to_destination.push_back(current->id); | |
| 324 } | |
| 325 | |
| 326 gfx::Transform combined_transform; | |
| 327 if (current->id > dest_id) { | |
| 328 // TODO(sunxd): Instead of using target space transform, only use to_parent | |
| 329 // here when we fully implement computing draw transforms on demand. | |
| 330 combined_transform = ToTarget(current->id, kInvalidNodeId); | |
| 331 // The stored target space transform has surface contents scale baked in, | |
| 332 // but we need the unscaled transform. | |
| 333 combined_transform.matrix().postScale( | |
| 334 1.0f / dest->surface_contents_scale.x(), | |
| 335 1.0f / dest->surface_contents_scale.y(), 1.0f); | |
| 336 } else if (current->id < dest_id) { | |
| 337 // We have reached the lowest common ancestor of the source and destination | |
| 338 // nodes. This case can occur when we are transforming between a node | |
| 339 // corresponding to a fixed-position layer (or its descendant) and the node | |
| 340 // corresponding to the layer's render target. For example, consider the | |
| 341 // layer tree R->T->S->F where F is fixed-position, S owns a render surface, | |
| 342 // and T has a significant transform. This will yield the following | |
| 343 // transform tree: | |
| 344 // R | |
| 345 // | | |
| 346 // T | |
| 347 // /| | |
| 348 // S F | |
| 349 // In this example, T will have id 2, S will have id 3, and F will have id | |
| 350 // 4. When walking up the ancestor chain from F, the first node with a | |
| 351 // smaller id than S will be T, the lowest common ancestor of these nodes. | |
| 352 // We compute the transform from T to S here, and then from F to T in the | |
| 353 // loop below. | |
| 354 DCHECK(IsDescendant(dest_id, current->id)); | |
| 355 CombineInversesBetween(current->id, dest_id, &combined_transform); | |
| 356 DCHECK(combined_transform.IsApproximatelyIdentityOrTranslation( | |
| 357 SkDoubleToMScalar(1e-4))); | |
| 358 } | |
| 359 | |
| 360 size_t source_to_destination_size = source_to_destination.size(); | |
| 361 for (size_t i = 0; i < source_to_destination_size; ++i) { | |
| 362 size_t index = source_to_destination_size - 1 - i; | |
| 363 const TransformNode* node = Node(source_to_destination[index]); | |
| 364 if (node->flattens_inherited_transform) | |
| 365 combined_transform.FlattenTo2d(); | |
| 366 combined_transform.PreconcatTransform(node->to_parent); | |
| 367 } | |
| 368 | |
| 369 transform->ConcatTransform(combined_transform); | |
| 370 } | |
| 371 | |
| 372 bool TransformTree::CombineInversesBetween(int source_id, | |
| 373 int dest_id, | |
| 374 gfx::Transform* transform) const { | |
| 375 DCHECK(source_id < dest_id); | |
| 376 const TransformNode* current = Node(dest_id); | |
| 377 const TransformNode* dest = Node(source_id); | |
| 378 // Just as in CombineTransformsBetween, we can use screen space transforms in | |
| 379 // this computation only when there isn't any non-trivial flattening | |
| 380 // involved. | |
| 381 if (current->ancestors_are_invertible && | |
| 382 current->node_and_ancestors_are_flat) { | |
| 383 transform->PreconcatTransform(FromScreen(current->id)); | |
| 384 if (dest) | |
| 385 transform->PreconcatTransform(ToScreen(dest->id)); | |
| 386 return true; | |
| 387 } | |
| 388 | |
| 389 // Inverting a flattening is not equivalent to flattening an inverse. This | |
| 390 // means we cannot, for example, use the inverse of each node's to_parent | |
| 391 // transform, flattening where needed. Instead, we must compute the transform | |
| 392 // from the destination to the source, with flattening, and then invert the | |
| 393 // result. | |
| 394 gfx::Transform dest_to_source; | |
| 395 CombineTransformsBetween(dest_id, source_id, &dest_to_source); | |
| 396 gfx::Transform source_to_dest; | |
| 397 bool all_are_invertible = dest_to_source.GetInverse(&source_to_dest); | |
| 398 transform->PreconcatTransform(source_to_dest); | |
| 399 return all_are_invertible; | |
| 400 } | |
| 401 | |
| 402 void TransformTree::UpdateLocalTransform(TransformNode* node) { | 259 void TransformTree::UpdateLocalTransform(TransformNode* node) { |
| 403 gfx::Transform transform = node->post_local; | 260 gfx::Transform transform = node->post_local; |
| 404 if (NeedsSourceToParentUpdate(node)) { | 261 if (NeedsSourceToParentUpdate(node)) { |
| 405 gfx::Transform to_parent; | 262 gfx::Transform to_parent; |
| 406 ComputeTranslation(node->source_node_id, node->parent_id, &to_parent); | 263 ComputeTranslation(node->source_node_id, node->parent_id, &to_parent); |
| 407 gfx::Vector2dF unsnapping; | 264 gfx::Vector2dF unsnapping; |
| 408 TransformNode* current; | 265 TransformNode* current; |
| 409 TransformNode* parent_node; | 266 TransformNode* parent_node; |
| 410 for (current = Node(node->source_node_id); current->id > node->parent_id; | 267 for (current = Node(node->source_node_id); current->id > node->parent_id; |
| 411 current = parent(current)) { | 268 current = parent(current)) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 } | 345 } |
| 489 | 346 |
| 490 float layer_scale_factor = | 347 float layer_scale_factor = |
| 491 device_scale_factor_ * device_transform_scale_factor_; | 348 device_scale_factor_ * device_transform_scale_factor_; |
| 492 if (node->in_subtree_of_page_scale_layer) | 349 if (node->in_subtree_of_page_scale_layer) |
| 493 layer_scale_factor *= page_scale_factor_; | 350 layer_scale_factor *= page_scale_factor_; |
| 494 node->surface_contents_scale = MathUtil::ComputeTransform2dScaleComponents( | 351 node->surface_contents_scale = MathUtil::ComputeTransform2dScaleComponents( |
| 495 ToScreen(node->id), layer_scale_factor); | 352 ToScreen(node->id), layer_scale_factor); |
| 496 } | 353 } |
| 497 | 354 |
| 498 void TransformTree::UpdateTargetSpaceTransform(TransformNode* node, | |
| 499 TransformNode* target_node) { | |
| 500 gfx::Transform target_space_transform; | |
| 501 if (node->needs_surface_contents_scale) { | |
| 502 target_space_transform.MakeIdentity(); | |
| 503 target_space_transform.Scale(node->surface_contents_scale.x(), | |
| 504 node->surface_contents_scale.y()); | |
| 505 } else { | |
| 506 // In order to include the root transform for the root surface, we walk up | |
| 507 // to the root of the transform tree in ComputeTransform. | |
| 508 int target_id = target_node->id; | |
| 509 ComputeTransform(node->id, target_id, &target_space_transform); | |
| 510 if (target_id != kRootNodeId) { | |
| 511 target_space_transform.matrix().postScale( | |
| 512 target_node->surface_contents_scale.x(), | |
| 513 target_node->surface_contents_scale.y(), 1.f); | |
| 514 } | |
| 515 } | |
| 516 | |
| 517 gfx::Transform from_target; | |
| 518 if (!target_space_transform.GetInverse(&from_target)) | |
| 519 node->ancestors_are_invertible = false; | |
| 520 SetToTarget(node->id, target_space_transform); | |
| 521 SetFromTarget(node->id, from_target); | |
| 522 } | |
| 523 | |
| 524 void TransformTree::UpdateAnimationProperties(TransformNode* node, | 355 void TransformTree::UpdateAnimationProperties(TransformNode* node, |
| 525 TransformNode* parent_node) { | 356 TransformNode* parent_node) { |
| 526 bool ancestor_is_animating = false; | 357 bool ancestor_is_animating = false; |
| 527 if (parent_node) | 358 if (parent_node) |
| 528 ancestor_is_animating = parent_node->to_screen_is_potentially_animated; | 359 ancestor_is_animating = parent_node->to_screen_is_potentially_animated; |
| 529 node->to_screen_is_potentially_animated = | 360 node->to_screen_is_potentially_animated = |
| 530 node->has_potential_animation || ancestor_is_animating; | 361 node->has_potential_animation || ancestor_is_animating; |
| 531 } | 362 } |
| 532 | 363 |
| 533 void TransformTree::UndoSnapping(TransformNode* node) { | 364 void TransformTree::UndoSnapping(TransformNode* node) { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 bool TransformTree::HasNodesAffectedByInnerViewportBoundsDelta() const { | 491 bool TransformTree::HasNodesAffectedByInnerViewportBoundsDelta() const { |
| 661 return !nodes_affected_by_inner_viewport_bounds_delta_.empty(); | 492 return !nodes_affected_by_inner_viewport_bounds_delta_.empty(); |
| 662 } | 493 } |
| 663 | 494 |
| 664 bool TransformTree::HasNodesAffectedByOuterViewportBoundsDelta() const { | 495 bool TransformTree::HasNodesAffectedByOuterViewportBoundsDelta() const { |
| 665 return !nodes_affected_by_outer_viewport_bounds_delta_.empty(); | 496 return !nodes_affected_by_outer_viewport_bounds_delta_.empty(); |
| 666 } | 497 } |
| 667 | 498 |
| 668 const gfx::Transform& TransformTree::FromTarget(int node_id, | 499 const gfx::Transform& TransformTree::FromTarget(int node_id, |
| 669 int effect_id) const { | 500 int effect_id) const { |
| 670 DCHECK(static_cast<int>(cached_data_.size()) > node_id); | 501 DCHECK(effect_id != EffectTree::kInvalidNodeId); |
| 671 if (effect_id != kInvalidNodeId && | 502 return property_trees()->GetDrawTransforms(node_id, effect_id).from_target; |
| 672 property_trees()->verify_transform_tree_calculations) { | |
| 673 const gfx::Transform& transform = | |
| 674 property_trees()->GetDrawTransforms(node_id, effect_id).from_target; | |
| 675 CHECK(transform.ApproximatelyEqual(cached_data_[node_id].from_target)); | |
| 676 } | |
| 677 return cached_data_[node_id].from_target; | |
| 678 } | |
| 679 | |
| 680 void TransformTree::SetFromTarget(int node_id, | |
| 681 const gfx::Transform& transform) { | |
| 682 DCHECK(static_cast<int>(cached_data_.size()) > node_id); | |
| 683 cached_data_[node_id].from_target = transform; | |
| 684 } | 503 } |
| 685 | 504 |
| 686 const gfx::Transform& TransformTree::ToTarget(int node_id, | 505 const gfx::Transform& TransformTree::ToTarget(int node_id, |
| 687 int effect_id) const { | 506 int effect_id) const { |
| 688 DCHECK(static_cast<int>(cached_data_.size()) > node_id); | 507 DCHECK(effect_id != EffectTree::kInvalidNodeId); |
| 689 if (effect_id != kInvalidNodeId && | 508 return property_trees()->GetDrawTransforms(node_id, effect_id).to_target; |
| 690 property_trees()->verify_transform_tree_calculations) { | |
| 691 const gfx::Transform& transform = | |
| 692 property_trees()->GetDrawTransforms(node_id, effect_id).to_target; | |
| 693 if (property_trees()->non_root_surfaces_enabled) | |
| 694 CHECK(transform.ApproximatelyEqual(cached_data_[node_id].to_target)); | |
| 695 else | |
| 696 CHECK(transform.ApproximatelyEqual(cached_data_[node_id].to_screen)); | |
| 697 } | |
| 698 return cached_data_[node_id].to_target; | |
| 699 } | |
| 700 | |
| 701 void TransformTree::SetToTarget(int node_id, const gfx::Transform& transform) { | |
| 702 DCHECK(static_cast<int>(cached_data_.size()) > node_id); | |
| 703 cached_data_[node_id].to_target = transform; | |
| 704 } | 509 } |
| 705 | 510 |
| 706 const gfx::Transform& TransformTree::FromScreen(int node_id) const { | 511 const gfx::Transform& TransformTree::FromScreen(int node_id) const { |
| 707 DCHECK(static_cast<int>(cached_data_.size()) > node_id); | 512 DCHECK(static_cast<int>(cached_data_.size()) > node_id); |
| 708 return cached_data_[node_id].from_screen; | 513 return cached_data_[node_id].from_screen; |
| 709 } | 514 } |
| 710 | 515 |
| 711 void TransformTree::SetFromScreen(int node_id, | 516 void TransformTree::SetFromScreen(int node_id, |
| 712 const gfx::Transform& transform) { | 517 const gfx::Transform& transform) { |
| 713 DCHECK(static_cast<int>(cached_data_.size()) > node_id); | 518 DCHECK(static_cast<int>(cached_data_.size()) > node_id); |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 if (effect_node->parent_id != -1) { | 825 if (effect_node->parent_id != -1) { |
| 1021 // For non-root surfaces, transform only by sub-layer scale. | 826 // For non-root surfaces, transform only by sub-layer scale. |
| 1022 source_id = destination_id; | 827 source_id = destination_id; |
| 1023 } else { | 828 } else { |
| 1024 // The root surface doesn't have the notion of sub-layer scale, but | 829 // The root surface doesn't have the notion of sub-layer scale, but |
| 1025 // instead has a similar notion of transforming from the space of the root | 830 // instead has a similar notion of transforming from the space of the root |
| 1026 // layer to the space of the screen. | 831 // layer to the space of the screen. |
| 1027 DCHECK_EQ(kRootNodeId, destination_id); | 832 DCHECK_EQ(kRootNodeId, destination_id); |
| 1028 source_id = TransformTree::kContentsRootNodeId; | 833 source_id = TransformTree::kContentsRootNodeId; |
| 1029 } | 834 } |
| 1030 gfx::Transform transform; | 835 gfx::Transform transform = |
| 1031 property_trees()->transform_tree.ComputeTransform(source_id, destination_id, | 836 property_trees()->GetDrawTransforms(source_id, node_id).to_target; |
| 1032 &transform); | |
| 1033 if (effect_node->id != kContentsRootNodeId) { | |
| 1034 transform.matrix().postScale(effect_node->surface_contents_scale.x(), | |
| 1035 effect_node->surface_contents_scale.y(), | |
| 1036 1.f); | |
| 1037 } | |
| 1038 it->set_area(MathUtil::MapEnclosingClippedRect(transform, it->area())); | 837 it->set_area(MathUtil::MapEnclosingClippedRect(transform, it->area())); |
| 1039 } | 838 } |
| 1040 } | 839 } |
| 1041 | 840 |
| 1042 bool EffectTree::HasCopyRequests() const { | 841 bool EffectTree::HasCopyRequests() const { |
| 1043 return !copy_requests_.empty(); | 842 return !copy_requests_.empty(); |
| 1044 } | 843 } |
| 1045 | 844 |
| 1046 void EffectTree::ClearCopyRequests() { | 845 void EffectTree::ClearCopyRequests() { |
| 1047 for (auto& node : nodes()) { | 846 for (auto& node : nodes()) { |
| (...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1610 | 1409 |
| 1611 PropertyTreesCachedData::~PropertyTreesCachedData() {} | 1410 PropertyTreesCachedData::~PropertyTreesCachedData() {} |
| 1612 | 1411 |
| 1613 PropertyTrees::PropertyTrees() | 1412 PropertyTrees::PropertyTrees() |
| 1614 : needs_rebuild(true), | 1413 : needs_rebuild(true), |
| 1615 non_root_surfaces_enabled(true), | 1414 non_root_surfaces_enabled(true), |
| 1616 changed(false), | 1415 changed(false), |
| 1617 full_tree_damaged(false), | 1416 full_tree_damaged(false), |
| 1618 sequence_number(0), | 1417 sequence_number(0), |
| 1619 is_main_thread(true), | 1418 is_main_thread(true), |
| 1620 is_active(false), | 1419 is_active(false) { |
| 1621 verify_transform_tree_calculations(false) { | |
| 1622 transform_tree.SetPropertyTrees(this); | 1420 transform_tree.SetPropertyTrees(this); |
| 1623 effect_tree.SetPropertyTrees(this); | 1421 effect_tree.SetPropertyTrees(this); |
| 1624 clip_tree.SetPropertyTrees(this); | 1422 clip_tree.SetPropertyTrees(this); |
| 1625 scroll_tree.SetPropertyTrees(this); | 1423 scroll_tree.SetPropertyTrees(this); |
| 1626 } | 1424 } |
| 1627 | 1425 |
| 1628 PropertyTrees::~PropertyTrees() {} | 1426 PropertyTrees::~PropertyTrees() {} |
| 1629 | 1427 |
| 1630 bool PropertyTrees::operator==(const PropertyTrees& other) const { | 1428 bool PropertyTrees::operator==(const PropertyTrees& other) const { |
| 1631 return transform_tree == other.transform_tree && | 1429 return transform_tree == other.transform_tree && |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1656 from.always_use_active_tree_opacity_effect_ids; | 1454 from.always_use_active_tree_opacity_effect_ids; |
| 1657 clip_id_to_index_map = from.clip_id_to_index_map; | 1455 clip_id_to_index_map = from.clip_id_to_index_map; |
| 1658 scroll_id_to_index_map = from.scroll_id_to_index_map; | 1456 scroll_id_to_index_map = from.scroll_id_to_index_map; |
| 1659 needs_rebuild = from.needs_rebuild; | 1457 needs_rebuild = from.needs_rebuild; |
| 1660 changed = from.changed; | 1458 changed = from.changed; |
| 1661 full_tree_damaged = from.full_tree_damaged; | 1459 full_tree_damaged = from.full_tree_damaged; |
| 1662 non_root_surfaces_enabled = from.non_root_surfaces_enabled; | 1460 non_root_surfaces_enabled = from.non_root_surfaces_enabled; |
| 1663 sequence_number = from.sequence_number; | 1461 sequence_number = from.sequence_number; |
| 1664 is_main_thread = from.is_main_thread; | 1462 is_main_thread = from.is_main_thread; |
| 1665 is_active = from.is_active; | 1463 is_active = from.is_active; |
| 1666 verify_transform_tree_calculations = from.verify_transform_tree_calculations; | |
| 1667 inner_viewport_container_bounds_delta_ = | 1464 inner_viewport_container_bounds_delta_ = |
| 1668 from.inner_viewport_container_bounds_delta(); | 1465 from.inner_viewport_container_bounds_delta(); |
| 1669 outer_viewport_container_bounds_delta_ = | 1466 outer_viewport_container_bounds_delta_ = |
| 1670 from.outer_viewport_container_bounds_delta(); | 1467 from.outer_viewport_container_bounds_delta(); |
| 1671 inner_viewport_scroll_bounds_delta_ = | 1468 inner_viewport_scroll_bounds_delta_ = |
| 1672 from.inner_viewport_scroll_bounds_delta(); | 1469 from.inner_viewport_scroll_bounds_delta(); |
| 1673 transform_tree.SetPropertyTrees(this); | 1470 transform_tree.SetPropertyTrees(this); |
| 1674 effect_tree.SetPropertyTrees(this); | 1471 effect_tree.SetPropertyTrees(this); |
| 1675 clip_tree.SetPropertyTrees(this); | 1472 clip_tree.SetPropertyTrees(this); |
| 1676 scroll_tree.SetPropertyTrees(this); | 1473 scroll_tree.SetPropertyTrees(this); |
| 1677 ResetCachedData(); | 1474 ResetCachedData(); |
| 1678 return *this; | 1475 return *this; |
| 1679 } | 1476 } |
| 1680 | 1477 |
| 1681 void PropertyTrees::ToProtobuf(proto::PropertyTrees* proto) const { | 1478 void PropertyTrees::ToProtobuf(proto::PropertyTrees* proto) const { |
| 1682 // TODO(khushalsagar): Add support for sending diffs when serializaing | 1479 // TODO(khushalsagar): Add support for sending diffs when serializaing |
| 1683 // property trees. See crbug/555370. | 1480 // property trees. See crbug/555370. |
| 1684 transform_tree.ToProtobuf(proto->mutable_transform_tree()); | 1481 transform_tree.ToProtobuf(proto->mutable_transform_tree()); |
| 1685 effect_tree.ToProtobuf(proto->mutable_effect_tree()); | 1482 effect_tree.ToProtobuf(proto->mutable_effect_tree()); |
| 1686 clip_tree.ToProtobuf(proto->mutable_clip_tree()); | 1483 clip_tree.ToProtobuf(proto->mutable_clip_tree()); |
| 1687 scroll_tree.ToProtobuf(proto->mutable_scroll_tree()); | 1484 scroll_tree.ToProtobuf(proto->mutable_scroll_tree()); |
| 1688 proto->set_needs_rebuild(needs_rebuild); | 1485 proto->set_needs_rebuild(needs_rebuild); |
| 1689 proto->set_changed(changed); | 1486 proto->set_changed(changed); |
| 1690 proto->set_full_tree_damaged(full_tree_damaged); | 1487 proto->set_full_tree_damaged(full_tree_damaged); |
| 1691 proto->set_non_root_surfaces_enabled(non_root_surfaces_enabled); | 1488 proto->set_non_root_surfaces_enabled(non_root_surfaces_enabled); |
| 1692 proto->set_is_main_thread(is_main_thread); | 1489 proto->set_is_main_thread(is_main_thread); |
| 1693 proto->set_is_active(is_active); | 1490 proto->set_is_active(is_active); |
| 1694 proto->set_verify_transform_tree_calculations( | |
| 1695 verify_transform_tree_calculations); | |
| 1696 | 1491 |
| 1697 // TODO(khushalsagar): Consider using the sequence number to decide if | 1492 // TODO(khushalsagar): Consider using the sequence number to decide if |
| 1698 // property trees need to be serialized again for a commit. See crbug/555370. | 1493 // property trees need to be serialized again for a commit. See crbug/555370. |
| 1699 proto->set_sequence_number(sequence_number); | 1494 proto->set_sequence_number(sequence_number); |
| 1700 | 1495 |
| 1701 for (auto i : always_use_active_tree_opacity_effect_ids) | 1496 for (auto i : always_use_active_tree_opacity_effect_ids) |
| 1702 proto->add_always_use_active_tree_opacity_effect_ids(i); | 1497 proto->add_always_use_active_tree_opacity_effect_ids(i); |
| 1703 } | 1498 } |
| 1704 | 1499 |
| 1705 // static | 1500 // static |
| 1706 void PropertyTrees::FromProtobuf(const proto::PropertyTrees& proto) { | 1501 void PropertyTrees::FromProtobuf(const proto::PropertyTrees& proto) { |
| 1707 transform_tree.FromProtobuf(proto.transform_tree(), | 1502 transform_tree.FromProtobuf(proto.transform_tree(), |
| 1708 &transform_id_to_index_map); | 1503 &transform_id_to_index_map); |
| 1709 effect_tree.FromProtobuf(proto.effect_tree(), &effect_id_to_index_map); | 1504 effect_tree.FromProtobuf(proto.effect_tree(), &effect_id_to_index_map); |
| 1710 clip_tree.FromProtobuf(proto.clip_tree(), &clip_id_to_index_map); | 1505 clip_tree.FromProtobuf(proto.clip_tree(), &clip_id_to_index_map); |
| 1711 scroll_tree.FromProtobuf(proto.scroll_tree(), &scroll_id_to_index_map); | 1506 scroll_tree.FromProtobuf(proto.scroll_tree(), &scroll_id_to_index_map); |
| 1712 | 1507 |
| 1713 needs_rebuild = proto.needs_rebuild(); | 1508 needs_rebuild = proto.needs_rebuild(); |
| 1714 changed = proto.changed(); | 1509 changed = proto.changed(); |
| 1715 full_tree_damaged = proto.full_tree_damaged(); | 1510 full_tree_damaged = proto.full_tree_damaged(); |
| 1716 non_root_surfaces_enabled = proto.non_root_surfaces_enabled(); | 1511 non_root_surfaces_enabled = proto.non_root_surfaces_enabled(); |
| 1717 sequence_number = proto.sequence_number(); | 1512 sequence_number = proto.sequence_number(); |
| 1718 is_main_thread = proto.is_main_thread(); | 1513 is_main_thread = proto.is_main_thread(); |
| 1719 is_active = proto.is_active(); | 1514 is_active = proto.is_active(); |
| 1720 verify_transform_tree_calculations = | |
| 1721 proto.verify_transform_tree_calculations(); | |
| 1722 | 1515 |
| 1723 transform_tree.SetPropertyTrees(this); | 1516 transform_tree.SetPropertyTrees(this); |
| 1724 effect_tree.SetPropertyTrees(this); | 1517 effect_tree.SetPropertyTrees(this); |
| 1725 clip_tree.SetPropertyTrees(this); | 1518 clip_tree.SetPropertyTrees(this); |
| 1726 scroll_tree.SetPropertyTrees(this); | 1519 scroll_tree.SetPropertyTrees(this); |
| 1727 for (auto i : proto.always_use_active_tree_opacity_effect_ids()) | 1520 for (auto i : proto.always_use_active_tree_opacity_effect_ids()) |
| 1728 always_use_active_tree_opacity_effect_ids.push_back(i); | 1521 always_use_active_tree_opacity_effect_ids.push_back(i); |
| 1729 } | 1522 } |
| 1730 | 1523 |
| 1731 void PropertyTrees::clear() { | 1524 void PropertyTrees::clear() { |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1939 !node->has_only_translation_animations || ancestor_is_animating_scale; | 1732 !node->has_only_translation_animations || ancestor_is_animating_scale; |
| 1940 | 1733 |
| 1941 // Once we've failed to compute a maximum animated scale at an ancestor, we | 1734 // Once we've failed to compute a maximum animated scale at an ancestor, we |
| 1942 // continue to fail. | 1735 // continue to fail. |
| 1943 bool failed_at_ancestor = | 1736 bool failed_at_ancestor = |
| 1944 ancestor_is_animating_scale && ancestor_maximum_target_scale == 0.f; | 1737 ancestor_is_animating_scale && ancestor_maximum_target_scale == 0.f; |
| 1945 | 1738 |
| 1946 // Computing maximum animated scale in the presence of non-scale/translation | 1739 // Computing maximum animated scale in the presence of non-scale/translation |
| 1947 // transforms isn't supported. | 1740 // transforms isn't supported. |
| 1948 bool failed_for_non_scale_or_translation = | 1741 bool failed_for_non_scale_or_translation = |
| 1949 !transform_tree.Node(transform_node_id) | 1742 !node->to_parent.IsScaleOrTranslation(); |
| 1950 ->to_parent.IsScaleOrTranslation(); | |
| 1951 | 1743 |
| 1952 // We don't attempt to accumulate animation scale from multiple nodes with | 1744 // We don't attempt to accumulate animation scale from multiple nodes with |
| 1953 // scale animations, because of the risk of significant overestimation. For | 1745 // scale animations, because of the risk of significant overestimation. For |
| 1954 // example, one node might be increasing scale from 1 to 10 at the same time | 1746 // example, one node might be increasing scale from 1 to 10 at the same time |
| 1955 // as another node is decreasing scale from 10 to 1. Naively combining these | 1747 // as another node is decreasing scale from 10 to 1. Naively combining these |
| 1956 // scales would produce a scale of 100. | 1748 // scales would produce a scale of 100. |
| 1957 bool failed_for_multiple_scale_animations = | 1749 bool failed_for_multiple_scale_animations = |
| 1958 ancestor_is_animating_scale && !node->has_only_translation_animations; | 1750 ancestor_is_animating_scale && !node->has_only_translation_animations; |
| 1959 | 1751 |
| 1960 if (failed_at_ancestor || failed_for_non_scale_or_translation || | 1752 if (failed_at_ancestor || failed_for_non_scale_or_translation || |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2130 cached_data_.draw_transforms[effect_id][transform_id].transforms.to_target = | 1922 cached_data_.draw_transforms[effect_id][transform_id].transforms.to_target = |
| 2131 target_space_transform; | 1923 target_space_transform; |
| 2132 } | 1924 } |
| 2133 return cached_data_.draw_transforms[effect_id][transform_id].transforms; | 1925 return cached_data_.draw_transforms[effect_id][transform_id].transforms; |
| 2134 } | 1926 } |
| 2135 | 1927 |
| 2136 void PropertyTrees::ResetCachedData() { | 1928 void PropertyTrees::ResetCachedData() { |
| 2137 cached_data_.property_tree_update_number = 0; | 1929 cached_data_.property_tree_update_number = 0; |
| 2138 cached_data_.animation_scales = std::vector<AnimationScaleData>( | 1930 cached_data_.animation_scales = std::vector<AnimationScaleData>( |
| 2139 transform_tree.nodes().size(), AnimationScaleData()); | 1931 transform_tree.nodes().size(), AnimationScaleData()); |
| 2140 cached_data_.draw_transforms = | 1932 cached_data_.draw_transforms = std::vector<std::map<int, DrawTransformData>>( |
| 2141 std::vector<std::unordered_map<int, DrawTransformData>>( | 1933 effect_tree.nodes().size(), std::map<int, DrawTransformData>()); |
| 2142 effect_tree.nodes().size(), | |
| 2143 std::unordered_map<int, DrawTransformData>()); | |
| 2144 } | 1934 } |
| 2145 | 1935 |
| 2146 void PropertyTrees::UpdateCachedNumber() { | 1936 void PropertyTrees::UpdateCachedNumber() { |
| 2147 cached_data_.property_tree_update_number++; | 1937 cached_data_.property_tree_update_number++; |
| 2148 } | 1938 } |
| 2149 | 1939 |
| 2150 gfx::Transform PropertyTrees::ToScreenSpaceTransformWithoutSurfaceContentsScale( | 1940 gfx::Transform PropertyTrees::ToScreenSpaceTransformWithoutSurfaceContentsScale( |
| 2151 int transform_id, | 1941 int transform_id, |
| 2152 int effect_id) const { | 1942 int effect_id) const { |
| 2153 DCHECK_GT(transform_id, 0); | 1943 DCHECK_GT(transform_id, 0); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2165 } | 1955 } |
| 2166 | 1956 |
| 2167 bool PropertyTrees::ComputeTransformToTarget(int transform_id, | 1957 bool PropertyTrees::ComputeTransformToTarget(int transform_id, |
| 2168 int effect_id, | 1958 int effect_id, |
| 2169 gfx::Transform* transform) const { | 1959 gfx::Transform* transform) const { |
| 2170 transform->MakeIdentity(); | 1960 transform->MakeIdentity(); |
| 2171 | 1961 |
| 2172 if (transform_id == TransformTree::kInvalidNodeId) | 1962 if (transform_id == TransformTree::kInvalidNodeId) |
| 2173 return true; | 1963 return true; |
| 2174 | 1964 |
| 2175 int target_transform_id; | |
| 2176 const EffectNode* effect_node = effect_tree.Node(effect_id); | 1965 const EffectNode* effect_node = effect_tree.Node(effect_id); |
| 2177 if (effect_id == EffectTree::kInvalidNodeId) { | 1966 bool success = true; |
| 2178 // This can happen when PaintArtifactCompositor builds property trees as | 1967 auto draw_transforms = GetDrawTransforms(transform_id, effect_id); |
| 2179 // it doesn't set effect ids on clip nodes. We want to compute transform | 1968 success = draw_transforms.invertible; |
| 2180 // to the root in this case. | 1969 transform->ConcatTransform(draw_transforms.to_target); |
| 2181 target_transform_id = TransformTree::kRootNodeId; | 1970 if (effect_node->surface_contents_scale.x() != 0.f && |
| 2182 } else { | 1971 effect_node->surface_contents_scale.y() != 0.f) |
| 2183 DCHECK(effect_node->has_render_surface || | 1972 transform->matrix().postScale( |
| 2184 effect_node->id == EffectTree::kRootNodeId); | 1973 1.0f / effect_node->surface_contents_scale.x(), |
| 2185 target_transform_id = effect_node->transform_id; | 1974 1.0f / effect_node->surface_contents_scale.y(), 1.0f); |
| 2186 } | |
| 2187 | |
| 2188 bool success = transform_tree.ComputeTransform( | |
| 2189 transform_id, target_transform_id, transform); | |
| 2190 if (verify_transform_tree_calculations) { | |
| 2191 gfx::Transform to_target; | |
| 2192 to_target.ConcatTransform( | |
| 2193 GetDrawTransforms(transform_id, effect_id).to_target); | |
| 2194 if (effect_node->surface_contents_scale.x() != 0.f && | |
| 2195 effect_node->surface_contents_scale.y() != 0.f) | |
| 2196 to_target.matrix().postScale( | |
| 2197 1.0f / effect_node->surface_contents_scale.x(), | |
| 2198 1.0f / effect_node->surface_contents_scale.y(), 1.0f); | |
| 2199 DCHECK(to_target.ApproximatelyEqual(*transform)); | |
| 2200 } | |
| 2201 return success; | 1975 return success; |
| 2202 } | 1976 } |
| 2203 | 1977 |
| 2204 bool PropertyTrees::ComputeTransformFromTarget( | 1978 bool PropertyTrees::ComputeTransformFromTarget( |
| 2205 int transform_id, | 1979 int transform_id, |
| 2206 int effect_id, | 1980 int effect_id, |
| 2207 gfx::Transform* transform) const { | 1981 gfx::Transform* transform) const { |
| 2208 transform->MakeIdentity(); | 1982 transform->MakeIdentity(); |
| 2209 | 1983 |
| 2210 if (transform_id == TransformTree::kInvalidNodeId) | 1984 if (transform_id == TransformTree::kInvalidNodeId) |
| 2211 return true; | 1985 return true; |
| 2212 | 1986 |
| 2213 int target_transform_id; | |
| 2214 const EffectNode* effect_node = effect_tree.Node(effect_id); | 1987 const EffectNode* effect_node = effect_tree.Node(effect_id); |
| 2215 if (effect_id == EffectTree::kInvalidNodeId) { | 1988 bool success = true; |
| 2216 // This can happen when PaintArtifactCompositor builds property trees as | 1989 auto draw_transforms = GetDrawTransforms(transform_id, effect_id); |
| 2217 // it doesn't set effect ids on clip nodes. We want to compute transform | 1990 success = draw_transforms.invertible; |
| 2218 // to the root in this case. | 1991 transform->ConcatTransform(draw_transforms.from_target); |
| 2219 target_transform_id = TransformTree::kRootNodeId; | 1992 transform->Scale(effect_node->surface_contents_scale.x(), |
| 2220 } else { | 1993 effect_node->surface_contents_scale.y()); |
| 2221 DCHECK(effect_node->has_render_surface || | |
| 2222 effect_node->id == EffectTree::kRootNodeId); | |
| 2223 target_transform_id = effect_node->transform_id; | |
| 2224 } | |
| 2225 | |
| 2226 bool success = transform_tree.ComputeTransform(target_transform_id, | |
| 2227 transform_id, transform); | |
| 2228 if (verify_transform_tree_calculations) { | |
| 2229 auto draw_transforms = GetDrawTransforms(transform_id, effect_id); | |
| 2230 gfx::Transform from_target; | |
| 2231 from_target.ConcatTransform(draw_transforms.from_target); | |
| 2232 from_target.Scale(effect_node->surface_contents_scale.x(), | |
| 2233 effect_node->surface_contents_scale.y()); | |
| 2234 DCHECK(from_target.ApproximatelyEqual(*transform) || | |
| 2235 !draw_transforms.invertible); | |
| 2236 } | |
| 2237 return success; | 1994 return success; |
| 2238 } | 1995 } |
| 2239 | 1996 |
| 2240 } // namespace cc | 1997 } // namespace cc |
| OLD | NEW |