Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(443)

Side by Side Diff: third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp

Issue 2194273002: Fix border radius on composited children. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update the comment on why we say an empty div can paint Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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)))) {
375 paintingInfo.ancestorHasClipPathClipping = true; 376 paintingInfo.ancestorHasClipPathClipping = true;
376 377
377 LayoutRect referenceBox(m_paintLayer.boxForClipPath()); 378 LayoutRect referenceBox(m_paintLayer.boxForClipPath());
378 // Note that this isn't going to work correctly if crossing a column 379 // Note that this isn't going to work correctly if crossing a column
379 // boundary. The reference box should be determined per-fragment, and hence 380 // boundary. The reference box should be determined per-fragment, and hence
380 // this ought to be performed after fragmentation. 381 // this ought to be performed after fragmentation.
381 if (m_paintLayer.enclosingPaginationLayer()) 382 if (m_paintLayer.enclosingPaginationLayer())
382 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor( 383 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor(
383 paintingInfo.rootLayer, referenceBox); 384 paintingInfo.rootLayer, referenceBox);
384 else 385 else
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 isSelfPaintingLayer && !isPaintingOverlayScrollbars; 421 isSelfPaintingLayer && !isPaintingOverlayScrollbars;
421 422
422 PaintLayerFragments layerFragments; 423 PaintLayerFragments layerFragments;
423 if (shouldPaintContent || shouldPaintSelfOutline || 424 if (shouldPaintContent || shouldPaintSelfOutline ||
424 isPaintingOverlayScrollbars) { 425 isPaintingOverlayScrollbars) {
425 // Collect the fragments. This will compute the clip rectangles and paint 426 // Collect the fragments. This will compute the clip rectangles and paint
426 // offsets for each layer fragment. 427 // offsets for each layer fragment.
427 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) 428 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects)
428 ? UncachedClipRects 429 ? UncachedClipRects
429 : PaintingClipRects; 430 : 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
430 // TODO(trchen): We haven't decided how to handle visual fragmentation with 447 // TODO(trchen): We haven't decided how to handle visual fragmentation with
431 // SPv2. Related thread 448 // SPv2. Related thread
432 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM 449 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM
433 if (fragmentPolicy == ForceSingleFragment || 450 if (fragmentPolicy == ForceSingleFragment ||
434 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 451 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
435 m_paintLayer.appendSingleFragmentIgnoringPagination( 452 paintLayerForFragments->appendSingleFragmentIgnoringPagination(
436 layerFragments, localPaintingInfo.rootLayer, 453 layerFragments, localPaintingInfo.rootLayer,
437 localPaintingInfo.paintDirtyRect, cacheSlot, 454 localPaintingInfo.paintDirtyRect, cacheSlot,
438 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, 455 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot,
439 localPaintingInfo.subPixelAccumulation); 456 localPaintingInfo.subPixelAccumulation);
440 else 457 } else {
441 m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, 458 paintLayerForFragments->collectFragments(
442 localPaintingInfo.paintDirtyRect, cacheSlot, 459 layerFragments, localPaintingInfo.rootLayer,
443 IgnoreOverlayScrollbarSize, 460 localPaintingInfo.paintDirtyRect, cacheSlot,
444 respectOverflowClip, &offsetFromRoot, 461 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot,
445 localPaintingInfo.subPixelAccumulation); 462 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 }
446 476
447 if (shouldPaintContent) { 477 if (shouldPaintContent) {
448 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar 478 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar
449 // optimization for slimming paint v2. 479 // optimization for slimming paint v2.
450 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect( 480 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect(
451 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot); 481 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot);
452 if (!shouldPaintContent) 482 if (!shouldPaintContent)
453 result = MayBeClippedByPaintDirtyRect; 483 result = MayBeClippedByPaintDirtyRect;
454 } 484 }
455 } 485 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 if (shouldPaintOverlayScrollbars) 569 if (shouldPaintOverlayScrollbars)
540 paintOverflowControlsForFragments(layerFragments, context, 570 paintOverflowControlsForFragments(layerFragments, context,
541 localPaintingInfo, paintFlags); 571 localPaintingInfo, paintFlags);
542 } // FilterPainter block 572 } // FilterPainter block
543 573
544 bool shouldPaintMask = 574 bool shouldPaintMask =
545 (paintFlags & PaintLayerPaintingCompositingMaskPhase) && 575 (paintFlags & PaintLayerPaintingCompositingMaskPhase) &&
546 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() && 576 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() &&
547 !selectionOnly; 577 !selectionOnly;
548 bool shouldPaintClippingMask = 578 bool shouldPaintClippingMask =
549 (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && 579 (paintFlags & (PaintLayerPaintingChildClippingMaskPhase |
580 PaintLayerPaintingAncestorClippingMaskPhase)) &&
550 shouldPaintContent && !selectionOnly; 581 shouldPaintContent && !selectionOnly;
551 582
552 if (shouldPaintMask) 583 if (shouldPaintMask)
553 paintMaskForFragments(layerFragments, context, localPaintingInfo, 584 paintMaskForFragments(layerFragments, context, localPaintingInfo,
554 paintFlags); 585 paintFlags);
555 if (shouldPaintClippingMask) { 586 if (shouldPaintClippingMask) {
556 // Paint the border radius mask for the fragments. 587 // Paint the border radius mask for the fragments.
557 paintChildClippingMaskForFragments(layerFragments, context, 588 paintChildClippingMaskForFragments(layerFragments, context,
558 localPaintingInfo, paintFlags); 589 localPaintingInfo, paintFlags);
559 } 590 }
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 if (needsToClip(paintingInfo, clipRectForFragment)) { 745 if (needsToClip(paintingInfo, clipRectForFragment)) {
715 if (m_paintLayer.layoutObject()->isPositioned() && 746 if (m_paintLayer.layoutObject()->isPositioned() &&
716 clipRectForFragment.isClippedByClipCss()) 747 clipRectForFragment.isClippedByClipCss())
717 UseCounter::count(m_paintLayer.layoutObject()->document(), 748 UseCounter::count(m_paintLayer.layoutObject()->document(),
718 UseCounter::ClipCssOfPositionedElement); 749 UseCounter::ClipCssOfPositionedElement);
719 if (m_paintLayer.layoutObject()->isFixedPositioned()) 750 if (m_paintLayer.layoutObject()->isFixedPositioned())
720 UseCounter::count(m_paintLayer.layoutObject()->document(), 751 UseCounter::count(m_paintLayer.layoutObject()->document(),
721 UseCounter::ClipCssOfFixedPositionElement); 752 UseCounter::ClipCssOfFixedPositionElement);
722 clipRecorder.emplace(context, *parentLayer->layoutObject(), 753 clipRecorder.emplace(context, *parentLayer->layoutObject(),
723 DisplayItem::kClipLayerParent, clipRectForFragment, 754 DisplayItem::kClipLayerParent, clipRectForFragment,
724 &paintingInfo, fragment.paginationOffset, 755 paintingInfo.rootLayer, fragment.paginationOffset,
725 paintFlags); 756 paintFlags);
726 } 757 }
727 } 758 }
728 if (paintFragmentByApplyingTransform(context, paintingInfo, paintFlags, 759 if (paintFragmentByApplyingTransform(context, paintingInfo, paintFlags,
729 fragment.paginationOffset) == 760 fragment.paginationOffset) ==
730 MayBeClippedByPaintDirtyRect) 761 MayBeClippedByPaintDirtyRect)
731 result = MayBeClippedByPaintDirtyRect; 762 result = MayBeClippedByPaintDirtyRect;
732 } 763 }
733 return result; 764 return result;
734 } 765 }
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 883
853 for (auto& fragment : layerFragments) { 884 for (auto& fragment : layerFragments) {
854 // We need to apply the same clips and transforms that 885 // We need to apply the same clips and transforms that
855 // paintFragmentWithPhase would have. 886 // paintFragmentWithPhase would have.
856 LayoutRect cullRect = fragment.backgroundRect.rect(); 887 LayoutRect cullRect = fragment.backgroundRect.rect();
857 888
858 Optional<LayerClipRecorder> clipRecorder; 889 Optional<LayerClipRecorder> clipRecorder;
859 if (needsToClip(localPaintingInfo, fragment.backgroundRect)) { 890 if (needsToClip(localPaintingInfo, fragment.backgroundRect)) {
860 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), 891 clipRecorder.emplace(context, *m_paintLayer.layoutObject(),
861 DisplayItem::kClipLayerOverflowControls, 892 DisplayItem::kClipLayerOverflowControls,
862 fragment.backgroundRect, &localPaintingInfo, 893 fragment.backgroundRect, localPaintingInfo.rootLayer,
863 fragment.paginationOffset, paintFlags); 894 fragment.paginationOffset, paintFlags);
864 } 895 }
865 896
866 Optional<ScrollRecorder> scrollRecorder; 897 Optional<ScrollRecorder> scrollRecorder;
867 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && 898 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() &&
868 !localPaintingInfo.scrollOffsetAccumulation.isZero()) { 899 !localPaintingInfo.scrollOffsetAccumulation.isZero()) {
869 cullRect.move(localPaintingInfo.scrollOffsetAccumulation); 900 cullRect.move(localPaintingInfo.scrollOffsetAccumulation);
870 scrollRecorder.emplace(context, *m_paintLayer.layoutObject(), 901 scrollRecorder.emplace(context, *m_paintLayer.layoutObject(),
871 DisplayItem::kScrollOverflowControls, 902 DisplayItem::kScrollOverflowControls,
872 localPaintingInfo.scrollOffsetAccumulation); 903 localPaintingInfo.scrollOffsetAccumulation);
(...skipping 29 matching lines...) Expand all
902 // handle clipping to self. 933 // handle clipping to self.
903 case PaintPhaseSelfOutlineOnly: 934 case PaintPhaseSelfOutlineOnly:
904 case PaintPhaseMask: // Mask painting will handle clipping to self. 935 case PaintPhaseMask: // Mask painting will handle clipping to self.
905 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius; 936 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius;
906 break; 937 break;
907 default: 938 default:
908 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius; 939 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius;
909 break; 940 break;
910 } 941 }
911 942
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
912 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, 946 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType,
913 clipRect, &paintingInfo, fragment.paginationOffset, 947 clipRect, paintingInfo.rootLayer,
914 paintFlags, clippingRule); 948 fragment.paginationOffset, paintFlags, clippingRule);
915 } 949 }
916 950
917 LayoutRect newCullRect(clipRect.rect()); 951 LayoutRect newCullRect(clipRect.rect());
918 Optional<ScrollRecorder> scrollRecorder; 952 Optional<ScrollRecorder> scrollRecorder;
919 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation(); 953 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation();
920 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { 954 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
921 const auto* objectPaintProperties = 955 const auto* objectPaintProperties =
922 m_paintLayer.layoutObject()->paintProperties(); 956 m_paintLayer.layoutObject()->paintProperties();
923 DCHECK(objectPaintProperties && 957 DCHECK(objectPaintProperties &&
924 objectPaintProperties->localBorderBoxProperties()); 958 objectPaintProperties->localBorderBoxProperties());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
976 // Optimize clipping for the single fragment case. 1010 // Optimize clipping for the single fragment case.
977 bool shouldClip = localPaintingInfo.clipToDirtyRect && 1011 bool shouldClip = localPaintingInfo.clipToDirtyRect &&
978 layerFragments.size() == 1 && 1012 layerFragments.size() == 1 &&
979 !layerFragments[0].foregroundRect.isEmpty(); 1013 !layerFragments[0].foregroundRect.isEmpty();
980 ClipState clipState = HasNotClipped; 1014 ClipState clipState = HasNotClipped;
981 Optional<LayerClipRecorder> clipRecorder; 1015 Optional<LayerClipRecorder> clipRecorder;
982 if (shouldClip && 1016 if (shouldClip &&
983 needsToClip(localPaintingInfo, layerFragments[0].foregroundRect)) { 1017 needsToClip(localPaintingInfo, layerFragments[0].foregroundRect)) {
984 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), 1018 clipRecorder.emplace(context, *m_paintLayer.layoutObject(),
985 DisplayItem::kClipLayerForeground, 1019 DisplayItem::kClipLayerForeground,
986 layerFragments[0].foregroundRect, &localPaintingInfo, 1020 layerFragments[0].foregroundRect,
1021 localPaintingInfo.rootLayer,
987 layerFragments[0].paginationOffset, paintFlags); 1022 layerFragments[0].paginationOffset, paintFlags);
988 clipState = HasClipped; 1023 clipState = HasClipped;
989 } 1024 }
990 1025
991 // We have to loop through every fragment multiple times, since we have to 1026 // We have to loop through every fragment multiple times, since we have to
992 // issue paint invalidations in each specific phase in order for interleaving 1027 // issue paint invalidations in each specific phase in order for interleaving
993 // of the fragments to work properly. 1028 // of the fragments to work properly.
994 if (selectionOnly) { 1029 if (selectionOnly) {
995 paintForegroundForFragmentsWithPhase(PaintPhaseSelection, layerFragments, 1030 paintForegroundForFragmentsWithPhase(PaintPhaseSelection, layerFragments,
996 context, localPaintingInfo, paintFlags, 1031 context, localPaintingInfo, paintFlags,
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1123 1158
1124 PaintLayerPaintingInfo paintingInfo(&m_paintLayer, 1159 PaintLayerPaintingInfo paintingInfo(&m_paintLayer,
1125 LayoutRect(enclosingIntRect(damageRect)), 1160 LayoutRect(enclosingIntRect(damageRect)),
1126 paintFlags, LayoutSize()); 1161 paintFlags, LayoutSize());
1127 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); 1162 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars);
1128 1163
1129 m_paintLayer.setContainsDirtyOverlayScrollbars(false); 1164 m_paintLayer.setContainsDirtyOverlayScrollbars(false);
1130 } 1165 }
1131 1166
1132 } // namespace blink 1167 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698