| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2014 Google Inc. All rights reserved. | 3 * Copyright (C) 2014 Google Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 void unite(const OverlapMapContainer& otherContainer) { | 58 void unite(const OverlapMapContainer& otherContainer) { |
| 59 m_layerRects.appendVector(otherContainer.m_layerRects); | 59 m_layerRects.appendVector(otherContainer.m_layerRects); |
| 60 m_boundingBox.unite(otherContainer.m_boundingBox); | 60 m_boundingBox.unite(otherContainer.m_boundingBox); |
| 61 } | 61 } |
| 62 | 62 |
| 63 private: | 63 private: |
| 64 Vector<IntRect, 64> m_layerRects; | 64 Vector<IntRect, 64> m_layerRects; |
| 65 IntRect m_boundingBox; | 65 IntRect m_boundingBox; |
| 66 }; | 66 }; |
| 67 | 67 |
| 68 struct OverlapMapContainers { |
| 69 OverlapMapContainer clipped; |
| 70 OverlapMapContainer unclipped; |
| 71 }; |
| 72 |
| 68 class CompositingRequirementsUpdater::OverlapMap { | 73 class CompositingRequirementsUpdater::OverlapMap { |
| 69 WTF_MAKE_NONCOPYABLE(OverlapMap); | 74 WTF_MAKE_NONCOPYABLE(OverlapMap); |
| 70 | 75 |
| 71 public: | 76 public: |
| 72 OverlapMap() { | 77 OverlapMap() { |
| 73 // Begin by assuming the root layer will be composited so that there | 78 // Begin by assuming the root layer will be composited so that there |
| 74 // is something on the stack. The root layer should also never get a | 79 // is something on the stack. The root layer should also never get a |
| 75 // finishCurrentOverlapTestingContext() call. | 80 // finishCurrentOverlapTestingContext() call. |
| 76 beginNewOverlapTestingContext(); | 81 beginNewOverlapTestingContext(); |
| 77 } | 82 } |
| 78 | 83 |
| 79 void add(PaintLayer* layer, const IntRect& bounds) { | 84 // Each rect added is marked as clipped or unclipped. clipped rects may |
| 85 // overlap only with other clipped rects, but unclipped rects may overlap |
| 86 // with anything. |
| 87 // |
| 88 // This is used to model composited overflow scrolling, where PaintLayers |
| 89 // within the scroller are not clipped for overlap testing, whereas |
| 90 // PaintLayers not within it are. This is necessary because PaintLayerClipper |
| 91 // is not smart enough to understand not to clip composited overflow clips, |
| 92 // but still clip otherwise. |
| 93 void add(PaintLayer* layer, const IntRect& bounds, bool isClipped) { |
| 80 DCHECK(!layer->isRootLayer()); | 94 DCHECK(!layer->isRootLayer()); |
| 81 if (bounds.isEmpty()) | 95 if (bounds.isEmpty()) |
| 82 return; | 96 return; |
| 83 | 97 |
| 84 // Layers do not contribute to overlap immediately--instead, they will | 98 // Layers do not contribute to overlap immediately--instead, they will |
| 85 // contribute to overlap as soon as they have been recursively processed | 99 // contribute to overlap as soon as they have been recursively processed |
| 86 // and popped off the stack. | 100 // and popped off the stack. |
| 87 DCHECK_GE(m_overlapStack.size(), 2ul); | 101 DCHECK_GE(m_overlapStack.size(), 2ul); |
| 88 m_overlapStack[m_overlapStack.size() - 2].add(bounds); | 102 if (isClipped) |
| 103 m_overlapStack[m_overlapStack.size() - 2].clipped.add(bounds); |
| 104 else |
| 105 m_overlapStack[m_overlapStack.size() - 2].unclipped.add(bounds); |
| 89 } | 106 } |
| 90 | 107 |
| 91 bool overlapsLayers(const IntRect& bounds) const { | 108 bool overlapsLayers(const IntRect& bounds, bool isClipped) const { |
| 92 return m_overlapStack.last().overlapsLayers(bounds); | 109 bool clippedOverlap = m_overlapStack.last().clipped.overlapsLayers(bounds); |
| 110 if (isClipped) |
| 111 return clippedOverlap; |
| 112 // Unclipped is allowed to overlap clipped, but not vice-versa. |
| 113 return clippedOverlap || |
| 114 m_overlapStack.last().unclipped.overlapsLayers(bounds); |
| 93 } | 115 } |
| 94 | 116 |
| 95 void beginNewOverlapTestingContext() { | 117 void beginNewOverlapTestingContext() { |
| 96 // This effectively creates a new "clean slate" for overlap state. | 118 // This effectively creates a new "clean slate" for overlap state. |
| 97 // This is used when we know that a subtree or remaining set of | 119 // This is used when we know that a subtree or remaining set of |
| 98 // siblings does not need to check overlap with things behind it. | 120 // siblings does not need to check overlap with things behind it. |
| 99 m_overlapStack.append(OverlapMapContainer()); | 121 m_overlapStack.append(OverlapMapContainers()); |
| 100 } | 122 } |
| 101 | 123 |
| 102 void finishCurrentOverlapTestingContext() { | 124 void finishCurrentOverlapTestingContext() { |
| 103 // The overlap information on the top of the stack is still necessary | 125 // The overlap information on the top of the stack is still necessary |
| 104 // for checking overlap of any layers outside this context that may | 126 // for checking overlap of any layers outside this context that may |
| 105 // overlap things from inside this context. Therefore, we must merge | 127 // overlap things from inside this context. Therefore, we must merge |
| 106 // the information from the top of the stack before popping the stack. | 128 // the information from the top of the stack before popping the stack. |
| 107 // | 129 // |
| 108 // FIXME: we may be able to avoid this deep copy by rearranging how | 130 // FIXME: we may be able to avoid this deep copy by rearranging how |
| 109 // overlapMap state is managed. | 131 // overlapMap state is managed. |
| 110 m_overlapStack[m_overlapStack.size() - 2].unite(m_overlapStack.last()); | 132 m_overlapStack[m_overlapStack.size() - 2].clipped.unite( |
| 133 m_overlapStack.last().clipped); |
| 134 m_overlapStack[m_overlapStack.size() - 2].unclipped.unite( |
| 135 m_overlapStack.last().unclipped); |
| 111 m_overlapStack.removeLast(); | 136 m_overlapStack.removeLast(); |
| 112 } | 137 } |
| 113 | 138 |
| 114 private: | 139 private: |
| 115 Vector<OverlapMapContainer> m_overlapStack; | 140 Vector<OverlapMapContainers> m_overlapStack; |
| 116 }; | 141 }; |
| 117 | 142 |
| 118 class CompositingRequirementsUpdater::RecursionData { | 143 class CompositingRequirementsUpdater::RecursionData { |
| 119 public: | 144 public: |
| 120 explicit RecursionData(PaintLayer* compositingAncestor) | 145 explicit RecursionData(PaintLayer* compositingAncestor) |
| 121 : m_compositingAncestor(compositingAncestor), | 146 : m_compositingAncestor(compositingAncestor), |
| 122 m_subtreeIsCompositing(false), | 147 m_subtreeIsCompositing(false), |
| 123 m_hasUnisolatedCompositedBlendingDescendant(false), | 148 m_hasUnisolatedCompositedBlendingDescendant(false), |
| 124 m_testingOverlap(true), | 149 m_testingOverlap(true), |
| 125 m_hasCompositedScrollingAncestor(false) {} | 150 m_hasCompositedScrollingAncestor(false) {} |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 m_compositingReasonFinder.directReasons(layer); | 251 m_compositingReasonFinder.directReasons(layer); |
| 227 | 252 |
| 228 // Video is special. It's the only PaintLayer type that can both have | 253 // Video is special. It's the only PaintLayer type that can both have |
| 229 // PaintLayer children and whose children can't use its backing to render | 254 // PaintLayer children and whose children can't use its backing to render |
| 230 // into. These children (the controls) always need to be promoted into their | 255 // into. These children (the controls) always need to be promoted into their |
| 231 // own layers to draw on top of the accelerated video. | 256 // own layers to draw on top of the accelerated video. |
| 232 if (currentRecursionData.m_compositingAncestor && | 257 if (currentRecursionData.m_compositingAncestor && |
| 233 currentRecursionData.m_compositingAncestor->layoutObject()->isVideo()) | 258 currentRecursionData.m_compositingAncestor->layoutObject()->isVideo()) |
| 234 directReasons |= CompositingReasonVideoOverlay; | 259 directReasons |= CompositingReasonVideoOverlay; |
| 235 | 260 |
| 261 bool hasCompositedScrollingAncestor = |
| 262 layer->ancestorScrollingLayer() && |
| 263 (m_compositingReasonFinder.directReasons( |
| 264 layer->ancestorScrollingLayer()) & |
| 265 CompositingReasonOverflowScrollingTouch); |
| 266 |
| 267 // TODO(chrishtr): use |hasCompositedScrollingAncestor| instead. |
| 236 if (currentRecursionData.m_hasCompositedScrollingAncestor && | 268 if (currentRecursionData.m_hasCompositedScrollingAncestor && |
| 237 layer->layoutObject()->styleRef().hasViewportConstrainedPosition()) | 269 layer->layoutObject()->styleRef().hasViewportConstrainedPosition()) |
| 238 directReasons |= CompositingReasonScrollDependentPosition; | 270 directReasons |= CompositingReasonScrollDependentPosition; |
| 239 | 271 |
| 240 bool canBeComposited = compositor->canBeComposited(layer); | 272 bool canBeComposited = compositor->canBeComposited(layer); |
| 241 if (canBeComposited) { | 273 if (canBeComposited) { |
| 242 reasonsToComposite |= directReasons; | 274 reasonsToComposite |= directReasons; |
| 243 | 275 |
| 244 if (layer->isRootLayer() && compositor->rootShouldAlwaysComposite()) | 276 if (layer->isRootLayer() && compositor->rootShouldAlwaysComposite()) |
| 245 reasonsToComposite |= CompositingReasonRoot; | 277 reasonsToComposite |= CompositingReasonRoot; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 271 | 303 |
| 272 // Next, accumulate reasons related to overlap. | 304 // Next, accumulate reasons related to overlap. |
| 273 // If overlap testing is used, this reason will be overridden. If overlap | 305 // If overlap testing is used, this reason will be overridden. If overlap |
| 274 // testing is not used, we must assume we overlap if there is anything | 306 // testing is not used, we must assume we overlap if there is anything |
| 275 // composited behind us in paint-order. | 307 // composited behind us in paint-order. |
| 276 CompositingReasons overlapCompositingReason = | 308 CompositingReasons overlapCompositingReason = |
| 277 currentRecursionData.m_subtreeIsCompositing | 309 currentRecursionData.m_subtreeIsCompositing |
| 278 ? CompositingReasonAssumedOverlap | 310 ? CompositingReasonAssumedOverlap |
| 279 : CompositingReasonNone; | 311 : CompositingReasonNone; |
| 280 | 312 |
| 313 // TODO(chrishtr): use |hasCompositedScrollingAncestor| instead. |
| 281 if (currentRecursionData.m_hasCompositedScrollingAncestor) { | 314 if (currentRecursionData.m_hasCompositedScrollingAncestor) { |
| 282 Vector<size_t> unclippedDescendantsToRemove; | 315 Vector<size_t> unclippedDescendantsToRemove; |
| 283 for (size_t i = 0; i < unclippedDescendants.size(); i++) { | 316 for (size_t i = 0; i < unclippedDescendants.size(); i++) { |
| 284 PaintLayer* unclippedDescendant = unclippedDescendants.at(i); | 317 PaintLayer* unclippedDescendant = unclippedDescendants.at(i); |
| 285 // If we've reached the containing block of one of the unclipped | 318 // If we've reached the containing block of one of the unclipped |
| 286 // descendants, that element is no longer relevant to whether or not we | 319 // descendants, that element is no longer relevant to whether or not we |
| 287 // should opt in. Unfortunately we can't easily remove from the list | 320 // should opt in. Unfortunately we can't easily remove from the list |
| 288 // while we're iterating, so we have to store it for later removal. | 321 // while we're iterating, so we have to store it for later removal. |
| 289 if (unclippedDescendant->layoutObject()->containingBlock() == | 322 if (unclippedDescendant->layoutObject()->containingBlock() == |
| 290 layer->layoutObject()) { | 323 layer->layoutObject()) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 303 } | 336 } |
| 304 | 337 |
| 305 if (reasonsToComposite & CompositingReasonOutOfFlowClipping) { | 338 if (reasonsToComposite & CompositingReasonOutOfFlowClipping) { |
| 306 // TODO(schenney): We only need to promote when the clipParent is not a | 339 // TODO(schenney): We only need to promote when the clipParent is not a |
| 307 // descendant of the ancestor scroller, which we do not check for here. | 340 // descendant of the ancestor scroller, which we do not check for here. |
| 308 // Hence we might be promoting needlessly. | 341 // Hence we might be promoting needlessly. |
| 309 unclippedDescendants.append(layer); | 342 unclippedDescendants.append(layer); |
| 310 } | 343 } |
| 311 } | 344 } |
| 312 | 345 |
| 313 const IntRect& absBounds = layer->clippedAbsoluteBoundingBox(); | 346 const IntRect& absBounds = hasCompositedScrollingAncestor |
| 347 ? layer->unclippedAbsoluteBoundingBox() |
| 348 : layer->clippedAbsoluteBoundingBox(); |
| 314 absoluteDescendantBoundingBox = absBounds; | 349 absoluteDescendantBoundingBox = absBounds; |
| 315 | |
| 316 if (currentRecursionData.m_testingOverlap && | 350 if (currentRecursionData.m_testingOverlap && |
| 317 !requiresCompositingOrSquashing(directReasons)) { | 351 !requiresCompositingOrSquashing(directReasons)) { |
| 318 overlapCompositingReason = overlapMap.overlapsLayers(absBounds) | 352 bool overlaps = |
| 319 ? CompositingReasonOverlap | 353 overlapMap.overlapsLayers(absBounds, !hasCompositedScrollingAncestor); |
| 320 : CompositingReasonNone; | 354 overlapCompositingReason = |
| 355 overlaps ? CompositingReasonOverlap : CompositingReasonNone; |
| 321 } | 356 } |
| 322 | 357 |
| 323 reasonsToComposite |= overlapCompositingReason; | 358 reasonsToComposite |= overlapCompositingReason; |
| 324 | 359 |
| 325 // The children of this layer don't need to composite, unless there is | 360 // The children of this layer don't need to composite, unless there is |
| 326 // a compositing layer among them, so start by inheriting the compositing | 361 // a compositing layer among them, so start by inheriting the compositing |
| 327 // ancestor with m_subtreeIsCompositing set to false. | 362 // ancestor with m_subtreeIsCompositing set to false. |
| 328 RecursionData childRecursionData = currentRecursionData; | 363 RecursionData childRecursionData = currentRecursionData; |
| 329 childRecursionData.m_subtreeIsCompositing = false; | 364 childRecursionData.m_subtreeIsCompositing = false; |
| 330 | 365 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 childRecursionData.m_compositingAncestor = layer; | 407 childRecursionData.m_compositingAncestor = layer; |
| 373 overlapMap.beginNewOverlapTestingContext(); | 408 overlapMap.beginNewOverlapTestingContext(); |
| 374 willBeCompositedOrSquashed = true; | 409 willBeCompositedOrSquashed = true; |
| 375 willHaveForegroundLayer = true; | 410 willHaveForegroundLayer = true; |
| 376 | 411 |
| 377 // FIXME: temporary solution for the first negative z-index composited | 412 // FIXME: temporary solution for the first negative z-index composited |
| 378 // child: re-compute the absBounds for the child so that we can add | 413 // child: re-compute the absBounds for the child so that we can add |
| 379 // the negative z-index child's bounds to the new overlap context. | 414 // the negative z-index child's bounds to the new overlap context. |
| 380 overlapMap.beginNewOverlapTestingContext(); | 415 overlapMap.beginNewOverlapTestingContext(); |
| 381 overlapMap.add(curNode->layer(), | 416 overlapMap.add(curNode->layer(), |
| 382 curNode->layer()->clippedAbsoluteBoundingBox()); | 417 curNode->layer()->clippedAbsoluteBoundingBox(), true); |
| 383 overlapMap.finishCurrentOverlapTestingContext(); | 418 overlapMap.finishCurrentOverlapTestingContext(); |
| 384 } | 419 } |
| 385 } | 420 } |
| 386 } | 421 } |
| 387 } | 422 } |
| 388 | 423 |
| 389 if (willHaveForegroundLayer) { | 424 if (willHaveForegroundLayer) { |
| 390 DCHECK(willBeCompositedOrSquashed); | 425 DCHECK(willBeCompositedOrSquashed); |
| 391 // A foreground layer effectively is a new backing for all subsequent | 426 // A foreground layer effectively is a new backing for all subsequent |
| 392 // children, so we don't need to test for overlap with anything behind this. | 427 // children, so we don't need to test for overlap with anything behind this. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 compositor->setCompositingModeEnabled(false); | 477 compositor->setCompositingModeEnabled(false); |
| 443 reasonsToComposite = CompositingReasonNone; | 478 reasonsToComposite = CompositingReasonNone; |
| 444 } | 479 } |
| 445 } else { | 480 } else { |
| 446 // All layers (even ones that aren't being composited) need to get added to | 481 // All layers (even ones that aren't being composited) need to get added to |
| 447 // the overlap map. Layers that are not separately composited will paint | 482 // the overlap map. Layers that are not separately composited will paint |
| 448 // into their compositing ancestor's backing, and so are still considered | 483 // into their compositing ancestor's backing, and so are still considered |
| 449 // for overlap. | 484 // for overlap. |
| 450 if (childRecursionData.m_compositingAncestor && | 485 if (childRecursionData.m_compositingAncestor && |
| 451 !childRecursionData.m_compositingAncestor->isRootLayer()) | 486 !childRecursionData.m_compositingAncestor->isRootLayer()) |
| 452 overlapMap.add(layer, absBounds); | 487 overlapMap.add(layer, absBounds, !hasCompositedScrollingAncestor); |
| 453 | 488 |
| 454 // Now check for reasons to become composited that depend on the state of | 489 // Now check for reasons to become composited that depend on the state of |
| 455 // descendant layers. | 490 // descendant layers. |
| 456 CompositingReasons subtreeCompositingReasons = subtreeReasonsForCompositing( | 491 CompositingReasons subtreeCompositingReasons = subtreeReasonsForCompositing( |
| 457 layer, childRecursionData.m_subtreeIsCompositing, | 492 layer, childRecursionData.m_subtreeIsCompositing, |
| 458 anyDescendantHas3DTransform); | 493 anyDescendantHas3DTransform); |
| 459 reasonsToComposite |= subtreeCompositingReasons; | 494 reasonsToComposite |= subtreeCompositingReasons; |
| 460 if (!willBeCompositedOrSquashed && canBeComposited && | 495 if (!willBeCompositedOrSquashed && canBeComposited && |
| 461 requiresCompositingOrSquashing(subtreeCompositingReasons)) { | 496 requiresCompositingOrSquashing(subtreeCompositingReasons)) { |
| 462 childRecursionData.m_compositingAncestor = layer; | 497 childRecursionData.m_compositingAncestor = layer; |
| 463 // FIXME: this context push is effectively a no-op but needs to exist for | 498 // FIXME: this context push is effectively a no-op but needs to exist for |
| 464 // now, because the code is designed to push overlap information to the | 499 // now, because the code is designed to push overlap information to the |
| 465 // second-from-top context of the stack. | 500 // second-from-top context of the stack. |
| 466 overlapMap.beginNewOverlapTestingContext(); | 501 overlapMap.beginNewOverlapTestingContext(); |
| 467 overlapMap.add(layer, absoluteDescendantBoundingBox); | 502 overlapMap.add(layer, absoluteDescendantBoundingBox, |
| 503 !hasCompositedScrollingAncestor); |
| 468 willBeCompositedOrSquashed = true; | 504 willBeCompositedOrSquashed = true; |
| 469 } | 505 } |
| 470 | 506 |
| 471 if (willBeCompositedOrSquashed) { | 507 if (willBeCompositedOrSquashed) { |
| 472 reasonsToComposite |= layer->potentialCompositingReasonsFromStyle() & | 508 reasonsToComposite |= layer->potentialCompositingReasonsFromStyle() & |
| 473 CompositingReasonInlineTransform; | 509 CompositingReasonInlineTransform; |
| 474 } | 510 } |
| 475 | 511 |
| 476 if (willBeCompositedOrSquashed && | 512 if (willBeCompositedOrSquashed && |
| 477 layer->layoutObject()->style()->hasBlendMode()) | 513 layer->layoutObject()->style()->hasBlendMode()) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 502 descendantHas3DTransform |= | 538 descendantHas3DTransform |= |
| 503 anyDescendantHas3DTransform || layer->has3DTransform(); | 539 anyDescendantHas3DTransform || layer->has3DTransform(); |
| 504 } | 540 } |
| 505 | 541 |
| 506 // At this point we have finished collecting all reasons to composite this | 542 // At this point we have finished collecting all reasons to composite this |
| 507 // layer. | 543 // layer. |
| 508 layer->setCompositingReasons(reasonsToComposite); | 544 layer->setCompositingReasons(reasonsToComposite); |
| 509 } | 545 } |
| 510 | 546 |
| 511 } // namespace blink | 547 } // namespace blink |
| OLD | NEW |