Index: Source/core/paint/DeprecatedPaintLayerPainter.cpp |
diff --git a/Source/core/paint/DeprecatedPaintLayerPainter.cpp b/Source/core/paint/DeprecatedPaintLayerPainter.cpp |
index b377cdfe02ee91c70e0e96d8affed000d1cd5b5d..638805aa871316bce06282f9672bafd7b8946eab 100644 |
--- a/Source/core/paint/DeprecatedPaintLayerPainter.cpp |
+++ b/Source/core/paint/DeprecatedPaintLayerPainter.cpp |
@@ -15,6 +15,7 @@ |
#include "core/paint/DeprecatedPaintLayer.h" |
#include "core/paint/FilterPainter.h" |
#include "core/paint/LayerClipRecorder.h" |
+#include "core/paint/LayerDescendantClipRecorder.h" |
#include "core/paint/LayerFixedPositionRecorder.h" |
#include "core/paint/PaintInfo.h" |
#include "core/paint/SVGClipPainter.h" |
@@ -22,10 +23,12 @@ |
#include "core/paint/ScrollRecorder.h" |
#include "core/paint/ScrollableAreaPainter.h" |
#include "core/paint/Transform3DRecorder.h" |
+#include "core/paint/TransformRecorder.h" |
#include "platform/graphics/GraphicsLayer.h" |
#include "platform/graphics/paint/ClipPathRecorder.h" |
#include "platform/graphics/paint/ClipRecorder.h" |
#include "platform/graphics/paint/CompositingDisplayItem.h" |
+#include "platform/graphics/paint/FixedPositionContainerDisplayItem.h" |
#include "platform/graphics/paint/SubsequenceRecorder.h" |
#include "platform/graphics/paint/Transform3DDisplayItem.h" |
#include "wtf/Optional.h" |
@@ -91,8 +94,6 @@ void DeprecatedPaintLayerPainter::paintLayer(GraphicsContext* context, const Dep |
if (m_paintLayer.paintsWithTransparency(paintingInfo.globalPaintFlags())) |
paintFlags |= PaintLayerHaveTransparency; |
- LayerFixedPositionRecorder fixedPositionRecorder(*context, *m_paintLayer.layoutObject()); |
pdr.
2015/09/08 04:23:53
Can you pull this refactoring of LayerFixedPositio
trchen
2015/09/15 04:48:40
Done.
|
- |
// PaintLayerAppliedTransform is used in LayoutReplica, to avoid applying the transform twice. |
if (m_paintLayer.paintsWithTransform(paintingInfo.globalPaintFlags()) && !(paintFlags & PaintLayerAppliedTransform)) { |
paintLayerWithTransform(context, paintingInfo, paintFlags); |
@@ -120,7 +121,7 @@ void DeprecatedPaintLayerPainter::paintLayerContentsAndReflection(GraphicsContex |
class ClipPathHelper { |
public: |
- ClipPathHelper(GraphicsContext* context, const DeprecatedPaintLayer& paintLayer, const DeprecatedPaintLayerPaintingInfo& paintingInfo, LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed, |
+ ClipPathHelper(GraphicsContext* context, const DeprecatedPaintLayer& paintLayer, const LayoutRect& interestRect, LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed, |
pdr.
2015/09/08 04:23:53
Chris just landed a patch that uses DPLPI's ancest
trchen
2015/09/15 04:48:40
Done.
|
const LayoutPoint& offsetFromRoot, PaintLayerFlags paintFlags) |
: m_resourceClipper(0), m_paintLayer(paintLayer), m_context(context) |
{ |
@@ -157,7 +158,7 @@ public: |
m_resourceClipper = toLayoutSVGResourceClipper(toLayoutSVGResourceContainer(element->layoutObject())); |
if (!SVGClipPainter(*m_resourceClipper).prepareEffect(*paintLayer.layoutObject(), FloatRect(rootRelativeBounds), |
- FloatRect(paintingInfo.paintDirtyRect), context, m_clipperState)) { |
+ FloatRect(interestRect), context, m_clipperState)) { |
// No need to post-apply the clipper if this failed. |
m_resourceClipper = 0; |
} |
@@ -206,20 +207,38 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c |
// Ensure our lists are up-to-date. |
m_paintLayer.stackingNode()->updateLayerListsIfNeeded(); |
- LayoutPoint offsetFromRoot; |
- m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); |
- |
- if (m_paintLayer.compositingState() == PaintsIntoOwnBacking) |
pdr.
2015/09/08 04:23:53
The offsetFromRoot refactoring looks correct, but
trchen
2015/09/15 04:48:40
Done. I think paintingInfo.subPixelAccumulation wi
|
- offsetFromRoot.move(m_paintLayer.subpixelAccumulation()); |
+ LayoutPoint offsetFromRoot = toLayoutPoint(paintingInfo.subPixelAccumulation); |
+ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
+ m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot, DeprecatedPaintLayer::ExcludeScroll); |
else |
- offsetFromRoot.move(paintingInfo.subPixelAccumulation); |
+ m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); |
LayoutRect rootRelativeBounds; |
bool rootRelativeBoundsComputed = false; |
+ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && !context->displayItemList()->displayItemConstructionIsDisabled()) { |
+ if (paintingInfo.rootLayer == &m_paintLayer) { |
+ // A counter scroll needs to be applied in non-rootLayerScrolls mode, |
+ // because we are supposed to paint in absolute space. |
+ // (i.e. Impl-side scrolling would be impossible.) |
+ // With rootLayerScrolls enabled, we are in the viewport space instead. |
+ AffineTransform counterScroll; |
+ if (m_paintLayer.layoutObject()->isLayoutView()) { |
+ Settings* settings = m_paintLayer.layoutObject()->document().settings(); |
+ if (settings && settings->rootLayerScrolls()) { |
+ IntSize scrollOffset = static_cast<LayoutView*>(m_paintLayer.layoutObject())->frameView()->scrollOffset(); |
+ counterScroll.translate(scrollOffset.width(), scrollOffset.height()); |
+ } |
+ } |
+ TransformRecorder frameScrollWorkaround(*context, *m_paintLayer.layoutObject(), counterScroll); |
+ |
+ context->displayItemList()->createAndAppend<FixedPositionContainerDisplayItem>(*m_paintLayer.layoutObject()); |
+ } |
+ } |
+ |
// These helpers output clip and compositing operations using a RAII pattern. Stack-allocated-varibles are destructed in the reverse order of construction, |
// so they are nested properly. |
- ClipPathHelper clipPathHelper(context, m_paintLayer, paintingInfo, rootRelativeBounds, rootRelativeBoundsComputed, offsetFromRoot, paintFlags); |
+ ClipPathHelper clipPathHelper(context, m_paintLayer, paintingInfo.paintDirtyRect, rootRelativeBounds, rootRelativeBoundsComputed, offsetFromRoot, paintFlags); |
Optional<CompositingRecorder> compositingRecorder; |
// Blending operations must be performed only with the nearest ancestor stacking context. |
@@ -233,33 +252,42 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c |
m_paintLayer.layoutObject()->opacity(), &compositingBounds); |
} |
- DeprecatedPaintLayerPaintingInfo localPaintingInfo(paintingInfo); |
- if (m_paintLayer.compositingState() == PaintsIntoOwnBacking) |
- localPaintingInfo.subPixelAccumulation = m_paintLayer.subpixelAccumulation(); |
- |
DeprecatedPaintLayerFragments layerFragments; |
if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) { |
// Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment. |
ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) ? UncachedClipRects : PaintingClipRects; |
ShouldRespectOverflowClip respectOverflowClip = shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()); |
- if (fragmentPolicy == ForceSingleFragment) |
- m_paintLayer.appendSingleFragmentIgnoringPagination(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, localPaintingInfo.subPixelAccumulation); |
- else |
- m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, localPaintingInfo.subPixelAccumulation); |
+ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
+ // TODO(trchen): Need to handle layer fragmentation. |
+ DeprecatedPaintLayerFragment fragment; |
+ fragment.layerBounds = LayoutRect(offsetFromRoot, LayoutSize(m_paintLayer.size())); |
+ fragment.backgroundRect = LayoutRect::infiniteRect(); |
+ fragment.foregroundRect = LayoutRect::infiniteRect(); |
+ fragment.outlineRect = LayoutRect::infiniteRect(); |
+ layerFragments.append(fragment); |
+ } else if (fragmentPolicy == ForceSingleFragment) { |
+ m_paintLayer.appendSingleFragmentIgnoringPagination(layerFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, paintingInfo.subPixelAccumulation); |
+ } else { |
+ m_paintLayer.collectFragments(layerFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, paintingInfo.subPixelAccumulation); |
+ } |
+ |
if (shouldPaintContent) |
- shouldPaintContent = atLeastOneFragmentIntersectsDamageRect(layerFragments, localPaintingInfo, paintFlags, offsetFromRoot); |
+ shouldPaintContent = atLeastOneFragmentIntersectsDamageRect(layerFragments, paintingInfo, paintFlags, offsetFromRoot); |
} |
- bool selectionOnly = localPaintingInfo.globalPaintFlags() & GlobalPaintSelectionOnly; |
+ bool selectionOnly = paintingInfo.globalPaintFlags() & GlobalPaintSelectionOnly; |
// If this layer's layoutObject is a child of the paintingRoot, we paint unconditionally, which |
// is done by passing a nil paintingRoot down to our layoutObject (as if no paintingRoot was ever set). |
// Else, our layout tree may or may not contain the painting root, so we pass that root along |
// so it will be tested against as we descend through the layoutObjects. |
LayoutObject* paintingRootForLayoutObject = 0; |
- if (localPaintingInfo.paintingRoot && !m_paintLayer.layoutObject()->isDescendantOf(localPaintingInfo.paintingRoot)) |
- paintingRootForLayoutObject = localPaintingInfo.paintingRoot; |
+ if (paintingInfo.paintingRoot && !m_paintLayer.layoutObject()->isDescendantOf(paintingInfo.paintingRoot)) |
+ paintingRootForLayoutObject = paintingInfo.paintingRoot; |
{ // Begin block for the lifetime of any filter. |
+ // FilterPainter may mutate paintingInfo. |
+ DeprecatedPaintLayerPaintingInfo localPaintingInfo(paintingInfo); |
+ localPaintingInfo.clipToDirtyRect = true; |
pdr.
2015/09/08 04:23:53
This violate's the comment above clipToDirtyRect b
trchen
2015/09/15 04:48:40
IMO clipToDirtyRect is not inherited and shouldn't
|
FilterPainter filterPainter(m_paintLayer, context, offsetFromRoot, layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect, localPaintingInfo, paintFlags, |
rootRelativeBounds, rootRelativeBoundsComputed); |
@@ -270,15 +298,15 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c |
bool shouldPaintOverlayScrollbars = isPaintingOverlayScrollbars; |
if (shouldPaintBackground) { |
- paintBackgroundForFragments(layerFragments, context, paintingInfo.paintDirtyRect, |
+ paintBackgroundForFragments(layerFragments, context, localPaintingInfo.paintDirtyRect, |
localPaintingInfo, paintingRootForLayoutObject, paintFlags); |
} |
if (shouldPaintNegZOrderList) |
- paintChildren(NegativeZOrderChildren, context, paintingInfo, paintFlags); |
+ paintChildren(NegativeZOrderChildren, context, localPaintingInfo, paintFlags); |
if (shouldPaintOwnContents) { |
- paintForegroundForFragments(layerFragments, context, paintingInfo.paintDirtyRect, |
+ paintForegroundForFragments(layerFragments, context, localPaintingInfo.paintDirtyRect, |
localPaintingInfo, paintingRootForLayoutObject, selectionOnly, paintFlags); |
} |
@@ -286,7 +314,7 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c |
paintOutlineForFragments(layerFragments, context, localPaintingInfo, paintingRootForLayoutObject, paintFlags); |
if (shouldPaintNormalFlowAndPosZOrderLists) |
- paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, paintingInfo, paintFlags); |
+ paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, localPaintingInfo, paintFlags); |
if (shouldPaintOverlayScrollbars) |
paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo, paintFlags); |
@@ -296,15 +324,18 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c |
bool shouldPaintClippingMask = (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && shouldPaintContent && !selectionOnly; |
if (shouldPaintMask) |
- paintMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForLayoutObject, paintFlags); |
+ paintMaskForFragments(layerFragments, context, paintingInfo, paintingRootForLayoutObject, paintFlags); |
if (shouldPaintClippingMask) { |
// Paint the border radius mask for the fragments. |
- paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForLayoutObject, paintFlags); |
+ paintChildClippingMaskForFragments(layerFragments, context, paintingInfo, paintingRootForLayoutObject, paintFlags); |
} |
} |
bool DeprecatedPaintLayerPainter::needsToClip(const DeprecatedPaintLayerPaintingInfo& localPaintingInfo, const ClipRect& clipRect) |
{ |
+ // With SPv2 a layer clips its descendants so a layer never clips itself. |
+ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
+ return false; |
return clipRect.rect() != localPaintingInfo.paintDirtyRect || clipRect.hasRadius(); |
} |
@@ -421,6 +452,11 @@ void DeprecatedPaintLayerPainter::paintChildren(unsigned childrenToVisit, Graphi |
LayerListMutationDetector mutationChecker(m_paintLayer.stackingNode()); |
#endif |
+ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
+ paintChildrenWithFullScrollClipChain(childrenToVisit, context, paintingInfo, paintFlags); |
+ return; |
+ } |
+ |
IntSize scrollOffsetAccumulation = paintingInfo.scrollOffsetAccumulation; |
if (m_paintLayer.layoutObject()->hasOverflowClip()) |
scrollOffsetAccumulation += m_paintLayer.layoutBox()->scrolledContentOffset(); |
@@ -445,6 +481,78 @@ void DeprecatedPaintLayerPainter::paintChildren(unsigned childrenToVisit, Graphi |
} |
} |
+static void recursivelyScrollAndPaintChildLayer(Vector<DeprecatedPaintLayer*>& clippingAncestors, DeprecatedPaintLayer& child, GraphicsContext& context, const DeprecatedPaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) |
+{ |
+ ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
+ if (clippingAncestors.isEmpty()) { |
+ DeprecatedPaintLayerPainter(child).paintLayer(&context, paintingInfo, paintFlags); |
+ return; |
+ } |
+ DeprecatedPaintLayer* layer = clippingAncestors.last(); |
+ clippingAncestors.removeLast(); |
+ |
+ ASSERT(layer->layoutObject()->hasOverflowClip() && layer->layoutObject()->isBox()); |
+ LayoutPoint paintOffset = toLayoutPoint(paintingInfo.subPixelAccumulation); |
+ // TODO(trchen): Hey this is slow. We should be able to calculate this on traversal. |
pdr.
2015/09/08 04:23:53
Would it be difficult to go ahead and compute all
trchen
2015/09/15 04:48:40
Done.
|
+ layer->convertToLayerCoords(paintingInfo.rootLayer, paintOffset, DeprecatedPaintLayer::ExcludeScroll); |
+ LayerDescendantClipRecorder clipRecorder(context, *layer->layoutBox(), paintOffset); |
+ |
+ IntSize scrollOffset = layer->layoutBox()->scrolledContentOffset(); |
+ Optional<ScrollRecorder> scrollRecorder; |
+ if (layer->scrollsOverflow() || !scrollOffset.isZero()) |
+ scrollRecorder.emplace(context, *layer->layoutObject(), PaintPhaseBlockBackground, scrollOffset); |
+ recursivelyScrollAndPaintChildLayer(clippingAncestors, child, context, paintingInfo, paintFlags); |
+} |
+ |
+// TODO(trchen): Measure performance of this and implement display item de-duping if needed. |
+// For the pessimistic case this function will generate O(n^2) of clip/scroll pairs, for example: |
+// <div style="overflow:scroll;"> * repeat 100 times |
+// <div style="position:relative;"></div> * repeat 100 times |
+// We will need to generate 100 clip/scroll pairs for each of the in-flow positioned children. |
+void DeprecatedPaintLayerPainter::paintChildrenWithFullScrollClipChain(unsigned childrenToVisit, GraphicsContext* context, const DeprecatedPaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) |
+{ |
+ ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
+ |
+ DeprecatedPaintLayerStackingNodeIterator iterator(*m_paintLayer.stackingNode(), childrenToVisit); |
+ while (DeprecatedPaintLayerStackingNode* childNode = iterator.next()) { |
+ DeprecatedPaintLayer* child = childNode->layer(); |
+ EPosition childPosition = child->layoutObject()->style()->position(); |
+ if (childPosition == FixedPosition) { |
+ ASSERT(paintingInfo.rootLayer == child->enclosingPositionedAncestor()); |
+ // TODO(trchen): Handle the insanity with reflection + fixed position. |
+ LayerFixedPositionRecorder fixedPositionRecorder(*context, *child->layoutObject(), *paintingInfo.rootLayer->layoutObject()); |
+ DeprecatedPaintLayerPainter(*child).paintLayer(context, paintingInfo, paintFlags); |
+ continue; |
+ } |
+ |
+ Vector<DeprecatedPaintLayer*> clippingAncestors; |
+ DeprecatedPaintLayer* currentLayer = child; |
pdr.
2015/09/08 04:23:53
Can you break this out into computeClippingLayersB
trchen
2015/09/15 04:48:40
Done.
|
+ while (currentLayer && currentLayer != &m_paintLayer) { |
+ EPosition position = currentLayer->layoutObject()->style()->position(); |
+ ASSERT(position != FixedPosition); |
+ |
+ DeprecatedPaintLayer* container = nullptr; |
+ if (position == AbsolutePosition) { |
+ bool ranPastThisLayer; |
+ container = currentLayer->enclosingPositionedAncestor(&m_paintLayer, &ranPastThisLayer); |
+ if (ranPastThisLayer) |
+ break; |
+ } else { |
+ container = currentLayer->parent(); |
+ } |
+ if (!container) |
+ break; |
+ |
+ if (container->layoutObject()->hasOverflowClip()) |
+ clippingAncestors.append(container); |
+ |
+ currentLayer = container; |
+ } |
+ |
+ recursivelyScrollAndPaintChildLayer(clippingAncestors, *child, *context, paintingInfo, paintFlags); |
+ } |
+} |
+ |
// FIXME: inline this. |
static bool paintForFixedRootBackground(const DeprecatedPaintLayer* layer, PaintLayerFlags paintFlags) |
{ |
@@ -482,6 +590,13 @@ void DeprecatedPaintLayerPainter::paintFragmentWithPhase(PaintPhase phase, const |
{ |
ASSERT(m_paintLayer.isSelfPaintingLayer()); |
+ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
+ PaintInfo paintInfo(context, enclosingIntRect(paintingInfo.paintDirtyRect), phase, paintingInfo.globalPaintFlags(), paintFlags, paintingRootForLayoutObject, paintingInfo.rootLayer->layoutObject()); |
+ LayoutPoint paintOffset = toPoint(fragment.layerBounds.location() - m_paintLayer.layoutBoxLocation()); |
+ m_paintLayer.layoutObject()->paint(paintInfo, paintOffset); |
+ return; |
+ } |
+ |
Optional<LayerClipRecorder> clipRecorder; |
if (clipState != HasClipped && paintingInfo.clipToDirtyRect && needsToClip(paintingInfo, clipRect)) { |
DisplayItem::Type clipType = DisplayItem::paintPhaseToClipLayerFragmentType(phase); |