Chromium Code Reviews| 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 "cc/trees/draw_property_utils.h" | 5 #include "cc/trees/draw_property_utils.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 namespace { | 27 namespace { |
| 28 | 28 |
| 29 static bool IsRootLayer(const Layer* layer) { | 29 static bool IsRootLayer(const Layer* layer) { |
| 30 return !layer->parent(); | 30 return !layer->parent(); |
| 31 } | 31 } |
| 32 | 32 |
| 33 static bool IsRootLayer(const LayerImpl* layer) { | 33 static bool IsRootLayer(const LayerImpl* layer) { |
| 34 return layer->layer_tree_impl()->IsRootLayer(layer); | 34 return layer->layer_tree_impl()->IsRootLayer(layer); |
| 35 } | 35 } |
| 36 | 36 |
| 37 static const EffectNode* ContentsTargetEffectNode( | |
| 38 const int effect_tree_index, | |
| 39 const EffectTree& effect_tree) { | |
| 40 const EffectNode* effect_node = effect_tree.Node(effect_tree_index); | |
| 41 return effect_tree.GetRenderSurface(effect_tree_index) | |
| 42 ? effect_node | |
| 43 : effect_tree.Node(effect_node->target_id); | |
| 44 } | |
| 45 | |
| 46 static bool ConvertRectBetweenSurfaceSpaces(const PropertyTrees* property_trees, | 37 static bool ConvertRectBetweenSurfaceSpaces(const PropertyTrees* property_trees, |
| 47 int source_effect_id, | 38 int source_effect_id, |
| 48 int dest_effect_id, | 39 int dest_effect_id, |
| 49 gfx::RectF clip_in_source_space, | 40 gfx::RectF clip_in_source_space, |
| 50 gfx::RectF* clip_in_dest_space) { | 41 gfx::RectF* clip_in_dest_space) { |
| 51 const EffectNode* source_effect_node = | 42 const EffectNode* source_effect_node = |
| 52 property_trees->effect_tree.Node(source_effect_id); | 43 property_trees->effect_tree.Node(source_effect_id); |
| 53 int source_transform_id = source_effect_node->transform_id; | 44 int source_transform_id = source_effect_node->transform_id; |
| 54 const EffectNode* dest_effect_node = | 45 const EffectNode* dest_effect_node = |
| 55 property_trees->effect_tree.Node(dest_effect_id); | 46 property_trees->effect_tree.Node(dest_effect_id); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 70 PostConcatSurfaceContentsScale(dest_effect_node, &source_to_dest); | 61 PostConcatSurfaceContentsScale(dest_effect_node, &source_to_dest); |
| 71 *clip_in_dest_space = | 62 *clip_in_dest_space = |
| 72 MathUtil::ProjectClippedRect(source_to_dest, clip_in_source_space); | 63 MathUtil::ProjectClippedRect(source_to_dest, clip_in_source_space); |
| 73 } else { | 64 } else { |
| 74 return false; | 65 return false; |
| 75 } | 66 } |
| 76 } | 67 } |
| 77 return true; | 68 return true; |
| 78 } | 69 } |
| 79 | 70 |
| 80 bool ComputeClipRectInTargetSpace(const LayerImpl* layer, | |
| 81 const ClipNode* clip_node, | |
| 82 const PropertyTrees* property_trees, | |
| 83 int target_node_id, | |
| 84 bool for_visible_rect_calculation, | |
| 85 gfx::RectF* clip_rect_in_target_space) { | |
| 86 DCHECK(layer->clip_tree_index() == clip_node->id); | |
| 87 DCHECK(clip_node->target_transform_id != target_node_id); | |
| 88 | |
| 89 const EffectTree& effect_tree = property_trees->effect_tree; | |
| 90 const EffectNode* target_effect_node = | |
| 91 ContentsTargetEffectNode(layer->effect_tree_index(), effect_tree); | |
| 92 gfx::Transform clip_to_target; | |
| 93 // We use the local clip for clip rect calculation and combined clip for | |
| 94 // visible rect calculation. | |
| 95 gfx::RectF clip_from_clip_node = | |
| 96 for_visible_rect_calculation ? clip_node->combined_clip_in_target_space | |
| 97 : clip_node->clip_in_target_space; | |
| 98 | |
| 99 return ConvertRectBetweenSurfaceSpaces( | |
| 100 property_trees, clip_node->target_effect_id, target_effect_node->id, | |
| 101 clip_from_clip_node, clip_rect_in_target_space); | |
| 102 } | |
| 103 | |
| 104 struct ConditionalClip { | |
| 105 bool is_clipped; | |
| 106 gfx::RectF clip_rect; | |
| 107 }; | |
| 108 | |
| 109 static ConditionalClip ComputeTargetRectInLocalSpace( | 71 static ConditionalClip ComputeTargetRectInLocalSpace( |
| 110 gfx::RectF rect, | 72 gfx::RectF rect, |
| 111 const PropertyTrees* property_trees, | 73 const PropertyTrees* property_trees, |
| 112 int target_transform_id, | 74 int target_transform_id, |
| 113 int local_transform_id, | 75 int local_transform_id, |
| 114 const int target_effect_id) { | 76 const int target_effect_id) { |
| 115 gfx::Transform target_to_local; | 77 gfx::Transform target_to_local; |
| 116 bool success = property_trees->GetFromTarget( | 78 const TransformNode* node = |
| 117 local_transform_id, target_effect_id, &target_to_local); | 79 property_trees->transform_tree.Node(local_transform_id); |
| 118 if (!success) | 80 if (target_transform_id == TransformTree::kRootNodeId && |
| 119 // If transform is not invertible, cannot apply clip. | 81 node->ancestors_are_invertible) { |
| 120 return ConditionalClip{false, gfx::RectF()}; | 82 target_to_local = property_trees->transform_tree.FromScreen(node->id); |
| 83 } else { | |
| 84 bool success = property_trees->GetFromTarget( | |
| 85 local_transform_id, target_effect_id, &target_to_local); | |
| 86 if (!success) | |
| 87 // If transform is not invertible, cannot apply clip. | |
| 88 return ConditionalClip{false, gfx::RectF()}; | |
| 89 } | |
| 121 | 90 |
| 122 if (target_transform_id > local_transform_id) | 91 if (target_transform_id > local_transform_id) |
| 123 return ConditionalClip{true, // is_clipped. | 92 return ConditionalClip{true, // is_clipped. |
| 124 MathUtil::MapClippedRect(target_to_local, rect)}; | 93 MathUtil::MapClippedRect(target_to_local, rect)}; |
| 125 | 94 |
| 126 return ConditionalClip{true, // is_clipped. | 95 return ConditionalClip{true, // is_clipped. |
| 127 MathUtil::ProjectClippedRect(target_to_local, rect)}; | 96 MathUtil::ProjectClippedRect(target_to_local, rect)}; |
| 128 } | 97 } |
| 129 | 98 |
| 130 static ConditionalClip ComputeLocalRectInTargetSpace( | 99 static ConditionalClip ComputeLocalRectInTargetSpace( |
| 131 gfx::RectF rect, | 100 gfx::RectF rect, |
| 132 const PropertyTrees* property_trees, | 101 const PropertyTrees* property_trees, |
| 133 int current_transform_id, | 102 int current_transform_id, |
| 134 int target_transform_id, | 103 int target_transform_id, |
| 135 int target_effect_id) { | 104 int target_effect_id) { |
| 136 gfx::Transform current_to_target; | 105 gfx::Transform current_to_target; |
| 137 if (!property_trees->GetToTarget(current_transform_id, target_effect_id, | 106 if (target_transform_id == TransformTree::kRootNodeId) { |
|
weiliangc
2017/03/14 22:04:30
Is it possible to make this logic part of GetToTar
jaydasika
2017/03/16 20:33:31
Ah, that makes sense, I added this to speed up tra
| |
| 138 ¤t_to_target)) { | 107 current_to_target = |
| 108 property_trees->transform_tree.ToScreen(current_transform_id); | |
| 109 } else if (!property_trees->GetToTarget( | |
| 110 current_transform_id, target_effect_id, ¤t_to_target)) { | |
| 139 // If transform is not invertible, cannot apply clip. | 111 // If transform is not invertible, cannot apply clip. |
| 140 return ConditionalClip{false, gfx::RectF()}; | 112 return ConditionalClip{false, gfx::RectF()}; |
| 141 } | 113 } |
| 142 | 114 |
| 143 if (current_transform_id > target_transform_id) | 115 if (current_transform_id > target_transform_id) |
| 144 return ConditionalClip{true, // is_clipped. | 116 return ConditionalClip{true, // is_clipped. |
| 145 MathUtil::MapClippedRect(current_to_target, rect)}; | 117 MathUtil::MapClippedRect(current_to_target, rect)}; |
| 146 | 118 |
| 147 return ConditionalClip{true, // is_clipped. | 119 return ConditionalClip{true, // is_clipped. |
| 148 MathUtil::ProjectClippedRect(current_to_target, rect)}; | 120 MathUtil::ProjectClippedRect(current_to_target, rect)}; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 | 183 |
| 212 // Put the expanded clip back into the original target space. | 184 // Put the expanded clip back into the original target space. |
| 213 success = ConvertRectBetweenSurfaceSpaces( | 185 success = ConvertRectBetweenSurfaceSpaces( |
| 214 property_trees, expanding_effect_node->id, target_id, | 186 property_trees, expanding_effect_node->id, target_id, |
| 215 expanded_clip_in_expanding_space, accumulated_clip); | 187 expanded_clip_in_expanding_space, accumulated_clip); |
| 216 // If transform is not invertible, no clip will be applied. | 188 // If transform is not invertible, no clip will be applied. |
| 217 if (!success) | 189 if (!success) |
| 218 return false; | 190 return false; |
| 219 return true; | 191 return true; |
| 220 } | 192 } |
| 221 case ClipNode::ClipType::NONE: | |
| 222 return true; | |
| 223 } | 193 } |
| 224 NOTREACHED(); | 194 NOTREACHED(); |
| 225 return true; | 195 return true; |
| 226 } | 196 } |
| 227 | 197 |
| 228 static ConditionalClip ComputeAccumulatedClip( | 198 static ConditionalClip ComputeAccumulatedClip(PropertyTrees* property_trees, |
| 229 const PropertyTrees* property_trees, | 199 bool include_expanding_clips, |
| 230 bool include_viewport_clip, | 200 int local_clip_id, |
| 231 bool include_expanding_clips, | 201 int target_id) { |
| 232 int local_clip_id, | 202 ClipRectData& cached_data = |
| 233 int target_id) { | 203 property_trees->FetchClipRectFromCache(local_clip_id, target_id); |
| 234 DCHECK(!include_viewport_clip || | 204 if (cached_data.target_id != EffectTree::kInvalidNodeId) { |
| 235 target_id == EffectTree::kContentsRootNodeId); | 205 // Cache hit |
| 206 return cached_data.clip; | |
| 207 } | |
| 208 cached_data.target_id = target_id; | |
| 209 | |
| 236 const ClipTree& clip_tree = property_trees->clip_tree; | 210 const ClipTree& clip_tree = property_trees->clip_tree; |
| 211 const ClipNode* clip_node = clip_tree.Node(local_clip_id); | |
| 237 const EffectTree& effect_tree = property_trees->effect_tree; | 212 const EffectTree& effect_tree = property_trees->effect_tree; |
| 238 | |
| 239 const ClipNode* clip_node = clip_tree.Node(local_clip_id); | |
| 240 const EffectNode* target_node = effect_tree.Node(target_id); | 213 const EffectNode* target_node = effect_tree.Node(target_id); |
| 241 int target_transform_id = target_node->transform_id; | 214 int target_transform_id = target_node->transform_id; |
| 242 | 215 |
| 216 bool cache_hit = false; | |
| 217 ConditionalClip cached_clip = ConditionalClip{false, gfx::RectF()}; | |
| 218 ConditionalClip unclipped = ConditionalClip{false, gfx::RectF()}; | |
| 219 | |
| 243 // Collect all the clips that need to be accumulated. | 220 // Collect all the clips that need to be accumulated. |
| 244 std::stack<const ClipNode*> parent_chain; | 221 std::stack<const ClipNode*, std::vector<const ClipNode*>> parent_chain; |
| 245 | 222 |
| 246 // If target is not direct ancestor of clip, this will find least common | 223 // If target is not direct ancestor of clip, this will find least common |
| 247 // ancestor between the target and the clip. | 224 // ancestor between the target and the clip. |
| 248 while (target_node->clip_id > clip_node->id || | 225 while (target_node->clip_id > clip_node->id || |
| 249 target_node->has_unclipped_descendants) { | 226 target_node->has_unclipped_descendants) { |
| 250 target_node = effect_tree.Node(target_node->target_id); | 227 target_node = effect_tree.Node(target_node->target_id); |
| 251 } | 228 } |
| 252 | 229 |
| 253 // Collect clip nodes up to the least common ancestor. | 230 // Collect clip nodes up to the least common ancestor or till we get a cache |
| 231 // hit. | |
| 254 while (target_node->clip_id < clip_node->id) { | 232 while (target_node->clip_id < clip_node->id) { |
| 233 if (parent_chain.size() > 0) { | |
| 234 // Search the cache. | |
| 235 for (auto& data : clip_node->cached_clip_rects) { | |
| 236 if (data.target_id == target_id) { | |
| 237 cache_hit = true; | |
| 238 cached_clip = data.clip; | |
| 239 } | |
| 240 } | |
| 241 } | |
| 255 parent_chain.push(clip_node); | 242 parent_chain.push(clip_node); |
| 256 clip_node = clip_tree.parent(clip_node); | 243 clip_node = clip_tree.parent(clip_node); |
| 257 } | 244 } |
| 258 DCHECK_EQ(target_node->clip_id, clip_node->id); | |
| 259 | 245 |
| 260 if (!include_viewport_clip && parent_chain.size() == 0) { | 246 if (parent_chain.size() == 0) { |
| 261 // There aren't any clips to apply. | 247 // No accumulated clip nodes. |
| 262 return ConditionalClip{false, gfx::RectF()}; | 248 cached_data.clip = unclipped; |
| 249 return unclipped; | |
| 263 } | 250 } |
| 264 | 251 |
| 265 if (!include_viewport_clip) { | 252 clip_node = parent_chain.top(); |
| 266 clip_node = parent_chain.top(); | 253 parent_chain.pop(); |
| 267 parent_chain.pop(); | 254 |
| 255 gfx::RectF accumulated_clip; | |
| 256 if (cache_hit && cached_clip.is_clipped) { | |
| 257 // Apply the first clip in parent_chain to the cached clip. | |
| 258 accumulated_clip = cached_clip.clip_rect; | |
| 259 bool success = ApplyClipNodeToAccumulatedClip( | |
| 260 property_trees, include_expanding_clips, target_id, target_transform_id, | |
| 261 clip_node, &accumulated_clip); | |
| 262 if (!success) { | |
| 263 // Singular transform | |
| 264 cached_data.clip = unclipped; | |
| 265 return unclipped; | |
| 266 } | |
| 267 } else { | |
| 268 // No cache hit or the cached clip has no clip to apply. We need to find | |
| 269 // the first clip that applies clip as there is no clip to expand. | |
| 270 while (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP && | |
| 271 parent_chain.size() > 0) { | |
| 272 clip_node = parent_chain.top(); | |
| 273 parent_chain.pop(); | |
| 274 } | |
| 275 | |
| 276 if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP) { | |
| 277 // No clip to apply. | |
| 278 cached_data.clip = unclipped; | |
| 279 return unclipped; | |
| 280 } | |
| 281 ConditionalClip current_clip = ComputeCurrentClip( | |
| 282 clip_node, property_trees, target_transform_id, target_id); | |
| 283 if (!current_clip.is_clipped) { | |
| 284 // Singular transform | |
| 285 cached_data.clip = unclipped; | |
| 286 return unclipped; | |
| 287 } | |
| 288 accumulated_clip = current_clip.clip_rect; | |
| 268 } | 289 } |
| 269 | 290 |
| 270 // Find the first clip in the chain that we need to apply. | 291 // Apply remaining clips |
| 271 while (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP && | |
| 272 parent_chain.size() > 0) { | |
| 273 clip_node = parent_chain.top(); | |
| 274 parent_chain.pop(); | |
| 275 } | |
| 276 | |
| 277 if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP) { | |
| 278 // No clip node applying clip in between. | |
| 279 return ConditionalClip{false, gfx::RectF()}; | |
| 280 } | |
| 281 | |
| 282 ConditionalClip current_clip = ComputeCurrentClip( | |
| 283 clip_node, property_trees, target_transform_id, target_id); | |
| 284 | |
| 285 // If transform is not invertible, no clip will be applied. | |
| 286 if (!current_clip.is_clipped) | |
| 287 return ConditionalClip{false, gfx::RectF()}; | |
| 288 gfx::RectF accumulated_clip = current_clip.clip_rect; | |
| 289 | |
| 290 while (parent_chain.size() > 0) { | 292 while (parent_chain.size() > 0) { |
| 291 clip_node = parent_chain.top(); | 293 clip_node = parent_chain.top(); |
| 292 parent_chain.pop(); | 294 parent_chain.pop(); |
| 293 bool success = ApplyClipNodeToAccumulatedClip( | 295 bool success = ApplyClipNodeToAccumulatedClip( |
| 294 property_trees, include_expanding_clips, target_id, target_transform_id, | 296 property_trees, include_expanding_clips, target_id, target_transform_id, |
| 295 clip_node, &accumulated_clip); | 297 clip_node, &accumulated_clip); |
| 296 | 298 if (!success) { |
| 297 // Failure to apply the clip means we encountered an uninvertible transform, | 299 // Singular transform |
| 298 // so no clip will be applied. | 300 cached_data.clip = unclipped; |
| 299 if (!success) | 301 return unclipped; |
| 300 return ConditionalClip{false /* is_clipped */, gfx::RectF()}; | 302 } |
| 301 } | 303 } |
| 302 | 304 |
| 303 return ConditionalClip{true /* is_clipped */, accumulated_clip.IsEmpty() | 305 ConditionalClip clip = ConditionalClip{ |
| 304 ? gfx::RectF() | 306 true /* is_clipped */, |
| 305 : accumulated_clip}; | 307 accumulated_clip.IsEmpty() ? gfx::RectF() : accumulated_clip}; |
| 306 } | 308 cached_data.clip = clip; |
| 307 | 309 return clip; |
| 308 static gfx::RectF ComputeAccumulatedClipInRootSpaceForVisibleRect( | |
| 309 const PropertyTrees* property_trees, | |
| 310 int local_clip_id) { | |
| 311 const int root_effect_id = EffectTree::kContentsRootNodeId; | |
| 312 bool include_viewport_clip = true; | |
| 313 bool include_expanding_clips = true; | |
| 314 ConditionalClip accumulated_clip = ComputeAccumulatedClip( | |
| 315 property_trees, include_viewport_clip, include_expanding_clips, | |
| 316 local_clip_id, root_effect_id); | |
| 317 DCHECK(accumulated_clip.is_clipped); | |
| 318 return accumulated_clip.clip_rect; | |
| 319 } | |
| 320 | |
| 321 void CalculateClipRects(const std::vector<LayerImpl*>& visible_layer_list, | |
| 322 const PropertyTrees* property_trees, | |
| 323 bool non_root_surfaces_enabled) { | |
| 324 const ClipTree& clip_tree = property_trees->clip_tree; | |
| 325 for (auto* layer : visible_layer_list) { | |
| 326 const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index()); | |
| 327 bool layer_needs_clip_rect = | |
| 328 non_root_surfaces_enabled | |
| 329 ? clip_node->layers_are_clipped | |
| 330 : clip_node->layers_are_clipped_when_surfaces_disabled; | |
| 331 if (!layer_needs_clip_rect) { | |
| 332 layer->set_clip_rect(gfx::Rect()); | |
| 333 continue; | |
| 334 } | |
| 335 if (!non_root_surfaces_enabled) { | |
| 336 layer->set_clip_rect( | |
| 337 gfx::ToEnclosingRect(clip_node->clip_in_target_space)); | |
| 338 continue; | |
| 339 } | |
| 340 | |
| 341 const TransformTree& transform_tree = property_trees->transform_tree; | |
| 342 const TransformNode* transform_node = | |
| 343 transform_tree.Node(layer->transform_tree_index()); | |
| 344 int target_node_id = transform_tree.ContentTargetId(transform_node->id); | |
| 345 | |
| 346 // The clip node stores clip rect in its target space. | |
| 347 gfx::RectF clip_rect_in_target_space = clip_node->clip_in_target_space; | |
| 348 | |
| 349 // If required, this clip rect should be mapped to the current layer's | |
| 350 // target space. | |
| 351 if (clip_node->target_transform_id != target_node_id) { | |
| 352 // In this case, layer has a clip parent or scroll parent (or shares the | |
| 353 // target with an ancestor layer that has clip parent) and the clip | |
| 354 // parent's target is different from the layer's target. As the layer's | |
| 355 // target has unclippped descendants, it is unclippped. | |
| 356 if (!clip_node->layers_are_clipped) | |
| 357 continue; | |
| 358 | |
| 359 // Compute the clip rect in target space and store it. | |
| 360 bool for_visible_rect_calculation = false; | |
| 361 if (!ComputeClipRectInTargetSpace( | |
| 362 layer, clip_node, property_trees, target_node_id, | |
| 363 for_visible_rect_calculation, &clip_rect_in_target_space)) | |
| 364 continue; | |
| 365 } | |
| 366 | |
| 367 if (!clip_rect_in_target_space.IsEmpty()) { | |
| 368 layer->set_clip_rect(gfx::ToEnclosingRect(clip_rect_in_target_space)); | |
| 369 } else { | |
| 370 layer->set_clip_rect(gfx::Rect()); | |
| 371 } | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 void CalculateVisibleRects(const LayerImplList& visible_layer_list, | |
| 376 const PropertyTrees* property_trees, | |
| 377 bool non_root_surfaces_enabled) { | |
| 378 const EffectTree& effect_tree = property_trees->effect_tree; | |
| 379 const TransformTree& transform_tree = property_trees->transform_tree; | |
| 380 const ClipTree& clip_tree = property_trees->clip_tree; | |
| 381 for (auto* layer : visible_layer_list) { | |
| 382 gfx::Size layer_bounds = layer->bounds(); | |
| 383 | |
| 384 int effect_ancestor_with_copy_request = | |
| 385 effect_tree.ClosestAncestorWithCopyRequest(layer->effect_tree_index()); | |
| 386 if (effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId) { | |
| 387 // Non root copy request. | |
| 388 bool include_viewport_clip = false; | |
| 389 bool include_expanding_clips = true; | |
| 390 ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip( | |
| 391 property_trees, include_viewport_clip, include_expanding_clips, | |
| 392 layer->clip_tree_index(), effect_ancestor_with_copy_request); | |
| 393 if (!accumulated_clip_rect.is_clipped) { | |
| 394 layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); | |
| 395 continue; | |
| 396 } | |
| 397 | |
| 398 gfx::RectF accumulated_clip_in_copy_request_space = | |
| 399 accumulated_clip_rect.clip_rect; | |
| 400 | |
| 401 const EffectNode* copy_request_effect_node = | |
| 402 effect_tree.Node(effect_ancestor_with_copy_request); | |
| 403 ConditionalClip clip_in_layer_space = ComputeTargetRectInLocalSpace( | |
| 404 accumulated_clip_in_copy_request_space, property_trees, | |
| 405 copy_request_effect_node->transform_id, layer->transform_tree_index(), | |
| 406 copy_request_effect_node->id); | |
| 407 | |
| 408 if (clip_in_layer_space.is_clipped) { | |
| 409 gfx::RectF clip_rect = clip_in_layer_space.clip_rect; | |
| 410 clip_rect.Offset(-layer->offset_to_transform_parent()); | |
| 411 gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_rect); | |
| 412 visible_rect.Intersect(gfx::Rect(layer_bounds)); | |
| 413 layer->set_visible_layer_rect(visible_rect); | |
| 414 } else { | |
| 415 layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); | |
| 416 } | |
| 417 continue; | |
| 418 } | |
| 419 | |
| 420 const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index()); | |
| 421 const TransformNode* transform_node = | |
| 422 transform_tree.Node(layer->transform_tree_index()); | |
| 423 if (!non_root_surfaces_enabled) { | |
| 424 // When we only have a root surface, the clip node and the layer must | |
| 425 // necessarily have the same target (the root). | |
| 426 if (transform_node->ancestors_are_invertible) { | |
| 427 gfx::RectF combined_clip_rect_in_target_space = | |
| 428 clip_node->combined_clip_in_target_space; | |
| 429 gfx::Transform target_to_content; | |
| 430 target_to_content.Translate(-layer->offset_to_transform_parent().x(), | |
| 431 -layer->offset_to_transform_parent().y()); | |
| 432 target_to_content.PreconcatTransform( | |
| 433 transform_tree.FromScreen(transform_node->id)); | |
| 434 | |
| 435 gfx::Rect visible_rect = | |
| 436 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( | |
| 437 target_to_content, combined_clip_rect_in_target_space)); | |
| 438 visible_rect.Intersect(gfx::Rect(layer_bounds)); | |
| 439 layer->set_visible_layer_rect(visible_rect); | |
| 440 } else { | |
| 441 layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); | |
| 442 } | |
| 443 continue; | |
| 444 } | |
| 445 | |
| 446 // When both the layer and the target are unclipped, we only have to apply | |
| 447 // the viewport clip. | |
| 448 const bool fully_visible = | |
| 449 !clip_node->layers_are_clipped && | |
| 450 !effect_tree.Node(clip_node->target_effect_id)->surface_is_clipped; | |
| 451 | |
| 452 if (fully_visible) { | |
| 453 if (!transform_node->ancestors_are_invertible) { | |
| 454 // An animated singular transform may become non-singular during the | |
| 455 // animation, so we still need to compute a visible rect. In this | |
| 456 // situation, we treat the entire layer as visible. | |
| 457 layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); | |
| 458 } else { | |
| 459 gfx::Transform from_screen; | |
| 460 from_screen.Translate(-layer->offset_to_transform_parent().x(), | |
| 461 -layer->offset_to_transform_parent().y()); | |
| 462 from_screen.PreconcatTransform( | |
| 463 property_trees->transform_tree.FromScreen(transform_node->id)); | |
| 464 gfx::Rect visible_rect = | |
| 465 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( | |
| 466 from_screen, property_trees->clip_tree.ViewportClip())); | |
| 467 visible_rect.Intersect(gfx::Rect(layer_bounds)); | |
| 468 layer->set_visible_layer_rect(visible_rect); | |
| 469 } | |
| 470 continue; | |
| 471 } | |
| 472 | |
| 473 int target_node_id = transform_tree.ContentTargetId(transform_node->id); | |
| 474 | |
| 475 // The clip node stores clip rect in its target space. If required, | |
| 476 // this clip rect should be mapped to the current layer's target space. | |
| 477 gfx::RectF combined_clip_rect_in_target_space; | |
| 478 | |
| 479 if (clip_node->target_transform_id != target_node_id) { | |
| 480 // In this case, layer has a clip parent or scroll parent (or shares the | |
| 481 // target with an ancestor layer that has clip parent) and the clip | |
| 482 // parent's target is different from the layer's target. As the layer's | |
| 483 // target has unclippped descendants, it is unclippped. | |
| 484 if (!clip_node->layers_are_clipped) { | |
| 485 layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); | |
| 486 continue; | |
| 487 } | |
| 488 | |
| 489 bool for_visible_rect_calculation = true; | |
| 490 if (!ComputeClipRectInTargetSpace(layer, clip_node, property_trees, | |
| 491 target_node_id, | |
| 492 for_visible_rect_calculation, | |
| 493 &combined_clip_rect_in_target_space)) { | |
| 494 layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); | |
| 495 continue; | |
| 496 } | |
| 497 } else { | |
| 498 combined_clip_rect_in_target_space = | |
| 499 clip_node->combined_clip_in_target_space; | |
| 500 } | |
| 501 | |
| 502 // The clip rect should be intersected with layer rect in target space. | |
| 503 gfx::Transform content_to_target; | |
| 504 property_trees->GetToTarget(transform_node->id, | |
| 505 layer->render_target_effect_tree_index(), | |
| 506 &content_to_target); | |
| 507 content_to_target.Translate(layer->offset_to_transform_parent().x(), | |
| 508 layer->offset_to_transform_parent().y()); | |
| 509 gfx::Rect layer_content_rect = gfx::Rect(layer_bounds); | |
| 510 gfx::RectF layer_content_bounds_in_target_space = MathUtil::MapClippedRect( | |
| 511 content_to_target, gfx::RectF(layer_content_rect)); | |
| 512 // If the layer is fully contained within the clip, treat it as fully | |
| 513 // visible. | |
| 514 if (!layer_content_bounds_in_target_space.IsEmpty() && | |
| 515 combined_clip_rect_in_target_space.Contains( | |
| 516 layer_content_bounds_in_target_space)) { | |
| 517 layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); | |
| 518 continue; | |
| 519 } | |
| 520 | |
| 521 combined_clip_rect_in_target_space.Intersect( | |
| 522 layer_content_bounds_in_target_space); | |
| 523 if (combined_clip_rect_in_target_space.IsEmpty()) { | |
| 524 layer->set_visible_layer_rect(gfx::Rect()); | |
| 525 continue; | |
| 526 } | |
| 527 | |
| 528 gfx::Transform target_to_layer; | |
| 529 const EffectNode* target_effect_node = | |
| 530 ContentsTargetEffectNode(layer->effect_tree_index(), effect_tree); | |
| 531 bool success = property_trees->GetFromTarget( | |
| 532 transform_node->id, target_effect_node->id, &target_to_layer); | |
| 533 if (!success) { | |
| 534 // An animated singular transform may become non-singular during the | |
| 535 // animation, so we still need to compute a visible rect. In this | |
| 536 // situation, we treat the entire layer as visible. | |
| 537 layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); | |
| 538 continue; | |
| 539 } | |
| 540 gfx::Transform target_to_content; | |
| 541 target_to_content.Translate(-layer->offset_to_transform_parent().x(), | |
| 542 -layer->offset_to_transform_parent().y()); | |
| 543 target_to_content.PreconcatTransform(target_to_layer); | |
| 544 | |
| 545 gfx::Rect visible_rect = gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( | |
| 546 target_to_content, combined_clip_rect_in_target_space)); | |
| 547 visible_rect.Intersect(gfx::Rect(layer_bounds)); | |
| 548 layer->set_visible_layer_rect(visible_rect); | |
| 549 } | |
| 550 } | 310 } |
| 551 | 311 |
| 552 static bool HasSingularTransform(int transform_tree_index, | 312 static bool HasSingularTransform(int transform_tree_index, |
| 553 const TransformTree& tree) { | 313 const TransformTree& tree) { |
| 554 const TransformNode* node = tree.Node(transform_tree_index); | 314 const TransformNode* node = tree.Node(transform_tree_index); |
| 555 return !node->is_invertible || !node->ancestors_are_invertible; | 315 return !node->is_invertible || !node->ancestors_are_invertible; |
| 556 } | 316 } |
| 557 | 317 |
| 558 template <typename LayerType> | 318 template <typename LayerType> |
| 559 static int TransformTreeIndexForBackfaceVisibility(LayerType* layer, | 319 static int TransformTreeIndexForBackfaceVisibility(LayerType* layer, |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 646 // backface is not visible. | 406 // backface is not visible. |
| 647 if (TransformToScreenIsKnown(layer, backface_transform_id, tree) && | 407 if (TransformToScreenIsKnown(layer, backface_transform_id, tree) && |
| 648 !HasSingularTransform(backface_transform_id, tree) && | 408 !HasSingularTransform(backface_transform_id, tree) && |
| 649 IsLayerBackFaceVisible(layer, backface_transform_id, property_trees)) | 409 IsLayerBackFaceVisible(layer, backface_transform_id, property_trees)) |
| 650 return false; | 410 return false; |
| 651 } | 411 } |
| 652 | 412 |
| 653 return true; | 413 return true; |
| 654 } | 414 } |
| 655 | 415 |
| 656 void FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl, | |
| 657 const PropertyTrees* property_trees, | |
| 658 std::vector<LayerImpl*>* visible_layer_list) { | |
| 659 const TransformTree& transform_tree = property_trees->transform_tree; | |
| 660 const EffectTree& effect_tree = property_trees->effect_tree; | |
| 661 | 416 |
| 662 for (auto* layer_impl : *layer_tree_impl) { | |
| 663 if (!IsRootLayer(layer_impl) && | |
| 664 LayerShouldBeSkipped(layer_impl, transform_tree, effect_tree)) | |
| 665 continue; | |
| 666 | |
| 667 bool layer_is_drawn = | |
| 668 effect_tree.Node(layer_impl->effect_tree_index())->is_drawn; | |
| 669 | |
| 670 if (LayerNeedsUpdate(layer_impl, layer_is_drawn, property_trees)) | |
| 671 visible_layer_list->push_back(layer_impl); | |
| 672 } | |
| 673 } | |
| 674 | 417 |
| 675 } // namespace | 418 } // namespace |
| 676 | 419 |
| 677 template <typename LayerType> | 420 template <typename LayerType> |
| 678 static inline bool LayerShouldBeSkippedInternal( | 421 static inline bool LayerShouldBeSkippedInternal( |
| 679 LayerType* layer, | 422 LayerType* layer, |
| 680 const TransformTree& transform_tree, | 423 const TransformTree& transform_tree, |
| 681 const EffectTree& effect_tree) { | 424 const EffectTree& effect_tree) { |
| 682 const TransformNode* transform_node = | 425 const TransformNode* transform_node = |
| 683 transform_tree.Node(layer->transform_tree_index()); | 426 transform_tree.Node(layer->transform_tree_index()); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 723 update_layer_list->push_back(layer); | 466 update_layer_list->push_back(layer); |
| 724 } | 467 } |
| 725 | 468 |
| 726 // Append mask layers to the update layer list. They don't have valid | 469 // Append mask layers to the update layer list. They don't have valid |
| 727 // visible rects, so need to get added after the above calculation. | 470 // visible rects, so need to get added after the above calculation. |
| 728 if (Layer* mask_layer = layer->mask_layer()) | 471 if (Layer* mask_layer = layer->mask_layer()) |
| 729 update_layer_list->push_back(mask_layer); | 472 update_layer_list->push_back(mask_layer); |
| 730 } | 473 } |
| 731 } | 474 } |
| 732 | 475 |
| 733 static void ResetIfHasNanCoordinate(gfx::RectF* rect) { | 476 void FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl, |
| 734 if (std::isnan(rect->x()) || std::isnan(rect->y()) || | 477 const PropertyTrees* property_trees, |
| 735 std::isnan(rect->right()) || std::isnan(rect->bottom())) | 478 std::vector<LayerImpl*>* visible_layer_list) { |
| 736 *rect = gfx::RectF(); | 479 const TransformTree& transform_tree = property_trees->transform_tree; |
| 480 const EffectTree& effect_tree = property_trees->effect_tree; | |
| 481 | |
| 482 for (auto* layer_impl : *layer_tree_impl) { | |
| 483 if (!IsRootLayer(layer_impl) && | |
| 484 LayerShouldBeSkipped(layer_impl, transform_tree, effect_tree)) | |
| 485 continue; | |
| 486 | |
| 487 bool layer_is_drawn = | |
| 488 effect_tree.Node(layer_impl->effect_tree_index())->is_drawn; | |
| 489 | |
| 490 if (LayerNeedsUpdate(layer_impl, layer_is_drawn, property_trees)) | |
| 491 visible_layer_list->push_back(layer_impl); | |
| 492 } | |
| 737 } | 493 } |
| 738 | 494 |
| 739 void PostConcatSurfaceContentsScale(const EffectNode* effect_node, | 495 void PostConcatSurfaceContentsScale(const EffectNode* effect_node, |
| 740 gfx::Transform* transform) { | 496 gfx::Transform* transform) { |
| 741 if (!effect_node) { | 497 if (!effect_node) { |
| 742 // This can happen when PaintArtifactCompositor builds property trees as it | 498 // This can happen when PaintArtifactCompositor builds property trees as it |
| 743 // doesn't set effect ids on clip nodes. | 499 // doesn't set effect ids on clip nodes. |
| 744 return; | 500 return; |
| 745 } | 501 } |
| 746 DCHECK(effect_node->has_render_surface); | 502 DCHECK(effect_node->has_render_surface); |
| 747 transform->matrix().postScale(effect_node->surface_contents_scale.x(), | 503 transform->matrix().postScale(effect_node->surface_contents_scale.x(), |
| 748 effect_node->surface_contents_scale.y(), 1.f); | 504 effect_node->surface_contents_scale.y(), 1.f); |
| 749 } | 505 } |
| 750 | 506 |
| 751 void ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, | 507 void ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, |
| 752 gfx::Transform* transform) { | 508 gfx::Transform* transform) { |
| 753 DCHECK(effect_node->has_render_surface); | 509 DCHECK(effect_node->has_render_surface); |
| 754 if (effect_node->surface_contents_scale.x() != 0.0 && | 510 if (effect_node->surface_contents_scale.x() != 0.0 && |
| 755 effect_node->surface_contents_scale.y() != 0.0) | 511 effect_node->surface_contents_scale.y() != 0.0) |
| 756 transform->Scale(1.0 / effect_node->surface_contents_scale.x(), | 512 transform->Scale(1.0 / effect_node->surface_contents_scale.x(), |
| 757 1.0 / effect_node->surface_contents_scale.y()); | 513 1.0 / effect_node->surface_contents_scale.y()); |
| 758 } | 514 } |
| 759 | 515 |
| 760 void ComputeClips(PropertyTrees* property_trees, | |
| 761 bool non_root_surfaces_enabled) { | |
| 762 ClipTree* clip_tree = &property_trees->clip_tree; | |
| 763 if (!clip_tree->needs_update()) | |
| 764 return; | |
| 765 for (int i = ClipTree::kViewportNodeId; | |
| 766 i < static_cast<int>(clip_tree->size()); ++i) { | |
| 767 ClipNode* clip_node = clip_tree->Node(i); | |
| 768 | |
| 769 if (clip_node->id == ClipTree::kViewportNodeId) { | |
| 770 ResetIfHasNanCoordinate(&clip_node->clip); | |
| 771 clip_node->clip_in_target_space = clip_node->clip; | |
| 772 clip_node->combined_clip_in_target_space = clip_node->clip; | |
| 773 continue; | |
| 774 } | |
| 775 const TransformTree& transform_tree = property_trees->transform_tree; | |
| 776 const EffectTree& effect_tree = property_trees->effect_tree; | |
| 777 const TransformNode* transform_node = | |
| 778 transform_tree.Node(clip_node->transform_id); | |
| 779 ClipNode* parent_clip_node = clip_tree->parent(clip_node); | |
| 780 | |
| 781 bool target_is_clipped = | |
| 782 effect_tree.Node(clip_node->target_effect_id)->surface_is_clipped; | |
| 783 | |
| 784 gfx::Transform parent_to_current; | |
| 785 const TransformNode* parent_target_transform_node = | |
| 786 transform_tree.Node(parent_clip_node->target_transform_id); | |
| 787 bool success = true; | |
| 788 | |
| 789 // Clips must be combined in target space. We cannot, for example, combine | |
| 790 // clips in the space of the child clip. The reason is non-affine | |
| 791 // transforms. Say we have the following tree T->A->B->C, and B clips C, but | |
| 792 // draw into target T. It may be the case that A applies a perspective | |
| 793 // transform, and B and C are at different z positions. When projected into | |
| 794 // target space, the relative sizes and positions of B and C can shift. | |
| 795 // Since it's the relationship in target space that matters, that's where we | |
| 796 // must combine clips. For each clip node, we save the clip rects in its | |
| 797 // target space. So, we need to get the ancestor clip rect in the current | |
| 798 // clip node's target space. | |
| 799 gfx::RectF parent_combined_clip_in_target_space = | |
| 800 parent_clip_node->combined_clip_in_target_space; | |
| 801 gfx::RectF parent_clip_in_target_space = | |
| 802 parent_clip_node->clip_in_target_space; | |
| 803 if (parent_target_transform_node && | |
| 804 parent_target_transform_node->id != clip_node->target_transform_id && | |
| 805 non_root_surfaces_enabled) { | |
| 806 success &= ConvertRectBetweenSurfaceSpaces( | |
| 807 property_trees, parent_clip_node->target_effect_id, | |
| 808 clip_node->target_effect_id, | |
| 809 parent_clip_node->combined_clip_in_target_space, | |
| 810 &parent_combined_clip_in_target_space); | |
| 811 // If we can't compute a transform, it's because we had to use the inverse | |
| 812 // of a singular transform. We won't draw in this case, so there's no need | |
| 813 // to compute clips. | |
| 814 if (!success) | |
| 815 continue; | |
| 816 if (clip_node->clip_type == ClipNode::ClipType::EXPANDS_CLIP) { | |
| 817 parent_combined_clip_in_target_space = | |
| 818 gfx::RectF(clip_node->clip_expander->MapRectReverse( | |
| 819 gfx::ToEnclosingRect(parent_combined_clip_in_target_space), | |
| 820 property_trees)); | |
| 821 } | |
| 822 ConvertRectBetweenSurfaceSpaces( | |
| 823 property_trees, parent_clip_node->target_effect_id, | |
| 824 clip_node->target_effect_id, parent_clip_node->clip_in_target_space, | |
| 825 &parent_clip_in_target_space); | |
| 826 } | |
| 827 // Only nodes affected by ancestor clips will have their clip adjusted due | |
| 828 // to intersecting with an ancestor clip. But, we still need to propagate | |
| 829 // the combined clip to our children because if they are clipped, they may | |
| 830 // need to clip using our parent clip and if we don't propagate it here, | |
| 831 // it will be lost. | |
| 832 if (clip_node->resets_clip && non_root_surfaces_enabled) { | |
| 833 if (clip_node->clip_type == ClipNode::ClipType::APPLIES_LOCAL_CLIP) { | |
| 834 gfx::Transform to_target; | |
| 835 property_trees->GetToTarget(clip_node->transform_id, | |
| 836 clip_node->target_effect_id, &to_target); | |
| 837 clip_node->clip_in_target_space = | |
| 838 MathUtil::MapClippedRect(to_target, clip_node->clip); | |
| 839 ResetIfHasNanCoordinate(&clip_node->clip_in_target_space); | |
| 840 clip_node->combined_clip_in_target_space = | |
| 841 gfx::IntersectRects(clip_node->clip_in_target_space, | |
| 842 parent_combined_clip_in_target_space); | |
| 843 } else { | |
| 844 DCHECK(!target_is_clipped); | |
| 845 DCHECK(!clip_node->layers_are_clipped); | |
| 846 clip_node->combined_clip_in_target_space = | |
| 847 parent_combined_clip_in_target_space; | |
| 848 } | |
| 849 ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space); | |
| 850 continue; | |
| 851 } | |
| 852 bool use_only_parent_clip = | |
| 853 clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP; | |
| 854 if (use_only_parent_clip) { | |
| 855 clip_node->combined_clip_in_target_space = | |
| 856 parent_combined_clip_in_target_space; | |
| 857 if (!non_root_surfaces_enabled) { | |
| 858 clip_node->clip_in_target_space = | |
| 859 parent_clip_node->clip_in_target_space; | |
| 860 } else if (!target_is_clipped) { | |
| 861 clip_node->clip_in_target_space = parent_clip_in_target_space; | |
| 862 } else { | |
| 863 // Render Surface applies clip and the owning layer itself applies | |
| 864 // no clip. So, clip_in_target_space is not used and hence we can set | |
| 865 // it to an empty rect. | |
| 866 clip_node->clip_in_target_space = gfx::RectF(); | |
| 867 } | |
| 868 } else { | |
| 869 gfx::Transform source_to_target; | |
| 870 | |
| 871 if (!non_root_surfaces_enabled) { | |
| 872 source_to_target = transform_tree.ToScreen(clip_node->transform_id); | |
| 873 } else if (transform_tree.ContentTargetId(transform_node->id) == | |
| 874 clip_node->target_transform_id) { | |
| 875 property_trees->GetToTarget(clip_node->transform_id, | |
| 876 clip_node->target_effect_id, | |
| 877 &source_to_target); | |
| 878 } else { | |
| 879 success = property_trees->GetToTarget( | |
| 880 transform_node->id, clip_node->target_effect_id, &source_to_target); | |
| 881 // source_to_target computation should be successful as target is an | |
| 882 // ancestor of the transform node. | |
| 883 DCHECK(success); | |
| 884 } | |
| 885 | |
| 886 gfx::RectF source_clip_in_target_space = | |
| 887 MathUtil::MapClippedRect(source_to_target, clip_node->clip); | |
| 888 | |
| 889 // With surfaces disabled, the only case where we use only the local clip | |
| 890 // for layer clipping is the case where no non-viewport ancestor node | |
| 891 // applies a local clip. | |
| 892 bool layer_clipping_uses_only_local_clip = | |
| 893 non_root_surfaces_enabled | |
| 894 ? clip_node->layer_clipping_uses_only_local_clip | |
| 895 : !parent_clip_node->layers_are_clipped_when_surfaces_disabled; | |
| 896 if (!layer_clipping_uses_only_local_clip) { | |
| 897 clip_node->clip_in_target_space = gfx::IntersectRects( | |
| 898 parent_clip_in_target_space, source_clip_in_target_space); | |
| 899 } else { | |
| 900 clip_node->clip_in_target_space = source_clip_in_target_space; | |
| 901 } | |
| 902 | |
| 903 clip_node->combined_clip_in_target_space = gfx::IntersectRects( | |
| 904 parent_combined_clip_in_target_space, source_clip_in_target_space); | |
| 905 } | |
| 906 ResetIfHasNanCoordinate(&clip_node->clip_in_target_space); | |
| 907 ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space); | |
| 908 } | |
| 909 clip_tree->set_needs_update(false); | |
| 910 } | |
| 911 | |
| 912 void ComputeTransforms(TransformTree* transform_tree) { | 516 void ComputeTransforms(TransformTree* transform_tree) { |
| 913 if (!transform_tree->needs_update()) | 517 if (!transform_tree->needs_update()) |
| 914 return; | 518 return; |
| 915 for (int i = TransformTree::kContentsRootNodeId; | 519 for (int i = TransformTree::kContentsRootNodeId; |
| 916 i < static_cast<int>(transform_tree->size()); ++i) | 520 i < static_cast<int>(transform_tree->size()); ++i) |
| 917 transform_tree->UpdateTransforms(i); | 521 transform_tree->UpdateTransforms(i); |
| 918 transform_tree->set_needs_update(false); | 522 transform_tree->set_needs_update(false); |
| 919 } | 523 } |
| 920 | 524 |
| 921 void UpdateRenderTarget(EffectTree* effect_tree, | 525 void UpdateRenderTarget(EffectTree* effect_tree, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 938 | 542 |
| 939 void ComputeEffects(EffectTree* effect_tree) { | 543 void ComputeEffects(EffectTree* effect_tree) { |
| 940 if (!effect_tree->needs_update()) | 544 if (!effect_tree->needs_update()) |
| 941 return; | 545 return; |
| 942 for (int i = EffectTree::kContentsRootNodeId; | 546 for (int i = EffectTree::kContentsRootNodeId; |
| 943 i < static_cast<int>(effect_tree->size()); ++i) | 547 i < static_cast<int>(effect_tree->size()); ++i) |
| 944 effect_tree->UpdateEffects(i); | 548 effect_tree->UpdateEffects(i); |
| 945 effect_tree->set_needs_update(false); | 549 effect_tree->set_needs_update(false); |
| 946 } | 550 } |
| 947 | 551 |
| 948 static void ComputeClipsWithEffectTree(PropertyTrees* property_trees) { | 552 void ComputeClips(PropertyTrees* property_trees) { |
| 949 EffectTree* effect_tree = &property_trees->effect_tree; | 553 ClipTree* clip_tree = &property_trees->clip_tree; |
| 950 const ClipTree* clip_tree = &property_trees->clip_tree; | 554 if (!clip_tree->needs_update()) |
| 951 EffectNode* root_effect_node = | 555 return; |
| 952 effect_tree->Node(EffectTree::kContentsRootNodeId); | 556 const int target_effect_id = EffectTree::kContentsRootNodeId; |
| 953 const RenderSurfaceImpl* root_render_surface = | 557 const int target_transform_id = TransformTree::kRootNodeId; |
| 954 effect_tree->GetRenderSurface(EffectTree::kContentsRootNodeId); | 558 const bool include_expanding_clips = true; |
| 955 gfx::Rect root_clip = | 559 for (int i = ClipTree::kViewportNodeId; |
| 956 gfx::ToEnclosingRect(clip_tree->Node(root_effect_node->clip_id)->clip); | 560 i < static_cast<int>(clip_tree->size()); ++i) { |
| 957 if (root_render_surface->is_clipped()) | 561 ClipNode* clip_node = clip_tree->Node(i); |
| 958 DCHECK(root_clip == root_render_surface->clip_rect()) | 562 // Clear the clip rect cache |
| 959 << "clip on root render surface: " | 563 clip_node->cached_clip_rects = std::vector<ClipRectData>(1); |
| 960 << root_render_surface->clip_rect().ToString() | 564 if (clip_node->id == ClipTree::kViewportNodeId) { |
| 961 << " v.s. root effect node's clip: " << root_clip.ToString(); | 565 clip_node->accumulated_rect_in_screen_space = clip_node->clip; |
| 962 for (int i = 2; i < static_cast<int>(effect_tree->size()); ++i) { | 566 continue; |
| 963 EffectNode* effect_node = effect_tree->Node(i); | |
| 964 const EffectNode* target_node = effect_tree->Node(effect_node->target_id); | |
| 965 bool include_viewport_clip = false; | |
| 966 bool include_expanding_clips = false; | |
| 967 ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip( | |
| 968 property_trees, include_viewport_clip, include_expanding_clips, | |
| 969 effect_node->clip_id, target_node->id); | |
| 970 gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect; | |
| 971 const RenderSurfaceImpl* render_surface = effect_tree->GetRenderSurface(i); | |
| 972 if (render_surface && render_surface->is_clipped()) { | |
| 973 DCHECK(gfx::ToEnclosingRect(accumulated_clip) == | |
| 974 render_surface->clip_rect()) | |
| 975 << " render surface's clip rect: " | |
| 976 << render_surface->clip_rect().ToString() | |
| 977 << " v.s. accumulated clip: " | |
| 978 << gfx::ToEnclosingRect(accumulated_clip).ToString(); | |
| 979 } | 567 } |
| 568 ClipNode* parent_clip_node = clip_tree->parent(clip_node); | |
| 569 DCHECK(parent_clip_node); | |
| 570 gfx::RectF accumulated_clip = | |
| 571 parent_clip_node->accumulated_rect_in_screen_space; | |
| 572 bool success = ApplyClipNodeToAccumulatedClip( | |
| 573 property_trees, include_expanding_clips, target_effect_id, | |
| 574 target_transform_id, clip_node, &accumulated_clip); | |
| 575 DCHECK(success); | |
| 576 clip_node->accumulated_rect_in_screen_space = accumulated_clip; | |
|
weiliangc
2017/03/14 22:04:30
Have you tried not calculating acculated_rect_in_s
jaydasika
2017/03/16 20:33:31
I tried that. The performance was almost same. I d
| |
| 980 } | 577 } |
| 578 clip_tree->set_needs_update(false); | |
| 981 } | 579 } |
| 982 | 580 |
| 983 static void ComputeLayerClipRect(const PropertyTrees* property_trees, | 581 static ConditionalClip LayerClipRect(PropertyTrees* property_trees, |
| 984 const LayerImpl* layer) { | 582 LayerImpl* layer) { |
| 985 const EffectTree* effect_tree = &property_trees->effect_tree; | 583 const EffectTree* effect_tree = &property_trees->effect_tree; |
| 986 const ClipTree* clip_tree = &property_trees->clip_tree; | |
| 987 const ClipNode* clip_node = clip_tree->Node(layer->clip_tree_index()); | |
| 988 const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index()); | 584 const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index()); |
| 989 const EffectNode* target_node = | 585 const EffectNode* target_node = |
| 990 effect_node->has_render_surface | 586 effect_node->has_render_surface |
| 991 ? effect_node | 587 ? effect_node |
| 992 : effect_tree->Node(effect_node->target_id); | 588 : effect_tree->Node(effect_node->target_id); |
| 993 // TODO(weiliangc): When effect node has up to date render surface info on | 589 // TODO(weiliangc): When effect node has up to date render surface info on |
| 994 // compositor thread, no need to check for resourceless draw mode | 590 // compositor thread, no need to check for resourceless draw mode |
| 995 if (!property_trees->non_root_surfaces_enabled) { | 591 if (!property_trees->non_root_surfaces_enabled) { |
| 996 target_node = effect_tree->Node(1); | 592 target_node = effect_tree->Node(1); |
| 997 } | 593 } |
| 998 | 594 |
| 999 bool include_viewport_clip = false; | |
| 1000 bool include_expanding_clips = false; | 595 bool include_expanding_clips = false; |
| 1001 ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip( | 596 return ComputeAccumulatedClip(property_trees, include_expanding_clips, |
| 1002 property_trees, include_viewport_clip, include_expanding_clips, | 597 layer->clip_tree_index(), target_node->id); |
| 1003 layer->clip_tree_index(), target_node->id); | |
| 1004 | |
| 1005 bool is_clipped_from_clip_tree = | |
| 1006 property_trees->non_root_surfaces_enabled | |
| 1007 ? clip_node->layers_are_clipped | |
| 1008 : clip_node->layers_are_clipped_when_surfaces_disabled; | |
| 1009 DCHECK_EQ(is_clipped_from_clip_tree, accumulated_clip_rect.is_clipped); | |
| 1010 | |
| 1011 gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect; | |
| 1012 | |
| 1013 DCHECK(layer->clip_rect() == gfx::ToEnclosingRect(accumulated_clip)) | |
| 1014 << " layer: " << layer->id() << " clip id: " << layer->clip_tree_index() | |
| 1015 << " layer clip: " << layer->clip_rect().ToString() << " v.s. " | |
| 1016 << gfx::ToEnclosingRect(accumulated_clip).ToString() | |
| 1017 << " and clip node clip: " | |
| 1018 << gfx::ToEnclosingRect(clip_node->clip_in_target_space).ToString(); | |
| 1019 } | 598 } |
| 1020 | 599 |
| 1021 void ComputeVisibleRects(LayerImpl* root_layer, | 600 static gfx::Rect LayerVisibleRect(PropertyTrees* property_trees, |
| 1022 PropertyTrees* property_trees, | 601 LayerImpl* layer) { |
| 1023 bool can_render_to_separate_surface, | |
| 1024 LayerImplList* visible_layer_list) { | |
| 1025 bool render_surfaces_need_update = false; | |
| 1026 if (property_trees->non_root_surfaces_enabled != | |
| 1027 can_render_to_separate_surface) { | |
| 1028 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; | |
| 1029 property_trees->transform_tree.set_needs_update(true); | |
| 1030 render_surfaces_need_update = true; | |
| 1031 } | |
| 1032 if (property_trees->transform_tree.needs_update()) { | |
| 1033 property_trees->clip_tree.set_needs_update(true); | |
| 1034 property_trees->effect_tree.set_needs_update(true); | |
| 1035 } | |
| 1036 | |
| 1037 if (render_surfaces_need_update) { | |
| 1038 property_trees->effect_tree.UpdateRenderSurfaces( | |
| 1039 root_layer->layer_tree_impl(), | |
| 1040 property_trees->non_root_surfaces_enabled); | |
| 1041 } | |
| 1042 UpdateRenderTarget(&property_trees->effect_tree, | |
| 1043 property_trees->non_root_surfaces_enabled); | |
| 1044 ComputeTransforms(&property_trees->transform_tree); | |
| 1045 // Computation of clips uses surface contents scale which is updated while | |
| 1046 // computing effects. So, ComputeEffects should be before ComputeClips. | |
| 1047 ComputeEffects(&property_trees->effect_tree); | |
| 1048 ComputeClips(property_trees, can_render_to_separate_surface); | |
| 1049 | |
| 1050 FindLayersThatNeedUpdates(root_layer->layer_tree_impl(), property_trees, | |
| 1051 visible_layer_list); | |
| 1052 CalculateClipRects(*visible_layer_list, property_trees, | |
| 1053 can_render_to_separate_surface); | |
| 1054 CalculateVisibleRects(*visible_layer_list, property_trees, | |
| 1055 can_render_to_separate_surface); | |
| 1056 } | |
| 1057 | |
| 1058 void UpdatePropertyTrees(PropertyTrees* property_trees, | |
| 1059 bool can_render_to_separate_surface) { | |
| 1060 if (property_trees->non_root_surfaces_enabled != | |
| 1061 can_render_to_separate_surface) { | |
| 1062 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; | |
| 1063 property_trees->transform_tree.set_needs_update(true); | |
| 1064 } | |
| 1065 if (property_trees->transform_tree.needs_update()) { | |
| 1066 property_trees->clip_tree.set_needs_update(true); | |
| 1067 property_trees->effect_tree.set_needs_update(true); | |
| 1068 } | |
| 1069 ComputeTransforms(&property_trees->transform_tree); | |
| 1070 // Computation of clips uses surface contents scale which is updated while | |
| 1071 // computing effects. So, ComputeEffects should be before ComputeClips. | |
| 1072 ComputeEffects(&property_trees->effect_tree); | |
| 1073 ComputeClips(property_trees, can_render_to_separate_surface); | |
| 1074 } | |
| 1075 | |
| 1076 void BuildPropertyTreesAndComputeVisibleRects( | |
| 1077 LayerImpl* root_layer, | |
| 1078 const LayerImpl* page_scale_layer, | |
| 1079 const LayerImpl* inner_viewport_scroll_layer, | |
| 1080 const LayerImpl* outer_viewport_scroll_layer, | |
| 1081 const LayerImpl* overscroll_elasticity_layer, | |
| 1082 const gfx::Vector2dF& elastic_overscroll, | |
| 1083 float page_scale_factor, | |
| 1084 float device_scale_factor, | |
| 1085 const gfx::Rect& viewport, | |
| 1086 const gfx::Transform& device_transform, | |
| 1087 bool can_render_to_separate_surface, | |
| 1088 PropertyTrees* property_trees, | |
| 1089 LayerImplList* visible_layer_list) { | |
| 1090 PropertyTreeBuilder::BuildPropertyTrees( | |
| 1091 root_layer, page_scale_layer, inner_viewport_scroll_layer, | |
| 1092 outer_viewport_scroll_layer, overscroll_elasticity_layer, | |
| 1093 elastic_overscroll, page_scale_factor, device_scale_factor, viewport, | |
| 1094 device_transform, property_trees); | |
| 1095 ComputeVisibleRects(root_layer, property_trees, | |
| 1096 can_render_to_separate_surface, visible_layer_list); | |
| 1097 } | |
| 1098 | |
| 1099 void VerifyClipTreeCalculations(const LayerImplList& layer_list, | |
| 1100 PropertyTrees* property_trees) { | |
| 1101 if (property_trees->non_root_surfaces_enabled) { | |
| 1102 ComputeClipsWithEffectTree(property_trees); | |
| 1103 } | |
| 1104 for (auto* layer : layer_list) | |
| 1105 ComputeLayerClipRect(property_trees, layer); | |
| 1106 } | |
| 1107 | |
| 1108 gfx::Rect ComputeLayerVisibleRectDynamic(const PropertyTrees* property_trees, | |
| 1109 const LayerImpl* layer) { | |
| 1110 int effect_ancestor_with_copy_request = | 602 int effect_ancestor_with_copy_request = |
| 1111 property_trees->effect_tree.ClosestAncestorWithCopyRequest( | 603 property_trees->effect_tree.ClosestAncestorWithCopyRequest( |
| 1112 layer->effect_tree_index()); | 604 layer->effect_tree_index()); |
| 1113 bool non_root_copy_request = | 605 bool non_root_copy_request = |
| 1114 effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId; | 606 effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId; |
| 1115 gfx::Rect layer_content_rect = gfx::Rect(layer->bounds()); | 607 gfx::Rect layer_content_rect = gfx::Rect(layer->bounds()); |
| 1116 gfx::RectF accumulated_clip_in_root_space; | 608 gfx::RectF accumulated_clip_in_root_space; |
| 1117 if (non_root_copy_request) { | 609 if (non_root_copy_request) { |
| 1118 bool include_viewport_clip = false; | |
| 1119 bool include_expanding_clips = true; | 610 bool include_expanding_clips = true; |
| 1120 ConditionalClip accumulated_clip = ComputeAccumulatedClip( | 611 ConditionalClip accumulated_clip = ComputeAccumulatedClip( |
| 1121 property_trees, include_viewport_clip, include_expanding_clips, | 612 property_trees, include_expanding_clips, layer->clip_tree_index(), |
| 1122 layer->clip_tree_index(), effect_ancestor_with_copy_request); | 613 effect_ancestor_with_copy_request); |
| 1123 if (!accumulated_clip.is_clipped) | 614 if (!accumulated_clip.is_clipped) |
| 1124 return layer_content_rect; | 615 return layer_content_rect; |
| 1125 accumulated_clip_in_root_space = accumulated_clip.clip_rect; | 616 accumulated_clip_in_root_space = accumulated_clip.clip_rect; |
| 1126 } else { | 617 } else { |
| 618 const ClipNode* clip_node = | |
| 619 property_trees->clip_tree.Node(layer->clip_tree_index()); | |
| 1127 accumulated_clip_in_root_space = | 620 accumulated_clip_in_root_space = |
| 1128 ComputeAccumulatedClipInRootSpaceForVisibleRect( | 621 clip_node->accumulated_rect_in_screen_space; |
| 1129 property_trees, layer->clip_tree_index()); | |
| 1130 } | 622 } |
| 1131 | 623 |
| 1132 const EffectNode* root_effect_node = | 624 const EffectNode* root_effect_node = |
| 1133 non_root_copy_request | 625 non_root_copy_request |
| 1134 ? property_trees->effect_tree.Node(effect_ancestor_with_copy_request) | 626 ? property_trees->effect_tree.Node(effect_ancestor_with_copy_request) |
| 1135 : property_trees->effect_tree.Node(EffectTree::kContentsRootNodeId); | 627 : property_trees->effect_tree.Node(EffectTree::kContentsRootNodeId); |
| 1136 ConditionalClip accumulated_clip_in_layer_space = | 628 ConditionalClip accumulated_clip_in_layer_space = |
| 1137 ComputeTargetRectInLocalSpace( | 629 ComputeTargetRectInLocalSpace( |
| 1138 accumulated_clip_in_root_space, property_trees, | 630 accumulated_clip_in_root_space, property_trees, |
| 1139 root_effect_node->transform_id, layer->transform_tree_index(), | 631 root_effect_node->transform_id, layer->transform_tree_index(), |
| 1140 root_effect_node->id); | 632 root_effect_node->id); |
| 1141 if (!accumulated_clip_in_layer_space.is_clipped) | 633 if (!accumulated_clip_in_layer_space.is_clipped) { |
| 1142 return layer_content_rect; | 634 return layer_content_rect; |
| 635 } | |
| 1143 gfx::RectF clip_in_layer_space = accumulated_clip_in_layer_space.clip_rect; | 636 gfx::RectF clip_in_layer_space = accumulated_clip_in_layer_space.clip_rect; |
| 1144 clip_in_layer_space.Offset(-layer->offset_to_transform_parent()); | 637 clip_in_layer_space.Offset(-layer->offset_to_transform_parent()); |
| 1145 | 638 |
| 1146 gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_in_layer_space); | 639 gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_in_layer_space); |
| 1147 visible_rect.Intersect(layer_content_rect); | 640 visible_rect.Intersect(layer_content_rect); |
| 1148 return visible_rect; | 641 return visible_rect; |
| 1149 } | 642 } |
| 1150 | 643 |
| 1151 void VerifyVisibleRectsCalculations(const LayerImplList& layer_list, | 644 void UpdatePropertyTrees(PropertyTrees* property_trees, |
| 1152 const PropertyTrees* property_trees) { | 645 bool can_render_to_separate_surface) { |
| 1153 for (auto* layer : layer_list) { | 646 if (property_trees->non_root_surfaces_enabled != |
| 1154 gfx::Rect visible_rect_dynamic = | 647 can_render_to_separate_surface) { |
| 1155 ComputeLayerVisibleRectDynamic(property_trees, layer); | 648 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; |
| 1156 DCHECK(layer->visible_layer_rect() == visible_rect_dynamic) | 649 property_trees->transform_tree.set_needs_update(true); |
| 1157 << " layer: " << layer->id() << " clip id: " << layer->clip_tree_index() | |
| 1158 << " visible rect cached: " << layer->visible_layer_rect().ToString() | |
| 1159 << " v.s. " | |
| 1160 << " visible rect dynamic: " << visible_rect_dynamic.ToString(); | |
| 1161 } | 650 } |
| 651 if (property_trees->transform_tree.needs_update()) { | |
| 652 property_trees->clip_tree.set_needs_update(true); | |
| 653 property_trees->effect_tree.set_needs_update(true); | |
| 654 } | |
| 655 ComputeTransforms(&property_trees->transform_tree); | |
| 656 // Computation of clips uses surface contents scale which is updated while | |
| 657 // computing effects. So, ComputeEffects should be before ComputeClips. | |
| 658 ComputeEffects(&property_trees->effect_tree); | |
| 659 ComputeClips(property_trees); | |
|
weiliangc
2017/03/14 22:04:29
Also DCHECK in ComputeClips that effect tree doesn
jaydasika
2017/03/16 20:33:31
Actually, after creating a fast-path of using ToSc
| |
| 660 } | |
| 661 | |
| 662 void UpdatePropertyTreesAndRenderSurfaces(LayerImpl* root_layer, | |
| 663 PropertyTrees* property_trees, | |
| 664 bool can_render_to_separate_surface) { | |
| 665 bool render_surfaces_need_update = false; | |
| 666 if (property_trees->non_root_surfaces_enabled != | |
| 667 can_render_to_separate_surface) { | |
| 668 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; | |
| 669 property_trees->transform_tree.set_needs_update(true); | |
| 670 render_surfaces_need_update = true; | |
| 671 } | |
| 672 if (property_trees->transform_tree.needs_update()) { | |
| 673 property_trees->clip_tree.set_needs_update(true); | |
| 674 property_trees->effect_tree.set_needs_update(true); | |
| 675 } | |
| 676 if (render_surfaces_need_update) { | |
| 677 property_trees->effect_tree.UpdateRenderSurfaces( | |
| 678 root_layer->layer_tree_impl(), | |
| 679 property_trees->non_root_surfaces_enabled); | |
| 680 } | |
| 681 UpdateRenderTarget(&property_trees->effect_tree, | |
| 682 property_trees->non_root_surfaces_enabled); | |
| 683 | |
| 684 ComputeTransforms(&property_trees->transform_tree); | |
| 685 // Computation of clips uses surface contents scale which is updated while | |
| 686 // computing effects. So, ComputeEffects should be before ComputeClips. | |
| 687 ComputeEffects(&property_trees->effect_tree); | |
| 688 ComputeClips(property_trees); | |
|
weiliangc
2017/03/14 22:04:30
DCHECK like above.
jaydasika
2017/03/16 20:33:30
Done.
| |
| 1162 } | 689 } |
| 1163 | 690 |
| 1164 bool LayerNeedsUpdate(Layer* layer, | 691 bool LayerNeedsUpdate(Layer* layer, |
| 1165 bool layer_is_drawn, | 692 bool layer_is_drawn, |
| 1166 const PropertyTrees* property_trees) { | 693 const PropertyTrees* property_trees) { |
| 1167 return LayerNeedsUpdateInternal(layer, layer_is_drawn, property_trees); | 694 return LayerNeedsUpdateInternal(layer, layer_is_drawn, property_trees); |
| 1168 } | 695 } |
| 1169 | 696 |
| 1170 bool LayerNeedsUpdate(LayerImpl* layer, | 697 bool LayerNeedsUpdate(LayerImpl* layer, |
| 1171 bool layer_is_drawn, | 698 bool layer_is_drawn, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1211 const EffectNode* target_effect_node = | 738 const EffectNode* target_effect_node = |
| 1212 effect_tree.Node(effect_node->target_id); | 739 effect_tree.Node(effect_node->target_id); |
| 1213 property_trees->GetToTarget(transform_node->id, target_effect_node->id, | 740 property_trees->GetToTarget(transform_node->id, target_effect_node->id, |
| 1214 &render_surface_transform); | 741 &render_surface_transform); |
| 1215 | 742 |
| 1216 ConcatInverseSurfaceContentsScale(effect_node, &render_surface_transform); | 743 ConcatInverseSurfaceContentsScale(effect_node, &render_surface_transform); |
| 1217 render_surface->SetDrawTransform(render_surface_transform); | 744 render_surface->SetDrawTransform(render_surface_transform); |
| 1218 } | 745 } |
| 1219 | 746 |
| 1220 static void SetSurfaceClipRect(const ClipNode* parent_clip_node, | 747 static void SetSurfaceClipRect(const ClipNode* parent_clip_node, |
| 1221 const PropertyTrees* property_trees, | 748 PropertyTrees* property_trees, |
| 1222 RenderSurfaceImpl* render_surface) { | 749 RenderSurfaceImpl* render_surface) { |
| 1223 if (!render_surface->is_clipped()) { | 750 if (!render_surface->is_clipped()) { |
| 1224 render_surface->SetClipRect(gfx::Rect()); | 751 render_surface->SetClipRect(gfx::Rect()); |
| 1225 return; | 752 return; |
| 1226 } | 753 } |
| 1227 | 754 |
| 1228 const EffectTree& effect_tree = property_trees->effect_tree; | 755 const EffectTree& effect_tree = property_trees->effect_tree; |
| 1229 const TransformTree& transform_tree = property_trees->transform_tree; | 756 const ClipTree& clip_tree = property_trees->clip_tree; |
| 1230 const TransformNode* transform_node = | |
| 1231 transform_tree.Node(render_surface->TransformTreeIndex()); | |
| 1232 if (transform_tree.TargetId(transform_node->id) == | |
| 1233 parent_clip_node->target_transform_id) { | |
| 1234 render_surface->SetClipRect( | |
| 1235 gfx::ToEnclosingRect(parent_clip_node->clip_in_target_space)); | |
| 1236 return; | |
| 1237 } | |
| 1238 | |
| 1239 // In this case, the clip child has reset the clip node for subtree and hence | |
| 1240 // the parent clip node's clip rect is in clip parent's target space and not | |
| 1241 // our target space. We need to transform it to our target space. | |
| 1242 const EffectNode* effect_node = | 757 const EffectNode* effect_node = |
| 1243 effect_tree.Node(render_surface->EffectTreeIndex()); | 758 effect_tree.Node(render_surface->EffectTreeIndex()); |
| 1244 int target_effect_id = effect_node->target_id; | 759 const EffectNode* target_node = effect_tree.Node(effect_node->target_id); |
| 1245 gfx::RectF clip_rect; | 760 bool include_expanding_clips = false; |
| 1246 const bool success = ConvertRectBetweenSurfaceSpaces( | 761 if (render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId) { |
| 1247 property_trees, parent_clip_node->target_effect_id, target_effect_id, | 762 render_surface->SetClipRect( |
| 1248 parent_clip_node->clip_in_target_space, &clip_rect); | 763 gfx::ToEnclosingRect(clip_tree.Node(effect_node->clip_id)->clip)); |
| 1249 | 764 } else { |
| 1250 if (!success) { | 765 ConditionalClip accumulated_clip_rect = |
| 1251 render_surface->SetClipRect(gfx::Rect()); | 766 ComputeAccumulatedClip(property_trees, include_expanding_clips, |
| 1252 return; | 767 effect_node->clip_id, target_node->id); |
| 768 render_surface->SetClipRect( | |
| 769 gfx::ToEnclosingRect(accumulated_clip_rect.clip_rect)); | |
| 1253 } | 770 } |
| 1254 render_surface->SetClipRect(gfx::ToEnclosingRect(clip_rect)); | |
| 1255 } | 771 } |
| 1256 | 772 |
| 1257 template <typename LayerType> | 773 template <typename LayerType> |
| 1258 static gfx::Transform ScreenSpaceTransformInternal(LayerType* layer, | 774 static gfx::Transform ScreenSpaceTransformInternal(LayerType* layer, |
| 1259 const TransformTree& tree) { | 775 const TransformTree& tree) { |
| 1260 gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(), | 776 gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(), |
| 1261 layer->offset_to_transform_parent().y()); | 777 layer->offset_to_transform_parent().y()); |
| 1262 gfx::Transform ssxform = tree.ToScreen(layer->transform_tree_index()); | 778 gfx::Transform ssxform = tree.ToScreen(layer->transform_tree_index()); |
| 1263 xform.ConcatTransform(ssxform); | 779 xform.ConcatTransform(ssxform); |
| 1264 if (layer->should_flatten_transform_from_property_tree()) | 780 if (layer->should_flatten_transform_from_property_tree()) |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1311 const LayerImpl* layer, | 827 const LayerImpl* layer, |
| 1312 const gfx::Rect& layer_bounds_in_target_space, | 828 const gfx::Rect& layer_bounds_in_target_space, |
| 1313 const gfx::Rect& clip_rect) { | 829 const gfx::Rect& clip_rect) { |
| 1314 if (layer->is_clipped()) | 830 if (layer->is_clipped()) |
| 1315 return IntersectRects(layer_bounds_in_target_space, clip_rect); | 831 return IntersectRects(layer_bounds_in_target_space, clip_rect); |
| 1316 | 832 |
| 1317 return layer_bounds_in_target_space; | 833 return layer_bounds_in_target_space; |
| 1318 } | 834 } |
| 1319 | 835 |
| 1320 void ComputeLayerDrawProperties(LayerImpl* layer, | 836 void ComputeLayerDrawProperties(LayerImpl* layer, |
| 1321 const PropertyTrees* property_trees) { | 837 PropertyTrees* property_trees) { |
| 1322 const TransformNode* transform_node = | 838 const TransformNode* transform_node = |
| 1323 property_trees->transform_tree.Node(layer->transform_tree_index()); | 839 property_trees->transform_tree.Node(layer->transform_tree_index()); |
| 1324 const ClipNode* clip_node = | |
| 1325 property_trees->clip_tree.Node(layer->clip_tree_index()); | |
| 1326 | 840 |
| 1327 layer->draw_properties().screen_space_transform = | 841 layer->draw_properties().screen_space_transform = |
| 1328 ScreenSpaceTransformInternal(layer, property_trees->transform_tree); | 842 ScreenSpaceTransformInternal(layer, property_trees->transform_tree); |
| 1329 layer->draw_properties().target_space_transform = DrawTransform( | 843 layer->draw_properties().target_space_transform = DrawTransform( |
| 1330 layer, property_trees->transform_tree, property_trees->effect_tree); | 844 layer, property_trees->transform_tree, property_trees->effect_tree); |
| 1331 layer->draw_properties().screen_space_transform_is_animating = | 845 layer->draw_properties().screen_space_transform_is_animating = |
| 1332 transform_node->to_screen_is_potentially_animated; | 846 transform_node->to_screen_is_potentially_animated; |
| 1333 | 847 |
| 1334 layer->draw_properties().opacity = | 848 layer->draw_properties().opacity = |
| 1335 LayerDrawOpacity(layer, property_trees->effect_tree); | 849 LayerDrawOpacity(layer, property_trees->effect_tree); |
| 1336 if (property_trees->non_root_surfaces_enabled) { | |
| 1337 layer->draw_properties().is_clipped = clip_node->layers_are_clipped; | |
| 1338 } else { | |
| 1339 layer->draw_properties().is_clipped = | |
| 1340 clip_node->layers_are_clipped_when_surfaces_disabled; | |
| 1341 } | |
| 1342 | 850 |
| 1343 gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect( | 851 gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect( |
| 1344 layer->draw_properties().target_space_transform, | 852 layer->draw_properties().target_space_transform, |
| 1345 gfx::Rect(layer->bounds())); | 853 gfx::Rect(layer->bounds())); |
| 854 ConditionalClip clip = LayerClipRect(property_trees, layer); | |
| 855 layer->draw_properties().is_clipped = clip.is_clipped; | |
| 856 layer->draw_properties().clip_rect = gfx::ToEnclosingRect(clip.clip_rect); | |
| 857 layer->draw_properties().visible_layer_rect = | |
| 858 LayerVisibleRect(property_trees, layer); | |
| 1346 layer->draw_properties().drawable_content_rect = LayerDrawableContentRect( | 859 layer->draw_properties().drawable_content_rect = LayerDrawableContentRect( |
| 1347 layer, bounds_in_target_space, layer->draw_properties().clip_rect); | 860 layer, bounds_in_target_space, layer->draw_properties().clip_rect); |
| 1348 } | 861 } |
| 1349 | 862 |
| 1350 void ComputeMaskDrawProperties(LayerImpl* mask_layer, | 863 void ComputeMaskDrawProperties(LayerImpl* mask_layer, |
| 1351 const PropertyTrees* property_trees) { | 864 const PropertyTrees* property_trees) { |
| 1352 // Mask draw properties are used only for rastering, so most of the draw | 865 // Mask draw properties are used only for rastering, so most of the draw |
| 1353 // properties computed for other layers are not needed. | 866 // properties computed for other layers are not needed. |
| 1354 mask_layer->draw_properties().screen_space_transform = | 867 mask_layer->draw_properties().screen_space_transform = |
| 1355 ScreenSpaceTransformInternal(mask_layer, | 868 ScreenSpaceTransformInternal(mask_layer, |
| 1356 property_trees->transform_tree); | 869 property_trees->transform_tree); |
| 1357 mask_layer->draw_properties().visible_layer_rect = | 870 mask_layer->draw_properties().visible_layer_rect = |
| 1358 gfx::Rect(mask_layer->bounds()); | 871 gfx::Rect(mask_layer->bounds()); |
| 1359 } | 872 } |
| 1360 | 873 |
| 1361 void ComputeSurfaceDrawProperties(const PropertyTrees* property_trees, | 874 void ComputeSurfaceDrawProperties(PropertyTrees* property_trees, |
| 1362 RenderSurfaceImpl* render_surface) { | 875 RenderSurfaceImpl* render_surface) { |
| 1363 const EffectNode* effect_node = | 876 const EffectNode* effect_node = |
| 1364 property_trees->effect_tree.Node(render_surface->EffectTreeIndex()); | 877 property_trees->effect_tree.Node(render_surface->EffectTreeIndex()); |
| 1365 render_surface->SetIsClipped(effect_node->surface_is_clipped); | 878 render_surface->SetIsClipped(effect_node->surface_is_clipped); |
| 1366 SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface); | 879 SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface); |
| 1367 SetSurfaceDrawTransform(property_trees, render_surface); | 880 SetSurfaceDrawTransform(property_trees, render_surface); |
| 1368 render_surface->SetScreenSpaceTransform( | 881 render_surface->SetScreenSpaceTransform( |
| 1369 property_trees->ToScreenSpaceTransformWithoutSurfaceContentsScale( | 882 property_trees->ToScreenSpaceTransformWithoutSurfaceContentsScale( |
| 1370 render_surface->TransformTreeIndex(), | 883 render_surface->TransformTreeIndex(), |
| 1371 render_surface->EffectTreeIndex())); | 884 render_surface->EffectTreeIndex())); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1471 void UpdateElasticOverscroll(PropertyTrees* property_trees, | 984 void UpdateElasticOverscroll(PropertyTrees* property_trees, |
| 1472 const Layer* overscroll_elasticity_layer, | 985 const Layer* overscroll_elasticity_layer, |
| 1473 const gfx::Vector2dF& elastic_overscroll) { | 986 const gfx::Vector2dF& elastic_overscroll) { |
| 1474 UpdateElasticOverscrollInternal(property_trees, overscroll_elasticity_layer, | 987 UpdateElasticOverscrollInternal(property_trees, overscroll_elasticity_layer, |
| 1475 elastic_overscroll); | 988 elastic_overscroll); |
| 1476 } | 989 } |
| 1477 | 990 |
| 1478 } // namespace draw_property_utils | 991 } // namespace draw_property_utils |
| 1479 | 992 |
| 1480 } // namespace cc | 993 } // namespace cc |
| OLD | NEW |