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

Side by Side Diff: third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h

Issue 2546013002: Improve property under-invalidation DCHECKs in FindPropertiesNeedingUpdate (Closed)
Patch Set: Created 4 years 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 | no next file » | 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 #ifndef FindPropertiesNeedingUpdate_h 5 #ifndef FindPropertiesNeedingUpdate_h
6 #define FindPropertiesNeedingUpdate_h 6 #define FindPropertiesNeedingUpdate_h
7 7
8 #if DCHECK_IS_ON() 8 #if DCHECK_IS_ON()
9 namespace blink { 9 namespace blink {
10 10
11 #define DCHECK_PTR_VAL_EQ(ptrA, ptrB) \
12 DCHECK((!!ptrA == !!ptrB) && ((!ptrA && !ptrB) || (*ptrA == *ptrB)));
13
14 // This file contains two scope classes for catching cases where paint 11 // This file contains two scope classes for catching cases where paint
15 // properties need an update but where not marked as such. If paint properties 12 // properties need an update but where not marked as such. If paint properties
16 // will change, the object must be marked as needing a paint property update 13 // will change, the object must be marked as needing a paint property update
17 // using {FrameView, LayoutObject}::setNeedsPaintPropertyUpdate(). 14 // using {FrameView, LayoutObject}::setNeedsPaintPropertyUpdate() or by forcing
15 // a subtree update (see: PaintPropertyTreeBuilderContext::forceSubtreeupdate).
18 // 16 //
19 // Both scope classes work by recording the paint property state of an object 17 // Both scope classes work by recording the paint property state of an object
20 // before rebuilding properties, forcing the properties to get updated, then 18 // before rebuilding properties, forcing the properties to get updated, then
21 // checking that the updated properties match the original properties. 19 // checking that the updated properties match the original properties.
22 20
21 #define DCHECK_FRAMEVIEW_PROPERTY_EQ(original, updated) \
22 do { \
23 DCHECK(!!original == !!updated) << "Property was created or deleted " \
24 "without the FrameView needing a " \
25 "paint property update."; \
26 if (!!original && !!updated) { \
27 DCHECK(*original == *updated) << "Property was updated without the " \
28 "FrameView needing a paint property " \
29 "update."; \
30 } \
31 } while (0);
32
23 class FindFrameViewPropertiesNeedingUpdateScope { 33 class FindFrameViewPropertiesNeedingUpdateScope {
24 public: 34 public:
25 FindFrameViewPropertiesNeedingUpdateScope( 35 FindFrameViewPropertiesNeedingUpdateScope(
26 FrameView* frameView, 36 FrameView* frameView,
27 PaintPropertyTreeBuilderContext& context) 37 PaintPropertyTreeBuilderContext& context)
28 : m_frameView(frameView), 38 : m_frameView(frameView),
29 m_neededPaintPropertyUpdate(frameView->needsPaintPropertyUpdate()), 39 m_neededPaintPropertyUpdate(frameView->needsPaintPropertyUpdate()),
30 m_neededForcedSubtreeUpdate(context.forceSubtreeUpdate) { 40 m_neededForcedSubtreeUpdate(context.forceSubtreeUpdate) {
31 // No need to check if an update was already needed. 41 // No need to check if an update was already needed.
32 if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate) 42 if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate)
33 return; 43 return;
34 44
35 // Mark the properties as needing an update to ensure they are rebuilt. 45 // Mark the properties as needing an update to ensure they are rebuilt.
36 m_frameView->setOnlyThisNeedsPaintPropertyUpdateForTesting(); 46 m_frameView->setOnlyThisNeedsPaintPropertyUpdateForTesting();
37 47
38 if (auto* preTranslation = m_frameView->preTranslation()) 48 if (auto* preTranslation = m_frameView->preTranslation())
39 m_preTranslation = preTranslation->clone(); 49 m_originalPreTranslation = preTranslation->clone();
40 if (auto* contentClip = m_frameView->contentClip()) 50 if (auto* contentClip = m_frameView->contentClip())
41 m_contentClip = contentClip->clone(); 51 m_originalContentClip = contentClip->clone();
42 if (auto* scrollTranslation = m_frameView->scrollTranslation()) 52 if (auto* scrollTranslation = m_frameView->scrollTranslation())
43 m_scrollTranslation = scrollTranslation->clone(); 53 m_originalScrollTranslation = scrollTranslation->clone();
44 if (auto* scroll = m_frameView->scroll()) 54 if (auto* scroll = m_frameView->scroll())
45 m_scroll = scroll->clone(); 55 m_originalScroll = scroll->clone();
46 } 56 }
47 57
48 ~FindFrameViewPropertiesNeedingUpdateScope() { 58 ~FindFrameViewPropertiesNeedingUpdateScope() {
49 // No need to check if an update was already needed. 59 // No need to check if an update was already needed.
50 if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate) 60 if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate)
51 return; 61 return;
52 62
53 // If paint properties are not marked as needing an update but still change, 63 // If these checks fail, the paint properties should not have changed but
54 // we are missing a call to FrameView::setNeedsPaintPropertyUpdate(). 64 // did. This is due to missing one of these paint property invalidations:
55 DCHECK_PTR_VAL_EQ(m_preTranslation, m_frameView->preTranslation()); 65 // 1) The FrameView should have been marked as needing an update with
56 DCHECK_PTR_VAL_EQ(m_contentClip, m_frameView->contentClip()); 66 // FrameView::setNeedsPaintPropertyUpdate().
57 DCHECK_PTR_VAL_EQ(m_scrollTranslation, m_frameView->scrollTranslation()); 67 // 2) The PrePaintTreeWalk should have had a forced subtree update (see:
58 DCHECK_PTR_VAL_EQ(m_scroll, m_frameView->scroll()); 68 // PaintPropertyTreeBuilderContext::forceSubtreeupdate).
69 DCHECK_FRAMEVIEW_PROPERTY_EQ(m_originalPreTranslation,
70 m_frameView->preTranslation());
71 DCHECK_FRAMEVIEW_PROPERTY_EQ(m_originalContentClip,
72 m_frameView->contentClip());
73 DCHECK_FRAMEVIEW_PROPERTY_EQ(m_originalScrollTranslation,
74 m_frameView->scrollTranslation());
75 DCHECK_FRAMEVIEW_PROPERTY_EQ(m_originalScroll, m_frameView->scroll());
59 76
60 // Restore original clean bit. 77 // Restore original clean bit.
61 m_frameView->clearNeedsPaintPropertyUpdate(); 78 m_frameView->clearNeedsPaintPropertyUpdate();
62 } 79 }
63 80
64 private: 81 private:
65 Persistent<FrameView> m_frameView; 82 Persistent<FrameView> m_frameView;
66 bool m_neededPaintPropertyUpdate; 83 bool m_neededPaintPropertyUpdate;
67 bool m_neededForcedSubtreeUpdate; 84 bool m_neededForcedSubtreeUpdate;
68 RefPtr<TransformPaintPropertyNode> m_preTranslation; 85 RefPtr<TransformPaintPropertyNode> m_originalPreTranslation;
69 RefPtr<ClipPaintPropertyNode> m_contentClip; 86 RefPtr<ClipPaintPropertyNode> m_originalContentClip;
70 RefPtr<TransformPaintPropertyNode> m_scrollTranslation; 87 RefPtr<TransformPaintPropertyNode> m_originalScrollTranslation;
71 RefPtr<ScrollPaintPropertyNode> m_scroll; 88 RefPtr<ScrollPaintPropertyNode> m_originalScroll;
72 }; 89 };
73 90
91 #define DCHECK_OBJECT_PROPERTY_EQ(object, original, updated) \
92 do { \
93 DCHECK(!!original == !!updated) << "Property was created or deleted " \
94 "without the layout object (" \
95 << object.debugName() \
96 << ") needing a paint property update."; \
97 if (!!original && !!updated) { \
98 DCHECK(*original == *updated) << "Property was updated without the " \
99 "layout object (" \
100 << object.debugName() \
101 << ") needing a paint property update."; \
102 } \
103 } while (0);
104
74 class FindObjectPropertiesNeedingUpdateScope { 105 class FindObjectPropertiesNeedingUpdateScope {
75 public: 106 public:
76 FindObjectPropertiesNeedingUpdateScope( 107 FindObjectPropertiesNeedingUpdateScope(
77 const LayoutObject& object, 108 const LayoutObject& object,
78 PaintPropertyTreeBuilderContext& context) 109 PaintPropertyTreeBuilderContext& context)
79 : m_object(object), 110 : m_object(object),
80 m_neededPaintPropertyUpdate(object.needsPaintPropertyUpdate()), 111 m_neededPaintPropertyUpdate(object.needsPaintPropertyUpdate()),
81 m_neededForcedSubtreeUpdate(context.forceSubtreeUpdate) { 112 m_neededForcedSubtreeUpdate(context.forceSubtreeUpdate) {
82 // No need to check if an update was already needed. 113 // No need to check if an update was already needed.
83 if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate) 114 if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate)
84 return; 115 return;
85 116
86 // Mark the properties as needing an update to ensure they are rebuilt. 117 // Mark the properties as needing an update to ensure they are rebuilt.
87 const_cast<LayoutObject&>(m_object) 118 const_cast<LayoutObject&>(m_object)
88 .setOnlyThisNeedsPaintPropertyUpdateForTesting(); 119 .setOnlyThisNeedsPaintPropertyUpdateForTesting();
89 120
90 if (const auto* properties = m_object.paintProperties()) 121 if (const auto* properties = m_object.paintProperties())
91 m_properties = properties->clone(); 122 m_originalProperties = properties->clone();
92 } 123 }
93 124
94 ~FindObjectPropertiesNeedingUpdateScope() { 125 ~FindObjectPropertiesNeedingUpdateScope() {
95 // No need to check if an update was already needed. 126 // No need to check if an update was already needed.
96 if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate) 127 if (m_neededPaintPropertyUpdate || m_neededForcedSubtreeUpdate)
97 return; 128 return;
98 129
99 // If paint properties are not marked as needing an update but still change, 130 // If these checks fail, the paint properties should not have changed but
100 // we are missing a call to LayoutObject::setNeedsPaintPropertyUpdate(). 131 // did. This is due to missing one of these paint property invalidations:
132 // 1) The LayoutObject should have been marked as needing an update with
133 // LayoutObject::setNeedsPaintPropertyUpdate().
134 // 2) The PrePaintTreeWalk should have had a forced subtree update (see:
135 // PaintPropertyTreeBuilderContext::forceSubtreeupdate).
101 const auto* objectProperties = m_object.paintProperties(); 136 const auto* objectProperties = m_object.paintProperties();
102 if (m_properties && objectProperties) { 137 if (m_originalProperties && objectProperties) {
103 DCHECK_PTR_VAL_EQ(m_properties->paintOffsetTranslation(), 138 DCHECK_OBJECT_PROPERTY_EQ(m_object,
104 objectProperties->paintOffsetTranslation()); 139 m_originalProperties->paintOffsetTranslation(),
105 DCHECK_PTR_VAL_EQ(m_properties->transform(), 140 objectProperties->paintOffsetTranslation());
106 objectProperties->transform()); 141 DCHECK_OBJECT_PROPERTY_EQ(m_object, m_originalProperties->transform(),
107 DCHECK_PTR_VAL_EQ(m_properties->effect(), objectProperties->effect()); 142 objectProperties->transform());
108 DCHECK_PTR_VAL_EQ(m_properties->cssClip(), objectProperties->cssClip()); 143 DCHECK_OBJECT_PROPERTY_EQ(m_object, m_originalProperties->effect(),
109 DCHECK_PTR_VAL_EQ(m_properties->cssClipFixedPosition(), 144 objectProperties->effect());
110 objectProperties->cssClipFixedPosition()); 145 DCHECK_OBJECT_PROPERTY_EQ(m_object, m_originalProperties->cssClip(),
111 DCHECK_PTR_VAL_EQ(m_properties->innerBorderRadiusClip(), 146 objectProperties->cssClip());
112 objectProperties->innerBorderRadiusClip()); 147 DCHECK_OBJECT_PROPERTY_EQ(m_object,
113 DCHECK_PTR_VAL_EQ(m_properties->overflowClip(), 148 m_originalProperties->cssClipFixedPosition(),
114 objectProperties->overflowClip()); 149 objectProperties->cssClipFixedPosition());
115 DCHECK_PTR_VAL_EQ(m_properties->perspective(), 150 DCHECK_OBJECT_PROPERTY_EQ(m_object,
116 objectProperties->perspective()); 151 m_originalProperties->innerBorderRadiusClip(),
117 DCHECK_PTR_VAL_EQ(m_properties->svgLocalToBorderBoxTransform(), 152 objectProperties->innerBorderRadiusClip());
118 objectProperties->svgLocalToBorderBoxTransform()); 153 DCHECK_OBJECT_PROPERTY_EQ(m_object, m_originalProperties->overflowClip(),
119 DCHECK_PTR_VAL_EQ(m_properties->scrollTranslation(), 154 objectProperties->overflowClip());
120 objectProperties->scrollTranslation()); 155 DCHECK_OBJECT_PROPERTY_EQ(m_object, m_originalProperties->perspective(),
121 DCHECK_PTR_VAL_EQ(m_properties->scrollbarPaintOffset(), 156 objectProperties->perspective());
122 objectProperties->scrollbarPaintOffset()); 157 DCHECK_OBJECT_PROPERTY_EQ(
123 const auto* borderBox = m_properties->localBorderBoxProperties(); 158 m_object, m_originalProperties->svgLocalToBorderBoxTransform(),
159 objectProperties->svgLocalToBorderBoxTransform());
160 DCHECK_OBJECT_PROPERTY_EQ(m_object,
161 m_originalProperties->scrollTranslation(),
162 objectProperties->scrollTranslation());
163 DCHECK_OBJECT_PROPERTY_EQ(m_object,
164 m_originalProperties->scrollTranslation(),
165 objectProperties->scrollTranslation());
166 DCHECK_OBJECT_PROPERTY_EQ(m_object,
167 m_originalProperties->scrollbarPaintOffset(),
168 objectProperties->scrollbarPaintOffset());
169 const auto* originalBorderBox =
170 m_originalProperties->localBorderBoxProperties();
124 const auto* objectBorderBox = 171 const auto* objectBorderBox =
125 objectProperties->localBorderBoxProperties(); 172 objectProperties->localBorderBoxProperties();
126 if (borderBox && objectBorderBox) { 173 if (originalBorderBox && objectBorderBox) {
127 DCHECK(borderBox->paintOffset == objectBorderBox->paintOffset); 174 DCHECK(originalBorderBox->paintOffset == objectBorderBox->paintOffset)
128 DCHECK_EQ(borderBox->propertyTreeState.transform(), 175 << "Border box paint offset was updated without the layout object ("
129 objectBorderBox->propertyTreeState.transform()); 176 << m_object.debugName() << ") needing a paint property update.";
130 DCHECK_EQ(borderBox->propertyTreeState.clip(), 177 DCHECK_OBJECT_PROPERTY_EQ(
131 objectBorderBox->propertyTreeState.clip()); 178 m_object, originalBorderBox->propertyTreeState.transform(),
132 DCHECK_EQ(borderBox->propertyTreeState.effect(), 179 objectBorderBox->propertyTreeState.transform());
133 objectBorderBox->propertyTreeState.effect()); 180 DCHECK_OBJECT_PROPERTY_EQ(m_object,
134 DCHECK_EQ(borderBox->propertyTreeState.scroll(), 181 originalBorderBox->propertyTreeState.clip(),
135 objectBorderBox->propertyTreeState.scroll()); 182 objectBorderBox->propertyTreeState.clip());
183 DCHECK_OBJECT_PROPERTY_EQ(m_object,
184 originalBorderBox->propertyTreeState.effect(),
185 objectBorderBox->propertyTreeState.effect());
186 DCHECK_OBJECT_PROPERTY_EQ(m_object,
187 originalBorderBox->propertyTreeState.scroll(),
188 objectBorderBox->propertyTreeState.scroll());
136 } else { 189 } else {
137 DCHECK_EQ(!!borderBox, !!objectBorderBox); 190 DCHECK_EQ(!!originalBorderBox, !!objectBorderBox);
138 } 191 }
139 } else { 192 } else {
140 DCHECK_EQ(!!m_properties, !!objectProperties); 193 DCHECK_EQ(!!m_originalProperties, !!objectProperties);
141 } 194 }
142 // Restore original clean bit. 195 // Restore original clean bit.
143 const_cast<LayoutObject&>(m_object).clearNeedsPaintPropertyUpdate(); 196 const_cast<LayoutObject&>(m_object).clearNeedsPaintPropertyUpdate();
144 } 197 }
145 198
146 private: 199 private:
147 const LayoutObject& m_object; 200 const LayoutObject& m_object;
148 bool m_neededPaintPropertyUpdate; 201 bool m_neededPaintPropertyUpdate;
149 bool m_neededForcedSubtreeUpdate; 202 bool m_neededForcedSubtreeUpdate;
150 std::unique_ptr<const ObjectPaintProperties> m_properties; 203 std::unique_ptr<const ObjectPaintProperties> m_originalProperties;
151 }; 204 };
152 205
153 } // namespace blink 206 } // namespace blink
154 #endif // DCHECK_IS_ON() 207 #endif // DCHECK_IS_ON()
155 208
156 #endif // FindPropertiesNeedingUpdate_h 209 #endif // FindPropertiesNeedingUpdate_h
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698