Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(277)

Side by Side Diff: third_party/WebKit/Source/core/layout/compositing/CompositingRequirementsUpdater.cpp

Issue 2425873005: Don't apply clips to children of composited-scrolling elements for overlap testing. (Closed)
Patch Set: none Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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;
Ian Vollick 2016/10/19 20:16:31 I think I follow. If we're below the composited sc
chrishtr 2016/10/19 21:44:51 Exactly, it will promote. (though you have to add
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698