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

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: Improve clip recording code Created 4 years, 1 month 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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 // These helpers output clip and compositing operations using a RAII pattern. 320 // These helpers output clip and compositing operations using a RAII pattern.
321 // Stack-allocated-varibles are destructed in the reverse order of 321 // Stack-allocated-varibles are destructed in the reverse order of
322 // construction, so they are nested properly. 322 // construction, so they are nested properly.
323 Optional<ClipPathClipper> clipPathClipper; 323 Optional<ClipPathClipper> clipPathClipper;
324 // Clip-path, like border radius, must not be applied to the contents of a 324 // Clip-path, like border radius, must not be applied to the contents of a
325 // composited-scrolling container. It must, however, still be applied to the 325 // composited-scrolling container. It must, however, still be applied to the
326 // mask layer, so that the compositor can properly mask the 326 // mask layer, so that the compositor can properly mask the
327 // scrolling contents and scrollbars. 327 // scrolling contents and scrollbars.
328 if (m_paintLayer.layoutObject()->hasClipPath() && 328 if (m_paintLayer.layoutObject()->hasClipPath() &&
329 (!m_paintLayer.needsCompositedScrolling() || 329 (!m_paintLayer.needsCompositedScrolling() ||
330 (paintFlags & PaintLayerPaintingChildClippingMaskPhase))) { 330 (paintFlags & (PaintLayerPaintingChildClippingMaskPhase |
331 PaintLayerPaintingAncestorClippingMaskPhase)))) {
331 paintingInfo.ancestorHasClipPathClipping = true; 332 paintingInfo.ancestorHasClipPathClipping = true;
332 333
333 LayoutRect referenceBox(m_paintLayer.boxForClipPath()); 334 LayoutRect referenceBox(m_paintLayer.boxForClipPath());
334 // Note that this isn't going to work correctly if crossing a column 335 // Note that this isn't going to work correctly if crossing a column
335 // boundary. The reference box should be determined per-fragment, and hence 336 // boundary. The reference box should be determined per-fragment, and hence
336 // this ought to be performed after fragmentation. 337 // this ought to be performed after fragmentation.
337 if (m_paintLayer.enclosingPaginationLayer()) 338 if (m_paintLayer.enclosingPaginationLayer())
338 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor( 339 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor(
339 paintingInfo.rootLayer, referenceBox); 340 paintingInfo.rootLayer, referenceBox);
340 else 341 else
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 isPaintingOverlayScrollbars) { 378 isPaintingOverlayScrollbars) {
378 // Collect the fragments. This will compute the clip rectangles and paint 379 // Collect the fragments. This will compute the clip rectangles and paint
379 // offsets for each layer fragment. 380 // offsets for each layer fragment.
380 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) 381 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects)
381 ? UncachedClipRects 382 ? UncachedClipRects
382 : PaintingClipRects; 383 : PaintingClipRects;
383 // TODO(trchen): We haven't decided how to handle visual fragmentation with 384 // TODO(trchen): We haven't decided how to handle visual fragmentation with
384 // SPv2. Related thread 385 // SPv2. Related thread
385 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM 386 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM
386 if (fragmentPolicy == ForceSingleFragment || 387 if (fragmentPolicy == ForceSingleFragment ||
387 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 388 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
388 m_paintLayer.appendSingleFragmentIgnoringPagination( 389 m_paintLayer.appendSingleFragmentIgnoringPagination(
389 layerFragments, localPaintingInfo.rootLayer, 390 layerFragments, localPaintingInfo.rootLayer,
390 localPaintingInfo.paintDirtyRect, cacheSlot, 391 localPaintingInfo.paintDirtyRect, cacheSlot,
391 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, 392 IgnoreOverlayScrollbarSize, respectOverflowClip,
392 localPaintingInfo.subPixelAccumulation); 393 paintFlags & PaintLayerPaintingAncestorClippingMaskPhase,
393 else 394 &offsetFromRoot, localPaintingInfo.subPixelAccumulation);
394 m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, 395 } else {
395 localPaintingInfo.paintDirtyRect, cacheSlot, 396 m_paintLayer.collectFragments(
396 IgnoreOverlayScrollbarSize, 397 layerFragments, localPaintingInfo.rootLayer,
397 respectOverflowClip, &offsetFromRoot, 398 localPaintingInfo.paintDirtyRect, cacheSlot,
398 localPaintingInfo.subPixelAccumulation); 399 IgnoreOverlayScrollbarSize, respectOverflowClip,
400 paintFlags & PaintLayerPaintingAncestorClippingMaskPhase,
401 &offsetFromRoot, localPaintingInfo.subPixelAccumulation);
402 }
399 403
400 if (shouldPaintContent) { 404 if (shouldPaintContent) {
401 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar 405 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar
402 // optimization for slimming paint v2. 406 // optimization for slimming paint v2.
403 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect( 407 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect(
404 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot); 408 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot);
405 if (!shouldPaintContent) 409 if (!shouldPaintContent)
406 result = MayBeClippedByPaintDirtyRect; 410 result = MayBeClippedByPaintDirtyRect;
407 } 411 }
408 } 412 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 if (shouldPaintOverlayScrollbars) 489 if (shouldPaintOverlayScrollbars)
486 paintOverflowControlsForFragments(layerFragments, context, 490 paintOverflowControlsForFragments(layerFragments, context,
487 localPaintingInfo, paintFlags); 491 localPaintingInfo, paintFlags);
488 } // FilterPainter block 492 } // FilterPainter block
489 493
490 bool shouldPaintMask = 494 bool shouldPaintMask =
491 (paintFlags & PaintLayerPaintingCompositingMaskPhase) && 495 (paintFlags & PaintLayerPaintingCompositingMaskPhase) &&
492 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() && 496 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() &&
493 !selectionOnly; 497 !selectionOnly;
494 bool shouldPaintClippingMask = 498 bool shouldPaintClippingMask =
495 (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && 499 (paintFlags & (PaintLayerPaintingChildClippingMaskPhase |
500 PaintLayerPaintingAncestorClippingMaskPhase)) &&
496 shouldPaintContent && !selectionOnly; 501 shouldPaintContent && !selectionOnly;
497 502
498 if (shouldPaintMask) 503 if (shouldPaintMask)
499 paintMaskForFragments(layerFragments, context, localPaintingInfo, 504 paintMaskForFragments(layerFragments, context, localPaintingInfo,
500 paintFlags); 505 paintFlags);
501 if (shouldPaintClippingMask) { 506 if (shouldPaintClippingMask) {
502 // Paint the border radius mask for the fragments. 507 // Paint the border radius mask for the fragments.
503 paintChildClippingMaskForFragments(layerFragments, context, 508 paintChildClippingMaskForFragments(layerFragments, context,
504 localPaintingInfo, paintFlags); 509 localPaintingInfo, paintFlags);
505 } 510 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 // its parent. 569 // its parent.
565 PaintLayer* parentLayer = m_paintLayer.parent(); 570 PaintLayer* parentLayer = m_paintLayer.parent();
566 571
567 LayoutObject* object = m_paintLayer.layoutObject(); 572 LayoutObject* object = m_paintLayer.layoutObject();
568 LayoutView* view = object->view(); 573 LayoutView* view = object->view();
569 bool isFixedPosObjectInPagedMedia = 574 bool isFixedPosObjectInPagedMedia =
570 object->style()->position() == FixedPosition && 575 object->style()->position() == FixedPosition &&
571 object->container() == view && view->pageLogicalHeight(); 576 object->container() == view && view->pageLogicalHeight();
572 PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer(); 577 PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer();
573 PaintLayerFragments fragments; 578 PaintLayerFragments fragments;
579
574 // TODO(crbug.com/619094): Figure out the correct behaviour for fixed position 580 // TODO(crbug.com/619094): Figure out the correct behaviour for fixed position
575 // objects in paged media with vertical writing modes. 581 // objects in paged media with vertical writing modes.
576 if (isFixedPosObjectInPagedMedia && view->isHorizontalWritingMode()) { 582 if (isFixedPosObjectInPagedMedia && view->isHorizontalWritingMode()) {
577 // "For paged media, boxes with fixed positions are repeated on every page." 583 // "For paged media, boxes with fixed positions are repeated on every page."
578 // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioni ng 584 // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioni ng
579 unsigned pages = 585 unsigned pages =
580 ceilf(view->documentRect().height() / view->pageLogicalHeight()); 586 ceilf(view->documentRect().height() / view->pageLogicalHeight());
581 LayoutPoint paginationOffset; 587 LayoutPoint paginationOffset;
582 588
583 // The fixed position object is offset from the top of the page, so remove 589 // The fixed position object is offset from the top of the page, so remove
(...skipping 21 matching lines...) Expand all
605 // Calculate the transformed bounding box in the current coordinate space, 611 // Calculate the transformed bounding box in the current coordinate space,
606 // to figure out which fragmentainers (e.g. columns) we need to visit. 612 // to figure out which fragmentainers (e.g. columns) we need to visit.
607 LayoutRect transformedExtent = PaintLayer::transparencyClipBox( 613 LayoutRect transformedExtent = PaintLayer::transparencyClipBox(
608 &m_paintLayer, paginationLayer, PaintLayer::PaintingTransparencyClipBox, 614 &m_paintLayer, paginationLayer, PaintLayer::PaintingTransparencyClipBox,
609 PaintLayer::RootOfTransparencyClipBox, 615 PaintLayer::RootOfTransparencyClipBox,
610 paintingInfo.subPixelAccumulation, paintingInfo.getGlobalPaintFlags()); 616 paintingInfo.subPixelAccumulation, paintingInfo.getGlobalPaintFlags());
611 // FIXME: we don't check if paginationLayer is within paintingInfo.rootLayer 617 // FIXME: we don't check if paginationLayer is within paintingInfo.rootLayer
612 // here. 618 // here.
613 paginationLayer->collectFragments( 619 paginationLayer->collectFragments(
614 fragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, 620 fragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect,
615 cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0, 621 cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, false, 0,
616 paintingInfo.subPixelAccumulation, &transformedExtent); 622 paintingInfo.subPixelAccumulation, &transformedExtent);
617 } else { 623 } else {
618 // We don't need to collect any fragments in the regular way here. We have 624 // We don't need to collect any fragments in the regular way here. We have
619 // already calculated a clip rectangle for the ancestry if it was needed, 625 // already calculated a clip rectangle for the ancestry if it was needed,
620 // and clipping this layer is something that can be done further down the 626 // and clipping this layer is something that can be done further down the
621 // path, when the transform has been applied. 627 // path, when the transform has been applied.
622 PaintLayerFragment fragment; 628 PaintLayerFragment fragment;
623 fragment.backgroundRect = paintingInfo.paintDirtyRect; 629 fragment.backgroundRect = paintingInfo.paintDirtyRect;
624 fragments.append(fragment); 630 fragments.append(fragment);
625 } 631 }
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 827
822 // We pass IntPoint() as the paint offset here, because 828 // We pass IntPoint() as the paint offset here, because
823 // ScrollableArea::paintOverflowControls just ignores it and uses the 829 // ScrollableArea::paintOverflowControls just ignores it and uses the
824 // offset found in a previous pass. 830 // offset found in a previous pass.
825 CullRect snappedCullRect(pixelSnappedIntRect(cullRect)); 831 CullRect snappedCullRect(pixelSnappedIntRect(cullRect));
826 ScrollableAreaPainter(*scrollableArea) 832 ScrollableAreaPainter(*scrollableArea)
827 .paintOverflowControls(context, IntPoint(), snappedCullRect, true); 833 .paintOverflowControls(context, IntPoint(), snappedCullRect, true);
828 } 834 }
829 } 835 }
830 836
837 LayoutPoint PaintLayerPainter::fragmentOffsetForAncestorClipMask(
838 const LayoutPoint& originalFragmentOffset) {
839 // The clipping container that will be used to define the clip and the
840 // child layer with respect to which the fragment offset is defined share
841 // a layer root. When the clip is recorded we will be using the clipping
842 // container's layer's offset to the root to position the clip. Hence we
843 // must convert the fragment offset into a corresponding offset in the
844 // clipping container's layer coordinates. To do that, we find the
845 // originalFragmentOffset's coordinate in the root layer, fragmentDelta.
846 // We also find the offset of the clipping container's origin in the root
847 // layer's coordinates, clippingDelta. clippingDelta - fragmentDelta gives
848 // the fragment's position in the root layer. But we need the position in
849 // the clipping layer coords, and we subtract clippingDelta to get that. The
850 // resulting offset is -fragmentDelta.
851 DCHECK_EQ(m_paintLayer.root(),
852 m_paintLayer.clippingContainer()->enclosingLayer()->root());
853 LayoutPoint fragmentDelta(originalFragmentOffset);
854 m_paintLayer.convertToLayerCoords(m_paintLayer.root(), fragmentDelta);
855 return LayoutPoint(-fragmentDelta.x(), -fragmentDelta.y());
856 }
857
831 void PaintLayerPainter::paintFragmentWithPhase( 858 void PaintLayerPainter::paintFragmentWithPhase(
832 PaintPhase phase, 859 PaintPhase phase,
833 const PaintLayerFragment& fragment, 860 const PaintLayerFragment& fragment,
834 GraphicsContext& context, 861 GraphicsContext& context,
835 const ClipRect& clipRect, 862 const ClipRect& clipRect,
836 const PaintLayerPaintingInfo& paintingInfo, 863 const PaintLayerPaintingInfo& paintingInfo,
837 PaintLayerFlags paintFlags, 864 PaintLayerFlags paintFlags,
838 ClipState clipState) { 865 ClipState clipState) {
839 DCHECK(m_paintLayer.isSelfPaintingLayer()); 866 DCHECK(m_paintLayer.isSelfPaintingLayer());
840 867
841 Optional<LayerClipRecorder> clipRecorder; 868 Optional<LayerClipRecorder> clipRecorder;
842 if (clipState != HasClipped && paintingInfo.clipToDirtyRect && 869 if (clipState != HasClipped && paintingInfo.clipToDirtyRect &&
843 needsToClip(paintingInfo, clipRect)) { 870 needsToClip(paintingInfo, clipRect)) {
844 DisplayItem::Type clipType = 871 DisplayItem::Type clipType =
845 DisplayItem::paintPhaseToClipLayerFragmentType(phase); 872 DisplayItem::paintPhaseToClipLayerFragmentType(phase);
846 LayerClipRecorder::BorderRadiusClippingRule clippingRule; 873 LayerClipRecorder::BorderRadiusClippingRule clippingRule;
847 switch (phase) { 874 switch (phase) {
848 case PaintPhaseSelfBlockBackgroundOnly: // Background painting will 875 case PaintPhaseSelfBlockBackgroundOnly: // Background painting will
849 // handle clipping to self. 876 // handle clipping to self.
850 case PaintPhaseSelfOutlineOnly: 877 case PaintPhaseSelfOutlineOnly:
851 case PaintPhaseMask: // Mask painting will handle clipping to self. 878 case PaintPhaseMask: // Mask painting will handle clipping to self.
852 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius; 879 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius;
853 break; 880 break;
854 default: 881 default:
855 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius; 882 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius;
856 break; 883 break;
857 } 884 }
858 885
859 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, 886 // When painting the clipping mask for a composited child, we pass
860 clipRect, &paintingInfo, fragment.paginationOffset, 887 // the clipping container object as the layoutObject to provide the clip.
861 paintFlags, clippingRule); 888 // The recorder assumes the fragment is positioned in that objects's
889 // layer coordinates, so we also convert that.
890 if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) {
891 clipRecorder.emplace(
892 context, *(toLayoutBoxModelObject(m_paintLayer.clippingContainer())),
893 clipType, clipRect, &paintingInfo,
894 fragmentOffsetForAncestorClipMask(fragment.paginationOffset),
895 paintFlags, clippingRule);
896 } else {
897 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType,
898 clipRect, &paintingInfo, fragment.paginationOffset,
899 paintFlags, clippingRule);
900 }
862 } 901 }
863 902
864 LayoutRect newCullRect(clipRect.rect()); 903 LayoutRect newCullRect(clipRect.rect());
865 Optional<ScrollRecorder> scrollRecorder; 904 Optional<ScrollRecorder> scrollRecorder;
866 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation(); 905 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation();
867 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { 906 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
868 const auto* objectPaintProperties = 907 const auto* objectPaintProperties =
869 m_paintLayer.layoutObject()->paintProperties(); 908 m_paintLayer.layoutObject()->paintProperties();
870 DCHECK(objectPaintProperties && 909 DCHECK(objectPaintProperties &&
871 objectPaintProperties->localBorderBoxProperties()); 910 objectPaintProperties->localBorderBoxProperties());
(...skipping 13 matching lines...) Expand all
885 924
886 newCullRect.move(paintingInfo.scrollOffsetAccumulation); 925 newCullRect.move(paintingInfo.scrollOffsetAccumulation);
887 scrollRecorder.emplace(context, *m_paintLayer.layoutObject(), phase, 926 scrollRecorder.emplace(context, *m_paintLayer.layoutObject(), phase,
888 paintingInfo.scrollOffsetAccumulation); 927 paintingInfo.scrollOffsetAccumulation);
889 } 928 }
890 } 929 }
891 PaintInfo paintInfo(context, pixelSnappedIntRect(newCullRect), phase, 930 PaintInfo paintInfo(context, pixelSnappedIntRect(newCullRect), phase,
892 paintingInfo.getGlobalPaintFlags(), paintFlags, 931 paintingInfo.getGlobalPaintFlags(), paintFlags,
893 paintingInfo.rootLayer->layoutObject()); 932 paintingInfo.rootLayer->layoutObject());
894 933
934 // TODO(schenney): This is the wrong object for painting AncestorClippingMask.
Stephen Chennney 2016/11/08 21:42:52 No it's not. It's the wrong object for all the cli
895 m_paintLayer.layoutObject()->paint(paintInfo, paintOffset); 935 m_paintLayer.layoutObject()->paint(paintInfo, paintOffset);
896 } 936 }
897 937
898 void PaintLayerPainter::paintBackgroundForFragments( 938 void PaintLayerPainter::paintBackgroundForFragments(
899 const PaintLayerFragments& layerFragments, 939 const PaintLayerFragments& layerFragments,
900 GraphicsContext& context, 940 GraphicsContext& context,
901 const LayoutRect& transparencyPaintDirtyRect, 941 const LayoutRect& transparencyPaintDirtyRect,
902 const PaintLayerPaintingInfo& localPaintingInfo, 942 const PaintLayerPaintingInfo& localPaintingInfo,
903 PaintLayerFlags paintFlags) { 943 PaintLayerFlags paintFlags) {
904 Optional<DisplayItemCacheSkipper> cacheSkipper; 944 Optional<DisplayItemCacheSkipper> cacheSkipper;
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 1110
1071 PaintLayerPaintingInfo paintingInfo(&m_paintLayer, 1111 PaintLayerPaintingInfo paintingInfo(&m_paintLayer,
1072 LayoutRect(enclosingIntRect(damageRect)), 1112 LayoutRect(enclosingIntRect(damageRect)),
1073 paintFlags, LayoutSize()); 1113 paintFlags, LayoutSize());
1074 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); 1114 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars);
1075 1115
1076 m_paintLayer.setContainsDirtyOverlayScrollbars(false); 1116 m_paintLayer.setContainsDirtyOverlayScrollbars(false);
1077 } 1117 }
1078 1118
1079 } // namespace blink 1119 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698