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 |