| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/layout/PaintInvalidationState.h" | 5 #include "core/layout/PaintInvalidationState.h" |
| 6 | 6 |
| 7 #include "core/frame/FrameView.h" | 7 #include "core/frame/FrameView.h" |
| 8 #include "core/frame/Settings.h" | 8 #include "core/frame/Settings.h" |
| 9 #include "core/layout/LayoutInline.h" | 9 #include "core/layout/LayoutInline.h" |
| 10 #include "core/layout/LayoutPart.h" | 10 #include "core/layout/LayoutPart.h" |
| 11 #include "core/layout/LayoutView.h" | 11 #include "core/layout/LayoutView.h" |
| 12 #include "core/layout/svg/LayoutSVGModelObject.h" | 12 #include "core/layout/svg/LayoutSVGModelObject.h" |
| 13 #include "core/layout/svg/LayoutSVGRoot.h" | 13 #include "core/layout/svg/LayoutSVGRoot.h" |
| 14 #include "core/layout/svg/SVGLayoutSupport.h" | 14 #include "core/layout/svg/SVGLayoutSupport.h" |
| 15 #include "core/paint/PaintLayer.h" | 15 #include "core/paint/PaintLayer.h" |
| 16 | 16 |
| 17 // We can't enable this by default because saturated operations of LayoutUnit | |
| 18 // don't conform commutative law for overflowing results, preventing us from | |
| 19 // making fast path and slow path always return the same result. | |
| 20 #define ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH (0 && ENABLE(ASSERT)) | |
| 21 | |
| 22 namespace blink { | 17 namespace blink { |
| 23 | 18 |
| 24 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH | |
| 25 // Make sure that the fast path and the slow path generate the same rect. | |
| 26 void assertRectsEqual(const LayoutObject& object, const LayoutBoxModelObject& an
cestor, const LayoutRect& rect, const LayoutRect& slowPathRect) | |
| 27 { | |
| 28 // TODO(wangxianzhu): This is for cases that a sub-frame creates a root Pain
tInvalidationState | |
| 29 // which doesn't inherit clip from ancestor frames. | |
| 30 // Remove the condition when we eliminate the latter case of PaintInvalidati
onState(const LayoutView&, ...). | |
| 31 if (object.isLayoutView()) | |
| 32 return; | |
| 33 | |
| 34 // We ignore ancestor clipping for FixedPosition in fast path. | |
| 35 if (object.styleRef().position() == FixedPosition) | |
| 36 return; | |
| 37 | |
| 38 // TODO(crbug.com/597903): Fast path and slow path should generate equal emp
ty rects. | |
| 39 if (rect.isEmpty() && slowPathRect.isEmpty()) | |
| 40 return; | |
| 41 | |
| 42 if (rect == slowPathRect) | |
| 43 return; | |
| 44 | |
| 45 // Tolerate the difference between the two paths when crossing frame boundar
ies. | |
| 46 if (object.view() != ancestor.view()) { | |
| 47 LayoutRect inflatedRect = rect; | |
| 48 inflatedRect.inflate(1); | |
| 49 if (inflatedRect.contains(slowPathRect)) | |
| 50 return; | |
| 51 LayoutRect inflatedSlowPathRect = slowPathRect; | |
| 52 inflatedSlowPathRect.inflate(1); | |
| 53 if (inflatedSlowPathRect.contains(rect)) | |
| 54 return; | |
| 55 } | |
| 56 | |
| 57 #ifndef NDEBUG | |
| 58 WTFLogAlways("Fast path paint invalidation rect differs from slow path: %s v
s %s", rect.toString().ascii().data(), slowPathRect.toString().ascii().data()); | |
| 59 showLayoutTree(&object); | |
| 60 #endif | |
| 61 ASSERT_NOT_REACHED(); | |
| 62 } | |
| 63 #endif | |
| 64 | |
| 65 static bool supportsCachedOffsets(const LayoutObject& object) | 19 static bool supportsCachedOffsets(const LayoutObject& object) |
| 66 { | 20 { |
| 67 return !object.hasTransformRelatedProperty() | 21 return !object.hasTransformRelatedProperty() |
| 68 && !object.hasReflection() | 22 && !object.hasReflection() |
| 69 && !object.hasFilterInducingProperty() | 23 && !object.hasFilterInducingProperty() |
| 70 && !object.isLayoutFlowThread() | 24 && !object.isLayoutFlowThread() |
| 71 && !object.isLayoutMultiColumnSpannerPlaceholder() | 25 && !object.isLayoutMultiColumnSpannerPlaceholder() |
| 72 && !object.styleRef().isFlippedBlocksWritingMode() | 26 && !object.styleRef().isFlippedBlocksWritingMode() |
| 73 && !(object.isLayoutBlock() && object.isSVG()); | 27 && !(object.isLayoutBlock() && object.isSVG()); |
| 74 } | 28 } |
| 75 | 29 |
| 76 PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vec
tor<LayoutObject*>& pendingDelayedPaintInvalidations) | 30 PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vec
tor<LayoutObject*>& pendingDelayedPaintInvalidations) |
| 77 : m_currentObject(layoutView) | 31 : m_currentObject(layoutView) |
| 78 , m_forcedSubtreeInvalidationWithinContainer(false) | 32 , m_forcedSubtreeInvalidationWithinContainer(false) |
| 79 , m_forcedSubtreeInvalidationRectUpdateWithinContainer(false) | 33 , m_forcedSubtreeInvalidationRectUpdateWithinContainer(false) |
| 80 , m_clipped(false) | 34 , m_clipped(false) |
| 81 , m_clippedForAbsolutePosition(false) | 35 , m_clippedForAbsolutePosition(false) |
| 82 , m_cachedOffsetsEnabled(true) | 36 , m_cachedOffsetsEnabled(true) |
| 83 , m_cachedOffsetsForAbsolutePositionEnabled(true) | 37 , m_cachedOffsetsForAbsolutePositionEnabled(true) |
| 84 , m_paintInvalidationContainer(&layoutView.containerForPaintInvalidation()) | 38 , m_paintInvalidationContainer(&layoutView.containerForPaintInvalidation()) |
| 85 , m_paintInvalidationContainerForStackedContents(m_paintInvalidationContaine
r) | 39 , m_paintInvalidationContainerForStackedContents(m_paintInvalidationContaine
r) |
| 86 , m_containerForAbsolutePosition(layoutView) | 40 , m_containerForAbsolutePosition(layoutView) |
| 87 , m_pendingDelayedPaintInvalidations(pendingDelayedPaintInvalidations) | 41 , m_pendingDelayedPaintInvalidations(pendingDelayedPaintInvalidations) |
| 88 , m_enclosingSelfPaintingLayer(*layoutView.layer()) | 42 , m_enclosingSelfPaintingLayer(*layoutView.layer()) |
| 89 #if ENABLE(ASSERT) | 43 #if ENABLE(ASSERT) |
| 90 , m_didUpdateForChildren(false) | 44 , m_didUpdateForChildren(false) |
| 91 #endif | 45 #endif |
| 46 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY |
| 47 , m_canCheckFastPathSlowPathEquality(layoutView == m_paintInvalidationContai
ner) |
| 48 #endif |
| 92 { | 49 { |
| 93 if (!supportsCachedOffsets(layoutView)) { | 50 if (!supportsCachedOffsets(layoutView)) { |
| 94 m_cachedOffsetsEnabled = false; | 51 m_cachedOffsetsEnabled = false; |
| 95 return; | 52 return; |
| 96 } | 53 } |
| 97 | 54 |
| 98 FloatPoint point = layoutView.localToAncestorPoint(FloatPoint(), m_paintInva
lidationContainer, TraverseDocumentBoundaries | InputIsInFrameCoordinates); | 55 FloatPoint point = layoutView.localToAncestorPoint(FloatPoint(), m_paintInva
lidationContainer, TraverseDocumentBoundaries | InputIsInFrameCoordinates); |
| 99 m_paintOffset = LayoutSize(point.x(), point.y()); | 56 m_paintOffset = LayoutSize(point.x(), point.y()); |
| 100 m_paintOffsetForAbsolutePosition = m_paintOffset; | 57 m_paintOffsetForAbsolutePosition = m_paintOffset; |
| 101 } | 58 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 114 , m_cachedOffsetsForAbsolutePositionEnabled(parentState.m_cachedOffsetsForAb
solutePositionEnabled) | 71 , m_cachedOffsetsForAbsolutePositionEnabled(parentState.m_cachedOffsetsForAb
solutePositionEnabled) |
| 115 , m_paintInvalidationContainer(parentState.m_paintInvalidationContainer) | 72 , m_paintInvalidationContainer(parentState.m_paintInvalidationContainer) |
| 116 , m_paintInvalidationContainerForStackedContents(parentState.m_paintInvalida
tionContainerForStackedContents) | 73 , m_paintInvalidationContainerForStackedContents(parentState.m_paintInvalida
tionContainerForStackedContents) |
| 117 , m_containerForAbsolutePosition(currentObject.canContainAbsolutePositionObj
ects() ? currentObject : parentState.m_containerForAbsolutePosition) | 74 , m_containerForAbsolutePosition(currentObject.canContainAbsolutePositionObj
ects() ? currentObject : parentState.m_containerForAbsolutePosition) |
| 118 , m_svgTransform(parentState.m_svgTransform) | 75 , m_svgTransform(parentState.m_svgTransform) |
| 119 , m_pendingDelayedPaintInvalidations(parentState.pendingDelayedPaintInvalida
tionTargets()) | 76 , m_pendingDelayedPaintInvalidations(parentState.pendingDelayedPaintInvalida
tionTargets()) |
| 120 , m_enclosingSelfPaintingLayer(parentState.enclosingSelfPaintingLayer(curren
tObject)) | 77 , m_enclosingSelfPaintingLayer(parentState.enclosingSelfPaintingLayer(curren
tObject)) |
| 121 #if ENABLE(ASSERT) | 78 #if ENABLE(ASSERT) |
| 122 , m_didUpdateForChildren(false) | 79 , m_didUpdateForChildren(false) |
| 123 #endif | 80 #endif |
| 81 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY |
| 82 , m_canCheckFastPathSlowPathEquality(parentState.m_canCheckFastPathSlowPathE
quality) |
| 83 #endif |
| 124 { | 84 { |
| 125 if (currentObject == parentState.m_currentObject) { | 85 if (currentObject == parentState.m_currentObject) { |
| 126 // Sometimes we create a new PaintInvalidationState from parentState on
the same object | 86 // Sometimes we create a new PaintInvalidationState from parentState on
the same object |
| 127 // (e.g. LayoutView, and the HorriblySlowRectMapping cases in LayoutBloc
k::invalidatePaintOfSubtreesIfNeeded()). | 87 // (e.g. LayoutView, and the HorriblySlowRectMapping cases in LayoutBloc
k::invalidatePaintOfSubtreesIfNeeded()). |
| 128 // TODO(wangxianzhu): Avoid this for RuntimeEnabledFeatures::slimmingPai
ntInvalidationEnabled(). | 88 // TODO(wangxianzhu): Avoid this for RuntimeEnabledFeatures::slimmingPai
ntInvalidationEnabled(). |
| 129 #if ENABLE(ASSERT) | 89 #if ENABLE(ASSERT) |
| 130 m_didUpdateForChildren = parentState.m_didUpdateForChildren; | 90 m_didUpdateForChildren = parentState.m_didUpdateForChildren; |
| 131 #endif | 91 #endif |
| 132 return; | 92 return; |
| 133 } | 93 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 // from the original paintInvalidationContainerForStackingContents,
then use this paint offset to adjust | 154 // from the original paintInvalidationContainerForStackingContents,
then use this paint offset to adjust |
| 195 // m_paintOffsetForAbsolutePosition. | 155 // m_paintOffsetForAbsolutePosition. |
| 196 updateForCurrentObject(parentState); | 156 updateForCurrentObject(parentState); |
| 197 m_paintOffsetForAbsolutePosition -= m_paintOffset; | 157 m_paintOffsetForAbsolutePosition -= m_paintOffset; |
| 198 if (m_clippedForAbsolutePosition) | 158 if (m_clippedForAbsolutePosition) |
| 199 m_clipRectForAbsolutePosition.move(-m_paintOffset); | 159 m_clipRectForAbsolutePosition.move(-m_paintOffset); |
| 200 } | 160 } |
| 201 | 161 |
| 202 m_clipped = false; // Will be updated in updateForChildren(). | 162 m_clipped = false; // Will be updated in updateForChildren(). |
| 203 m_paintOffset = LayoutSize(); | 163 m_paintOffset = LayoutSize(); |
| 164 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY |
| 165 m_canCheckFastPathSlowPathEquality = true; |
| 166 #endif |
| 204 return; | 167 return; |
| 205 } | 168 } |
| 206 | 169 |
| 207 updateForCurrentObject(parentState); | 170 updateForCurrentObject(parentState); |
| 208 } | 171 } |
| 209 | 172 |
| 210 void PaintInvalidationState::updateForCurrentObject(const PaintInvalidationState
& parentState) | 173 void PaintInvalidationState::updateForCurrentObject(const PaintInvalidationState
& parentState) |
| 211 { | 174 { |
| 212 if (!m_cachedOffsetsEnabled) | 175 if (!m_cachedOffsetsEnabled) |
| 213 return; | 176 return; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 228 // is under the containing LayoutView. | 191 // is under the containing LayoutView. |
| 229 m_cachedOffsetsEnabled = false; | 192 m_cachedOffsetsEnabled = false; |
| 230 return; | 193 return; |
| 231 } | 194 } |
| 232 // Use slow path to get the offset of the fixed-position, and enable fas
t path for descendants. | 195 // Use slow path to get the offset of the fixed-position, and enable fas
t path for descendants. |
| 233 FloatPoint fixedOffset = m_currentObject.localToAncestorPoint(FloatPoint
(), m_paintInvalidationContainer, TraverseDocumentBoundaries); | 196 FloatPoint fixedOffset = m_currentObject.localToAncestorPoint(FloatPoint
(), m_paintInvalidationContainer, TraverseDocumentBoundaries); |
| 234 m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()); | 197 m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()); |
| 235 // In the above way to get paint offset, we can't get accurate clip rect
, so just assume no clip. | 198 // In the above way to get paint offset, we can't get accurate clip rect
, so just assume no clip. |
| 236 // Clip on fixed-position is rare, in case that paintInvalidationContain
er crosses frame boundary | 199 // Clip on fixed-position is rare, in case that paintInvalidationContain
er crosses frame boundary |
| 237 // and the LayoutView is clipped by something in owner document. | 200 // and the LayoutView is clipped by something in owner document. |
| 238 m_clipped = false; | 201 if (m_clipped) { |
| 202 m_clipped = false; |
| 203 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY |
| 204 m_canCheckFastPathSlowPathEquality = false; |
| 205 #endif |
| 206 } |
| 239 return; | 207 return; |
| 240 } | 208 } |
| 241 | 209 |
| 242 if (position == AbsolutePosition) { | 210 if (position == AbsolutePosition) { |
| 243 m_cachedOffsetsEnabled = m_cachedOffsetsForAbsolutePositionEnabled; | 211 m_cachedOffsetsEnabled = m_cachedOffsetsForAbsolutePositionEnabled; |
| 244 if (!m_cachedOffsetsEnabled) | 212 if (!m_cachedOffsetsEnabled) |
| 245 return; | 213 return; |
| 246 | 214 |
| 247 m_paintOffset = m_paintOffsetForAbsolutePosition; | 215 m_paintOffset = m_paintOffsetForAbsolutePosition; |
| 248 m_clipped = m_clippedForAbsolutePosition; | 216 m_clipped = m_clippedForAbsolutePosition; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 LayoutPoint PaintInvalidationState::computePositionFromPaintInvalidationBacking(
) const | 309 LayoutPoint PaintInvalidationState::computePositionFromPaintInvalidationBacking(
) const |
| 342 { | 310 { |
| 343 ASSERT(!m_didUpdateForChildren); | 311 ASSERT(!m_didUpdateForChildren); |
| 344 | 312 |
| 345 FloatPoint point; | 313 FloatPoint point; |
| 346 if (m_paintInvalidationContainer != &m_currentObject) { | 314 if (m_paintInvalidationContainer != &m_currentObject) { |
| 347 if (m_cachedOffsetsEnabled) { | 315 if (m_cachedOffsetsEnabled) { |
| 348 if (m_currentObject.isSVG() && !m_currentObject.isSVGRoot()) | 316 if (m_currentObject.isSVG() && !m_currentObject.isSVGRoot()) |
| 349 point = m_svgTransform.mapPoint(point); | 317 point = m_svgTransform.mapPoint(point); |
| 350 point += FloatPoint(m_paintOffset); | 318 point += FloatPoint(m_paintOffset); |
| 351 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH | 319 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY |
| 352 // TODO(wangxianzhu): We can't enable this ASSERT for now because of
crbug.com/597745. | 320 // TODO(wangxianzhu): We can't enable this ASSERT for now because of
crbug.com/597745. |
| 353 // ASSERT(point == slowLocalOriginToAncestorPoint(m_currentObject, m
_paintInvalidationContainer, FloatPoint()); | 321 // ASSERT(point == slowLocalOriginToAncestorPoint(m_currentObject, m
_paintInvalidationContainer, FloatPoint()); |
| 354 #endif | 322 #endif |
| 355 } else { | 323 } else { |
| 356 point = slowLocalToAncestorPoint(m_currentObject, *m_paintInvalidati
onContainer, FloatPoint()); | 324 point = slowLocalToAncestorPoint(m_currentObject, *m_paintInvalidati
onContainer, FloatPoint()); |
| 357 } | 325 } |
| 358 } | 326 } |
| 359 | 327 |
| 360 if (m_paintInvalidationContainer->layer()->groupedMapping()) | 328 if (m_paintInvalidationContainer->layer()->groupedMapping()) |
| 361 PaintLayer::mapPointInPaintInvalidationContainerToBacking(*m_paintInvali
dationContainer, point); | 329 PaintLayer::mapPointInPaintInvalidationContainerToBacking(*m_paintInvali
dationContainer, point); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 377 | 345 |
| 378 LayoutRect PaintInvalidationState::computePaintInvalidationRectInBackingForSVG()
const | 346 LayoutRect PaintInvalidationState::computePaintInvalidationRectInBackingForSVG()
const |
| 379 { | 347 { |
| 380 LayoutRect rect; | 348 LayoutRect rect; |
| 381 if (m_cachedOffsetsEnabled) { | 349 if (m_cachedOffsetsEnabled) { |
| 382 FloatRect svgRect = SVGLayoutSupport::localOverflowRectForPaintInvalidat
ion(m_currentObject); | 350 FloatRect svgRect = SVGLayoutSupport::localOverflowRectForPaintInvalidat
ion(m_currentObject); |
| 383 rect = SVGLayoutSupport::transformPaintInvalidationRect(m_currentObject,
m_svgTransform, svgRect); | 351 rect = SVGLayoutSupport::transformPaintInvalidationRect(m_currentObject,
m_svgTransform, svgRect); |
| 384 rect.move(m_paintOffset); | 352 rect.move(m_paintOffset); |
| 385 if (m_clipped) | 353 if (m_clipped) |
| 386 rect.intersect(m_clipRect); | 354 rect.intersect(m_clipRect); |
| 387 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH | 355 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY |
| 388 LayoutRect slowPathRect = SVGLayoutSupport::clippedOverflowRectForPaintI
nvalidation(m_currentObject, *m_paintInvalidationContainer); | 356 LayoutRect slowPathRect = SVGLayoutSupport::clippedOverflowRectForPaintI
nvalidation(m_currentObject, *m_paintInvalidationContainer); |
| 389 assertRectsEqual(m_currentObject, m_paintInvalidationContainer, rect, sl
owPathRect); | 357 assertFastPathAndSlowPathRectsEqual(rect, slowPathRect); |
| 390 #endif | 358 #endif |
| 391 } else { | 359 } else { |
| 392 // TODO(wangxianzhu): Sometimes m_cachedOffsetsEnabled==false doesn't me
an we can't use cached | 360 // TODO(wangxianzhu): Sometimes m_cachedOffsetsEnabled==false doesn't me
an we can't use cached |
| 393 // m_svgTransform. We can use hybrid fast path (for SVG) and slow path (
for things above the SVGRoot). | 361 // m_svgTransform. We can use hybrid fast path (for SVG) and slow path (
for things above the SVGRoot). |
| 394 rect = SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(m_curre
ntObject, *m_paintInvalidationContainer); | 362 rect = SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(m_curre
ntObject, *m_paintInvalidationContainer); |
| 395 } | 363 } |
| 396 | 364 |
| 397 if (m_paintInvalidationContainer->layer()->groupedMapping()) | 365 if (m_paintInvalidationContainer->layer()->groupedMapping()) |
| 398 PaintLayer::mapRectInPaintInvalidationContainerToBacking(*m_paintInvalid
ationContainer, rect); | 366 PaintLayer::mapRectInPaintInvalidationContainerToBacking(*m_paintInvalid
ationContainer, rect); |
| 399 return rect; | 367 return rect; |
| 400 } | 368 } |
| 401 | 369 |
| 402 static void slowMapToVisualRectInAncestorSpace(const LayoutObject& object, const
LayoutBoxModelObject& ancestor, LayoutRect& rect) | 370 static void slowMapToVisualRectInAncestorSpace(const LayoutObject& object, const
LayoutBoxModelObject& ancestor, LayoutRect& rect) |
| 403 { | 371 { |
| 404 if (object.isLayoutView()) | 372 if (object.isLayoutView()) |
| 405 toLayoutView(object).mapToVisualRectInAncestorSpace(&ancestor, rect, Inp
utIsInFrameCoordinates, DefaultVisualRectFlags); | 373 toLayoutView(object).mapToVisualRectInAncestorSpace(&ancestor, rect, Inp
utIsInFrameCoordinates, DefaultVisualRectFlags); |
| 406 else | 374 else |
| 407 object.mapToVisualRectInAncestorSpace(&ancestor, rect); | 375 object.mapToVisualRectInAncestorSpace(&ancestor, rect); |
| 408 } | 376 } |
| 409 | 377 |
| 410 void PaintInvalidationState::mapLocalRectToPaintInvalidationContainer(LayoutRect
& rect) const | 378 void PaintInvalidationState::mapLocalRectToPaintInvalidationContainer(LayoutRect
& rect) const |
| 411 { | 379 { |
| 412 ASSERT(!m_didUpdateForChildren); | 380 ASSERT(!m_didUpdateForChildren); |
| 413 | 381 |
| 414 if (m_cachedOffsetsEnabled) { | 382 if (m_cachedOffsetsEnabled) { |
| 415 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH | 383 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY |
| 416 LayoutRect slowPathRect(rect); | 384 LayoutRect slowPathRect(rect); |
| 417 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, slowPathRect); | 385 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, slowPathRect); |
| 418 #endif | 386 #endif |
| 419 rect.move(m_paintOffset); | 387 rect.move(m_paintOffset); |
| 420 if (m_clipped) | 388 if (m_clipped) |
| 421 rect.intersect(m_clipRect); | 389 rect.intersect(m_clipRect); |
| 422 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH | 390 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY |
| 423 assertRectsEqual(m_currentObject, *m_paintInvalidationContainer, rect, s
lowPathRect); | 391 assertFastPathAndSlowPathRectsEqual(rect, slowPathRect); |
| 424 #endif | 392 #endif |
| 425 } else { | 393 } else { |
| 426 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, rect); | 394 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, rect); |
| 427 } | 395 } |
| 428 } | 396 } |
| 429 | 397 |
| 430 void PaintInvalidationState::mapLocalRectToPaintInvalidationBacking(LayoutRect&
rect) const | 398 void PaintInvalidationState::mapLocalRectToPaintInvalidationBacking(LayoutRect&
rect) const |
| 431 { | 399 { |
| 432 mapLocalRectToPaintInvalidationContainer(rect); | 400 mapLocalRectToPaintInvalidationContainer(rect); |
| 433 | 401 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 448 } | 416 } |
| 449 | 417 |
| 450 PaintLayer& PaintInvalidationState::enclosingSelfPaintingLayer(const LayoutObjec
t& layoutObject) const | 418 PaintLayer& PaintInvalidationState::enclosingSelfPaintingLayer(const LayoutObjec
t& layoutObject) const |
| 451 { | 419 { |
| 452 if (layoutObject.hasLayer() && toLayoutBoxModelObject(layoutObject).hasSelfP
aintingLayer()) | 420 if (layoutObject.hasLayer() && toLayoutBoxModelObject(layoutObject).hasSelfP
aintingLayer()) |
| 453 return *toLayoutBoxModelObject(layoutObject).layer(); | 421 return *toLayoutBoxModelObject(layoutObject).layer(); |
| 454 | 422 |
| 455 return m_enclosingSelfPaintingLayer; | 423 return m_enclosingSelfPaintingLayer; |
| 456 } | 424 } |
| 457 | 425 |
| 426 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY |
| 427 |
| 428 static bool mayHaveBeenSaturated(LayoutUnit value) |
| 429 { |
| 430 // This is not accurate, just to avoid too big values. |
| 431 return value.abs() >= LayoutUnit::max() / 2; |
| 432 } |
| 433 |
| 434 static bool mayHaveBeenSaturated(const LayoutRect& rect) |
| 435 { |
| 436 return mayHaveBeenSaturated(rect.x()) || mayHaveBeenSaturated(rect.y()) || m
ayHaveBeenSaturated(rect.width()) || mayHaveBeenSaturated(rect.height()); |
| 437 } |
| 438 |
| 439 void PaintInvalidationState::assertFastPathAndSlowPathRectsEqual(const LayoutRec
t& fastPathRect, const LayoutRect& slowPathRect) const |
| 440 { |
| 441 if (!m_canCheckFastPathSlowPathEquality) |
| 442 return; |
| 443 |
| 444 // TODO(crbug.com/597903): Fast path and slow path should generate equal emp
ty rects. |
| 445 if (fastPathRect.isEmpty() && slowPathRect.isEmpty()) |
| 446 return; |
| 447 |
| 448 if (fastPathRect == slowPathRect) |
| 449 return; |
| 450 |
| 451 // LayoutUnit uses saturated arithmetic operations. If any interim or final
result is saturated, |
| 452 // the same operations in different order produce different results. Don't c
ompare results |
| 453 // if any of them may have been saturated. |
| 454 if (mayHaveBeenSaturated(fastPathRect) || mayHaveBeenSaturated(slowPathRect)
) |
| 455 return; |
| 456 |
| 457 // Tolerate the difference between the two paths when crossing frame boundar
ies. |
| 458 if (m_currentObject.view() != m_paintInvalidationContainer->view()) { |
| 459 LayoutRect inflatedFastPathRect = fastPathRect; |
| 460 inflatedFastPathRect.inflate(1); |
| 461 if (inflatedFastPathRect.contains(slowPathRect)) |
| 462 return; |
| 463 LayoutRect inflatedSlowPathRect = slowPathRect; |
| 464 inflatedSlowPathRect.inflate(1); |
| 465 if (inflatedSlowPathRect.contains(fastPathRect)) |
| 466 return; |
| 467 } |
| 468 |
| 469 WTFLogAlways("Fast path paint invalidation rect differs from slow path: fast
: %s vs slow: %s", |
| 470 fastPathRect.toString().ascii().data(), slowPathRect.toString().ascii().
data()); |
| 471 showLayoutTree(&m_currentObject); |
| 472 |
| 473 ASSERT_NOT_REACHED(); |
| 474 } |
| 475 |
| 476 #endif // CHECK_FAST_PATH_SLOW_PATH_EQUALITY |
| 477 |
| 458 } // namespace blink | 478 } // namespace blink |
| OLD | NEW |