| 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/paint/PaintLayerPainter.h" | 5 #include "core/paint/PaintLayerPainter.h" |
| 6 | 6 |
| 7 #include "core/frame/LocalFrame.h" | 7 #include "core/frame/LocalFrame.h" |
| 8 #include "core/layout/LayoutView.h" | 8 #include "core/layout/LayoutView.h" |
| 9 #include "core/paint/ClipPathClipper.h" | 9 #include "core/paint/ClipPathClipper.h" |
| 10 #include "core/paint/FilterPainter.h" | 10 #include "core/paint/FilterPainter.h" |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 // These helpers output clip and compositing operations using a RAII pattern. | 364 // These helpers output clip and compositing operations using a RAII pattern. |
| 365 // Stack-allocated-varibles are destructed in the reverse order of | 365 // Stack-allocated-varibles are destructed in the reverse order of |
| 366 // construction, so they are nested properly. | 366 // construction, so they are nested properly. |
| 367 Optional<ClipPathClipper> clipPathClipper; | 367 Optional<ClipPathClipper> clipPathClipper; |
| 368 // Clip-path, like border radius, must not be applied to the contents of a | 368 // Clip-path, like border radius, must not be applied to the contents of a |
| 369 // composited-scrolling container. It must, however, still be applied to the | 369 // composited-scrolling container. It must, however, still be applied to the |
| 370 // mask layer, so that the compositor can properly mask the | 370 // mask layer, so that the compositor can properly mask the |
| 371 // scrolling contents and scrollbars. | 371 // scrolling contents and scrollbars. |
| 372 if (m_paintLayer.layoutObject()->hasClipPath() && | 372 if (m_paintLayer.layoutObject()->hasClipPath() && |
| 373 (!m_paintLayer.needsCompositedScrolling() || | 373 (!m_paintLayer.needsCompositedScrolling() || |
| 374 (paintFlags & (PaintLayerPaintingChildClippingMaskPhase | | 374 (paintFlags & PaintLayerPaintingChildClippingMaskPhase))) { |
| 375 PaintLayerPaintingAncestorClippingMaskPhase)))) { | |
| 376 paintingInfo.ancestorHasClipPathClipping = true; | 375 paintingInfo.ancestorHasClipPathClipping = true; |
| 377 | 376 |
| 378 LayoutRect referenceBox(m_paintLayer.boxForClipPath()); | 377 LayoutRect referenceBox(m_paintLayer.boxForClipPath()); |
| 379 // Note that this isn't going to work correctly if crossing a column | 378 // Note that this isn't going to work correctly if crossing a column |
| 380 // boundary. The reference box should be determined per-fragment, and hence | 379 // boundary. The reference box should be determined per-fragment, and hence |
| 381 // this ought to be performed after fragmentation. | 380 // this ought to be performed after fragmentation. |
| 382 if (m_paintLayer.enclosingPaginationLayer()) | 381 if (m_paintLayer.enclosingPaginationLayer()) |
| 383 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor( | 382 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor( |
| 384 paintingInfo.rootLayer, referenceBox); | 383 paintingInfo.rootLayer, referenceBox); |
| 385 else | 384 else |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 isSelfPaintingLayer && !isPaintingOverlayScrollbars; | 420 isSelfPaintingLayer && !isPaintingOverlayScrollbars; |
| 422 | 421 |
| 423 PaintLayerFragments layerFragments; | 422 PaintLayerFragments layerFragments; |
| 424 if (shouldPaintContent || shouldPaintSelfOutline || | 423 if (shouldPaintContent || shouldPaintSelfOutline || |
| 425 isPaintingOverlayScrollbars) { | 424 isPaintingOverlayScrollbars) { |
| 426 // Collect the fragments. This will compute the clip rectangles and paint | 425 // Collect the fragments. This will compute the clip rectangles and paint |
| 427 // offsets for each layer fragment. | 426 // offsets for each layer fragment. |
| 428 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) | 427 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) |
| 429 ? UncachedClipRects | 428 ? UncachedClipRects |
| 430 : PaintingClipRects; | 429 : PaintingClipRects; |
| 431 LayoutPoint offsetToClipper; | |
| 432 PaintLayer* paintLayerForFragments = &m_paintLayer; | |
| 433 if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) { | |
| 434 // Compute fragments and their clips with respect to the clipping | |
| 435 // container. The paint rect is in this layer's space, so convert it | |
| 436 // to the clipper's layer's space. The rootLayer is also changed to | |
| 437 // the clipper's layer to simplify coordinate system adjustments. | |
| 438 // The change to rootLayer must persist to correctly record the clips. | |
| 439 paintLayerForFragments = | |
| 440 m_paintLayer.clippingContainer()->enclosingLayer(); | |
| 441 localPaintingInfo.rootLayer = paintLayerForFragments; | |
| 442 m_paintLayer.convertToLayerCoords(localPaintingInfo.rootLayer, | |
| 443 offsetToClipper); | |
| 444 localPaintingInfo.paintDirtyRect.moveBy(offsetToClipper); | |
| 445 } | |
| 446 | |
| 447 // TODO(trchen): We haven't decided how to handle visual fragmentation with | 430 // TODO(trchen): We haven't decided how to handle visual fragmentation with |
| 448 // SPv2. Related thread | 431 // SPv2. Related thread |
| 449 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW
Ff-mxM | 432 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW
Ff-mxM |
| 450 if (fragmentPolicy == ForceSingleFragment || | 433 if (fragmentPolicy == ForceSingleFragment || |
| 451 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 434 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 452 paintLayerForFragments->appendSingleFragmentIgnoringPagination( | 435 m_paintLayer.appendSingleFragmentIgnoringPagination( |
| 453 layerFragments, localPaintingInfo.rootLayer, | 436 layerFragments, localPaintingInfo.rootLayer, |
| 454 localPaintingInfo.paintDirtyRect, cacheSlot, | 437 localPaintingInfo.paintDirtyRect, cacheSlot, |
| 455 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, | 438 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, |
| 456 localPaintingInfo.subPixelAccumulation); | 439 localPaintingInfo.subPixelAccumulation); |
| 457 } else { | 440 else |
| 458 paintLayerForFragments->collectFragments( | 441 m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, |
| 459 layerFragments, localPaintingInfo.rootLayer, | 442 localPaintingInfo.paintDirtyRect, cacheSlot, |
| 460 localPaintingInfo.paintDirtyRect, cacheSlot, | 443 IgnoreOverlayScrollbarSize, |
| 461 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, | 444 respectOverflowClip, &offsetFromRoot, |
| 462 localPaintingInfo.subPixelAccumulation); | 445 localPaintingInfo.subPixelAccumulation); |
| 463 } | |
| 464 | |
| 465 if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) { | |
| 466 // Fragment offsets have been computed in the clipping container's | |
| 467 // layer's coordinate system, but for the rest of painting we need | |
| 468 // them in the layer coordinate. So move them and the foreground rect | |
| 469 // that is also in the clipper's space. | |
| 470 LayoutSize negativeOffset(-offsetToClipper.x(), -offsetToClipper.y()); | |
| 471 for (auto& fragment : layerFragments) { | |
| 472 fragment.foregroundRect.move(negativeOffset); | |
| 473 fragment.paginationOffset.move(negativeOffset); | |
| 474 } | |
| 475 } | |
| 476 | 446 |
| 477 if (shouldPaintContent) { | 447 if (shouldPaintContent) { |
| 478 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar | 448 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar |
| 479 // optimization for slimming paint v2. | 449 // optimization for slimming paint v2. |
| 480 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect( | 450 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect( |
| 481 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot); | 451 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot); |
| 482 if (!shouldPaintContent) | 452 if (!shouldPaintContent) |
| 483 result = MayBeClippedByPaintDirtyRect; | 453 result = MayBeClippedByPaintDirtyRect; |
| 484 } | 454 } |
| 485 } | 455 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 if (shouldPaintOverlayScrollbars) | 539 if (shouldPaintOverlayScrollbars) |
| 570 paintOverflowControlsForFragments(layerFragments, context, | 540 paintOverflowControlsForFragments(layerFragments, context, |
| 571 localPaintingInfo, paintFlags); | 541 localPaintingInfo, paintFlags); |
| 572 } // FilterPainter block | 542 } // FilterPainter block |
| 573 | 543 |
| 574 bool shouldPaintMask = | 544 bool shouldPaintMask = |
| 575 (paintFlags & PaintLayerPaintingCompositingMaskPhase) && | 545 (paintFlags & PaintLayerPaintingCompositingMaskPhase) && |
| 576 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() && | 546 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() && |
| 577 !selectionOnly; | 547 !selectionOnly; |
| 578 bool shouldPaintClippingMask = | 548 bool shouldPaintClippingMask = |
| 579 (paintFlags & (PaintLayerPaintingChildClippingMaskPhase | | 549 (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && |
| 580 PaintLayerPaintingAncestorClippingMaskPhase)) && | |
| 581 shouldPaintContent && !selectionOnly; | 550 shouldPaintContent && !selectionOnly; |
| 582 | 551 |
| 583 if (shouldPaintMask) | 552 if (shouldPaintMask) |
| 584 paintMaskForFragments(layerFragments, context, localPaintingInfo, | 553 paintMaskForFragments(layerFragments, context, localPaintingInfo, |
| 585 paintFlags); | 554 paintFlags); |
| 586 if (shouldPaintClippingMask) { | 555 if (shouldPaintClippingMask) { |
| 587 // Paint the border radius mask for the fragments. | 556 // Paint the border radius mask for the fragments. |
| 588 paintChildClippingMaskForFragments(layerFragments, context, | 557 paintChildClippingMaskForFragments(layerFragments, context, |
| 589 localPaintingInfo, paintFlags); | 558 localPaintingInfo, paintFlags); |
| 590 } | 559 } |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 if (needsToClip(paintingInfo, clipRectForFragment)) { | 714 if (needsToClip(paintingInfo, clipRectForFragment)) { |
| 746 if (m_paintLayer.layoutObject()->isPositioned() && | 715 if (m_paintLayer.layoutObject()->isPositioned() && |
| 747 clipRectForFragment.isClippedByClipCss()) | 716 clipRectForFragment.isClippedByClipCss()) |
| 748 UseCounter::count(m_paintLayer.layoutObject()->document(), | 717 UseCounter::count(m_paintLayer.layoutObject()->document(), |
| 749 UseCounter::ClipCssOfPositionedElement); | 718 UseCounter::ClipCssOfPositionedElement); |
| 750 if (m_paintLayer.layoutObject()->isFixedPositioned()) | 719 if (m_paintLayer.layoutObject()->isFixedPositioned()) |
| 751 UseCounter::count(m_paintLayer.layoutObject()->document(), | 720 UseCounter::count(m_paintLayer.layoutObject()->document(), |
| 752 UseCounter::ClipCssOfFixedPositionElement); | 721 UseCounter::ClipCssOfFixedPositionElement); |
| 753 clipRecorder.emplace(context, *parentLayer->layoutObject(), | 722 clipRecorder.emplace(context, *parentLayer->layoutObject(), |
| 754 DisplayItem::kClipLayerParent, clipRectForFragment, | 723 DisplayItem::kClipLayerParent, clipRectForFragment, |
| 755 paintingInfo.rootLayer, fragment.paginationOffset, | 724 &paintingInfo, fragment.paginationOffset, |
| 756 paintFlags); | 725 paintFlags); |
| 757 } | 726 } |
| 758 } | 727 } |
| 759 if (paintFragmentByApplyingTransform(context, paintingInfo, paintFlags, | 728 if (paintFragmentByApplyingTransform(context, paintingInfo, paintFlags, |
| 760 fragment.paginationOffset) == | 729 fragment.paginationOffset) == |
| 761 MayBeClippedByPaintDirtyRect) | 730 MayBeClippedByPaintDirtyRect) |
| 762 result = MayBeClippedByPaintDirtyRect; | 731 result = MayBeClippedByPaintDirtyRect; |
| 763 } | 732 } |
| 764 return result; | 733 return result; |
| 765 } | 734 } |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 883 | 852 |
| 884 for (auto& fragment : layerFragments) { | 853 for (auto& fragment : layerFragments) { |
| 885 // We need to apply the same clips and transforms that | 854 // We need to apply the same clips and transforms that |
| 886 // paintFragmentWithPhase would have. | 855 // paintFragmentWithPhase would have. |
| 887 LayoutRect cullRect = fragment.backgroundRect.rect(); | 856 LayoutRect cullRect = fragment.backgroundRect.rect(); |
| 888 | 857 |
| 889 Optional<LayerClipRecorder> clipRecorder; | 858 Optional<LayerClipRecorder> clipRecorder; |
| 890 if (needsToClip(localPaintingInfo, fragment.backgroundRect)) { | 859 if (needsToClip(localPaintingInfo, fragment.backgroundRect)) { |
| 891 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), | 860 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), |
| 892 DisplayItem::kClipLayerOverflowControls, | 861 DisplayItem::kClipLayerOverflowControls, |
| 893 fragment.backgroundRect, localPaintingInfo.rootLayer, | 862 fragment.backgroundRect, &localPaintingInfo, |
| 894 fragment.paginationOffset, paintFlags); | 863 fragment.paginationOffset, paintFlags); |
| 895 } | 864 } |
| 896 | 865 |
| 897 Optional<ScrollRecorder> scrollRecorder; | 866 Optional<ScrollRecorder> scrollRecorder; |
| 898 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && | 867 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && |
| 899 !localPaintingInfo.scrollOffsetAccumulation.isZero()) { | 868 !localPaintingInfo.scrollOffsetAccumulation.isZero()) { |
| 900 cullRect.move(localPaintingInfo.scrollOffsetAccumulation); | 869 cullRect.move(localPaintingInfo.scrollOffsetAccumulation); |
| 901 scrollRecorder.emplace(context, *m_paintLayer.layoutObject(), | 870 scrollRecorder.emplace(context, *m_paintLayer.layoutObject(), |
| 902 DisplayItem::kScrollOverflowControls, | 871 DisplayItem::kScrollOverflowControls, |
| 903 localPaintingInfo.scrollOffsetAccumulation); | 872 localPaintingInfo.scrollOffsetAccumulation); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 933 // handle clipping to self. | 902 // handle clipping to self. |
| 934 case PaintPhaseSelfOutlineOnly: | 903 case PaintPhaseSelfOutlineOnly: |
| 935 case PaintPhaseMask: // Mask painting will handle clipping to self. | 904 case PaintPhaseMask: // Mask painting will handle clipping to self. |
| 936 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius; | 905 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius; |
| 937 break; | 906 break; |
| 938 default: | 907 default: |
| 939 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius; | 908 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius; |
| 940 break; | 909 break; |
| 941 } | 910 } |
| 942 | 911 |
| 943 // TODO(schenney): Nested border-radius clips are not applied to composited | |
| 944 // children, probably due to an incorrect clipRoot. | |
| 945 // https://bugs.chromium.org/p/chromium/issues/detail?id=672561 | |
| 946 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, | 912 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, |
| 947 clipRect, paintingInfo.rootLayer, | 913 clipRect, &paintingInfo, fragment.paginationOffset, |
| 948 fragment.paginationOffset, paintFlags, clippingRule); | 914 paintFlags, clippingRule); |
| 949 } | 915 } |
| 950 | 916 |
| 951 LayoutRect newCullRect(clipRect.rect()); | 917 LayoutRect newCullRect(clipRect.rect()); |
| 952 Optional<ScrollRecorder> scrollRecorder; | 918 Optional<ScrollRecorder> scrollRecorder; |
| 953 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation(); | 919 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation(); |
| 954 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 920 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 955 const auto* objectPaintProperties = | 921 const auto* objectPaintProperties = |
| 956 m_paintLayer.layoutObject()->paintProperties(); | 922 m_paintLayer.layoutObject()->paintProperties(); |
| 957 DCHECK(objectPaintProperties && | 923 DCHECK(objectPaintProperties && |
| 958 objectPaintProperties->localBorderBoxProperties()); | 924 objectPaintProperties->localBorderBoxProperties()); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 // Optimize clipping for the single fragment case. | 976 // Optimize clipping for the single fragment case. |
| 1011 bool shouldClip = localPaintingInfo.clipToDirtyRect && | 977 bool shouldClip = localPaintingInfo.clipToDirtyRect && |
| 1012 layerFragments.size() == 1 && | 978 layerFragments.size() == 1 && |
| 1013 !layerFragments[0].foregroundRect.isEmpty(); | 979 !layerFragments[0].foregroundRect.isEmpty(); |
| 1014 ClipState clipState = HasNotClipped; | 980 ClipState clipState = HasNotClipped; |
| 1015 Optional<LayerClipRecorder> clipRecorder; | 981 Optional<LayerClipRecorder> clipRecorder; |
| 1016 if (shouldClip && | 982 if (shouldClip && |
| 1017 needsToClip(localPaintingInfo, layerFragments[0].foregroundRect)) { | 983 needsToClip(localPaintingInfo, layerFragments[0].foregroundRect)) { |
| 1018 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), | 984 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), |
| 1019 DisplayItem::kClipLayerForeground, | 985 DisplayItem::kClipLayerForeground, |
| 1020 layerFragments[0].foregroundRect, | 986 layerFragments[0].foregroundRect, &localPaintingInfo, |
| 1021 localPaintingInfo.rootLayer, | |
| 1022 layerFragments[0].paginationOffset, paintFlags); | 987 layerFragments[0].paginationOffset, paintFlags); |
| 1023 clipState = HasClipped; | 988 clipState = HasClipped; |
| 1024 } | 989 } |
| 1025 | 990 |
| 1026 // We have to loop through every fragment multiple times, since we have to | 991 // We have to loop through every fragment multiple times, since we have to |
| 1027 // issue paint invalidations in each specific phase in order for interleaving | 992 // issue paint invalidations in each specific phase in order for interleaving |
| 1028 // of the fragments to work properly. | 993 // of the fragments to work properly. |
| 1029 if (selectionOnly) { | 994 if (selectionOnly) { |
| 1030 paintForegroundForFragmentsWithPhase(PaintPhaseSelection, layerFragments, | 995 paintForegroundForFragmentsWithPhase(PaintPhaseSelection, layerFragments, |
| 1031 context, localPaintingInfo, paintFlags, | 996 context, localPaintingInfo, paintFlags, |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 | 1123 |
| 1159 PaintLayerPaintingInfo paintingInfo(&m_paintLayer, | 1124 PaintLayerPaintingInfo paintingInfo(&m_paintLayer, |
| 1160 LayoutRect(enclosingIntRect(damageRect)), | 1125 LayoutRect(enclosingIntRect(damageRect)), |
| 1161 paintFlags, LayoutSize()); | 1126 paintFlags, LayoutSize()); |
| 1162 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); | 1127 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); |
| 1163 | 1128 |
| 1164 m_paintLayer.setContainsDirtyOverlayScrollbars(false); | 1129 m_paintLayer.setContainsDirtyOverlayScrollbars(false); |
| 1165 } | 1130 } |
| 1166 | 1131 |
| 1167 } // namespace blink | 1132 } // namespace blink |
| OLD | NEW |