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

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

Issue 2588853002: Fix border radius on composited children. (Closed)
Patch Set: SPV2 expectations Created 3 years, 11 months 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"
11 #include "core/paint/LayerClipRecorder.h" 11 #include "core/paint/LayerClipRecorder.h"
12 #include "core/paint/LayoutObjectDrawingRecorder.h"
12 #include "core/paint/ObjectPaintProperties.h" 13 #include "core/paint/ObjectPaintProperties.h"
13 #include "core/paint/PaintInfo.h" 14 #include "core/paint/PaintInfo.h"
14 #include "core/paint/PaintLayer.h" 15 #include "core/paint/PaintLayer.h"
15 #include "core/paint/ScrollRecorder.h" 16 #include "core/paint/ScrollRecorder.h"
16 #include "core/paint/ScrollableAreaPainter.h" 17 #include "core/paint/ScrollableAreaPainter.h"
17 #include "core/paint/Transform3DRecorder.h" 18 #include "core/paint/Transform3DRecorder.h"
18 #include "platform/RuntimeEnabledFeatures.h" 19 #include "platform/RuntimeEnabledFeatures.h"
19 #include "platform/geometry/FloatPoint3D.h" 20 #include "platform/geometry/FloatPoint3D.h"
20 #include "platform/graphics/GraphicsLayer.h" 21 #include "platform/graphics/GraphicsLayer.h"
21 #include "platform/graphics/paint/CompositingRecorder.h" 22 #include "platform/graphics/paint/CompositingRecorder.h"
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 // These helpers output clip and compositing operations using a RAII pattern. 355 // These helpers output clip and compositing operations using a RAII pattern.
355 // Stack-allocated-varibles are destructed in the reverse order of 356 // Stack-allocated-varibles are destructed in the reverse order of
356 // construction, so they are nested properly. 357 // construction, so they are nested properly.
357 Optional<ClipPathClipper> clipPathClipper; 358 Optional<ClipPathClipper> clipPathClipper;
358 // Clip-path, like border radius, must not be applied to the contents of a 359 // Clip-path, like border radius, must not be applied to the contents of a
359 // composited-scrolling container. It must, however, still be applied to the 360 // composited-scrolling container. It must, however, still be applied to the
360 // mask layer, so that the compositor can properly mask the 361 // mask layer, so that the compositor can properly mask the
361 // scrolling contents and scrollbars. 362 // scrolling contents and scrollbars.
362 if (m_paintLayer.layoutObject()->hasClipPath() && 363 if (m_paintLayer.layoutObject()->hasClipPath() &&
363 (!m_paintLayer.needsCompositedScrolling() || 364 (!m_paintLayer.needsCompositedScrolling() ||
364 (paintFlags & PaintLayerPaintingChildClippingMaskPhase))) { 365 (paintFlags & (PaintLayerPaintingChildClippingMaskPhase |
366 PaintLayerPaintingAncestorClippingMaskPhase)))) {
365 paintingInfo.ancestorHasClipPathClipping = true; 367 paintingInfo.ancestorHasClipPathClipping = true;
366 368
367 LayoutRect referenceBox(m_paintLayer.boxForClipPath()); 369 LayoutRect referenceBox(m_paintLayer.boxForClipPath());
368 // Note that this isn't going to work correctly if crossing a column 370 // Note that this isn't going to work correctly if crossing a column
369 // boundary. The reference box should be determined per-fragment, and hence 371 // boundary. The reference box should be determined per-fragment, and hence
370 // this ought to be performed after fragmentation. 372 // this ought to be performed after fragmentation.
371 if (m_paintLayer.enclosingPaginationLayer()) 373 if (m_paintLayer.enclosingPaginationLayer())
372 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor( 374 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor(
373 paintingInfo.rootLayer, referenceBox); 375 paintingInfo.rootLayer, referenceBox);
374 else 376 else
(...skipping 30 matching lines...) Expand all
405 isSelfPaintingLayer && !isPaintingOverlayScrollbars; 407 isSelfPaintingLayer && !isPaintingOverlayScrollbars;
406 408
407 PaintLayerFragments layerFragments; 409 PaintLayerFragments layerFragments;
408 if (shouldPaintContent || shouldPaintSelfOutline || 410 if (shouldPaintContent || shouldPaintSelfOutline ||
409 isPaintingOverlayScrollbars) { 411 isPaintingOverlayScrollbars) {
410 // Collect the fragments. This will compute the clip rectangles and paint 412 // Collect the fragments. This will compute the clip rectangles and paint
411 // offsets for each layer fragment. 413 // offsets for each layer fragment.
412 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) 414 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects)
413 ? UncachedClipRects 415 ? UncachedClipRects
414 : PaintingClipRects; 416 : PaintingClipRects;
417 LayoutPoint offsetToClipper;
418 PaintLayer* paintLayerForFragments = &m_paintLayer;
419 if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) {
420 // Compute fragments and their clips with respect to the clipping
421 // container. The paint rect is in this layer's space, so convert it
422 // to the clipper's layer's space. The rootLayer is also changed to
423 // the clipper's layer to simplify coordinate system adjustments.
424 // The change to rootLayer must persist to correctly record the clips.
425 paintLayerForFragments =
426 m_paintLayer.clippingContainer()->enclosingLayer();
427 localPaintingInfo.rootLayer = paintLayerForFragments;
428 m_paintLayer.convertToLayerCoords(localPaintingInfo.rootLayer,
429 offsetToClipper);
430 localPaintingInfo.paintDirtyRect.moveBy(offsetToClipper);
431 }
432
415 // TODO(trchen): We haven't decided how to handle visual fragmentation with 433 // TODO(trchen): We haven't decided how to handle visual fragmentation with
416 // SPv2. Related thread 434 // SPv2. Related thread
417 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM 435 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM
418 if (fragmentPolicy == ForceSingleFragment || 436 if (fragmentPolicy == ForceSingleFragment ||
419 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { 437 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
420 m_paintLayer.appendSingleFragmentIgnoringPagination( 438 paintLayerForFragments->appendSingleFragmentIgnoringPagination(
421 layerFragments, localPaintingInfo.rootLayer, 439 layerFragments, localPaintingInfo.rootLayer,
422 localPaintingInfo.paintDirtyRect, cacheSlot, 440 localPaintingInfo.paintDirtyRect, cacheSlot,
423 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, 441 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot,
424 localPaintingInfo.subPixelAccumulation); 442 localPaintingInfo.subPixelAccumulation);
425 } else if (isFixedPositionObjectInPagedMedia()) { 443 } else if (isFixedPositionObjectInPagedMedia()) {
426 PaintLayerFragments singleFragment; 444 PaintLayerFragments singleFragment;
427 m_paintLayer.appendSingleFragmentIgnoringPagination( 445 paintLayerForFragments->appendSingleFragmentIgnoringPagination(
428 singleFragment, localPaintingInfo.rootLayer, 446 singleFragment, localPaintingInfo.rootLayer,
429 localPaintingInfo.paintDirtyRect, cacheSlot, 447 localPaintingInfo.paintDirtyRect, cacheSlot,
430 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, 448 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot,
431 localPaintingInfo.subPixelAccumulation); 449 localPaintingInfo.subPixelAccumulation);
432 repeatFixedPositionObjectInPages(singleFragment[0], paintingInfo, 450 repeatFixedPositionObjectInPages(singleFragment[0], paintingInfo,
433 layerFragments); 451 layerFragments);
434 } else { 452 } else {
435 m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, 453 paintLayerForFragments->collectFragments(
436 localPaintingInfo.paintDirtyRect, cacheSlot, 454 layerFragments, localPaintingInfo.rootLayer,
437 IgnoreOverlayScrollbarSize, 455 localPaintingInfo.paintDirtyRect, cacheSlot,
438 respectOverflowClip, &offsetFromRoot, 456 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot,
439 localPaintingInfo.subPixelAccumulation); 457 localPaintingInfo.subPixelAccumulation);
458 }
459
460 if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) {
461 // Fragment offsets have been computed in the clipping container's
462 // layer's coordinate system, but for the rest of painting we need
463 // them in the layer coordinate. So move them and the foreground rect
464 // that is also in the clipper's space.
465 LayoutSize negativeOffset(-offsetToClipper.x(), -offsetToClipper.y());
466 for (auto& fragment : layerFragments) {
467 fragment.foregroundRect.move(negativeOffset);
468 fragment.paginationOffset.move(negativeOffset);
469 }
440 } 470 }
441 471
442 if (shouldPaintContent) { 472 if (shouldPaintContent) {
443 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar 473 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar
444 // optimization for slimming paint v2. 474 // optimization for slimming paint v2.
445 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect( 475 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect(
446 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot); 476 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot);
447 if (!shouldPaintContent) 477 if (!shouldPaintContent)
448 result = MayBeClippedByPaintDirtyRect; 478 result = MayBeClippedByPaintDirtyRect;
449 } 479 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 if (shouldPaintOverlayScrollbars) 560 if (shouldPaintOverlayScrollbars)
531 paintOverflowControlsForFragments(layerFragments, context, 561 paintOverflowControlsForFragments(layerFragments, context,
532 localPaintingInfo, paintFlags); 562 localPaintingInfo, paintFlags);
533 } // FilterPainter block 563 } // FilterPainter block
534 564
535 bool shouldPaintMask = 565 bool shouldPaintMask =
536 (paintFlags & PaintLayerPaintingCompositingMaskPhase) && 566 (paintFlags & PaintLayerPaintingCompositingMaskPhase) &&
537 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() && 567 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() &&
538 !selectionOnly; 568 !selectionOnly;
539 bool shouldPaintClippingMask = 569 bool shouldPaintClippingMask =
540 (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && 570 (paintFlags & (PaintLayerPaintingChildClippingMaskPhase |
571 PaintLayerPaintingAncestorClippingMaskPhase)) &&
541 shouldPaintContent && !selectionOnly; 572 shouldPaintContent && !selectionOnly;
542 573
543 if (shouldPaintMask) 574 if (shouldPaintMask)
544 paintMaskForFragments(layerFragments, context, localPaintingInfo, 575 paintMaskForFragments(layerFragments, context, localPaintingInfo,
545 paintFlags); 576 paintFlags);
546 if (shouldPaintClippingMask) { 577 if (shouldPaintClippingMask) {
547 // Paint the border radius mask for the fragments. 578 // Paint the border radius mask for the fragments.
548 paintChildClippingMaskForFragments(layerFragments, context, 579 paintChildClippingMaskForFragments(layerFragments, context,
549 localPaintingInfo, paintFlags); 580 localPaintingInfo, paintFlags);
550 } 581 }
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 // A fixed-position object is repeated on every page instead of paginated, 746 // A fixed-position object is repeated on every page instead of paginated,
716 // so we should apply the original ancestor clip rect. 747 // so we should apply the original ancestor clip rect.
717 if (!isFixedPositionObjectInPagedMedia) 748 if (!isFixedPositionObjectInPagedMedia)
718 clipRectForFragment.moveBy(fragment.paginationOffset); 749 clipRectForFragment.moveBy(fragment.paginationOffset);
719 clipRectForFragment.intersect(fragment.backgroundRect); 750 clipRectForFragment.intersect(fragment.backgroundRect);
720 if (clipRectForFragment.isEmpty()) 751 if (clipRectForFragment.isEmpty())
721 continue; 752 continue;
722 if (needsToClip(paintingInfo, clipRectForFragment)) { 753 if (needsToClip(paintingInfo, clipRectForFragment)) {
723 clipRecorder.emplace(context, *parentLayer->layoutObject(), 754 clipRecorder.emplace(context, *parentLayer->layoutObject(),
724 DisplayItem::kClipLayerParent, clipRectForFragment, 755 DisplayItem::kClipLayerParent, clipRectForFragment,
725 &paintingInfo, fragment.paginationOffset, 756 paintingInfo.rootLayer, fragment.paginationOffset,
726 paintFlags); 757 paintFlags);
727 } 758 }
728 } 759 }
729 if (paintFragmentByApplyingTransform(context, paintingInfo, paintFlags, 760 if (paintFragmentByApplyingTransform(context, paintingInfo, paintFlags,
730 fragment.paginationOffset) == 761 fragment.paginationOffset) ==
731 MayBeClippedByPaintDirtyRect) 762 MayBeClippedByPaintDirtyRect)
732 result = MayBeClippedByPaintDirtyRect; 763 result = MayBeClippedByPaintDirtyRect;
733 } 764 }
734 return result; 765 return result;
735 } 766 }
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 884
854 for (auto& fragment : layerFragments) { 885 for (auto& fragment : layerFragments) {
855 // We need to apply the same clips and transforms that 886 // We need to apply the same clips and transforms that
856 // paintFragmentWithPhase would have. 887 // paintFragmentWithPhase would have.
857 LayoutRect cullRect = fragment.backgroundRect.rect(); 888 LayoutRect cullRect = fragment.backgroundRect.rect();
858 889
859 Optional<LayerClipRecorder> clipRecorder; 890 Optional<LayerClipRecorder> clipRecorder;
860 if (needsToClip(localPaintingInfo, fragment.backgroundRect)) { 891 if (needsToClip(localPaintingInfo, fragment.backgroundRect)) {
861 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), 892 clipRecorder.emplace(context, *m_paintLayer.layoutObject(),
862 DisplayItem::kClipLayerOverflowControls, 893 DisplayItem::kClipLayerOverflowControls,
863 fragment.backgroundRect, &localPaintingInfo, 894 fragment.backgroundRect, localPaintingInfo.rootLayer,
864 fragment.paginationOffset, paintFlags); 895 fragment.paginationOffset, paintFlags);
865 } 896 }
866 897
867 Optional<ScrollRecorder> scrollRecorder; 898 Optional<ScrollRecorder> scrollRecorder;
868 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && 899 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() &&
869 !localPaintingInfo.scrollOffsetAccumulation.isZero()) { 900 !localPaintingInfo.scrollOffsetAccumulation.isZero()) {
870 cullRect.move(localPaintingInfo.scrollOffsetAccumulation); 901 cullRect.move(localPaintingInfo.scrollOffsetAccumulation);
871 scrollRecorder.emplace(context, *m_paintLayer.layoutObject(), 902 scrollRecorder.emplace(context, *m_paintLayer.layoutObject(),
872 DisplayItem::kScrollOverflowControls, 903 DisplayItem::kScrollOverflowControls,
873 localPaintingInfo.scrollOffsetAccumulation); 904 localPaintingInfo.scrollOffsetAccumulation);
(...skipping 29 matching lines...) Expand all
903 // handle clipping to self. 934 // handle clipping to self.
904 case PaintPhaseSelfOutlineOnly: 935 case PaintPhaseSelfOutlineOnly:
905 case PaintPhaseMask: // Mask painting will handle clipping to self. 936 case PaintPhaseMask: // Mask painting will handle clipping to self.
906 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius; 937 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius;
907 break; 938 break;
908 default: 939 default:
909 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius; 940 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius;
910 break; 941 break;
911 } 942 }
912 943
944 // TODO(schenney): Nested border-radius clips are not applied to composited
945 // children, probably due to an incorrect clipRoot.
946 // https://bugs.chromium.org/p/chromium/issues/detail?id=672561
913 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, 947 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType,
914 clipRect, &paintingInfo, fragment.paginationOffset, 948 clipRect, paintingInfo.rootLayer,
915 paintFlags, clippingRule); 949 fragment.paginationOffset, paintFlags, clippingRule);
950 }
951
952 // If we are painting a mask for any reason and we have already processed the
953 // clips, there is no need to go through the remaining painting pipeline.
954 // We know that the mask just needs the area bounded by the clip rects to be
955 // filled with black.
956 if (clipRecorder && phase == PaintPhaseClippingMask) {
957 fillMaskingFragment(context, clipRect);
958 return;
916 } 959 }
917 960
918 LayoutRect newCullRect(clipRect.rect()); 961 LayoutRect newCullRect(clipRect.rect());
919 Optional<ScrollRecorder> scrollRecorder; 962 Optional<ScrollRecorder> scrollRecorder;
920 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation(); 963 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation();
921 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { 964 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
922 const auto* objectPaintProperties = 965 const auto* objectPaintProperties =
923 m_paintLayer.layoutObject()->paintProperties(); 966 m_paintLayer.layoutObject()->paintProperties();
924 DCHECK(objectPaintProperties && 967 DCHECK(objectPaintProperties &&
925 objectPaintProperties->localBorderBoxProperties()); 968 objectPaintProperties->localBorderBoxProperties());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 // Optimize clipping for the single fragment case. 1020 // Optimize clipping for the single fragment case.
978 bool shouldClip = localPaintingInfo.clipToDirtyRect && 1021 bool shouldClip = localPaintingInfo.clipToDirtyRect &&
979 layerFragments.size() == 1 && 1022 layerFragments.size() == 1 &&
980 !layerFragments[0].foregroundRect.isEmpty(); 1023 !layerFragments[0].foregroundRect.isEmpty();
981 ClipState clipState = HasNotClipped; 1024 ClipState clipState = HasNotClipped;
982 Optional<LayerClipRecorder> clipRecorder; 1025 Optional<LayerClipRecorder> clipRecorder;
983 if (shouldClip && 1026 if (shouldClip &&
984 needsToClip(localPaintingInfo, layerFragments[0].foregroundRect)) { 1027 needsToClip(localPaintingInfo, layerFragments[0].foregroundRect)) {
985 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), 1028 clipRecorder.emplace(context, *m_paintLayer.layoutObject(),
986 DisplayItem::kClipLayerForeground, 1029 DisplayItem::kClipLayerForeground,
987 layerFragments[0].foregroundRect, &localPaintingInfo, 1030 layerFragments[0].foregroundRect,
1031 localPaintingInfo.rootLayer,
988 layerFragments[0].paginationOffset, paintFlags); 1032 layerFragments[0].paginationOffset, paintFlags);
989 clipState = HasClipped; 1033 clipState = HasClipped;
990 } 1034 }
991 1035
992 // We have to loop through every fragment multiple times, since we have to 1036 // We have to loop through every fragment multiple times, since we have to
993 // issue paint invalidations in each specific phase in order for interleaving 1037 // issue paint invalidations in each specific phase in order for interleaving
994 // of the fragments to work properly. 1038 // of the fragments to work properly.
995 if (selectionOnly) { 1039 if (selectionOnly) {
996 paintForegroundForFragmentsWithPhase(PaintPhaseSelection, layerFragments, 1040 paintForegroundForFragmentsWithPhase(PaintPhaseSelection, layerFragments,
997 context, localPaintingInfo, paintFlags, 1041 context, localPaintingInfo, paintFlags,
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1123 return; 1167 return;
1124 1168
1125 PaintLayerPaintingInfo paintingInfo(&m_paintLayer, 1169 PaintLayerPaintingInfo paintingInfo(&m_paintLayer,
1126 LayoutRect(enclosingIntRect(damageRect)), 1170 LayoutRect(enclosingIntRect(damageRect)),
1127 paintFlags, LayoutSize()); 1171 paintFlags, LayoutSize());
1128 paint(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); 1172 paint(context, paintingInfo, PaintLayerPaintingOverlayScrollbars);
1129 1173
1130 m_paintLayer.setContainsDirtyOverlayScrollbars(false); 1174 m_paintLayer.setContainsDirtyOverlayScrollbars(false);
1131 } 1175 }
1132 1176
1177 void PaintLayerPainter::fillMaskingFragment(GraphicsContext& context,
1178 const ClipRect& clipRect) {
1179 const LayoutBox* layoutBox = toLayoutBox(m_paintLayer.layoutObject());
1180 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(
1181 context, *layoutBox, PaintPhaseClippingMask))
1182 return;
1183
1184 IntRect snappedClipRect = pixelSnappedIntRect(clipRect.rect());
1185 LayoutObjectDrawingRecorder drawingRecorder(
1186 context, *layoutBox, PaintPhaseClippingMask, snappedClipRect);
1187 context.fillRect(snappedClipRect, Color::black);
1188 }
1189
1133 } // namespace blink 1190 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698