| 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 |
| 17 namespace blink { | 22 namespace blink { |
| 18 | 23 |
| 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 |
| 19 static bool supportsCachedOffsets(const LayoutObject& object) | 65 static bool supportsCachedOffsets(const LayoutObject& object) |
| 20 { | 66 { |
| 21 return !object.hasTransformRelatedProperty() | 67 return !object.hasTransformRelatedProperty() |
| 22 && !object.hasReflection() | 68 && !object.hasReflection() |
| 23 && !object.hasFilterInducingProperty() | 69 && !object.hasFilterInducingProperty() |
| 24 && !object.isLayoutFlowThread() | 70 && !object.isLayoutFlowThread() |
| 25 && !object.isLayoutMultiColumnSpannerPlaceholder() | 71 && !object.isLayoutMultiColumnSpannerPlaceholder() |
| 26 && !object.styleRef().isFlippedBlocksWritingMode() | 72 && !object.styleRef().isFlippedBlocksWritingMode() |
| 27 && !(object.isLayoutBlock() && object.isSVG()); | 73 && !(object.isLayoutBlock() && object.isSVG()); |
| 28 } | 74 } |
| 29 | 75 |
| 30 PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vec
tor<LayoutObject*>& pendingDelayedPaintInvalidations) | 76 PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vec
tor<LayoutObject*>& pendingDelayedPaintInvalidations) |
| 31 : m_currentObject(layoutView) | 77 : m_currentObject(layoutView) |
| 32 , m_forcedSubtreeInvalidationWithinContainer(false) | 78 , m_forcedSubtreeInvalidationWithinContainer(false) |
| 33 , m_forcedSubtreeInvalidationRectUpdateWithinContainer(false) | 79 , m_forcedSubtreeInvalidationRectUpdateWithinContainer(false) |
| 34 , m_clipped(false) | 80 , m_clipped(false) |
| 35 , m_clippedForAbsolutePosition(false) | 81 , m_clippedForAbsolutePosition(false) |
| 36 , m_cachedOffsetsEnabled(true) | 82 , m_cachedOffsetsEnabled(true) |
| 37 , m_cachedOffsetsForAbsolutePositionEnabled(true) | 83 , m_cachedOffsetsForAbsolutePositionEnabled(true) |
| 38 , m_paintInvalidationContainer(&layoutView.containerForPaintInvalidation()) | 84 , m_paintInvalidationContainer(&layoutView.containerForPaintInvalidation()) |
| 39 , m_paintInvalidationContainerForStackedContents(m_paintInvalidationContaine
r) | 85 , m_paintInvalidationContainerForStackedContents(m_paintInvalidationContaine
r) |
| 40 , m_containerForAbsolutePosition(layoutView) | 86 , m_containerForAbsolutePosition(layoutView) |
| 41 , m_pendingDelayedPaintInvalidations(pendingDelayedPaintInvalidations) | 87 , m_pendingDelayedPaintInvalidations(pendingDelayedPaintInvalidations) |
| 42 , m_enclosingSelfPaintingLayer(*layoutView.layer()) | 88 , m_enclosingSelfPaintingLayer(*layoutView.layer()) |
| 43 #if ENABLE(ASSERT) | 89 #if ENABLE(ASSERT) |
| 44 , m_didUpdateForChildren(false) | 90 , m_didUpdateForChildren(false) |
| 45 #endif | 91 #endif |
| 46 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY | |
| 47 , m_canCheckFastPathSlowPathEquality(layoutView == m_paintInvalidationContai
ner) | |
| 48 #endif | |
| 49 { | 92 { |
| 50 if (!supportsCachedOffsets(layoutView)) { | 93 if (!supportsCachedOffsets(layoutView)) { |
| 51 m_cachedOffsetsEnabled = false; | 94 m_cachedOffsetsEnabled = false; |
| 52 return; | 95 return; |
| 53 } | 96 } |
| 54 | 97 |
| 55 FloatPoint point = layoutView.localToAncestorPoint(FloatPoint(), m_paintInva
lidationContainer, TraverseDocumentBoundaries | InputIsInFrameCoordinates); | 98 FloatPoint point = layoutView.localToAncestorPoint(FloatPoint(), m_paintInva
lidationContainer, TraverseDocumentBoundaries | InputIsInFrameCoordinates); |
| 56 m_paintOffset = LayoutSize(point.x(), point.y()); | 99 m_paintOffset = LayoutSize(point.x(), point.y()); |
| 57 m_paintOffsetForAbsolutePosition = m_paintOffset; | 100 m_paintOffsetForAbsolutePosition = m_paintOffset; |
| 58 } | 101 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 71 , m_cachedOffsetsForAbsolutePositionEnabled(parentState.m_cachedOffsetsForAb
solutePositionEnabled) | 114 , m_cachedOffsetsForAbsolutePositionEnabled(parentState.m_cachedOffsetsForAb
solutePositionEnabled) |
| 72 , m_paintInvalidationContainer(parentState.m_paintInvalidationContainer) | 115 , m_paintInvalidationContainer(parentState.m_paintInvalidationContainer) |
| 73 , m_paintInvalidationContainerForStackedContents(parentState.m_paintInvalida
tionContainerForStackedContents) | 116 , m_paintInvalidationContainerForStackedContents(parentState.m_paintInvalida
tionContainerForStackedContents) |
| 74 , m_containerForAbsolutePosition(currentObject.canContainAbsolutePositionObj
ects() ? currentObject : parentState.m_containerForAbsolutePosition) | 117 , m_containerForAbsolutePosition(currentObject.canContainAbsolutePositionObj
ects() ? currentObject : parentState.m_containerForAbsolutePosition) |
| 75 , m_svgTransform(parentState.m_svgTransform) | 118 , m_svgTransform(parentState.m_svgTransform) |
| 76 , m_pendingDelayedPaintInvalidations(parentState.pendingDelayedPaintInvalida
tionTargets()) | 119 , m_pendingDelayedPaintInvalidations(parentState.pendingDelayedPaintInvalida
tionTargets()) |
| 77 , m_enclosingSelfPaintingLayer(parentState.enclosingSelfPaintingLayer(curren
tObject)) | 120 , m_enclosingSelfPaintingLayer(parentState.enclosingSelfPaintingLayer(curren
tObject)) |
| 78 #if ENABLE(ASSERT) | 121 #if ENABLE(ASSERT) |
| 79 , m_didUpdateForChildren(false) | 122 , m_didUpdateForChildren(false) |
| 80 #endif | 123 #endif |
| 81 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY | |
| 82 , m_canCheckFastPathSlowPathEquality(parentState.m_canCheckFastPathSlowPathE
quality) | |
| 83 #endif | |
| 84 { | 124 { |
| 85 if (currentObject == parentState.m_currentObject) { | 125 if (currentObject == parentState.m_currentObject) { |
| 86 // Sometimes we create a new PaintInvalidationState from parentState on
the same object | 126 // Sometimes we create a new PaintInvalidationState from parentState on
the same object |
| 87 // (e.g. LayoutView, and the HorriblySlowRectMapping cases in LayoutBloc
k::invalidatePaintOfSubtreesIfNeeded()). | 127 // (e.g. LayoutView, and the HorriblySlowRectMapping cases in LayoutBloc
k::invalidatePaintOfSubtreesIfNeeded()). |
| 88 // TODO(wangxianzhu): Avoid this for RuntimeEnabledFeatures::slimmingPai
ntInvalidationEnabled(). | 128 // TODO(wangxianzhu): Avoid this for RuntimeEnabledFeatures::slimmingPai
ntInvalidationEnabled(). |
| 89 #if ENABLE(ASSERT) | 129 #if ENABLE(ASSERT) |
| 90 m_didUpdateForChildren = parentState.m_didUpdateForChildren; | 130 m_didUpdateForChildren = parentState.m_didUpdateForChildren; |
| 91 #endif | 131 #endif |
| 92 return; | 132 return; |
| 93 } | 133 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 // from the original paintInvalidationContainerForStackingContents,
then use this paint offset to adjust | 194 // from the original paintInvalidationContainerForStackingContents,
then use this paint offset to adjust |
| 155 // m_paintOffsetForAbsolutePosition. | 195 // m_paintOffsetForAbsolutePosition. |
| 156 updateForCurrentObject(parentState); | 196 updateForCurrentObject(parentState); |
| 157 m_paintOffsetForAbsolutePosition -= m_paintOffset; | 197 m_paintOffsetForAbsolutePosition -= m_paintOffset; |
| 158 if (m_clippedForAbsolutePosition) | 198 if (m_clippedForAbsolutePosition) |
| 159 m_clipRectForAbsolutePosition.move(-m_paintOffset); | 199 m_clipRectForAbsolutePosition.move(-m_paintOffset); |
| 160 } | 200 } |
| 161 | 201 |
| 162 m_clipped = false; // Will be updated in updateForChildren(). | 202 m_clipped = false; // Will be updated in updateForChildren(). |
| 163 m_paintOffset = LayoutSize(); | 203 m_paintOffset = LayoutSize(); |
| 164 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY | |
| 165 m_canCheckFastPathSlowPathEquality = true; | |
| 166 #endif | |
| 167 return; | 204 return; |
| 168 } | 205 } |
| 169 | 206 |
| 170 updateForCurrentObject(parentState); | 207 updateForCurrentObject(parentState); |
| 171 } | 208 } |
| 172 | 209 |
| 173 void PaintInvalidationState::updateForCurrentObject(const PaintInvalidationState
& parentState) | 210 void PaintInvalidationState::updateForCurrentObject(const PaintInvalidationState
& parentState) |
| 174 { | 211 { |
| 175 if (!m_cachedOffsetsEnabled) | 212 if (!m_cachedOffsetsEnabled) |
| 176 return; | 213 return; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 191 // is under the containing LayoutView. | 228 // is under the containing LayoutView. |
| 192 m_cachedOffsetsEnabled = false; | 229 m_cachedOffsetsEnabled = false; |
| 193 return; | 230 return; |
| 194 } | 231 } |
| 195 // Use slow path to get the offset of the fixed-position, and enable fas
t path for descendants. | 232 // Use slow path to get the offset of the fixed-position, and enable fas
t path for descendants. |
| 196 FloatPoint fixedOffset = m_currentObject.localToAncestorPoint(FloatPoint
(), m_paintInvalidationContainer, TraverseDocumentBoundaries); | 233 FloatPoint fixedOffset = m_currentObject.localToAncestorPoint(FloatPoint
(), m_paintInvalidationContainer, TraverseDocumentBoundaries); |
| 197 m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()); | 234 m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()); |
| 198 // In the above way to get paint offset, we can't get accurate clip rect
, so just assume no clip. | 235 // In the above way to get paint offset, we can't get accurate clip rect
, so just assume no clip. |
| 199 // Clip on fixed-position is rare, in case that paintInvalidationContain
er crosses frame boundary | 236 // Clip on fixed-position is rare, in case that paintInvalidationContain
er crosses frame boundary |
| 200 // and the LayoutView is clipped by something in owner document. | 237 // and the LayoutView is clipped by something in owner document. |
| 201 if (m_clipped) { | 238 m_clipped = false; |
| 202 m_clipped = false; | |
| 203 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY | |
| 204 m_canCheckFastPathSlowPathEquality = false; | |
| 205 #endif | |
| 206 } | |
| 207 return; | 239 return; |
| 208 } | 240 } |
| 209 | 241 |
| 210 if (position == AbsolutePosition) { | 242 if (position == AbsolutePosition) { |
| 211 m_cachedOffsetsEnabled = m_cachedOffsetsForAbsolutePositionEnabled; | 243 m_cachedOffsetsEnabled = m_cachedOffsetsForAbsolutePositionEnabled; |
| 212 if (!m_cachedOffsetsEnabled) | 244 if (!m_cachedOffsetsEnabled) |
| 213 return; | 245 return; |
| 214 | 246 |
| 215 m_paintOffset = m_paintOffsetForAbsolutePosition; | 247 m_paintOffset = m_paintOffsetForAbsolutePosition; |
| 216 m_clipped = m_clippedForAbsolutePosition; | 248 m_clipped = m_clippedForAbsolutePosition; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 LayoutPoint PaintInvalidationState::computePositionFromPaintInvalidationBacking(
) const | 341 LayoutPoint PaintInvalidationState::computePositionFromPaintInvalidationBacking(
) const |
| 310 { | 342 { |
| 311 ASSERT(!m_didUpdateForChildren); | 343 ASSERT(!m_didUpdateForChildren); |
| 312 | 344 |
| 313 FloatPoint point; | 345 FloatPoint point; |
| 314 if (m_paintInvalidationContainer != &m_currentObject) { | 346 if (m_paintInvalidationContainer != &m_currentObject) { |
| 315 if (m_cachedOffsetsEnabled) { | 347 if (m_cachedOffsetsEnabled) { |
| 316 if (m_currentObject.isSVG() && !m_currentObject.isSVGRoot()) | 348 if (m_currentObject.isSVG() && !m_currentObject.isSVGRoot()) |
| 317 point = m_svgTransform.mapPoint(point); | 349 point = m_svgTransform.mapPoint(point); |
| 318 point += FloatPoint(m_paintOffset); | 350 point += FloatPoint(m_paintOffset); |
| 319 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY | 351 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH |
| 320 // TODO(wangxianzhu): We can't enable this ASSERT for now because of
crbug.com/597745. | 352 // TODO(wangxianzhu): We can't enable this ASSERT for now because of
crbug.com/597745. |
| 321 // ASSERT(point == slowLocalOriginToAncestorPoint(m_currentObject, m
_paintInvalidationContainer, FloatPoint()); | 353 // ASSERT(point == slowLocalOriginToAncestorPoint(m_currentObject, m
_paintInvalidationContainer, FloatPoint()); |
| 322 #endif | 354 #endif |
| 323 } else { | 355 } else { |
| 324 point = slowLocalToAncestorPoint(m_currentObject, *m_paintInvalidati
onContainer, FloatPoint()); | 356 point = slowLocalToAncestorPoint(m_currentObject, *m_paintInvalidati
onContainer, FloatPoint()); |
| 325 } | 357 } |
| 326 } | 358 } |
| 327 | 359 |
| 328 if (m_paintInvalidationContainer->layer()->groupedMapping()) | 360 if (m_paintInvalidationContainer->layer()->groupedMapping()) |
| 329 PaintLayer::mapPointInPaintInvalidationContainerToBacking(*m_paintInvali
dationContainer, point); | 361 PaintLayer::mapPointInPaintInvalidationContainerToBacking(*m_paintInvali
dationContainer, point); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 345 | 377 |
| 346 LayoutRect PaintInvalidationState::computePaintInvalidationRectInBackingForSVG()
const | 378 LayoutRect PaintInvalidationState::computePaintInvalidationRectInBackingForSVG()
const |
| 347 { | 379 { |
| 348 LayoutRect rect; | 380 LayoutRect rect; |
| 349 if (m_cachedOffsetsEnabled) { | 381 if (m_cachedOffsetsEnabled) { |
| 350 FloatRect svgRect = SVGLayoutSupport::localOverflowRectForPaintInvalidat
ion(m_currentObject); | 382 FloatRect svgRect = SVGLayoutSupport::localOverflowRectForPaintInvalidat
ion(m_currentObject); |
| 351 rect = SVGLayoutSupport::transformPaintInvalidationRect(m_currentObject,
m_svgTransform, svgRect); | 383 rect = SVGLayoutSupport::transformPaintInvalidationRect(m_currentObject,
m_svgTransform, svgRect); |
| 352 rect.move(m_paintOffset); | 384 rect.move(m_paintOffset); |
| 353 if (m_clipped) | 385 if (m_clipped) |
| 354 rect.intersect(m_clipRect); | 386 rect.intersect(m_clipRect); |
| 355 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY | 387 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH |
| 356 LayoutRect slowPathRect = SVGLayoutSupport::clippedOverflowRectForPaintI
nvalidation(m_currentObject, *m_paintInvalidationContainer); | 388 LayoutRect slowPathRect = SVGLayoutSupport::clippedOverflowRectForPaintI
nvalidation(m_currentObject, *m_paintInvalidationContainer); |
| 357 assertFastPathAndSlowPathRectsEqual(rect, slowPathRect); | 389 assertRectsEqual(m_currentObject, m_paintInvalidationContainer, rect, sl
owPathRect); |
| 358 #endif | 390 #endif |
| 359 } else { | 391 } else { |
| 360 // TODO(wangxianzhu): Sometimes m_cachedOffsetsEnabled==false doesn't me
an we can't use cached | 392 // TODO(wangxianzhu): Sometimes m_cachedOffsetsEnabled==false doesn't me
an we can't use cached |
| 361 // m_svgTransform. We can use hybrid fast path (for SVG) and slow path (
for things above the SVGRoot). | 393 // m_svgTransform. We can use hybrid fast path (for SVG) and slow path (
for things above the SVGRoot). |
| 362 rect = SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(m_curre
ntObject, *m_paintInvalidationContainer); | 394 rect = SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(m_curre
ntObject, *m_paintInvalidationContainer); |
| 363 } | 395 } |
| 364 | 396 |
| 365 if (m_paintInvalidationContainer->layer()->groupedMapping()) | 397 if (m_paintInvalidationContainer->layer()->groupedMapping()) |
| 366 PaintLayer::mapRectInPaintInvalidationContainerToBacking(*m_paintInvalid
ationContainer, rect); | 398 PaintLayer::mapRectInPaintInvalidationContainerToBacking(*m_paintInvalid
ationContainer, rect); |
| 367 return rect; | 399 return rect; |
| 368 } | 400 } |
| 369 | 401 |
| 370 static void slowMapToVisualRectInAncestorSpace(const LayoutObject& object, const
LayoutBoxModelObject& ancestor, LayoutRect& rect) | 402 static void slowMapToVisualRectInAncestorSpace(const LayoutObject& object, const
LayoutBoxModelObject& ancestor, LayoutRect& rect) |
| 371 { | 403 { |
| 372 if (object.isLayoutView()) | 404 if (object.isLayoutView()) |
| 373 toLayoutView(object).mapToVisualRectInAncestorSpace(&ancestor, rect, Inp
utIsInFrameCoordinates, DefaultVisualRectFlags); | 405 toLayoutView(object).mapToVisualRectInAncestorSpace(&ancestor, rect, Inp
utIsInFrameCoordinates, DefaultVisualRectFlags); |
| 374 else | 406 else |
| 375 object.mapToVisualRectInAncestorSpace(&ancestor, rect); | 407 object.mapToVisualRectInAncestorSpace(&ancestor, rect); |
| 376 } | 408 } |
| 377 | 409 |
| 378 void PaintInvalidationState::mapLocalRectToPaintInvalidationContainer(LayoutRect
& rect) const | 410 void PaintInvalidationState::mapLocalRectToPaintInvalidationContainer(LayoutRect
& rect) const |
| 379 { | 411 { |
| 380 ASSERT(!m_didUpdateForChildren); | 412 ASSERT(!m_didUpdateForChildren); |
| 381 | 413 |
| 382 if (m_cachedOffsetsEnabled) { | 414 if (m_cachedOffsetsEnabled) { |
| 383 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY | 415 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH |
| 384 LayoutRect slowPathRect(rect); | 416 LayoutRect slowPathRect(rect); |
| 385 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, slowPathRect); | 417 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, slowPathRect); |
| 386 #endif | 418 #endif |
| 387 rect.move(m_paintOffset); | 419 rect.move(m_paintOffset); |
| 388 if (m_clipped) | 420 if (m_clipped) |
| 389 rect.intersect(m_clipRect); | 421 rect.intersect(m_clipRect); |
| 390 #ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY | 422 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH |
| 391 assertFastPathAndSlowPathRectsEqual(rect, slowPathRect); | 423 assertRectsEqual(m_currentObject, *m_paintInvalidationContainer, rect, s
lowPathRect); |
| 392 #endif | 424 #endif |
| 393 } else { | 425 } else { |
| 394 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, rect); | 426 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, rect); |
| 395 } | 427 } |
| 396 } | 428 } |
| 397 | 429 |
| 398 void PaintInvalidationState::mapLocalRectToPaintInvalidationBacking(LayoutRect&
rect) const | 430 void PaintInvalidationState::mapLocalRectToPaintInvalidationBacking(LayoutRect&
rect) const |
| 399 { | 431 { |
| 400 mapLocalRectToPaintInvalidationContainer(rect); | 432 mapLocalRectToPaintInvalidationContainer(rect); |
| 401 | 433 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 416 } | 448 } |
| 417 | 449 |
| 418 PaintLayer& PaintInvalidationState::enclosingSelfPaintingLayer(const LayoutObjec
t& layoutObject) const | 450 PaintLayer& PaintInvalidationState::enclosingSelfPaintingLayer(const LayoutObjec
t& layoutObject) const |
| 419 { | 451 { |
| 420 if (layoutObject.hasLayer() && toLayoutBoxModelObject(layoutObject).hasSelfP
aintingLayer()) | 452 if (layoutObject.hasLayer() && toLayoutBoxModelObject(layoutObject).hasSelfP
aintingLayer()) |
| 421 return *toLayoutBoxModelObject(layoutObject).layer(); | 453 return *toLayoutBoxModelObject(layoutObject).layer(); |
| 422 | 454 |
| 423 return m_enclosingSelfPaintingLayer; | 455 return m_enclosingSelfPaintingLayer; |
| 424 } | 456 } |
| 425 | 457 |
| 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 | |
| 478 } // namespace blink | 458 } // namespace blink |
| OLD | NEW |