| OLD | NEW |
| 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 |
| OLD | NEW |