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

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

Issue 2639283003: Fix traverseNonCompositingDescendantsInPaintOrder for float-under-inline cases (Closed)
Patch Set: - Created 3 years, 11 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-flow, 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
chrishtr 2017/01/21 04:01:04 Add an example of why non-block-flow elements migh
Xianzhu 2017/01/24 06:38:39 Done.
73 // descendants. 73 // function traverses all such descendants.
74 DCHECK(object.isPaintInvalidationContainer() && 74 DCHECK(object.isPaintInvalidationContainer() &&
75 !object.styleRef().isStackingContext()); 75 (!object.styleRef().isStackingContext() || !object.isLayoutBlock()));
76 76
77 LayoutObject* descendant = object.nextInPreOrder(&object); 77 LayoutObject* descendant = object.nextInPreOrder(&object);
78 while (descendant) { 78 while (descendant) {
79 if (!descendant->hasLayer() || !descendant->styleRef().isStacked()) { 79 if (!descendant->hasLayer() || !descendant->styleRef().isStacked()) {
80 // Case 1: The descendant is not stacked (or is stacked but has not been 80 // 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 81 // 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 82 // invalidation container in the same situation as |object|, or its paint
83 // invalidation container is in such situation. Keep searching until a 83 // invalidation container is in such situation. Keep searching until a
84 // stacked layer is found. 84 // stacked layer is found.
85 descendant = descendant->nextInPreOrder(&object); 85 if (!object.isLayoutBlock() && descendant->isFloating()) {
86 // Case 1a (rare): However, if the descendant is a floating object below
87 // a composited non-block object, the subtree may belong to an ancestor
88 // in paint order, thus recur into the subtree. Note that for
89 // performance, we don't check whether the floating object's container
90 // is above or under |object|, so we may traverse more than expected.
91 traverseNonCompositingDescendantsInPaintOrder(*descendant, functor);
92 descendant = descendant->nextInPreOrderAfterChildren(&object);
93 } else {
94 descendant = descendant->nextInPreOrder(&object);
95 }
86 } else if (!descendant->isPaintInvalidationContainer()) { 96 } else if (!descendant->isPaintInvalidationContainer()) {
87 // Case 2: The descendant is stacked and is not composited. 97 // Case 2: The descendant is stacked and is not composited.
88 // The invalidation container of its subtree is our ancestor, 98 // The invalidation container of its subtree is our ancestor,
89 // thus recur into the subtree. 99 // thus recur into the subtree.
90 traverseNonCompositingDescendantsInPaintOrder(*descendant, functor); 100 traverseNonCompositingDescendantsInPaintOrder(*descendant, functor);
91 descendant = descendant->nextInPreOrderAfterChildren(&object); 101 descendant = descendant->nextInPreOrderAfterChildren(&object);
92 } else if (descendant->styleRef().isStackingContext()) { 102 } else if (descendant->styleRef().isStackingContext() &&
103 descendant->isLayoutBlock()) {
93 // Case 3: The descendant is an invalidation container and is a stacking 104 // Case 3: The descendant is an invalidation container and is a stacking
94 // context. No objects in the subtree can have invalidation container 105 // context. No objects in the subtree can have invalidation container
95 // outside of it, thus skip the whole subtree. 106 // outside of it, thus skip the whole subtree.
107 // This excludes non-block because there might be floating objects under
108 // the descendant belonging to some ancestor in paint order.
96 descendant = descendant->nextInPreOrderAfterChildren(&object); 109 descendant = descendant->nextInPreOrderAfterChildren(&object);
97 } else { 110 } else {
98 // Case 4: The descendant is an invalidation container but not a stacking 111 // Case 4: The descendant is an invalidation container but not a stacking
99 // context. This is the same situation as |object|, thus keep searching. 112 // context, or the descendant is a non-block stacking context.
113 // This is the same situation as |object|, thus keep searching.
100 descendant = descendant->nextInPreOrder(&object); 114 descendant = descendant->nextInPreOrder(&object);
101 } 115 }
102 } 116 }
103 } 117 }
104 118
105 template <typename LayoutObjectTraversalFunctor> 119 static void traverseNonCompositingDescendantsInPaintOrder(
106 void traverseNonCompositingDescendantsInPaintOrder(
107 const LayoutObject& object, 120 const LayoutObject& object,
108 const LayoutObjectTraversalFunctor& functor) { 121 const LayoutObjectTraversalFunctor& functor) {
109 functor(object); 122 functor(object);
110 LayoutObject* descendant = object.nextInPreOrder(&object); 123 LayoutObject* descendant = object.nextInPreOrder(&object);
111 while (descendant) { 124 while (descendant) {
112 if (!descendant->isPaintInvalidationContainer()) { 125 if (!descendant->isPaintInvalidationContainer()) {
113 functor(*descendant); 126 functor(*descendant);
114 descendant = descendant->nextInPreOrder(&object); 127 descendant = descendant->nextInPreOrder(&object);
115 } else if (descendant->styleRef().isStackingContext()) { 128 } else if (descendant->styleRef().isStackingContext() &&
129 descendant->isLayoutBlock()) {
116 // The descendant is an invalidation container and is a stacking context. 130 // The descendant is an invalidation container and is a stacking context.
117 // No objects in the subtree can have invalidation container outside of 131 // No objects in the subtree can have invalidation container outside of
118 // it, thus skip the whole subtree. 132 // it, thus skip the whole subtree.
133 // This excludes non-blocks because there might be floating objects under
134 // the descendant belonging to some ancestor in paint order.
119 descendant = descendant->nextInPreOrderAfterChildren(&object); 135 descendant = descendant->nextInPreOrderAfterChildren(&object);
120 } else { 136 } else {
121 // If a paint invalidation container is not a stacking context, 137 // If a paint invalidation container is not a stacking context, or the
122 // some of its descendants may belong to the parent container. 138 // descendant is a non-block stacking context, some of its descendants may
139 // belong to the parent container.
123 traverseNonCompositingDescendantsBelongingToAncestorPaintInvalidationConta iner( 140 traverseNonCompositingDescendantsBelongingToAncestorPaintInvalidationConta iner(
124 *descendant, functor); 141 *descendant, functor);
125 descendant = descendant->nextInPreOrderAfterChildren(&object); 142 descendant = descendant->nextInPreOrderAfterChildren(&object);
126 } 143 }
127 } 144 }
128 } 145 }
129 146
147 static void setPaintingLayerNeedsRepaintDuringTraverse(
148 const LayoutObject& object) {
149 if (object.hasLayer() &&
150 toLayoutBoxModelObject(object).hasSelfPaintingLayer()) {
151 toLayoutBoxModelObject(object).layer()->setNeedsRepaint();
152 } else if (object.isFloating() && object.parent() &&
153 !object.parent()->canContainFloatingObject(object)) {
154 object.paintingLayer()->setNeedsRepaint();
155 }
156 }
157
130 void ObjectPaintInvalidator:: 158 void ObjectPaintInvalidator::
131 invalidateDisplayItemClientsIncludingNonCompositingDescendants( 159 invalidateDisplayItemClientsIncludingNonCompositingDescendants(
132 PaintInvalidationReason reason) { 160 PaintInvalidationReason reason) {
133 // This is valid because we want to invalidate the client in the display item 161 // This is valid because we want to invalidate the client in the display item
134 // list of the current backing. 162 // list of the current backing.
135 DisableCompositingQueryAsserts disabler; 163 DisableCompositingQueryAsserts disabler;
136 164
137 slowSetPaintingLayerNeedsRepaint(); 165 slowSetPaintingLayerNeedsRepaint();
138 traverseNonCompositingDescendantsInPaintOrder( 166 traverseNonCompositingDescendantsInPaintOrder(
139 m_object, [reason](const LayoutObject& object) { 167 m_object, [reason](const LayoutObject& object) {
140 if (object.hasLayer() && 168 setPaintingLayerNeedsRepaintDuringTraverse(object);
141 toLayoutBoxModelObject(object).hasSelfPaintingLayer())
142 toLayoutBoxModelObject(object).layer()->setNeedsRepaint();
143 object.invalidateDisplayItemClients(reason); 169 object.invalidateDisplayItemClients(reason);
144 }); 170 });
145 } 171 }
146 172
147 DISABLE_CFI_PERF 173 DISABLE_CFI_PERF
148 void ObjectPaintInvalidator::invalidatePaintOfPreviousVisualRect( 174 void ObjectPaintInvalidator::invalidatePaintOfPreviousVisualRect(
149 const LayoutBoxModelObject& paintInvalidationContainer, 175 const LayoutBoxModelObject& paintInvalidationContainer,
150 PaintInvalidationReason reason) { 176 PaintInvalidationReason reason) {
151 // It's caller's responsibility to ensure enclosingSelfPaintingLayer's 177 // It's caller's responsibility to ensure enclosingSelfPaintingLayer's
152 // needsRepaint is set. Don't set the flag here because getting 178 // 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. 196 // the new paint invalidation container happens to be the same as the old one.
171 m_object.getMutableForPainting().clearPreviousVisualRects(); 197 m_object.getMutableForPainting().clearPreviousVisualRects();
172 } 198 }
173 199
174 void ObjectPaintInvalidator:: 200 void ObjectPaintInvalidator::
175 invalidatePaintIncludingNonCompositingDescendants() { 201 invalidatePaintIncludingNonCompositingDescendants() {
176 // Since we're only painting non-composited layers, we know that they all 202 // Since we're only painting non-composited layers, we know that they all
177 // share the same paintInvalidationContainer. 203 // share the same paintInvalidationContainer.
178 const LayoutBoxModelObject& paintInvalidationContainer = 204 const LayoutBoxModelObject& paintInvalidationContainer =
179 m_object.containerForPaintInvalidation(); 205 m_object.containerForPaintInvalidation();
206 slowSetPaintingLayerNeedsRepaint();
180 traverseNonCompositingDescendantsInPaintOrder( 207 traverseNonCompositingDescendantsInPaintOrder(
181 m_object, [&paintInvalidationContainer](const LayoutObject& object) { 208 m_object, [&paintInvalidationContainer](const LayoutObject& object) {
182 if (object.hasLayer()) 209 setPaintingLayerNeedsRepaintDuringTraverse(object);
183 toLayoutBoxModelObject(object).layer()->setNeedsRepaint();
184 ObjectPaintInvalidator(object).invalidatePaintOfPreviousVisualRect( 210 ObjectPaintInvalidator(object).invalidatePaintOfPreviousVisualRect(
185 paintInvalidationContainer, PaintInvalidationSubtree); 211 paintInvalidationContainer, PaintInvalidationSubtree);
186 }); 212 });
187 } 213 }
188 214
189 void ObjectPaintInvalidator:: 215 void ObjectPaintInvalidator::
190 invalidatePaintIncludingNonSelfPaintingLayerDescendantsInternal( 216 invalidatePaintIncludingNonSelfPaintingLayerDescendantsInternal(
191 const LayoutBoxModelObject& paintInvalidationContainer) { 217 const LayoutBoxModelObject& paintInvalidationContainer) {
192 invalidatePaintOfPreviousVisualRect(paintInvalidationContainer, 218 invalidatePaintOfPreviousVisualRect(paintInvalidationContainer,
193 PaintInvalidationSubtree); 219 PaintInvalidationSubtree);
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 599
574 m_context.paintingLayer->setNeedsRepaint(); 600 m_context.paintingLayer->setNeedsRepaint();
575 m_object.invalidateDisplayItemClients(reason); 601 m_object.invalidateDisplayItemClients(reason);
576 return reason; 602 return reason;
577 } 603 }
578 604
579 DisablePaintInvalidationStateAsserts::DisablePaintInvalidationStateAsserts() 605 DisablePaintInvalidationStateAsserts::DisablePaintInvalidationStateAsserts()
580 : m_disabler(&gDisablePaintInvalidationStateAsserts, true) {} 606 : m_disabler(&gDisablePaintInvalidationStateAsserts, true) {}
581 607
582 } // namespace blink 608 } // 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