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

Side by Side Diff: third_party/WebKit/Source/core/paint/ObjectPaintInvalidator.cpp

Issue 2639283003: Fix traverseNonCompositingDescendantsInPaintOrder for float-under-inline cases (Closed)
Patch Set: Rebase Created 3 years, 10 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
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/paint/ObjectPaintInvalidatorTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "core/paint/ObjectPaintInvalidator.h" 5 #include "core/paint/ObjectPaintInvalidator.h"
6 6
7 #include "core/frame/FrameView.h" 7 #include "core/frame/FrameView.h"
8 #include "core/frame/LocalFrame.h" 8 #include "core/frame/LocalFrame.h"
9 #include "core/layout/LayoutView.h" 9 #include "core/layout/LayoutView.h"
10 #include "core/layout/api/LayoutPartItem.h" 10 #include "core/layout/api/LayoutPartItem.h"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 selectionVisualRectMap().contains(&object)); 50 selectionVisualRectMap().contains(&object));
51 if (object.hasPreviousSelectionVisualRect()) 51 if (object.hasPreviousSelectionVisualRect())
52 selectionVisualRectMap().remove(&object); 52 selectionVisualRectMap().remove(&object);
53 53
54 DCHECK(object.hasPreviousLocationInBacking() == 54 DCHECK(object.hasPreviousLocationInBacking() ==
55 locationInBackingMap().contains(&object)); 55 locationInBackingMap().contains(&object));
56 if (object.hasPreviousLocationInBacking()) 56 if (object.hasPreviousLocationInBacking())
57 locationInBackingMap().remove(&object); 57 locationInBackingMap().remove(&object);
58 } 58 }
59 59
60 // TODO(trchen): Use std::function<void, LayoutObject&> when available. 60 using LayoutObjectTraversalFunctor = std::function<void(const LayoutObject&)>;
61 template <typename LayoutObjectTraversalFunctor> 61
62 void traverseNonCompositingDescendantsInPaintOrder( 62 static void traverseNonCompositingDescendantsInPaintOrder(
63 const LayoutObject&, 63 const LayoutObject&,
64 const LayoutObjectTraversalFunctor&); 64 const LayoutObjectTraversalFunctor&);
65 65
66 template <typename LayoutObjectTraversalFunctor> 66 static void
67 void traverseNonCompositingDescendantsBelongingToAncestorPaintInvalidationContai ner( 67 traverseNonCompositingDescendantsBelongingToAncestorPaintInvalidationContainer(
68 const LayoutObject& object, 68 const LayoutObject& object,
69 const LayoutObjectTraversalFunctor& functor) { 69 const LayoutObjectTraversalFunctor& functor) {
70 // |object| is a paint invalidation container but is not a stacking context, 70 // |object| is a paint invalidation container, but is not a stacking context
71 // so the paint invalidation container of stacked descendants don't belong to 71 // or is a non-block, so the paint invalidation container of stacked
72 // |object| but belong to an ancestor. This function traverses all such 72 // descendants may not belong to |object| but belong to an ancestor. This
73 // descendants. 73 // function traverses all such descendants. See Case 1a and Case 2 below for
74 // details.
74 DCHECK(object.isPaintInvalidationContainer() && 75 DCHECK(object.isPaintInvalidationContainer() &&
75 !object.styleRef().isStackingContext()); 76 (!object.styleRef().isStackingContext() || !object.isLayoutBlock()));
76 77
77 LayoutObject* descendant = object.nextInPreOrder(&object); 78 LayoutObject* descendant = object.nextInPreOrder(&object);
78 while (descendant) { 79 while (descendant) {
79 if (!descendant->hasLayer() || !descendant->styleRef().isStacked()) { 80 if (!descendant->hasLayer() || !descendant->styleRef().isStacked()) {
80 // Case 1: The descendant is not stacked (or is stacked but has not been 81 // Case 1: The descendant is not stacked (or is stacked but has not been
81 // allocated a layer yet during style change), so either it's a paint 82 // allocated a layer yet during style change), so either it's a paint
82 // invalidation container in the same situation as |object|, or its paint 83 // invalidation container in the same situation as |object|, or its paint
83 // invalidation container is in such situation. Keep searching until a 84 // invalidation container is in such situation. Keep searching until a
84 // stacked layer is found. 85 // stacked layer is found.
85 descendant = descendant->nextInPreOrder(&object); 86 if (!object.isLayoutBlock() && descendant->isFloating()) {
87 // Case 1a (rare): However, if the descendant is a floating object below
88 // a composited non-block object, the subtree may belong to an ancestor
89 // in paint order, thus recur into the subtree. Note that for
90 // performance, we don't check whether the floating object's container
91 // is above or under |object|, so we may traverse more than expected.
92 // Example:
93 // <span id="object" class="position: relative; will-change: transform">
94 // <div id="descendant" class="float: left"></div>"
95 // </span>
96 traverseNonCompositingDescendantsInPaintOrder(*descendant, functor);
97 descendant = descendant->nextInPreOrderAfterChildren(&object);
98 } else {
99 descendant = descendant->nextInPreOrder(&object);
100 }
86 } else if (!descendant->isPaintInvalidationContainer()) { 101 } else if (!descendant->isPaintInvalidationContainer()) {
87 // Case 2: The descendant is stacked and is not composited. 102 // Case 2: The descendant is stacked and is not composited.
88 // The invalidation container of its subtree is our ancestor, 103 // The invalidation container of its subtree is our ancestor,
89 // thus recur into the subtree. 104 // thus recur into the subtree.
90 traverseNonCompositingDescendantsInPaintOrder(*descendant, functor); 105 traverseNonCompositingDescendantsInPaintOrder(*descendant, functor);
91 descendant = descendant->nextInPreOrderAfterChildren(&object); 106 descendant = descendant->nextInPreOrderAfterChildren(&object);
92 } else if (descendant->styleRef().isStackingContext()) { 107 } else if (descendant->styleRef().isStackingContext() &&
108 descendant->isLayoutBlock()) {
93 // Case 3: The descendant is an invalidation container and is a stacking 109 // Case 3: The descendant is an invalidation container and is a stacking
94 // context. No objects in the subtree can have invalidation container 110 // context. No objects in the subtree can have invalidation container
95 // outside of it, thus skip the whole subtree. 111 // outside of it, thus skip the whole subtree.
112 // This excludes non-block because there might be floating objects under
113 // the descendant belonging to some ancestor in paint order (Case 1a).
96 descendant = descendant->nextInPreOrderAfterChildren(&object); 114 descendant = descendant->nextInPreOrderAfterChildren(&object);
97 } else { 115 } else {
98 // Case 4: The descendant is an invalidation container but not a stacking 116 // Case 4: The descendant is an invalidation container but not a stacking
99 // context. This is the same situation as |object|, thus keep searching. 117 // context, or the descendant is a non-block stacking context.
118 // This is the same situation as |object|, thus keep searching.
100 descendant = descendant->nextInPreOrder(&object); 119 descendant = descendant->nextInPreOrder(&object);
101 } 120 }
102 } 121 }
103 } 122 }
104 123
105 template <typename LayoutObjectTraversalFunctor> 124 static void traverseNonCompositingDescendantsInPaintOrder(
106 void traverseNonCompositingDescendantsInPaintOrder(
107 const LayoutObject& object, 125 const LayoutObject& object,
108 const LayoutObjectTraversalFunctor& functor) { 126 const LayoutObjectTraversalFunctor& functor) {
109 functor(object); 127 functor(object);
110 LayoutObject* descendant = object.nextInPreOrder(&object); 128 LayoutObject* descendant = object.nextInPreOrder(&object);
111 while (descendant) { 129 while (descendant) {
112 if (!descendant->isPaintInvalidationContainer()) { 130 if (!descendant->isPaintInvalidationContainer()) {
113 functor(*descendant); 131 functor(*descendant);
114 descendant = descendant->nextInPreOrder(&object); 132 descendant = descendant->nextInPreOrder(&object);
115 } else if (descendant->styleRef().isStackingContext()) { 133 } else if (descendant->styleRef().isStackingContext() &&
134 descendant->isLayoutBlock()) {
116 // The descendant is an invalidation container and is a stacking context. 135 // The descendant is an invalidation container and is a stacking context.
117 // No objects in the subtree can have invalidation container outside of 136 // No objects in the subtree can have invalidation container outside of
118 // it, thus skip the whole subtree. 137 // it, thus skip the whole subtree.
138 // This excludes non-blocks because there might be floating objects under
139 // the descendant belonging to some ancestor in paint order (Case 1a).
119 descendant = descendant->nextInPreOrderAfterChildren(&object); 140 descendant = descendant->nextInPreOrderAfterChildren(&object);
120 } else { 141 } else {
121 // If a paint invalidation container is not a stacking context, 142 // If a paint invalidation container is not a stacking context, or the
122 // some of its descendants may belong to the parent container. 143 // descendant is a non-block stacking context, some of its descendants may
144 // belong to the parent container.
123 traverseNonCompositingDescendantsBelongingToAncestorPaintInvalidationConta iner( 145 traverseNonCompositingDescendantsBelongingToAncestorPaintInvalidationConta iner(
124 *descendant, functor); 146 *descendant, functor);
125 descendant = descendant->nextInPreOrderAfterChildren(&object); 147 descendant = descendant->nextInPreOrderAfterChildren(&object);
126 } 148 }
127 } 149 }
128 } 150 }
129 151
152 static void setPaintingLayerNeedsRepaintDuringTraverse(
153 const LayoutObject& object) {
154 if (object.hasLayer() &&
155 toLayoutBoxModelObject(object).hasSelfPaintingLayer()) {
156 toLayoutBoxModelObject(object).layer()->setNeedsRepaint();
157 } else if (object.isFloating() && object.parent() &&
158 !object.parent()->isLayoutBlock()) {
159 object.paintingLayer()->setNeedsRepaint();
160 }
161 }
162
130 void ObjectPaintInvalidator:: 163 void ObjectPaintInvalidator::
131 invalidateDisplayItemClientsIncludingNonCompositingDescendants( 164 invalidateDisplayItemClientsIncludingNonCompositingDescendants(
132 PaintInvalidationReason reason) { 165 PaintInvalidationReason reason) {
133 // This is valid because we want to invalidate the client in the display item 166 // This is valid because we want to invalidate the client in the display item
134 // list of the current backing. 167 // list of the current backing.
135 DisableCompositingQueryAsserts disabler; 168 DisableCompositingQueryAsserts disabler;
136 169
137 slowSetPaintingLayerNeedsRepaint(); 170 slowSetPaintingLayerNeedsRepaint();
138 traverseNonCompositingDescendantsInPaintOrder( 171 traverseNonCompositingDescendantsInPaintOrder(
139 m_object, [reason](const LayoutObject& object) { 172 m_object, [reason](const LayoutObject& object) {
140 if (object.hasLayer() && 173 setPaintingLayerNeedsRepaintDuringTraverse(object);
141 toLayoutBoxModelObject(object).hasSelfPaintingLayer())
142 toLayoutBoxModelObject(object).layer()->setNeedsRepaint();
143 object.invalidateDisplayItemClients(reason); 174 object.invalidateDisplayItemClients(reason);
144 }); 175 });
145 } 176 }
146 177
147 DISABLE_CFI_PERF 178 DISABLE_CFI_PERF
148 void ObjectPaintInvalidator::invalidatePaintOfPreviousVisualRect( 179 void ObjectPaintInvalidator::invalidatePaintOfPreviousVisualRect(
149 const LayoutBoxModelObject& paintInvalidationContainer, 180 const LayoutBoxModelObject& paintInvalidationContainer,
150 PaintInvalidationReason reason) { 181 PaintInvalidationReason reason) {
151 // It's caller's responsibility to ensure enclosingSelfPaintingLayer's 182 // It's caller's responsibility to ensure enclosingSelfPaintingLayer's
152 // needsRepaint is set. Don't set the flag here because getting 183 // needsRepaint is set. Don't set the flag here because getting
(...skipping 17 matching lines...) Expand all
170 // the new paint invalidation container happens to be the same as the old one. 201 // the new paint invalidation container happens to be the same as the old one.
171 m_object.getMutableForPainting().clearPreviousVisualRects(); 202 m_object.getMutableForPainting().clearPreviousVisualRects();
172 } 203 }
173 204
174 void ObjectPaintInvalidator:: 205 void ObjectPaintInvalidator::
175 invalidatePaintIncludingNonCompositingDescendants() { 206 invalidatePaintIncludingNonCompositingDescendants() {
176 // Since we're only painting non-composited layers, we know that they all 207 // Since we're only painting non-composited layers, we know that they all
177 // share the same paintInvalidationContainer. 208 // share the same paintInvalidationContainer.
178 const LayoutBoxModelObject& paintInvalidationContainer = 209 const LayoutBoxModelObject& paintInvalidationContainer =
179 m_object.containerForPaintInvalidation(); 210 m_object.containerForPaintInvalidation();
211 slowSetPaintingLayerNeedsRepaint();
180 traverseNonCompositingDescendantsInPaintOrder( 212 traverseNonCompositingDescendantsInPaintOrder(
181 m_object, [&paintInvalidationContainer](const LayoutObject& object) { 213 m_object, [&paintInvalidationContainer](const LayoutObject& object) {
182 if (object.hasLayer()) 214 setPaintingLayerNeedsRepaintDuringTraverse(object);
183 toLayoutBoxModelObject(object).layer()->setNeedsRepaint();
184 ObjectPaintInvalidator(object).invalidatePaintOfPreviousVisualRect( 215 ObjectPaintInvalidator(object).invalidatePaintOfPreviousVisualRect(
185 paintInvalidationContainer, PaintInvalidationSubtree); 216 paintInvalidationContainer, PaintInvalidationSubtree);
186 }); 217 });
187 } 218 }
188 219
189 void ObjectPaintInvalidator:: 220 void ObjectPaintInvalidator::
190 invalidatePaintIncludingNonSelfPaintingLayerDescendantsInternal( 221 invalidatePaintIncludingNonSelfPaintingLayerDescendantsInternal(
191 const LayoutBoxModelObject& paintInvalidationContainer) { 222 const LayoutBoxModelObject& paintInvalidationContainer) {
192 invalidatePaintOfPreviousVisualRect(paintInvalidationContainer, 223 invalidatePaintOfPreviousVisualRect(paintInvalidationContainer,
193 PaintInvalidationSubtree); 224 PaintInvalidationSubtree);
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 604
574 m_context.paintingLayer->setNeedsRepaint(); 605 m_context.paintingLayer->setNeedsRepaint();
575 m_object.invalidateDisplayItemClients(reason); 606 m_object.invalidateDisplayItemClients(reason);
576 return reason; 607 return reason;
577 } 608 }
578 609
579 DisablePaintInvalidationStateAsserts::DisablePaintInvalidationStateAsserts() 610 DisablePaintInvalidationStateAsserts::DisablePaintInvalidationStateAsserts()
580 : m_disabler(&gDisablePaintInvalidationStateAsserts, true) {} 611 : m_disabler(&gDisablePaintInvalidationStateAsserts, true) {}
581 612
582 } // namespace blink 613 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/paint/ObjectPaintInvalidatorTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698