| 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 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 } else { | 335 } else { |
| 336 context.forcedSubtreeInvalidationFlags = 0; | 336 context.forcedSubtreeInvalidationFlags = 0; |
| 337 } | 337 } |
| 338 } | 338 } |
| 339 | 339 |
| 340 DCHECK(context.paintInvalidationContainer == | 340 DCHECK(context.paintInvalidationContainer == |
| 341 object.containerForPaintInvalidation()); | 341 object.containerForPaintInvalidation()); |
| 342 DCHECK(context.paintingLayer == object.paintingLayer()); | 342 DCHECK(context.paintingLayer == object.paintingLayer()); |
| 343 } | 343 } |
| 344 | 344 |
| 345 void PaintInvalidator::updateVisualRect(const LayoutObject& object, | 345 void PaintInvalidator::updateVisualRectIfNeeded( |
| 346 PaintInvalidatorContext& context) { | 346 const LayoutObject& object, |
| 347 Optional<ScopedUndoFrameViewContentClipAndScroll> | 347 PaintInvalidatorContext& context) { |
| 348 undoFrameViewContentClipAndScroll; | |
| 349 | |
| 350 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled() && | |
| 351 object.isLayoutView() && !object.isPaintInvalidationContainer()) { | |
| 352 undoFrameViewContentClipAndScroll.emplace(*toLayoutView(object).frameView(), | |
| 353 context); | |
| 354 } | |
| 355 | |
| 356 // TODO(crbug.com/637313): Use GeometryMapper which now supports filter | 348 // TODO(crbug.com/637313): Use GeometryMapper which now supports filter |
| 357 // geometry effects, after skia optimizes filter's mapRect operation. | 349 // geometry effects, after skia optimizes filter's mapRect operation. |
| 358 // TODO(crbug.com/648274): This is a workaround for multi-column contents. | 350 // TODO(crbug.com/648274): This is a workaround for multi-column contents. |
| 359 if (object.hasFilterInducingProperty() || object.isLayoutFlowThread()) { | 351 if (object.hasFilterInducingProperty() || object.isLayoutFlowThread()) { |
| 360 context.forcedSubtreeInvalidationFlags |= | 352 context.forcedSubtreeInvalidationFlags |= |
| 361 PaintInvalidatorContext::ForcedSubtreeSlowPathRect; | 353 PaintInvalidatorContext::ForcedSubtreeSlowPathRect; |
| 362 } | 354 } |
| 363 | 355 |
| 364 ObjectPaintInvalidator objectPaintInvalidator(object); | 356 ObjectPaintInvalidator objectPaintInvalidator(object); |
| 365 context.oldVisualRect = object.visualRect(); | 357 context.oldVisualRect = object.visualRect(); |
| 366 context.oldLocation = objectPaintInvalidator.locationInBacking(); | 358 context.oldLocation = objectPaintInvalidator.locationInBacking(); |
| 367 | 359 |
| 360 if (!needsVisualRectUpdate(object, context)) { |
| 361 #if CHECK_VISUAL_RECT_UPDATE |
| 362 updateVisualRect(object, context); |
| 363 DCHECK( |
| 364 (context.oldVisualRect.isEmpty() && context.newVisualRect.isEmpty()) || |
| 365 enclosingIntRect(context.oldVisualRect) == |
| 366 enclosingIntRect(context.newVisualRect)) |
| 367 << "Visual rect changed without needsPaintOffsetAndVisualRectUpdate:" |
| 368 << " object=" << object.debugName() |
| 369 << " old=" << context.oldVisualRect.toString() |
| 370 << " new=" << context.newVisualRect.toString(); |
| 371 DCHECK(object.isText() || context.oldLocation == context.newLocation) |
| 372 << "Location changed without needsPaintOffsetAndVisualRectUpdate:" |
| 373 << " old=" << context.oldLocation.toString() |
| 374 << " new=" << context.newLocation.toString(); |
| 375 #endif |
| 376 context.newVisualRect = context.oldVisualRect; |
| 377 context.newLocation = context.oldLocation; |
| 378 return; |
| 379 } |
| 380 |
| 381 #if DCHECK_IS_ON() |
| 382 DCHECK(context.treeBuilderContext.updatedForSelf); |
| 383 #endif |
| 384 updateVisualRect(object, context); |
| 385 object.getMutableForPainting().setVisualRect(context.newVisualRect); |
| 386 objectPaintInvalidator.setLocationInBacking(context.newLocation); |
| 387 } |
| 388 |
| 389 void PaintInvalidator::updateVisualRect(const LayoutObject& object, |
| 390 PaintInvalidatorContext& context) { |
| 391 // The paint offset should already be updated through |
| 392 // PaintPropertyTreeBuilder::updatePropertiesForSelf. |
| 393 DCHECK(context.treeBuilderContext.current.paintOffset == |
| 394 object.paintOffset()); |
| 395 |
| 396 Optional<ScopedUndoFrameViewContentClipAndScroll> |
| 397 undoFrameViewContentClipAndScroll; |
| 398 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled() && |
| 399 object.isLayoutView() && !object.isPaintInvalidationContainer()) { |
| 400 undoFrameViewContentClipAndScroll.emplace(*toLayoutView(object).frameView(), |
| 401 context); |
| 402 } |
| 403 |
| 368 IntSize adjustment = object.scrollAdjustmentForPaintInvalidation( | 404 IntSize adjustment = object.scrollAdjustmentForPaintInvalidation( |
| 369 *context.paintInvalidationContainer); | 405 *context.paintInvalidationContainer); |
| 370 context.newVisualRect = computeVisualRectInBacking(object, context); | 406 context.newVisualRect = computeVisualRectInBacking(object, context); |
| 371 context.newVisualRect.move(adjustment); | 407 context.newVisualRect.move(adjustment); |
| 372 | 408 |
| 373 if (object.isText()) { | 409 if (object.isText()) { |
| 374 // Use visual rect location for LayoutTexts because it suffices to check | 410 // Use visual rect location for LayoutTexts because it suffices to check |
| 375 // whether a visual rect changes for layout caused invalidation. | 411 // whether a visual rect changes for layout caused invalidation. |
| 376 context.newLocation = context.newVisualRect.location(); | 412 context.newLocation = context.newVisualRect.location(); |
| 377 } else { | 413 } else { |
| 378 context.newLocation = computeLocationInBacking(object, context); | 414 context.newLocation = computeLocationInBacking(object, context); |
| 379 context.newLocation.move(adjustment); | 415 context.newLocation.move(adjustment); |
| 380 | 416 |
| 381 // Location of empty visual rect doesn't affect paint invalidation. Set it | 417 // Location of empty visual rect doesn't affect paint invalidation. Set it |
| 382 // to newLocation to avoid saving the previous location separately in | 418 // to newLocation to avoid saving the previous location separately in |
| 383 // ObjectPaintInvalidator. | 419 // ObjectPaintInvalidator. |
| 384 if (context.newVisualRect.isEmpty()) | 420 if (context.newVisualRect.isEmpty()) |
| 385 context.newVisualRect.setLocation(context.newLocation); | 421 context.newVisualRect.setLocation(context.newLocation); |
| 386 } | 422 } |
| 387 | |
| 388 object.getMutableForPainting().setVisualRect(context.newVisualRect); | |
| 389 objectPaintInvalidator.setLocationInBacking(context.newLocation); | |
| 390 } | 423 } |
| 391 | 424 |
| 392 void PaintInvalidator::invalidatePaintIfNeeded( | 425 void PaintInvalidator::invalidatePaintIfNeeded( |
| 393 FrameView& frameView, | 426 FrameView& frameView, |
| 394 PaintInvalidatorContext& context) { | 427 PaintInvalidatorContext& context) { |
| 395 LayoutView* layoutView = frameView.layoutView(); | 428 LayoutView* layoutView = frameView.layoutView(); |
| 396 CHECK(layoutView); | 429 CHECK(layoutView); |
| 397 | 430 |
| 398 context.paintInvalidationContainer = | 431 context.paintInvalidationContainer = |
| 399 context.paintInvalidationContainerForStackedContents = | 432 context.paintInvalidationContainerForStackedContents = |
| 400 &layoutView->containerForPaintInvalidation(); | 433 &layoutView->containerForPaintInvalidation(); |
| 401 context.paintingLayer = layoutView->layer(); | 434 context.paintingLayer = layoutView->layer(); |
| 402 | 435 |
| 403 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { | 436 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
| 404 ScopedUndoFrameViewContentClipAndScroll undo(frameView, context); | 437 ScopedUndoFrameViewContentClipAndScroll undo(frameView, context); |
| 405 frameView.invalidatePaintOfScrollControlsIfNeeded(context); | 438 frameView.invalidatePaintOfScrollControlsIfNeeded(context); |
| 406 } | 439 } |
| 407 } | 440 } |
| 408 | 441 |
| 409 void PaintInvalidator::invalidatePaintIfNeeded( | 442 void PaintInvalidator::invalidatePaintIfNeeded( |
| 410 const LayoutObject& object, | 443 const LayoutObject& object, |
| 411 PaintInvalidatorContext& context) { | 444 PaintInvalidatorContext& context) { |
| 412 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), | 445 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), |
| 413 "PaintInvalidator::invalidatePaintIfNeeded()", "object", | 446 "PaintInvalidator::invalidatePaintIfNeeded()", "object", |
| 414 object.debugName().ascii()); | 447 object.debugName().ascii()); |
| 415 | 448 |
| 416 object.getMutableForPainting().ensureIsReadyForPaintInvalidation(); | 449 object.getMutableForPainting().ensureIsReadyForPaintInvalidation(); |
| 417 | 450 |
| 418 // The paint offset should already be updated through | |
| 419 // PaintPropertyTreeBuilder::updatePropertiesForSelf. | |
| 420 DCHECK(context.treeBuilderContext.current.paintOffset == | |
| 421 object.paintOffset()); | |
| 422 | |
| 423 updatePaintingLayer(object, context); | 451 updatePaintingLayer(object, context); |
| 424 | 452 |
| 425 if (object.document().printing() && | 453 if (object.document().printing() && |
| 426 !RuntimeEnabledFeatures::printBrowserEnabled()) | 454 !RuntimeEnabledFeatures::printBrowserEnabled()) |
| 427 return; // Don't invalidate paints if we're printing. | 455 return; // Don't invalidate paints if we're printing. |
| 428 | 456 |
| 429 updatePaintInvalidationContainer(object, context); | 457 updatePaintInvalidationContainer(object, context); |
| 458 updateVisualRectIfNeeded(object, context); |
| 430 | 459 |
| 431 bool objectShouldCheckForPaintInvalidation = | 460 if (!object |
| 432 object | 461 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState()
&& |
| 433 .shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState(); | 462 !(context.forcedSubtreeInvalidationFlags & |
| 434 if (!context.forcedSubtreeInvalidationFlags && | 463 ~PaintInvalidatorContext::ForcedSubtreeVisualRectUpdate)) { |
| 435 !objectShouldCheckForPaintInvalidation) { | 464 // We are done updating anything needed. No other paint invalidation work to |
| 436 #if CHECK_VISUAL_RECT_UPDATE | |
| 437 updateVisualRect(object, context); | |
| 438 DCHECK( | |
| 439 (context.oldVisualRect.isEmpty() && context.newVisualRect.isEmpty()) || | |
| 440 enclosingIntRect(context.oldVisualRect) == | |
| 441 enclosingIntRect(context.newVisualRect)) | |
| 442 << "Visual rect changed without needing paint invalidation:" | |
| 443 << " object=" << object.debugName() | |
| 444 << " old=" << context.oldVisualRect.toString() | |
| 445 << " new=" << context.newVisualRect.toString(); | |
| 446 DCHECK(object.isText() || context.oldLocation == context.newLocation) | |
| 447 << "Location changed without needing paint invalidation:" | |
| 448 << " old=" << context.oldLocation.toString() | |
| 449 << " new=" << context.newLocation.toString(); | |
| 450 #endif | |
| 451 return; | |
| 452 } | |
| 453 | |
| 454 updateVisualRect(object, context); | |
| 455 | |
| 456 if (!objectShouldCheckForPaintInvalidation && | |
| 457 context.forcedSubtreeInvalidationFlags == | |
| 458 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate) { | |
| 459 // We are done updating the visual rect. No other paint invalidation work to | |
| 460 // do for this object. | 465 // do for this object. |
| 461 return; | 466 return; |
| 462 } | 467 } |
| 463 | 468 |
| 464 PaintInvalidationReason reason = object.invalidatePaintIfNeeded(context); | 469 PaintInvalidationReason reason = object.invalidatePaintIfNeeded(context); |
| 465 switch (reason) { | 470 switch (reason) { |
| 466 case PaintInvalidationDelayedFull: | 471 case PaintInvalidationDelayedFull: |
| 467 m_pendingDelayedPaintInvalidations.push_back(&object); | 472 m_pendingDelayedPaintInvalidations.push_back(&object); |
| 468 break; | 473 break; |
| 469 case PaintInvalidationSubtree: | 474 case PaintInvalidationSubtree: |
| (...skipping 20 matching lines...) Expand all Loading... |
| 490 PaintInvalidatorContext::ForcedSubtreeInvalidationChecking; | 495 PaintInvalidatorContext::ForcedSubtreeInvalidationChecking; |
| 491 } | 496 } |
| 492 } | 497 } |
| 493 | 498 |
| 494 void PaintInvalidator::processPendingDelayedPaintInvalidations() { | 499 void PaintInvalidator::processPendingDelayedPaintInvalidations() { |
| 495 for (auto target : m_pendingDelayedPaintInvalidations) | 500 for (auto target : m_pendingDelayedPaintInvalidations) |
| 496 target->getMutableForPainting().setShouldDoFullPaintInvalidation( | 501 target->getMutableForPainting().setShouldDoFullPaintInvalidation( |
| 497 PaintInvalidationDelayedFull); | 502 PaintInvalidationDelayedFull); |
| 498 } | 503 } |
| 499 | 504 |
| 505 bool PaintInvalidator::needsVisualRectUpdate( |
| 506 const LayoutObject& object, |
| 507 const PaintInvalidatorContext& context) { |
| 508 return object.needsPaintOffsetAndVisualRectUpdate() || |
| 509 (context.forcedSubtreeInvalidationFlags & |
| 510 ~PaintInvalidatorContext::ForcedSubtreeSlowPathRect); |
| 511 } |
| 512 |
| 500 } // namespace blink | 513 } // namespace blink |
| OLD | NEW |