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 |