| 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/PaintInvalidator.h" | 5 #include "core/paint/PaintInvalidator.h" |
| 6 | 6 |
| 7 #include "core/editing/FrameSelection.h" | 7 #include "core/editing/FrameSelection.h" |
| 8 #include "core/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
| 9 #include "core/frame/LocalFrame.h" | 9 #include "core/frame/LocalFrame.h" |
| 10 #include "core/frame/Settings.h" | 10 #include "core/frame/Settings.h" |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 point.moveBy(-containerContentsProperties.paintOffset); | 185 point.moveBy(-containerContentsProperties.paintOffset); |
| 186 } | 186 } |
| 187 | 187 |
| 188 if (context.paintInvalidationContainer->layer()->groupedMapping()) | 188 if (context.paintInvalidationContainer->layer()->groupedMapping()) |
| 189 PaintLayer::mapPointInPaintInvalidationContainerToBacking( | 189 PaintLayer::mapPointInPaintInvalidationContainerToBacking( |
| 190 *context.paintInvalidationContainer, point); | 190 *context.paintInvalidationContainer, point); |
| 191 | 191 |
| 192 return LayoutPoint(point); | 192 return LayoutPoint(point); |
| 193 } | 193 } |
| 194 | 194 |
| 195 static LayoutPoint computePaintOffset(const LayoutObject& object, |
| 196 PaintInvalidatorContext& context) { |
| 197 LayoutPoint paintOffset = context.treeBuilderContext.current.paintOffset; |
| 198 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 199 return paintOffset; |
| 200 |
| 201 if (object.isSVG() && !object.isSVGRoot()) |
| 202 return paintOffset; |
| 203 |
| 204 if (object.isLayoutView() || |
| 205 (object.hasLayer() && |
| 206 toLayoutBoxModelObject(object).layer()->paintsWithTransform( |
| 207 GlobalPaintNormalPhase))) { |
| 208 if (object != context.paintInvalidationContainer) { |
| 209 context.shouldAdjustPaintOffsetToContainer = false; |
| 210 LOG(ERROR) << "reset shouldAdjustToContainer by " << object.debugName(); |
| 211 } |
| 212 if (object != context.paintInvalidationContainerForStackedContents) { |
| 213 LOG(ERROR) << "reset shouldAdjustToContainerForStackedContents by " |
| 214 << object.debugName(); |
| 215 context.shouldAdjustPaintOffsetToContainerForStackedContents = false; |
| 216 } |
| 217 } |
| 218 |
| 219 if (context.shouldAdjustPaintOffsetToContainer) { |
| 220 LOG(ERROR) << object.debugName() << " adjust paint offset to " |
| 221 << context.paintInvalidationContainer->debugName() |
| 222 << " paint offset=" << paintOffset.toString(); |
| 223 paintOffset -= toIntSize( |
| 224 roundedIntPoint(context.paintInvalidationContainer->paintProperties() |
| 225 ->localBorderBoxProperties() |
| 226 ->paintOffset)); |
| 227 LOG(ERROR) << " after adjustment=" << paintOffset.toString(); |
| 228 } |
| 229 if (object != context.paintInvalidationContainer && |
| 230 context.paintInvalidationContainer->usesCompositedScrolling()) { |
| 231 const LayoutBox* box = toLayoutBox(context.paintInvalidationContainer); |
| 232 if (box->hasOverflowClip()) |
| 233 paintOffset += box->scrolledContentOffset(); |
| 234 LOG(ERROR) << " after adjustment for scroll offset=" |
| 235 << paintOffset.toString(); |
| 236 } |
| 237 return paintOffset; |
| 238 } |
| 239 |
| 195 void PaintInvalidator::updatePaintingLayer(const LayoutObject& object, | 240 void PaintInvalidator::updatePaintingLayer(const LayoutObject& object, |
| 196 PaintInvalidatorContext& context) { | 241 PaintInvalidatorContext& context) { |
| 197 if (object.hasLayer() && | 242 if (object.hasLayer() && |
| 198 toLayoutBoxModelObject(object).hasSelfPaintingLayer()) | 243 toLayoutBoxModelObject(object).hasSelfPaintingLayer()) |
| 199 context.paintingLayer = toLayoutBoxModelObject(object).layer(); | 244 context.paintingLayer = toLayoutBoxModelObject(object).layer(); |
| 200 | 245 |
| 201 if (object.isLayoutBlockFlow() && toLayoutBlockFlow(object).containsFloats()) | 246 if (object.isLayoutBlockFlow() && toLayoutBlockFlow(object).containsFloats()) |
| 202 context.paintingLayer->setNeedsPaintPhaseFloat(); | 247 context.paintingLayer->setNeedsPaintPhaseFloat(); |
| 203 | 248 |
| 204 if (object == context.paintingLayer->layoutObject()) | 249 if (object == context.paintingLayer->layoutObject()) |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 | 302 |
| 258 } // namespace | 303 } // namespace |
| 259 | 304 |
| 260 void PaintInvalidator::updateContext(const LayoutObject& object, | 305 void PaintInvalidator::updateContext(const LayoutObject& object, |
| 261 PaintInvalidatorContext& context) { | 306 PaintInvalidatorContext& context) { |
| 262 Optional<ScopedUndoFrameViewContentClipAndScroll> | 307 Optional<ScopedUndoFrameViewContentClipAndScroll> |
| 263 undoFrameViewContentClipAndScroll; | 308 undoFrameViewContentClipAndScroll; |
| 264 | 309 |
| 265 if (object.isPaintInvalidationContainer()) { | 310 if (object.isPaintInvalidationContainer()) { |
| 266 context.paintInvalidationContainer = toLayoutBoxModelObject(&object); | 311 context.paintInvalidationContainer = toLayoutBoxModelObject(&object); |
| 267 if (object.styleRef().isStackingContext()) | 312 context.shouldAdjustPaintOffsetToContainer = true; |
| 313 if (object.styleRef().isStackingContext()) { |
| 268 context.paintInvalidationContainerForStackedContents = | 314 context.paintInvalidationContainerForStackedContents = |
| 269 toLayoutBoxModelObject(&object); | 315 toLayoutBoxModelObject(&object); |
| 316 context.shouldAdjustPaintOffsetToContainerForStackedContents = true; |
| 317 } |
| 270 } else if (object.isLayoutView()) { | 318 } else if (object.isLayoutView()) { |
| 271 // paintInvalidationContainerForStackedContents is only for stacked | 319 // paintInvalidationContainerForStackedContents is only for stacked |
| 272 // descendants in its own frame, because it doesn't establish stacking | 320 // descendants in its own frame, because it doesn't establish stacking |
| 273 // context for stacked contents in sub-frames. | 321 // context for stacked contents in sub-frames. |
| 274 // Contents stacked in the root stacking context in this frame should use | 322 // Contents stacked in the root stacking context in this frame should use |
| 275 // this frame's paintInvalidationContainer. | 323 // this frame's paintInvalidationContainer. |
| 276 context.paintInvalidationContainerForStackedContents = | 324 context.paintInvalidationContainerForStackedContents = |
| 277 context.paintInvalidationContainer; | 325 context.paintInvalidationContainer; |
| 326 context.shouldAdjustPaintOffsetToContainerForStackedContents = |
| 327 context.shouldAdjustPaintOffsetToContainer; |
| 278 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled()) | 328 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled()) |
| 279 undoFrameViewContentClipAndScroll.emplace( | 329 undoFrameViewContentClipAndScroll.emplace( |
| 280 *toLayoutView(object).frameView(), context); | 330 *toLayoutView(object).frameView(), context); |
| 281 } else if (object.styleRef().isStacked() && | 331 } else if (object.styleRef().isStacked() && |
| 282 // This is to exclude some objects (e.g. LayoutText) inheriting | 332 // This is to exclude some objects (e.g. LayoutText) inheriting |
| 283 // stacked style from parent but aren't actually stacked. | 333 // stacked style from parent but aren't actually stacked. |
| 284 object.hasLayer() && | 334 object.hasLayer() && |
| 285 context.paintInvalidationContainer != | 335 context.paintInvalidationContainer != |
| 286 context.paintInvalidationContainerForStackedContents) { | 336 context.paintInvalidationContainerForStackedContents) { |
| 287 // The current object is stacked, so we should use | 337 // The current object is stacked, so we should use |
| 288 // m_paintInvalidationContainerForStackedContents as its paint invalidation | 338 // m_paintInvalidationContainerForStackedContents as its paint invalidation |
| 289 // container on which the current object is painted. | 339 // container on which the current object is painted. |
| 290 context.paintInvalidationContainer = | 340 context.paintInvalidationContainer = |
| 291 context.paintInvalidationContainerForStackedContents; | 341 context.paintInvalidationContainerForStackedContents; |
| 342 context.shouldAdjustPaintOffsetToContainer = |
| 343 context.shouldAdjustPaintOffsetToContainerForStackedContents; |
| 292 if (context.forcedSubtreeInvalidationFlags & | 344 if (context.forcedSubtreeInvalidationFlags & |
| 293 PaintInvalidatorContext:: | 345 PaintInvalidatorContext:: |
| 294 ForcedSubtreeFullInvalidationForStackedContents) | 346 ForcedSubtreeFullInvalidationForStackedContents) { |
| 295 context.forcedSubtreeInvalidationFlags |= | 347 context.forcedSubtreeInvalidationFlags |= |
| 296 PaintInvalidatorContext::ForcedSubtreeFullInvalidation; | 348 PaintInvalidatorContext::ForcedSubtreeFullInvalidation; |
| 349 } |
| 297 } | 350 } |
| 298 | 351 |
| 299 if (object == context.paintInvalidationContainer) { | 352 if (object == context.paintInvalidationContainer) { |
| 300 // When we hit a new paint invalidation container, we don't need to | 353 // When we hit a new paint invalidation container, we don't need to |
| 301 // continue forcing a check for paint invalidation, since we're | 354 // continue forcing a check for paint invalidation, since we're |
| 302 // descending into a different invalidation container. (For instance if | 355 // descending into a different invalidation container. (For instance if |
| 303 // our parents were moved, the entire container will just move.) | 356 // our parents were moved, the entire container will just move.) |
| 304 if (object != context.paintInvalidationContainerForStackedContents) { | 357 if (object != context.paintInvalidationContainerForStackedContents) { |
| 305 // However, we need to keep the | 358 // However, we need to keep the |
| 306 // ForcedSubtreeFullInvalidationForStackedContents flag if the current | 359 // ForcedSubtreeFullInvalidationForStackedContents flag if the current |
| (...skipping 16 matching lines...) Expand all Loading... |
| 323 // TODO(crbug.com/637313): This is temporary before we support filters in | 376 // TODO(crbug.com/637313): This is temporary before we support filters in |
| 324 // paint property tree. | 377 // paint property tree. |
| 325 // TODO(crbug.com/648274): This is a workaround for multi-column contents. | 378 // TODO(crbug.com/648274): This is a workaround for multi-column contents. |
| 326 if (object.hasFilterInducingProperty() || object.isLayoutFlowThread()) | 379 if (object.hasFilterInducingProperty() || object.isLayoutFlowThread()) |
| 327 context.forcedSubtreeInvalidationFlags |= | 380 context.forcedSubtreeInvalidationFlags |= |
| 328 PaintInvalidatorContext::ForcedSubtreeSlowPathRect; | 381 PaintInvalidatorContext::ForcedSubtreeSlowPathRect; |
| 329 | 382 |
| 330 ObjectPaintInvalidator objectPaintInvalidator(object); | 383 ObjectPaintInvalidator objectPaintInvalidator(object); |
| 331 context.oldVisualRect = object.previousVisualRect(); | 384 context.oldVisualRect = object.previousVisualRect(); |
| 332 context.oldLocation = objectPaintInvalidator.previousLocationInBacking(); | 385 context.oldLocation = objectPaintInvalidator.previousLocationInBacking(); |
| 386 context.oldPaintOffset = object.previousPaintOffset(); |
| 333 context.newVisualRect = computeVisualRectInBacking(object, context); | 387 context.newVisualRect = computeVisualRectInBacking(object, context); |
| 334 context.newLocation = computeLocationInBacking(object, context); | 388 context.newLocation = computeLocationInBacking(object, context); |
| 389 context.newPaintOffset = computePaintOffset(object, context); |
| 335 | 390 |
| 336 IntSize adjustment = object.scrollAdjustmentForPaintInvalidation( | 391 IntSize adjustment = object.scrollAdjustmentForPaintInvalidation( |
| 337 *context.paintInvalidationContainer); | 392 *context.paintInvalidationContainer); |
| 338 context.newLocation.move(adjustment); | 393 context.newLocation.move(adjustment); |
| 339 context.newVisualRect.move(adjustment); | 394 context.newVisualRect.move(adjustment); |
| 340 | 395 |
| 341 object.getMutableForPainting().setPreviousVisualRect(context.newVisualRect); | 396 object.getMutableForPainting().setPreviousVisualRect(context.newVisualRect); |
| 397 object.getMutableForPainting().setPreviousPaintOffset(context.newPaintOffset); |
| 342 objectPaintInvalidator.setPreviousLocationInBacking(context.newLocation); | 398 objectPaintInvalidator.setPreviousLocationInBacking(context.newLocation); |
| 343 } | 399 } |
| 344 | 400 |
| 345 void PaintInvalidator::invalidatePaintIfNeeded( | 401 void PaintInvalidator::invalidatePaintIfNeeded( |
| 346 FrameView& frameView, | 402 FrameView& frameView, |
| 347 PaintInvalidatorContext& context) { | 403 PaintInvalidatorContext& context) { |
| 348 LayoutView* layoutView = frameView.layoutView(); | 404 LayoutView* layoutView = frameView.layoutView(); |
| 349 CHECK(layoutView); | 405 CHECK(layoutView); |
| 350 | 406 |
| 351 context.paintInvalidationContainer = | 407 context.paintInvalidationContainer = |
| 352 context.paintInvalidationContainerForStackedContents = | 408 context.paintInvalidationContainerForStackedContents = |
| 353 &layoutView->containerForPaintInvalidation(); | 409 &layoutView->containerForPaintInvalidation(); |
| 410 context.shouldAdjustPaintOffsetToContainer = |
| 411 context.shouldAdjustPaintOffsetToContainerForStackedContents = true; |
| 354 context.paintingLayer = layoutView->layer(); | 412 context.paintingLayer = layoutView->layer(); |
| 355 | 413 |
| 356 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { | 414 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
| 357 ScopedUndoFrameViewContentClipAndScroll undo(frameView, context); | 415 ScopedUndoFrameViewContentClipAndScroll undo(frameView, context); |
| 358 frameView.invalidatePaintOfScrollControlsIfNeeded(context); | 416 frameView.invalidatePaintOfScrollControlsIfNeeded(context); |
| 359 } | 417 } |
| 360 | 418 |
| 361 if (frameView.frame().selection().isCaretBoundsDirty()) | 419 if (frameView.frame().selection().isCaretBoundsDirty()) |
| 362 frameView.frame().selection().invalidateCaretRect(); | 420 frameView.frame().selection().invalidateCaretRect(); |
| 363 | 421 |
| 364 // Temporary callback for crbug.com/487345,402044 | 422 // Temporary callback for crbug.com/487345,402044 |
| 365 // TODO(ojan): Make this more general to be used by PositionObserver | 423 // TODO(ojan): Make this more general to be used by PositionObserver |
| 366 // and rAF throttling. | 424 // and rAF throttling. |
| 367 IntRect visibleRect = | 425 IntRect visibleRect = |
| 368 frameView.rootFrameToContents(frameView.computeVisibleArea()); | 426 frameView.rootFrameToContents(frameView.computeVisibleArea()); |
| 369 layoutView->sendMediaPositionChangeNotifications(visibleRect); | 427 layoutView->sendMediaPositionChangeNotifications(visibleRect); |
| 370 } | 428 } |
| 371 | 429 |
| 372 static bool hasPercentageTransform(const ComputedStyle& style) { | |
| 373 if (TransformOperation* translate = style.translate()) { | |
| 374 if (translate->dependsOnBoxSize()) | |
| 375 return true; | |
| 376 } | |
| 377 return style.transform().dependsOnBoxSize() || | |
| 378 (style.transformOriginX() != Length(50, Percent) && | |
| 379 style.transformOriginX().isPercentOrCalc()) || | |
| 380 (style.transformOriginY() != Length(50, Percent) && | |
| 381 style.transformOriginY().isPercentOrCalc()); | |
| 382 } | |
| 383 | |
| 384 void PaintInvalidator::invalidatePaintIfNeeded( | 430 void PaintInvalidator::invalidatePaintIfNeeded( |
| 385 const LayoutObject& object, | 431 const LayoutObject& object, |
| 386 PaintInvalidatorContext& context) { | 432 PaintInvalidatorContext& context) { |
| 387 object.getMutableForPainting().ensureIsReadyForPaintInvalidation(); | 433 object.getMutableForPainting().ensureIsReadyForPaintInvalidation(); |
| 388 | 434 |
| 389 if (!context.forcedSubtreeInvalidationFlags && | 435 if (!context.forcedSubtreeInvalidationFlags && |
| 390 !object | 436 !object |
| 391 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) | 437 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()) |
| 392 return; | 438 return; |
| 393 | 439 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 423 ForcedSubtreeFullInvalidationForStackedContents); | 469 ForcedSubtreeFullInvalidationForStackedContents); |
| 424 break; | 470 break; |
| 425 case PaintInvalidationSVGResourceChange: | 471 case PaintInvalidationSVGResourceChange: |
| 426 context.forcedSubtreeInvalidationFlags |= | 472 context.forcedSubtreeInvalidationFlags |= |
| 427 PaintInvalidatorContext::ForcedSubtreeSVGResourceChange; | 473 PaintInvalidatorContext::ForcedSubtreeSVGResourceChange; |
| 428 break; | 474 break; |
| 429 default: | 475 default: |
| 430 break; | 476 break; |
| 431 } | 477 } |
| 432 | 478 |
| 433 if (context.oldLocation != context.newLocation) | 479 if (context.oldLocation != context.newLocation || |
| 480 context.oldPaintOffset != context.newPaintOffset) { |
| 434 context.forcedSubtreeInvalidationFlags |= | 481 context.forcedSubtreeInvalidationFlags |= |
| 435 PaintInvalidatorContext::ForcedSubtreeInvalidationChecking; | 482 PaintInvalidatorContext::ForcedSubtreeInvalidationChecking; |
| 436 | 483 } |
| 437 // TODO(crbug.com/533277): This is a workaround for the bug. Remove when we | |
| 438 // detect paint offset change. | |
| 439 if (reason != PaintInvalidationNone && | |
| 440 hasPercentageTransform(object.styleRef())) | |
| 441 context.forcedSubtreeInvalidationFlags |= | |
| 442 PaintInvalidatorContext::ForcedSubtreeInvalidationChecking; | |
| 443 | 484 |
| 444 // TODO(crbug.com/490725): This is a workaround for the bug, to force | 485 // TODO(crbug.com/490725): This is a workaround for the bug, to force |
| 445 // descendant to update visual rects on clipping change. | 486 // descendant to update visual rects on clipping change. |
| 446 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && | 487 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && |
| 447 context.oldVisualRect != context.newVisualRect | 488 context.oldVisualRect != context.newVisualRect |
| 448 // Note that isLayoutView() below becomes unnecessary after the launch of | 489 // Note that isLayoutView() below becomes unnecessary after the launch of |
| 449 // root layer scrolling. | 490 // root layer scrolling. |
| 450 && (object.hasOverflowClip() || object.isLayoutView()) && | 491 && (object.hasOverflowClip() || object.isLayoutView()) && |
| 451 !toLayoutBox(object).usesCompositedScrolling()) | 492 !toLayoutBox(object).usesCompositedScrolling()) |
| 452 context.forcedSubtreeInvalidationFlags |= | 493 context.forcedSubtreeInvalidationFlags |= |
| 453 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; | 494 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate; |
| 454 | 495 |
| 455 object.getMutableForPainting().clearPaintInvalidationFlags(); | 496 object.getMutableForPainting().clearPaintInvalidationFlags(); |
| 456 } | 497 } |
| 457 | 498 |
| 458 void PaintInvalidator::processPendingDelayedPaintInvalidations() { | 499 void PaintInvalidator::processPendingDelayedPaintInvalidations() { |
| 459 for (auto target : m_pendingDelayedPaintInvalidations) | 500 for (auto target : m_pendingDelayedPaintInvalidations) |
| 460 target->getMutableForPainting().setShouldDoFullPaintInvalidation( | 501 target->getMutableForPainting().setShouldDoFullPaintInvalidation( |
| 461 PaintInvalidationDelayedFull); | 502 PaintInvalidationDelayedFull); |
| 462 } | 503 } |
| 463 | 504 |
| 464 } // namespace blink | 505 } // namespace blink |
| OLD | NEW |