| 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 bool success = property_trees->GetFromTarget( |
| 117 local_transform_id, target_effect_id, &target_to_local); | 79 local_transform_id, target_effect_id, &target_to_local); |
| 80 // If transform is not invertible, cannot apply clip. |
| 118 if (!success) | 81 if (!success) |
| 119 // If transform is not invertible, cannot apply clip. | |
| 120 return ConditionalClip{false, gfx::RectF()}; | 82 return ConditionalClip{false, gfx::RectF()}; |
| 121 | 83 |
| 122 if (target_transform_id > local_transform_id) | 84 if (target_transform_id > local_transform_id) |
| 123 return ConditionalClip{true, // is_clipped. | 85 return ConditionalClip{true, // is_clipped. |
| 124 MathUtil::MapClippedRect(target_to_local, rect)}; | 86 MathUtil::MapClippedRect(target_to_local, rect)}; |
| 125 | 87 |
| 126 return ConditionalClip{true, // is_clipped. | 88 return ConditionalClip{true, // is_clipped. |
| 127 MathUtil::ProjectClippedRect(target_to_local, rect)}; | 89 MathUtil::ProjectClippedRect(target_to_local, rect)}; |
| 128 } | 90 } |
| 129 | 91 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 | 173 |
| 212 // Put the expanded clip back into the original target space. | 174 // Put the expanded clip back into the original target space. |
| 213 success = ConvertRectBetweenSurfaceSpaces( | 175 success = ConvertRectBetweenSurfaceSpaces( |
| 214 property_trees, expanding_effect_node->id, target_id, | 176 property_trees, expanding_effect_node->id, target_id, |
| 215 expanded_clip_in_expanding_space, accumulated_clip); | 177 expanded_clip_in_expanding_space, accumulated_clip); |
| 216 // If transform is not invertible, no clip will be applied. | 178 // If transform is not invertible, no clip will be applied. |
| 217 if (!success) | 179 if (!success) |
| 218 return false; | 180 return false; |
| 219 return true; | 181 return true; |
| 220 } | 182 } |
| 221 case ClipNode::ClipType::NONE: | |
| 222 return true; | |
| 223 } | 183 } |
| 224 NOTREACHED(); | 184 NOTREACHED(); |
| 225 return true; | 185 return true; |
| 226 } | 186 } |
| 227 | 187 |
| 228 static ConditionalClip ComputeAccumulatedClip( | 188 static ConditionalClip ComputeAccumulatedClip(PropertyTrees* property_trees, |
| 229 const PropertyTrees* property_trees, | 189 bool include_expanding_clips, |
| 230 bool include_viewport_clip, | 190 int local_clip_id, |
| 231 bool include_expanding_clips, | 191 int target_id) { |
| 232 int local_clip_id, | 192 ClipRectData* cached_data = |
| 233 int target_id) { | 193 property_trees->FetchClipRectFromCache(local_clip_id, target_id); |
| 234 DCHECK(!include_viewport_clip || | 194 if (cached_data->target_id != EffectTree::kInvalidNodeId) { |
| 235 target_id == EffectTree::kContentsRootNodeId); | 195 // Cache hit |
| 196 return cached_data->clip; |
| 197 } |
| 198 cached_data->target_id = target_id; |
| 199 |
| 236 const ClipTree& clip_tree = property_trees->clip_tree; | 200 const ClipTree& clip_tree = property_trees->clip_tree; |
| 201 const ClipNode* clip_node = clip_tree.Node(local_clip_id); |
| 237 const EffectTree& effect_tree = property_trees->effect_tree; | 202 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); | 203 const EffectNode* target_node = effect_tree.Node(target_id); |
| 241 int target_transform_id = target_node->transform_id; | 204 int target_transform_id = target_node->transform_id; |
| 242 | 205 |
| 206 bool cache_hit = false; |
| 207 ConditionalClip cached_clip = ConditionalClip{false, gfx::RectF()}; |
| 208 ConditionalClip unclipped = ConditionalClip{false, gfx::RectF()}; |
| 209 |
| 243 // Collect all the clips that need to be accumulated. | 210 // Collect all the clips that need to be accumulated. |
| 244 std::stack<const ClipNode*> parent_chain; | 211 std::stack<const ClipNode*, std::vector<const ClipNode*>> parent_chain; |
| 245 | 212 |
| 246 // If target is not direct ancestor of clip, this will find least common | 213 // If target is not direct ancestor of clip, this will find least common |
| 247 // ancestor between the target and the clip. | 214 // ancestor between the target and the clip. |
| 248 while (target_node->clip_id > clip_node->id || | 215 while (target_node->clip_id > clip_node->id || |
| 249 target_node->has_unclipped_descendants) { | 216 target_node->has_unclipped_descendants) { |
| 250 target_node = effect_tree.Node(target_node->target_id); | 217 target_node = effect_tree.Node(target_node->target_id); |
| 251 } | 218 } |
| 252 | 219 |
| 253 // Collect clip nodes up to the least common ancestor. | 220 // Collect clip nodes up to the least common ancestor or till we get a cache |
| 221 // hit. |
| 254 while (target_node->clip_id < clip_node->id) { | 222 while (target_node->clip_id < clip_node->id) { |
| 223 if (parent_chain.size() > 0) { |
| 224 // Search the cache. |
| 225 for (auto& data : clip_node->cached_clip_rects) { |
| 226 if (data.target_id == target_id) { |
| 227 cache_hit = true; |
| 228 cached_clip = data.clip; |
| 229 } |
| 230 } |
| 231 } |
| 255 parent_chain.push(clip_node); | 232 parent_chain.push(clip_node); |
| 256 clip_node = clip_tree.parent(clip_node); | 233 clip_node = clip_tree.parent(clip_node); |
| 257 } | 234 } |
| 258 DCHECK_EQ(target_node->clip_id, clip_node->id); | |
| 259 | 235 |
| 260 if (!include_viewport_clip && parent_chain.size() == 0) { | 236 if (parent_chain.size() == 0) { |
| 261 // There aren't any clips to apply. | 237 // No accumulated clip nodes. |
| 262 return ConditionalClip{false, gfx::RectF()}; | 238 cached_data->clip = unclipped; |
| 239 return unclipped; |
| 263 } | 240 } |
| 264 | 241 |
| 265 if (!include_viewport_clip) { | 242 clip_node = parent_chain.top(); |
| 266 clip_node = parent_chain.top(); | 243 parent_chain.pop(); |
| 267 parent_chain.pop(); | 244 |
| 245 gfx::RectF accumulated_clip; |
| 246 if (cache_hit && cached_clip.is_clipped) { |
| 247 // Apply the first clip in parent_chain to the cached clip. |
| 248 accumulated_clip = cached_clip.clip_rect; |
| 249 bool success = ApplyClipNodeToAccumulatedClip( |
| 250 property_trees, include_expanding_clips, target_id, target_transform_id, |
| 251 clip_node, &accumulated_clip); |
| 252 if (!success) { |
| 253 // Singular transform |
| 254 cached_data->clip = unclipped; |
| 255 return unclipped; |
| 256 } |
| 257 } else { |
| 258 // No cache hit or the cached clip has no clip to apply. We need to find |
| 259 // the first clip that applies clip as there is no clip to expand. |
| 260 while (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP && |
| 261 parent_chain.size() > 0) { |
| 262 clip_node = parent_chain.top(); |
| 263 parent_chain.pop(); |
| 264 } |
| 265 |
| 266 if (clip_node->clip_type != ClipNode::ClipType::APPLIES_LOCAL_CLIP) { |
| 267 // No clip to apply. |
| 268 cached_data->clip = unclipped; |
| 269 return unclipped; |
| 270 } |
| 271 ConditionalClip current_clip = ComputeCurrentClip( |
| 272 clip_node, property_trees, target_transform_id, target_id); |
| 273 if (!current_clip.is_clipped) { |
| 274 // Singular transform |
| 275 cached_data->clip = unclipped; |
| 276 return unclipped; |
| 277 } |
| 278 accumulated_clip = current_clip.clip_rect; |
| 268 } | 279 } |
| 269 | 280 |
| 270 // Find the first clip in the chain that we need to apply. | 281 // 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) { | 282 while (parent_chain.size() > 0) { |
| 291 clip_node = parent_chain.top(); | 283 clip_node = parent_chain.top(); |
| 292 parent_chain.pop(); | 284 parent_chain.pop(); |
| 293 bool success = ApplyClipNodeToAccumulatedClip( | 285 bool success = ApplyClipNodeToAccumulatedClip( |
| 294 property_trees, include_expanding_clips, target_id, target_transform_id, | 286 property_trees, include_expanding_clips, target_id, target_transform_id, |
| 295 clip_node, &accumulated_clip); | 287 clip_node, &accumulated_clip); |
| 296 | 288 if (!success) { |
| 297 // Failure to apply the clip means we encountered an uninvertible transform, | 289 // Singular transform |
| 298 // so no clip will be applied. | 290 cached_data->clip = unclipped; |
| 299 if (!success) | 291 return unclipped; |
| 300 return ConditionalClip{false /* is_clipped */, gfx::RectF()}; | 292 } |
| 301 } | 293 } |
| 302 | 294 |
| 303 return ConditionalClip{true /* is_clipped */, accumulated_clip.IsEmpty() | 295 ConditionalClip clip = ConditionalClip{ |
| 304 ? gfx::RectF() | 296 true /* is_clipped */, |
| 305 : accumulated_clip}; | 297 accumulated_clip.IsEmpty() ? gfx::RectF() : accumulated_clip}; |
| 306 } | 298 cached_data->clip = clip; |
| 307 | 299 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 } | 300 } |
| 551 | 301 |
| 552 static bool HasSingularTransform(int transform_tree_index, | 302 static bool HasSingularTransform(int transform_tree_index, |
| 553 const TransformTree& tree) { | 303 const TransformTree& tree) { |
| 554 const TransformNode* node = tree.Node(transform_tree_index); | 304 const TransformNode* node = tree.Node(transform_tree_index); |
| 555 return !node->is_invertible || !node->ancestors_are_invertible; | 305 return !node->is_invertible || !node->ancestors_are_invertible; |
| 556 } | 306 } |
| 557 | 307 |
| 558 template <typename LayerType> | 308 template <typename LayerType> |
| 559 static int TransformTreeIndexForBackfaceVisibility(LayerType* layer, | 309 static int TransformTreeIndexForBackfaceVisibility(LayerType* layer, |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 // backface is not visible. | 396 // backface is not visible. |
| 647 if (TransformToScreenIsKnown(layer, backface_transform_id, tree) && | 397 if (TransformToScreenIsKnown(layer, backface_transform_id, tree) && |
| 648 !HasSingularTransform(backface_transform_id, tree) && | 398 !HasSingularTransform(backface_transform_id, tree) && |
| 649 IsLayerBackFaceVisible(layer, backface_transform_id, property_trees)) | 399 IsLayerBackFaceVisible(layer, backface_transform_id, property_trees)) |
| 650 return false; | 400 return false; |
| 651 } | 401 } |
| 652 | 402 |
| 653 return true; | 403 return true; |
| 654 } | 404 } |
| 655 | 405 |
| 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 | 406 |
| 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 | 407 |
| 675 } // namespace | 408 } // namespace |
| 676 | 409 |
| 677 template <typename LayerType> | 410 template <typename LayerType> |
| 678 static inline bool LayerShouldBeSkippedInternal( | 411 static inline bool LayerShouldBeSkippedInternal( |
| 679 LayerType* layer, | 412 LayerType* layer, |
| 680 const TransformTree& transform_tree, | 413 const TransformTree& transform_tree, |
| 681 const EffectTree& effect_tree) { | 414 const EffectTree& effect_tree) { |
| 682 const TransformNode* transform_node = | 415 const TransformNode* transform_node = |
| 683 transform_tree.Node(layer->transform_tree_index()); | 416 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); | 456 update_layer_list->push_back(layer); |
| 724 } | 457 } |
| 725 | 458 |
| 726 // Append mask layers to the update layer list. They don't have valid | 459 // 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. | 460 // visible rects, so need to get added after the above calculation. |
| 728 if (Layer* mask_layer = layer->mask_layer()) | 461 if (Layer* mask_layer = layer->mask_layer()) |
| 729 update_layer_list->push_back(mask_layer); | 462 update_layer_list->push_back(mask_layer); |
| 730 } | 463 } |
| 731 } | 464 } |
| 732 | 465 |
| 733 static void ResetIfHasNanCoordinate(gfx::RectF* rect) { | 466 void FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl, |
| 734 if (std::isnan(rect->x()) || std::isnan(rect->y()) || | 467 const PropertyTrees* property_trees, |
| 735 std::isnan(rect->right()) || std::isnan(rect->bottom())) | 468 std::vector<LayerImpl*>* visible_layer_list) { |
| 736 *rect = gfx::RectF(); | 469 const TransformTree& transform_tree = property_trees->transform_tree; |
| 470 const EffectTree& effect_tree = property_trees->effect_tree; |
| 471 |
| 472 for (auto* layer_impl : *layer_tree_impl) { |
| 473 if (!IsRootLayer(layer_impl) && |
| 474 LayerShouldBeSkipped(layer_impl, transform_tree, effect_tree)) |
| 475 continue; |
| 476 |
| 477 bool layer_is_drawn = |
| 478 effect_tree.Node(layer_impl->effect_tree_index())->is_drawn; |
| 479 |
| 480 if (LayerNeedsUpdate(layer_impl, layer_is_drawn, property_trees)) |
| 481 visible_layer_list->push_back(layer_impl); |
| 482 } |
| 737 } | 483 } |
| 738 | 484 |
| 739 void PostConcatSurfaceContentsScale(const EffectNode* effect_node, | 485 void PostConcatSurfaceContentsScale(const EffectNode* effect_node, |
| 740 gfx::Transform* transform) { | 486 gfx::Transform* transform) { |
| 741 if (!effect_node) { | 487 if (!effect_node) { |
| 742 // This can happen when PaintArtifactCompositor builds property trees as it | 488 // This can happen when PaintArtifactCompositor builds property trees as it |
| 743 // doesn't set effect ids on clip nodes. | 489 // doesn't set effect ids on clip nodes. |
| 744 return; | 490 return; |
| 745 } | 491 } |
| 746 DCHECK(effect_node->has_render_surface); | 492 DCHECK(effect_node->has_render_surface); |
| 747 transform->matrix().postScale(effect_node->surface_contents_scale.x(), | 493 transform->matrix().postScale(effect_node->surface_contents_scale.x(), |
| 748 effect_node->surface_contents_scale.y(), 1.f); | 494 effect_node->surface_contents_scale.y(), 1.f); |
| 749 } | 495 } |
| 750 | 496 |
| 751 void ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, | 497 void ConcatInverseSurfaceContentsScale(const EffectNode* effect_node, |
| 752 gfx::Transform* transform) { | 498 gfx::Transform* transform) { |
| 753 DCHECK(effect_node->has_render_surface); | 499 DCHECK(effect_node->has_render_surface); |
| 754 if (effect_node->surface_contents_scale.x() != 0.0 && | 500 if (effect_node->surface_contents_scale.x() != 0.0 && |
| 755 effect_node->surface_contents_scale.y() != 0.0) | 501 effect_node->surface_contents_scale.y() != 0.0) |
| 756 transform->Scale(1.0 / effect_node->surface_contents_scale.x(), | 502 transform->Scale(1.0 / effect_node->surface_contents_scale.x(), |
| 757 1.0 / effect_node->surface_contents_scale.y()); | 503 1.0 / effect_node->surface_contents_scale.y()); |
| 758 } | 504 } |
| 759 | 505 |
| 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) { | 506 void ComputeTransforms(TransformTree* transform_tree) { |
| 913 if (!transform_tree->needs_update()) | 507 if (!transform_tree->needs_update()) |
| 914 return; | 508 return; |
| 915 for (int i = TransformTree::kContentsRootNodeId; | 509 for (int i = TransformTree::kContentsRootNodeId; |
| 916 i < static_cast<int>(transform_tree->size()); ++i) | 510 i < static_cast<int>(transform_tree->size()); ++i) |
| 917 transform_tree->UpdateTransforms(i); | 511 transform_tree->UpdateTransforms(i); |
| 918 transform_tree->set_needs_update(false); | 512 transform_tree->set_needs_update(false); |
| 919 } | 513 } |
| 920 | 514 |
| 921 void UpdateRenderTarget(EffectTree* effect_tree, | 515 void UpdateRenderTarget(EffectTree* effect_tree, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 938 | 532 |
| 939 void ComputeEffects(EffectTree* effect_tree) { | 533 void ComputeEffects(EffectTree* effect_tree) { |
| 940 if (!effect_tree->needs_update()) | 534 if (!effect_tree->needs_update()) |
| 941 return; | 535 return; |
| 942 for (int i = EffectTree::kContentsRootNodeId; | 536 for (int i = EffectTree::kContentsRootNodeId; |
| 943 i < static_cast<int>(effect_tree->size()); ++i) | 537 i < static_cast<int>(effect_tree->size()); ++i) |
| 944 effect_tree->UpdateEffects(i); | 538 effect_tree->UpdateEffects(i); |
| 945 effect_tree->set_needs_update(false); | 539 effect_tree->set_needs_update(false); |
| 946 } | 540 } |
| 947 | 541 |
| 948 static void ComputeClipsWithEffectTree(PropertyTrees* property_trees) { | 542 void ComputeClips(PropertyTrees* property_trees) { |
| 949 EffectTree* effect_tree = &property_trees->effect_tree; | 543 DCHECK(!property_trees->transform_tree.needs_update()); |
| 950 const ClipTree* clip_tree = &property_trees->clip_tree; | 544 ClipTree* clip_tree = &property_trees->clip_tree; |
| 951 EffectNode* root_effect_node = | 545 if (!clip_tree->needs_update()) |
| 952 effect_tree->Node(EffectTree::kContentsRootNodeId); | 546 return; |
| 953 const RenderSurfaceImpl* root_render_surface = | 547 const int target_effect_id = EffectTree::kContentsRootNodeId; |
| 954 effect_tree->GetRenderSurface(EffectTree::kContentsRootNodeId); | 548 const int target_transform_id = TransformTree::kRootNodeId; |
| 955 gfx::Rect root_clip = | 549 const bool include_expanding_clips = true; |
| 956 gfx::ToEnclosingRect(clip_tree->Node(root_effect_node->clip_id)->clip); | 550 for (int i = ClipTree::kViewportNodeId; |
| 957 if (root_render_surface->is_clipped()) | 551 i < static_cast<int>(clip_tree->size()); ++i) { |
| 958 DCHECK(root_clip == root_render_surface->clip_rect()) | 552 ClipNode* clip_node = clip_tree->Node(i); |
| 959 << "clip on root render surface: " | 553 // Clear the clip rect cache |
| 960 << root_render_surface->clip_rect().ToString() | 554 clip_node->cached_clip_rects = std::vector<ClipRectData>(1); |
| 961 << " v.s. root effect node's clip: " << root_clip.ToString(); | 555 if (clip_node->id == ClipTree::kViewportNodeId) { |
| 962 for (int i = 2; i < static_cast<int>(effect_tree->size()); ++i) { | 556 clip_node->cached_accumulated_rect_in_screen_space = clip_node->clip; |
| 963 EffectNode* effect_node = effect_tree->Node(i); | 557 continue; |
| 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 } | 558 } |
| 559 ClipNode* parent_clip_node = clip_tree->parent(clip_node); |
| 560 DCHECK(parent_clip_node); |
| 561 gfx::RectF accumulated_clip = |
| 562 parent_clip_node->cached_accumulated_rect_in_screen_space; |
| 563 bool success = ApplyClipNodeToAccumulatedClip( |
| 564 property_trees, include_expanding_clips, target_effect_id, |
| 565 target_transform_id, clip_node, &accumulated_clip); |
| 566 DCHECK(success); |
| 567 clip_node->cached_accumulated_rect_in_screen_space = accumulated_clip; |
| 980 } | 568 } |
| 569 clip_tree->set_needs_update(false); |
| 981 } | 570 } |
| 982 | 571 |
| 983 static void ComputeLayerClipRect(const PropertyTrees* property_trees, | 572 static ConditionalClip LayerClipRect(PropertyTrees* property_trees, |
| 984 const LayerImpl* layer) { | 573 LayerImpl* layer) { |
| 985 const EffectTree* effect_tree = &property_trees->effect_tree; | 574 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()); | 575 const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index()); |
| 989 const EffectNode* target_node = | 576 const EffectNode* target_node = |
| 990 effect_node->has_render_surface | 577 effect_node->has_render_surface |
| 991 ? effect_node | 578 ? effect_node |
| 992 : effect_tree->Node(effect_node->target_id); | 579 : effect_tree->Node(effect_node->target_id); |
| 993 // TODO(weiliangc): When effect node has up to date render surface info on | 580 // TODO(weiliangc): When effect node has up to date render surface info on |
| 994 // compositor thread, no need to check for resourceless draw mode | 581 // compositor thread, no need to check for resourceless draw mode |
| 995 if (!property_trees->non_root_surfaces_enabled) { | 582 if (!property_trees->non_root_surfaces_enabled) { |
| 996 target_node = effect_tree->Node(1); | 583 target_node = effect_tree->Node(1); |
| 997 } | 584 } |
| 998 | 585 |
| 999 bool include_viewport_clip = false; | |
| 1000 bool include_expanding_clips = false; | 586 bool include_expanding_clips = false; |
| 1001 ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip( | 587 return ComputeAccumulatedClip(property_trees, include_expanding_clips, |
| 1002 property_trees, include_viewport_clip, include_expanding_clips, | 588 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 } | 589 } |
| 1020 | 590 |
| 1021 void ComputeVisibleRects(LayerImpl* root_layer, | 591 static gfx::Rect LayerVisibleRect(PropertyTrees* property_trees, |
| 1022 PropertyTrees* property_trees, | 592 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 = | 593 int effect_ancestor_with_copy_request = |
| 1111 property_trees->effect_tree.ClosestAncestorWithCopyRequest( | 594 property_trees->effect_tree.ClosestAncestorWithCopyRequest( |
| 1112 layer->effect_tree_index()); | 595 layer->effect_tree_index()); |
| 1113 bool non_root_copy_request = | 596 bool non_root_copy_request = |
| 1114 effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId; | 597 effect_ancestor_with_copy_request > EffectTree::kContentsRootNodeId; |
| 1115 gfx::Rect layer_content_rect = gfx::Rect(layer->bounds()); | 598 gfx::Rect layer_content_rect = gfx::Rect(layer->bounds()); |
| 1116 gfx::RectF accumulated_clip_in_root_space; | 599 gfx::RectF accumulated_clip_in_root_space; |
| 1117 if (non_root_copy_request) { | 600 if (non_root_copy_request) { |
| 1118 bool include_viewport_clip = false; | |
| 1119 bool include_expanding_clips = true; | 601 bool include_expanding_clips = true; |
| 1120 ConditionalClip accumulated_clip = ComputeAccumulatedClip( | 602 ConditionalClip accumulated_clip = ComputeAccumulatedClip( |
| 1121 property_trees, include_viewport_clip, include_expanding_clips, | 603 property_trees, include_expanding_clips, layer->clip_tree_index(), |
| 1122 layer->clip_tree_index(), effect_ancestor_with_copy_request); | 604 effect_ancestor_with_copy_request); |
| 1123 if (!accumulated_clip.is_clipped) | 605 if (!accumulated_clip.is_clipped) |
| 1124 return layer_content_rect; | 606 return layer_content_rect; |
| 1125 accumulated_clip_in_root_space = accumulated_clip.clip_rect; | 607 accumulated_clip_in_root_space = accumulated_clip.clip_rect; |
| 1126 } else { | 608 } else { |
| 1127 accumulated_clip_in_root_space = | 609 const ClipNode* clip_node = |
| 1128 ComputeAccumulatedClipInRootSpaceForVisibleRect( | 610 property_trees->clip_tree.Node(layer->clip_tree_index()); |
| 1129 property_trees, layer->clip_tree_index()); | 611 const EffectNode* effect_node = property_trees->effect_tree.Node( |
| 612 layer->render_target_effect_tree_index()); |
| 613 bool fully_visible = |
| 614 !layer->is_clipped() && !effect_node->surface_is_clipped; |
| 615 if (fully_visible) { |
| 616 accumulated_clip_in_root_space = property_trees->clip_tree.ViewportClip(); |
| 617 } else { |
| 618 accumulated_clip_in_root_space = |
| 619 clip_node->cached_accumulated_rect_in_screen_space; |
| 620 } |
| 1130 } | 621 } |
| 1131 | 622 |
| 1132 const EffectNode* root_effect_node = | 623 const EffectNode* root_effect_node = |
| 1133 non_root_copy_request | 624 non_root_copy_request |
| 1134 ? property_trees->effect_tree.Node(effect_ancestor_with_copy_request) | 625 ? property_trees->effect_tree.Node(effect_ancestor_with_copy_request) |
| 1135 : property_trees->effect_tree.Node(EffectTree::kContentsRootNodeId); | 626 : property_trees->effect_tree.Node(EffectTree::kContentsRootNodeId); |
| 1136 ConditionalClip accumulated_clip_in_layer_space = | 627 ConditionalClip accumulated_clip_in_layer_space = |
| 1137 ComputeTargetRectInLocalSpace( | 628 ComputeTargetRectInLocalSpace( |
| 1138 accumulated_clip_in_root_space, property_trees, | 629 accumulated_clip_in_root_space, property_trees, |
| 1139 root_effect_node->transform_id, layer->transform_tree_index(), | 630 root_effect_node->transform_id, layer->transform_tree_index(), |
| 1140 root_effect_node->id); | 631 root_effect_node->id); |
| 1141 if (!accumulated_clip_in_layer_space.is_clipped) | 632 if (!accumulated_clip_in_layer_space.is_clipped) { |
| 1142 return layer_content_rect; | 633 return layer_content_rect; |
| 634 } |
| 1143 gfx::RectF clip_in_layer_space = accumulated_clip_in_layer_space.clip_rect; | 635 gfx::RectF clip_in_layer_space = accumulated_clip_in_layer_space.clip_rect; |
| 1144 clip_in_layer_space.Offset(-layer->offset_to_transform_parent()); | 636 clip_in_layer_space.Offset(-layer->offset_to_transform_parent()); |
| 1145 | 637 |
| 1146 gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_in_layer_space); | 638 gfx::Rect visible_rect = gfx::ToEnclosingRect(clip_in_layer_space); |
| 1147 visible_rect.Intersect(layer_content_rect); | 639 visible_rect.Intersect(layer_content_rect); |
| 1148 return visible_rect; | 640 return visible_rect; |
| 1149 } | 641 } |
| 1150 | 642 |
| 1151 void VerifyVisibleRectsCalculations(const LayerImplList& layer_list, | 643 void UpdatePropertyTrees(PropertyTrees* property_trees, |
| 1152 const PropertyTrees* property_trees) { | 644 bool can_render_to_separate_surface) { |
| 1153 for (auto* layer : layer_list) { | 645 if (property_trees->non_root_surfaces_enabled != |
| 1154 gfx::Rect visible_rect_dynamic = | 646 can_render_to_separate_surface) { |
| 1155 ComputeLayerVisibleRectDynamic(property_trees, layer); | 647 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; |
| 1156 DCHECK(layer->visible_layer_rect() == visible_rect_dynamic) | 648 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 } | 649 } |
| 650 if (property_trees->transform_tree.needs_update()) { |
| 651 property_trees->clip_tree.set_needs_update(true); |
| 652 property_trees->effect_tree.set_needs_update(true); |
| 653 } |
| 654 ComputeTransforms(&property_trees->transform_tree); |
| 655 ComputeEffects(&property_trees->effect_tree); |
| 656 // Computation of clips uses ToScreen which is updated while computing |
| 657 // transforms. So, ComputeTransforms should be before ComputeClips. |
| 658 ComputeClips(property_trees); |
| 659 } |
| 660 |
| 661 void UpdatePropertyTreesAndRenderSurfaces(LayerImpl* root_layer, |
| 662 PropertyTrees* property_trees, |
| 663 bool can_render_to_separate_surface) { |
| 664 bool render_surfaces_need_update = false; |
| 665 if (property_trees->non_root_surfaces_enabled != |
| 666 can_render_to_separate_surface) { |
| 667 property_trees->non_root_surfaces_enabled = can_render_to_separate_surface; |
| 668 property_trees->transform_tree.set_needs_update(true); |
| 669 render_surfaces_need_update = true; |
| 670 } |
| 671 if (property_trees->transform_tree.needs_update()) { |
| 672 property_trees->clip_tree.set_needs_update(true); |
| 673 property_trees->effect_tree.set_needs_update(true); |
| 674 } |
| 675 if (render_surfaces_need_update) { |
| 676 property_trees->effect_tree.UpdateRenderSurfaces( |
| 677 root_layer->layer_tree_impl(), |
| 678 property_trees->non_root_surfaces_enabled); |
| 679 } |
| 680 UpdateRenderTarget(&property_trees->effect_tree, |
| 681 property_trees->non_root_surfaces_enabled); |
| 682 |
| 683 ComputeTransforms(&property_trees->transform_tree); |
| 684 ComputeEffects(&property_trees->effect_tree); |
| 685 // Computation of clips uses ToScreen which is updated while computing |
| 686 // transforms. So, ComputeTransforms should be before ComputeClips. |
| 687 ComputeClips(property_trees); |
| 1162 } | 688 } |
| 1163 | 689 |
| 1164 bool LayerNeedsUpdate(Layer* layer, | 690 bool LayerNeedsUpdate(Layer* layer, |
| 1165 bool layer_is_drawn, | 691 bool layer_is_drawn, |
| 1166 const PropertyTrees* property_trees) { | 692 const PropertyTrees* property_trees) { |
| 1167 return LayerNeedsUpdateInternal(layer, layer_is_drawn, property_trees); | 693 return LayerNeedsUpdateInternal(layer, layer_is_drawn, property_trees); |
| 1168 } | 694 } |
| 1169 | 695 |
| 1170 bool LayerNeedsUpdate(LayerImpl* layer, | 696 bool LayerNeedsUpdate(LayerImpl* layer, |
| 1171 bool layer_is_drawn, | 697 bool layer_is_drawn, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1211 const EffectNode* target_effect_node = | 737 const EffectNode* target_effect_node = |
| 1212 effect_tree.Node(effect_node->target_id); | 738 effect_tree.Node(effect_node->target_id); |
| 1213 property_trees->GetToTarget(transform_node->id, target_effect_node->id, | 739 property_trees->GetToTarget(transform_node->id, target_effect_node->id, |
| 1214 &render_surface_transform); | 740 &render_surface_transform); |
| 1215 | 741 |
| 1216 ConcatInverseSurfaceContentsScale(effect_node, &render_surface_transform); | 742 ConcatInverseSurfaceContentsScale(effect_node, &render_surface_transform); |
| 1217 render_surface->SetDrawTransform(render_surface_transform); | 743 render_surface->SetDrawTransform(render_surface_transform); |
| 1218 } | 744 } |
| 1219 | 745 |
| 1220 static void SetSurfaceClipRect(const ClipNode* parent_clip_node, | 746 static void SetSurfaceClipRect(const ClipNode* parent_clip_node, |
| 1221 const PropertyTrees* property_trees, | 747 PropertyTrees* property_trees, |
| 1222 RenderSurfaceImpl* render_surface) { | 748 RenderSurfaceImpl* render_surface) { |
| 1223 if (!render_surface->is_clipped()) { | 749 if (!render_surface->is_clipped()) { |
| 1224 render_surface->SetClipRect(gfx::Rect()); | 750 render_surface->SetClipRect(gfx::Rect()); |
| 1225 return; | 751 return; |
| 1226 } | 752 } |
| 1227 | 753 |
| 1228 const EffectTree& effect_tree = property_trees->effect_tree; | 754 const EffectTree& effect_tree = property_trees->effect_tree; |
| 1229 const TransformTree& transform_tree = property_trees->transform_tree; | 755 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 = | 756 const EffectNode* effect_node = |
| 1243 effect_tree.Node(render_surface->EffectTreeIndex()); | 757 effect_tree.Node(render_surface->EffectTreeIndex()); |
| 1244 int target_effect_id = effect_node->target_id; | 758 const EffectNode* target_node = effect_tree.Node(effect_node->target_id); |
| 1245 gfx::RectF clip_rect; | 759 bool include_expanding_clips = false; |
| 1246 const bool success = ConvertRectBetweenSurfaceSpaces( | 760 if (render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId) { |
| 1247 property_trees, parent_clip_node->target_effect_id, target_effect_id, | 761 render_surface->SetClipRect( |
| 1248 parent_clip_node->clip_in_target_space, &clip_rect); | 762 gfx::ToEnclosingRect(clip_tree.Node(effect_node->clip_id)->clip)); |
| 1249 | 763 } else { |
| 1250 if (!success) { | 764 ConditionalClip accumulated_clip_rect = |
| 1251 render_surface->SetClipRect(gfx::Rect()); | 765 ComputeAccumulatedClip(property_trees, include_expanding_clips, |
| 1252 return; | 766 effect_node->clip_id, target_node->id); |
| 767 render_surface->SetClipRect( |
| 768 gfx::ToEnclosingRect(accumulated_clip_rect.clip_rect)); |
| 1253 } | 769 } |
| 1254 render_surface->SetClipRect(gfx::ToEnclosingRect(clip_rect)); | |
| 1255 } | 770 } |
| 1256 | 771 |
| 1257 template <typename LayerType> | 772 template <typename LayerType> |
| 1258 static gfx::Transform ScreenSpaceTransformInternal(LayerType* layer, | 773 static gfx::Transform ScreenSpaceTransformInternal(LayerType* layer, |
| 1259 const TransformTree& tree) { | 774 const TransformTree& tree) { |
| 1260 gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(), | 775 gfx::Transform xform(1, 0, 0, 1, layer->offset_to_transform_parent().x(), |
| 1261 layer->offset_to_transform_parent().y()); | 776 layer->offset_to_transform_parent().y()); |
| 1262 gfx::Transform ssxform = tree.ToScreen(layer->transform_tree_index()); | 777 gfx::Transform ssxform = tree.ToScreen(layer->transform_tree_index()); |
| 1263 xform.ConcatTransform(ssxform); | 778 xform.ConcatTransform(ssxform); |
| 1264 if (layer->should_flatten_transform_from_property_tree()) | 779 if (layer->should_flatten_transform_from_property_tree()) |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1310 static gfx::Rect LayerDrawableContentRect( | 825 static gfx::Rect LayerDrawableContentRect( |
| 1311 const LayerImpl* layer, | 826 const LayerImpl* layer, |
| 1312 const gfx::Rect& layer_bounds_in_target_space, | 827 const gfx::Rect& layer_bounds_in_target_space, |
| 1313 const gfx::Rect& clip_rect) { | 828 const gfx::Rect& clip_rect) { |
| 1314 if (layer->is_clipped()) | 829 if (layer->is_clipped()) |
| 1315 return IntersectRects(layer_bounds_in_target_space, clip_rect); | 830 return IntersectRects(layer_bounds_in_target_space, clip_rect); |
| 1316 | 831 |
| 1317 return layer_bounds_in_target_space; | 832 return layer_bounds_in_target_space; |
| 1318 } | 833 } |
| 1319 | 834 |
| 1320 void ComputeLayerDrawProperties(LayerImpl* layer, | 835 void ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, |
| 1321 const PropertyTrees* property_trees) { | 836 PropertyTrees* property_trees) { |
| 1322 const TransformNode* transform_node = | 837 // Compute transforms |
| 1323 property_trees->transform_tree.Node(layer->transform_tree_index()); | 838 for (LayerImpl* layer : *layer_list) { |
| 1324 const ClipNode* clip_node = | 839 const TransformNode* transform_node = |
| 1325 property_trees->clip_tree.Node(layer->clip_tree_index()); | 840 property_trees->transform_tree.Node(layer->transform_tree_index()); |
| 1326 | 841 |
| 1327 layer->draw_properties().screen_space_transform = | 842 layer->draw_properties().screen_space_transform = |
| 1328 ScreenSpaceTransformInternal(layer, property_trees->transform_tree); | 843 ScreenSpaceTransformInternal(layer, property_trees->transform_tree); |
| 1329 layer->draw_properties().target_space_transform = DrawTransform( | 844 layer->draw_properties().target_space_transform = DrawTransform( |
| 1330 layer, property_trees->transform_tree, property_trees->effect_tree); | 845 layer, property_trees->transform_tree, property_trees->effect_tree); |
| 1331 layer->draw_properties().screen_space_transform_is_animating = | 846 layer->draw_properties().screen_space_transform_is_animating = |
| 1332 transform_node->to_screen_is_potentially_animated; | 847 transform_node->to_screen_is_potentially_animated; |
| 1333 | |
| 1334 layer->draw_properties().opacity = | |
| 1335 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 } | 848 } |
| 1342 | 849 |
| 1343 gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect( | 850 // Compute draw opacities |
| 1344 layer->draw_properties().target_space_transform, | 851 for (LayerImpl* layer : *layer_list) { |
| 1345 gfx::Rect(layer->bounds())); | 852 layer->draw_properties().opacity = |
| 1346 layer->draw_properties().drawable_content_rect = LayerDrawableContentRect( | 853 LayerDrawOpacity(layer, property_trees->effect_tree); |
| 1347 layer, bounds_in_target_space, layer->draw_properties().clip_rect); | 854 } |
| 855 |
| 856 // Compute clips and viisble rects |
| 857 for (LayerImpl* layer : *layer_list) { |
| 858 ConditionalClip clip = LayerClipRect(property_trees, layer); |
| 859 // is_clipped should be set before visible rect computation as it is used |
| 860 // there. |
| 861 layer->draw_properties().is_clipped = clip.is_clipped; |
| 862 layer->draw_properties().clip_rect = gfx::ToEnclosingRect(clip.clip_rect); |
| 863 layer->draw_properties().visible_layer_rect = |
| 864 LayerVisibleRect(property_trees, layer); |
| 865 } |
| 866 |
| 867 // Compute drawable content rects |
| 868 for (LayerImpl* layer : *layer_list) { |
| 869 gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect( |
| 870 layer->draw_properties().target_space_transform, |
| 871 gfx::Rect(layer->bounds())); |
| 872 layer->draw_properties().drawable_content_rect = LayerDrawableContentRect( |
| 873 layer, bounds_in_target_space, layer->draw_properties().clip_rect); |
| 874 } |
| 1348 } | 875 } |
| 1349 | 876 |
| 1350 void ComputeMaskDrawProperties(LayerImpl* mask_layer, | 877 void ComputeMaskDrawProperties(LayerImpl* mask_layer, |
| 1351 const PropertyTrees* property_trees) { | 878 const PropertyTrees* property_trees) { |
| 1352 // Mask draw properties are used only for rastering, so most of the draw | 879 // Mask draw properties are used only for rastering, so most of the draw |
| 1353 // properties computed for other layers are not needed. | 880 // properties computed for other layers are not needed. |
| 1354 mask_layer->draw_properties().screen_space_transform = | 881 mask_layer->draw_properties().screen_space_transform = |
| 1355 ScreenSpaceTransformInternal(mask_layer, | 882 ScreenSpaceTransformInternal(mask_layer, |
| 1356 property_trees->transform_tree); | 883 property_trees->transform_tree); |
| 1357 mask_layer->draw_properties().visible_layer_rect = | 884 mask_layer->draw_properties().visible_layer_rect = |
| 1358 gfx::Rect(mask_layer->bounds()); | 885 gfx::Rect(mask_layer->bounds()); |
| 1359 } | 886 } |
| 1360 | 887 |
| 1361 void ComputeSurfaceDrawProperties(const PropertyTrees* property_trees, | 888 void ComputeSurfaceDrawProperties(PropertyTrees* property_trees, |
| 1362 RenderSurfaceImpl* render_surface) { | 889 RenderSurfaceImpl* render_surface, |
| 890 const bool use_layer_lists) { |
| 1363 const EffectNode* effect_node = | 891 const EffectNode* effect_node = |
| 1364 property_trees->effect_tree.Node(render_surface->EffectTreeIndex()); | 892 property_trees->effect_tree.Node(render_surface->EffectTreeIndex()); |
| 1365 render_surface->SetIsClipped(effect_node->surface_is_clipped); | 893 if (use_layer_lists) { |
| 894 // TODO(crbug.com/702010) : Calculate surface's is_clipped value outside |
| 895 // cc property tree building. This is a temporary hack to make SPv2 layout |
| 896 // tests pass. |
| 897 bool is_clipped = effect_node->id == EffectTree::kContentsRootNodeId || |
| 898 (render_surface->render_target()->ClipTreeIndex() != |
| 899 render_surface->ClipTreeIndex()); |
| 900 render_surface->SetIsClipped(is_clipped); |
| 901 } else { |
| 902 render_surface->SetIsClipped(effect_node->surface_is_clipped); |
| 903 } |
| 1366 SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface); | 904 SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface); |
| 1367 SetSurfaceDrawTransform(property_trees, render_surface); | 905 SetSurfaceDrawTransform(property_trees, render_surface); |
| 1368 render_surface->SetScreenSpaceTransform( | 906 render_surface->SetScreenSpaceTransform( |
| 1369 property_trees->ToScreenSpaceTransformWithoutSurfaceContentsScale( | 907 property_trees->ToScreenSpaceTransformWithoutSurfaceContentsScale( |
| 1370 render_surface->TransformTreeIndex(), | 908 render_surface->TransformTreeIndex(), |
| 1371 render_surface->EffectTreeIndex())); | 909 render_surface->EffectTreeIndex())); |
| 1372 | 910 |
| 1373 const ClipNode* clip_node = | 911 const ClipNode* clip_node = |
| 1374 property_trees->clip_tree.Node(render_surface->ClipTreeIndex()); | 912 property_trees->clip_tree.Node(render_surface->ClipTreeIndex()); |
| 1375 SetSurfaceClipRect(clip_node, property_trees, render_surface); | 913 SetSurfaceClipRect(clip_node, property_trees, render_surface); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1471 void UpdateElasticOverscroll(PropertyTrees* property_trees, | 1009 void UpdateElasticOverscroll(PropertyTrees* property_trees, |
| 1472 const Layer* overscroll_elasticity_layer, | 1010 const Layer* overscroll_elasticity_layer, |
| 1473 const gfx::Vector2dF& elastic_overscroll) { | 1011 const gfx::Vector2dF& elastic_overscroll) { |
| 1474 UpdateElasticOverscrollInternal(property_trees, overscroll_elasticity_layer, | 1012 UpdateElasticOverscrollInternal(property_trees, overscroll_elasticity_layer, |
| 1475 elastic_overscroll); | 1013 elastic_overscroll); |
| 1476 } | 1014 } |
| 1477 | 1015 |
| 1478 } // namespace draw_property_utils | 1016 } // namespace draw_property_utils |
| 1479 | 1017 |
| 1480 } // namespace cc | 1018 } // namespace cc |
| OLD | NEW |