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 |