| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/paint/BoxPaintInvalidator.h" | 5 #include "core/paint/BoxPaintInvalidator.h" |
| 6 | 6 |
| 7 #include "core/frame/Settings.h" | 7 #include "core/frame/Settings.h" |
| 8 #include "core/layout/LayoutView.h" | 8 #include "core/layout/LayoutView.h" |
| 9 #include "core/layout/compositing/CompositedLayerMapping.h" | 9 #include "core/layout/compositing/CompositedLayerMapping.h" |
| 10 #include "core/paint/ObjectPaintInvalidator.h" | 10 #include "core/paint/ObjectPaintInvalidator.h" |
| 11 #include "core/paint/PaintInvalidator.h" | 11 #include "core/paint/PaintInvalidator.h" |
| 12 #include "core/paint/PaintLayer.h" | 12 #include "core/paint/PaintLayer.h" |
| 13 #include "core/paint/PaintLayerScrollableArea.h" | 13 #include "core/paint/PaintLayerScrollableArea.h" |
| 14 #include "platform/geometry/LayoutRect.h" | 14 #include "platform/geometry/LayoutRect.h" |
| 15 | 15 |
| 16 namespace blink { | 16 namespace blink { |
| 17 | 17 |
| 18 struct PreviousBoxGeometries { | 18 struct PreviousBoxGeometries { |
| 19 LayoutSize borderBoxSize; | |
| 20 LayoutRect contentBoxRect; | 19 LayoutRect contentBoxRect; |
| 21 LayoutRect layoutOverflowRect; | 20 LayoutRect layoutOverflowRect; |
| 22 }; | 21 }; |
| 23 | 22 |
| 24 typedef HashMap<const LayoutBox*, PreviousBoxGeometries> | 23 typedef HashMap<const LayoutBox*, PreviousBoxGeometries> |
| 25 PreviousBoxGeometriesMap; | 24 PreviousBoxGeometriesMap; |
| 26 static PreviousBoxGeometriesMap& previousBoxGeometriesMap() { | 25 static PreviousBoxGeometriesMap& previousBoxGeometriesMap() { |
| 27 DEFINE_STATIC_LOCAL(PreviousBoxGeometriesMap, map, ()); | 26 DEFINE_STATIC_LOCAL(PreviousBoxGeometriesMap, map, ()); |
| 28 return map; | 27 return map; |
| 29 } | 28 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 } | 115 } |
| 117 | 116 |
| 118 const ComputedStyle& style = m_box.styleRef(); | 117 const ComputedStyle& style = m_box.styleRef(); |
| 119 | 118 |
| 120 if ((style.backgroundLayers().thisOrNextLayersUseContentBox() || | 119 if ((style.backgroundLayers().thisOrNextLayersUseContentBox() || |
| 121 style.maskLayers().thisOrNextLayersUseContentBox() || | 120 style.maskLayers().thisOrNextLayersUseContentBox() || |
| 122 style.boxSizing() == EBoxSizing::kBorderBox) && | 121 style.boxSizing() == EBoxSizing::kBorderBox) && |
| 123 previousContentBoxRect() != m_box.contentBoxRect()) | 122 previousContentBoxRect() != m_box.contentBoxRect()) |
| 124 return PaintInvalidationContentBoxChange; | 123 return PaintInvalidationContentBoxChange; |
| 125 | 124 |
| 126 LayoutSize oldBorderBoxSize = | 125 LayoutSize oldBorderBoxSize = m_box.previousSize(); |
| 127 previousBorderBoxSize(m_box, m_context.oldVisualRect.size()); | |
| 128 LayoutSize newBorderBoxSize = m_box.size(); | 126 LayoutSize newBorderBoxSize = m_box.size(); |
| 129 bool borderBoxChanged = oldBorderBoxSize != newBorderBoxSize; | 127 bool borderBoxChanged = oldBorderBoxSize != newBorderBoxSize; |
| 130 if (!borderBoxChanged && m_context.oldVisualRect == m_context.newVisualRect) | 128 if (!borderBoxChanged && m_context.oldVisualRect == m_context.newVisualRect) |
| 131 return PaintInvalidationNone; | 129 return PaintInvalidationNone; |
| 132 | 130 |
| 133 // If either border box changed or bounds changed, and old or new border box | 131 // If either border box changed or bounds changed, and old or new border box |
| 134 // doesn't equal old or new bounds, incremental invalidation is not | 132 // doesn't equal old or new bounds, incremental invalidation is not |
| 135 // applicable. This captures the following cases: | 133 // applicable. This captures the following cases: |
| 136 // - pixel snapping of paint invalidation bounds, | 134 // - pixel snapping of paint invalidation bounds, |
| 137 // - scale, rotate, skew etc. transforms, | 135 // - scale, rotate, skew etc. transforms, |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 | 223 |
| 226 bool shouldFullyInvalidateOnScrollingContentsLayer = false; | 224 bool shouldFullyInvalidateOnScrollingContentsLayer = false; |
| 227 if (m_box.backgroundChangedSinceLastPaintInvalidation()) { | 225 if (m_box.backgroundChangedSinceLastPaintInvalidation()) { |
| 228 if (!paintsOntoScrollingContentsLayer) { | 226 if (!paintsOntoScrollingContentsLayer) { |
| 229 // The box should have been set needing full invalidation on style change. | 227 // The box should have been set needing full invalidation on style change. |
| 230 DCHECK(m_box.shouldDoFullPaintInvalidation()); | 228 DCHECK(m_box.shouldDoFullPaintInvalidation()); |
| 231 return; | 229 return; |
| 232 } | 230 } |
| 233 shouldFullyInvalidateOnScrollingContentsLayer = true; | 231 shouldFullyInvalidateOnScrollingContentsLayer = true; |
| 234 } else { | 232 } else { |
| 235 // Check change of layout overflow for incremental invalidation. | 233 // Check change of layout overflow for full or incremental invalidation. |
| 236 if (!m_box.hasPreviousBoxGeometries() || | 234 if (newLayoutOverflow == oldLayoutOverflow) |
| 237 newLayoutOverflow == oldLayoutOverflow) | |
| 238 return; | 235 return; |
| 236 bool shouldFullyInvalidate = |
| 237 shouldFullyInvalidateBackgroundOnLayoutOverflowChange( |
| 238 oldLayoutOverflow, newLayoutOverflow); |
| 239 if (!paintsOntoScrollingContentsLayer) { | 239 if (!paintsOntoScrollingContentsLayer) { |
| 240 if (shouldFullyInvalidateBackgroundOnLayoutOverflowChange( | 240 if (shouldFullyInvalidate) { |
| 241 oldLayoutOverflow, newLayoutOverflow)) { | |
| 242 m_box.getMutableForPainting().setShouldDoFullPaintInvalidation( | 241 m_box.getMutableForPainting().setShouldDoFullPaintInvalidation( |
| 243 PaintInvalidationLayoutOverflowBoxChange); | 242 PaintInvalidationLayoutOverflowBoxChange); |
| 244 } | 243 } |
| 245 return; | 244 return; |
| 246 } | 245 } |
| 247 shouldFullyInvalidateOnScrollingContentsLayer = | 246 shouldFullyInvalidateOnScrollingContentsLayer = shouldFullyInvalidate; |
| 248 shouldFullyInvalidateBackgroundOnLayoutOverflowChange( | |
| 249 oldLayoutOverflow, newLayoutOverflow); | |
| 250 } | 247 } |
| 251 | 248 |
| 252 if (shouldFullyInvalidateOnScrollingContentsLayer) { | 249 if (shouldFullyInvalidateOnScrollingContentsLayer) { |
| 253 ObjectPaintInvalidatorWithContext(m_box, m_context) | 250 ObjectPaintInvalidatorWithContext(m_box, m_context) |
| 254 .fullyInvalidatePaint( | 251 .fullyInvalidatePaint( |
| 255 PaintInvalidationBackgroundOnScrollingContentsLayer, | 252 PaintInvalidationBackgroundOnScrollingContentsLayer, |
| 256 oldLayoutOverflow, newLayoutOverflow); | 253 oldLayoutOverflow, newLayoutOverflow); |
| 257 } else { | 254 } else { |
| 258 incrementallyInvalidatePaint( | 255 incrementallyInvalidatePaint( |
| 259 PaintInvalidationBackgroundOnScrollingContentsLayer, oldLayoutOverflow, | 256 PaintInvalidationBackgroundOnScrollingContentsLayer, oldLayoutOverflow, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 273 | 270 |
| 274 PaintInvalidationReason reason = computePaintInvalidationReason(); | 271 PaintInvalidationReason reason = computePaintInvalidationReason(); |
| 275 if (reason == PaintInvalidationIncremental) { | 272 if (reason == PaintInvalidationIncremental) { |
| 276 bool invalidated; | 273 bool invalidated; |
| 277 if (m_box.isLayoutView() && | 274 if (m_box.isLayoutView() && |
| 278 !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { | 275 !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
| 279 invalidated = incrementallyInvalidatePaint( | 276 invalidated = incrementallyInvalidatePaint( |
| 280 reason, m_context.oldVisualRect, m_context.newVisualRect); | 277 reason, m_context.oldVisualRect, m_context.newVisualRect); |
| 281 } else { | 278 } else { |
| 282 invalidated = incrementallyInvalidatePaint( | 279 invalidated = incrementallyInvalidatePaint( |
| 283 reason, LayoutRect(m_context.oldLocation, | 280 reason, LayoutRect(m_context.oldLocation, m_box.previousSize()), |
| 284 previousBorderBoxSize( | |
| 285 m_box, m_context.oldVisualRect.size())), | |
| 286 LayoutRect(m_context.newLocation, m_box.size())); | 281 LayoutRect(m_context.newLocation, m_box.size())); |
| 287 } | 282 } |
| 288 if (invalidated) { | 283 if (invalidated) { |
| 289 m_context.paintingLayer->setNeedsRepaint(); | 284 m_context.paintingLayer->setNeedsRepaint(); |
| 290 m_box.invalidateDisplayItemClients(reason); | 285 m_box.invalidateDisplayItemClients(reason); |
| 291 } else { | 286 } else { |
| 292 reason = PaintInvalidationNone; | 287 reason = PaintInvalidationNone; |
| 293 } | 288 } |
| 294 | 289 |
| 295 // Though we have done incremental invalidation, we still need to call | 290 // Though we have done incremental invalidation, we still need to call |
| (...skipping 11 matching lines...) Expand all Loading... |
| 307 if (PaintLayerScrollableArea* area = m_box.getScrollableArea()) | 302 if (PaintLayerScrollableArea* area = m_box.getScrollableArea()) |
| 308 area->invalidatePaintOfScrollControlsIfNeeded(m_context); | 303 area->invalidatePaintOfScrollControlsIfNeeded(m_context); |
| 309 | 304 |
| 310 // This is for the next invalidatePaintIfNeeded so must be at the end. | 305 // This is for the next invalidatePaintIfNeeded so must be at the end. |
| 311 savePreviousBoxGeometriesIfNeeded(); | 306 savePreviousBoxGeometriesIfNeeded(); |
| 312 | 307 |
| 313 return reason; | 308 return reason; |
| 314 } | 309 } |
| 315 | 310 |
| 316 bool BoxPaintInvalidator::needsToSavePreviousBoxGeometries() { | 311 bool BoxPaintInvalidator::needsToSavePreviousBoxGeometries() { |
| 317 LayoutSize paintInvalidationSize = m_context.newVisualRect.size(); | 312 // Don't save old box geometries if the paint rect is empty because we'll |
| 313 // fully invalidate once the paint rect becomes non-empty. |
| 314 if (m_context.newVisualRect.isEmpty()) |
| 315 return false; |
| 318 | 316 |
| 319 // The shortcuts doesn't apply to HTML element. ViewPaintInvalidator needs to | 317 if (m_box.paintedOutputOfObjectHasNoEffectRegardlessOfSize()) |
| 320 // know its previous border box size even if it has visibility:hidden (causing | 318 return false; |
| 321 // empty paintInvalidationSize) or has no painted output. | |
| 322 if (!m_box.node() || !m_box.node()->isHTMLElement()) { | |
| 323 // Don't save old box geometries if the paint rect is empty because we'll | |
| 324 // fully invalidate once the paint rect becomes non-empty. | |
| 325 if (paintInvalidationSize.isEmpty()) | |
| 326 return false; | |
| 327 | |
| 328 if (m_box.paintedOutputOfObjectHasNoEffectRegardlessOfSize()) | |
| 329 return false; | |
| 330 } | |
| 331 | 319 |
| 332 const ComputedStyle& style = m_box.styleRef(); | 320 const ComputedStyle& style = m_box.styleRef(); |
| 333 | 321 |
| 334 // If we use border-box sizing we need to track changes in the size of the | 322 // If we use border-box sizing we need to track changes in the size of the |
| 335 // content box. | 323 // content box. |
| 336 if (style.boxSizing() == EBoxSizing::kBorderBox) | 324 if (style.boxSizing() == EBoxSizing::kBorderBox) |
| 337 return true; | 325 return true; |
| 338 | 326 |
| 339 // No need to save old border box size if we can use size of the old paint | |
| 340 // rect as the old border box size in the next invalidation. | |
| 341 if (paintInvalidationSize != m_box.size()) | |
| 342 return true; | |
| 343 | |
| 344 // Background and mask layers can depend on other boxes than border box. See | 327 // Background and mask layers can depend on other boxes than border box. See |
| 345 // crbug.com/490533 | 328 // crbug.com/490533 |
| 346 if (style.backgroundLayers().thisOrNextLayersUseContentBox() || | 329 if (style.backgroundLayers().thisOrNextLayersUseContentBox() || |
| 347 style.maskLayers().thisOrNextLayersUseContentBox() || | 330 style.maskLayers().thisOrNextLayersUseContentBox() || |
| 348 backgroundGeometryDependsOnLayoutOverflowRect() || | 331 backgroundGeometryDependsOnLayoutOverflowRect() || |
| 349 backgroundPaintsOntoScrollingContentsLayer()) | 332 backgroundPaintsOntoScrollingContentsLayer()) |
| 350 return true; | 333 return true; |
| 351 | 334 |
| 352 return false; | 335 return false; |
| 353 } | 336 } |
| 354 | 337 |
| 355 void BoxPaintInvalidator::savePreviousBoxGeometriesIfNeeded() { | 338 void BoxPaintInvalidator::savePreviousBoxGeometriesIfNeeded() { |
| 339 m_box.getMutableForPainting().setPreviousSize(m_box.size()); |
| 340 |
| 356 DCHECK(m_box.hasPreviousBoxGeometries() == | 341 DCHECK(m_box.hasPreviousBoxGeometries() == |
| 357 previousBoxGeometriesMap().contains(&m_box)); | 342 previousBoxGeometriesMap().contains(&m_box)); |
| 358 if (!needsToSavePreviousBoxGeometries()) { | 343 if (!needsToSavePreviousBoxGeometries()) { |
| 359 if (m_box.hasPreviousBoxGeometries()) { | 344 if (m_box.hasPreviousBoxGeometries()) { |
| 360 previousBoxGeometriesMap().erase(&m_box); | 345 previousBoxGeometriesMap().erase(&m_box); |
| 361 m_box.getMutableForPainting().setHasPreviousBoxGeometries(false); | 346 m_box.getMutableForPainting().setHasPreviousBoxGeometries(false); |
| 362 } | 347 } |
| 363 return; | 348 return; |
| 364 } | 349 } |
| 365 | 350 |
| 366 PreviousBoxGeometries geometries = {m_box.size(), m_box.contentBoxRect(), | 351 PreviousBoxGeometries geometries = {m_box.contentBoxRect(), |
| 367 m_box.layoutOverflowRect()}; | 352 m_box.layoutOverflowRect()}; |
| 368 previousBoxGeometriesMap().set(&m_box, geometries); | 353 previousBoxGeometriesMap().set(&m_box, geometries); |
| 369 m_box.getMutableForPainting().setHasPreviousBoxGeometries(true); | 354 m_box.getMutableForPainting().setHasPreviousBoxGeometries(true); |
| 370 } | 355 } |
| 371 | 356 |
| 372 LayoutSize BoxPaintInvalidator::previousBorderBoxSize( | |
| 373 const LayoutBox& box, | |
| 374 const LayoutSize& defaultSize) { | |
| 375 DCHECK(box.hasPreviousBoxGeometries() == | |
| 376 previousBoxGeometriesMap().contains(&box)); | |
| 377 if (box.hasPreviousBoxGeometries()) | |
| 378 return previousBoxGeometriesMap().get(&box).borderBoxSize; | |
| 379 return defaultSize; | |
| 380 } | |
| 381 | |
| 382 LayoutRect BoxPaintInvalidator::previousContentBoxRect() { | 357 LayoutRect BoxPaintInvalidator::previousContentBoxRect() { |
| 383 DCHECK(m_box.hasPreviousBoxGeometries() == | 358 DCHECK(m_box.hasPreviousBoxGeometries() == |
| 384 previousBoxGeometriesMap().contains(&m_box)); | 359 previousBoxGeometriesMap().contains(&m_box)); |
| 385 return m_box.hasPreviousBoxGeometries() | 360 return m_box.hasPreviousBoxGeometries() |
| 386 ? previousBoxGeometriesMap().get(&m_box).contentBoxRect | 361 ? previousBoxGeometriesMap().get(&m_box).contentBoxRect |
| 387 : LayoutRect(); | 362 : LayoutRect(LayoutPoint(), m_box.previousSize()); |
| 388 } | 363 } |
| 389 | 364 |
| 390 LayoutRect BoxPaintInvalidator::previousLayoutOverflowRect() { | 365 LayoutRect BoxPaintInvalidator::previousLayoutOverflowRect() { |
| 391 DCHECK(m_box.hasPreviousBoxGeometries() == | 366 DCHECK(m_box.hasPreviousBoxGeometries() == |
| 392 previousBoxGeometriesMap().contains(&m_box)); | 367 previousBoxGeometriesMap().contains(&m_box)); |
| 393 return m_box.hasPreviousBoxGeometries() | 368 return m_box.hasPreviousBoxGeometries() |
| 394 ? previousBoxGeometriesMap().get(&m_box).layoutOverflowRect | 369 ? previousBoxGeometriesMap().get(&m_box).layoutOverflowRect |
| 395 : LayoutRect(); | 370 : LayoutRect(LayoutPoint(), m_box.previousSize()); |
| 396 } | 371 } |
| 397 | 372 |
| 398 } // namespace blink | 373 } // namespace blink |
| OLD | NEW |