Chromium Code Reviews| Index: Source/core/paint/DeprecatedPaintLayerPainter.cpp |
| diff --git a/Source/core/paint/DeprecatedPaintLayerPainter.cpp b/Source/core/paint/DeprecatedPaintLayerPainter.cpp |
| index 0ab32897c8ccba9a5eb9adc2ca63c1e1b6ff839b..2ec6f509ffb817581e7cac9d6b7b72f5f662b417 100644 |
| --- a/Source/core/paint/DeprecatedPaintLayerPainter.cpp |
| +++ b/Source/core/paint/DeprecatedPaintLayerPainter.cpp |
| @@ -110,7 +110,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, |
| const LayoutPoint& offsetFromRoot, PaintLayerFlags paintFlags) |
| : m_resourceClipper(0), m_paintLayer(paintLayer), m_context(context) |
| { |
| @@ -129,7 +129,7 @@ public: |
| ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style.clipPath()); |
| if (clipPath->isValid()) { |
| if (!rootRelativeBoundsComputed) { |
| - rootRelativeBounds = paintLayer.physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot); |
| + rootRelativeBounds = paintLayer.physicalBoundingBoxIncludingReflectionAndStackingChildren(offsetFromRoot); |
| rootRelativeBoundsComputed = true; |
| } |
| m_clipPathRecorder.emplace(*context, *paintLayer.layoutObject(), clipPath->path(rootRelativeBounds)); |
| @@ -141,13 +141,13 @@ public: |
| Element* element = document.getElementById(referenceClipPathOperation->fragment()); |
| if (isSVGClipPathElement(element) && element->layoutObject()) { |
| if (!rootRelativeBoundsComputed) { |
| - rootRelativeBounds = paintLayer.physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot); |
| + rootRelativeBounds = paintLayer.physicalBoundingBoxIncludingReflectionAndStackingChildren(offsetFromRoot); |
| rootRelativeBoundsComputed = true; |
| } |
| m_resourceClipper = toLayoutSVGResourceClipper(toLayoutSVGResourceContainer(element->layoutObject())); |
| if (!SVGClipPainter(*m_resourceClipper).applyClippingToContext(*paintLayer.layoutObject(), rootRelativeBounds, |
| - paintingInfo.paintDirtyRect, context, m_clipperState)) { |
| + interestRect, context, m_clipperState)) { |
| // No need to post-apply the clipper if this failed. |
| m_resourceClipper = 0; |
| } |
| @@ -196,20 +196,18 @@ 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) |
| - offsetFromRoot.move(m_paintLayer.subpixelAccumulation()); |
| + LayoutPoint offsetFromRoot = toLayoutPoint(paintingInfo.subPixelAccumulation); |
| + if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| + m_paintLayer.convertToLayerCoordsSansOverflowScroll(paintingInfo.rootLayer, offsetFromRoot); |
| else |
| - offsetFromRoot.move(paintingInfo.subPixelAccumulation); |
| + m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); |
| LayoutRect rootRelativeBounds; |
| bool rootRelativeBoundsComputed = false; |
| // 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<LayerClipRecorder> clipRecorder; |
| Optional<CompositingRecorder> compositingRecorder; |
| @@ -218,43 +216,73 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c |
| // FIXME: this should be unified further into DeprecatedPaintLayer::paintsWithTransparency(). |
| bool shouldCompositeForBlendMode = (!m_paintLayer.layoutObject()->isDocumentElement() || m_paintLayer.layoutObject()->isSVGRoot()) && m_paintLayer.stackingNode()->isStackingContext() && m_paintLayer.hasNonIsolatedDescendantWithBlendMode(); |
| if (shouldCompositeForBlendMode || m_paintLayer.paintsWithTransparency(paintingInfo.globalPaintFlags())) { |
| - clipRecorder.emplace(*context, *m_paintLayer.layoutObject(), DisplayItem::TransparencyClip, |
| - m_paintLayer.paintingExtent(paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.globalPaintFlags()), |
| - &paintingInfo, LayoutPoint(), paintFlags); |
| + // TODO(trchen): The transparent clip serves the purpose of raster hint for Skia, |
|
pdr.
2015/08/25 20:47:55
Can we fix this before landing your patch? I agree
trchen
2015/08/26 07:39:04
Done.
|
| + // so the Skia layer can be sized according to the bounding box of contents being |
| + // composited. The clip itself should be no-op, but will actually cause anti-alias |
| + // artifact for transformed contents. Should remove this and use the 'bounds' parameter |
| + // in CompositingRecorder instead. |
| + // For SPv2 the compositing bounds is unknown until layerization and impl-side animation |
| + // has been applied. It should be computed using display item cull rects at a later stage. |
| + if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| + clipRecorder.emplace(*context, *m_paintLayer.layoutObject(), DisplayItem::TransparencyClip, |
| + m_paintLayer.paintingExtent(paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.globalPaintFlags()), |
| + &paintingInfo, LayoutPoint(), paintFlags); |
| + } |
| compositingRecorder.emplace(*context, *m_paintLayer.layoutObject(), |
| WebCoreCompositeToSkiaComposite(CompositeSourceOver, m_paintLayer.layoutObject()->style()->blendMode()), |
| m_paintLayer.layoutObject()->opacity()); |
| } |
| - 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 filterPainter(m_paintLayer, context, offsetFromRoot, layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect, localPaintingInfo, paintFlags, |
| + // FilterRecorder may mutate paintingInfo. |
| + DeprecatedPaintLayerPaintingInfo localPaintingInfo(paintingInfo); |
| + ClipRect compositingBound; |
| + if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| + // Similar to transparency clip above, for SPv2 the compositing bound is only |
| + // known since layerization and impl-side animation has been applied. |
| + compositingBound = localPaintingInfo.paintDirtyRect; |
| + } else if (!layerFragments.isEmpty()) { |
| + // TODO(trchen): Using layerFragments[0].backgroundRect as compositing bound is |
| + // incorrect. Using the union of the fragment clip rects could be a workaround |
| + // but is still wrong in operation order. Conceptually it should be equivalent |
| + // as painting the filtered stacking context as a whole, then cut the results into |
| + // fragments for pasting. |
| + compositingBound = layerFragments[0].backgroundRect; |
| + } |
| + FilterPainter filterPainter(m_paintLayer, context, offsetFromRoot, compositingBound, localPaintingInfo, paintFlags, |
| rootRelativeBounds, rootRelativeBoundsComputed); |
| bool shouldPaintBackground = isPaintingCompositedBackground && shouldPaintContent && !selectionOnly; |
| @@ -264,15 +292,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); |
| } |
| @@ -280,7 +308,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); |
| @@ -290,10 +318,10 @@ 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); |
| } |
| } |
| @@ -317,7 +345,7 @@ bool DeprecatedPaintLayerPainter::atLeastOneFragmentIntersectsDamageRect(Depreca |
| // (i.e. only contains an overflow portion of the layer), intersection will fail. The reason |
| // for this is that fragment.layerBounds is set to the border box, not the bounding box, of |
| // the layer. |
| - if (m_paintLayer.intersectsDamageRect(fragment.layerBounds, fragment.backgroundRect.rect(), localPaintingInfo.rootLayer, &newOffsetFromRoot)) |
| + if (m_paintLayer.intersectsDamageRect(fragment.layerBounds, fragment.backgroundRect.rect(), nullptr, &newOffsetFromRoot)) |
| return true; |
| } |
| return false; |
| @@ -415,6 +443,9 @@ void DeprecatedPaintLayerPainter::paintChildren(unsigned childrenToVisit, Graphi |
| LayerListMutationDetector mutationChecker(m_paintLayer.stackingNode()); |
| #endif |
| + if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| + paintChildrenV2(childrenToVisit, context, paintingInfo, paintFlags); |
|
pdr.
2015/08/25 20:47:55
return here?
trchen
2015/08/26 07:39:04
Done.
|
| + |
| IntSize scrollOffsetAccumulation = paintingInfo.scrollOffsetAccumulation; |
| if (m_paintLayer.layoutObject()->hasOverflowClip()) |
| scrollOffsetAccumulation += m_paintLayer.layoutBox()->scrolledContentOffset(); |
| @@ -439,6 +470,65 @@ void DeprecatedPaintLayerPainter::paintChildren(unsigned childrenToVisit, Graphi |
| } |
| } |
| +static void recursivelyScrollAndPaintChildLayer(Vector<DeprecatedPaintLayer*>& clippingAncestors, DeprecatedPaintLayer& child, GraphicsContext& context, const DeprecatedPaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) |
| +{ |
| + if (clippingAncestors.isEmpty()) { |
| + DeprecatedPaintLayerPainter childPainter(child); |
| + childPainter.paintLayer(&context, paintingInfo, paintFlags); |
| + return; |
| + } |
| + DeprecatedPaintLayer* layer = clippingAncestors.last(); |
| + clippingAncestors.removeLast(); |
| + |
| + // TODO(trchen): Add LayerClipRecorder here. |
| + |
| + 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); |
| +} |
| + |
| +void DeprecatedPaintLayerPainter::paintChildrenV2(unsigned childrenToVisit, GraphicsContext* context, const DeprecatedPaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) |
| +{ |
| + DeprecatedPaintLayerStackingNodeIterator iterator(*m_paintLayer.stackingNode(), childrenToVisit); |
| + while (DeprecatedPaintLayerStackingNode* child = iterator.next()) { |
| + EPosition childPosition = child->layer()->layoutObject()->style()->position(); |
| + if (childPosition == FixedPosition) { |
| + // TODO(trchen): Refer to the transform/clip node of the nearest transformed ancestor. |
| + continue; |
| + } |
| + |
| + Vector<DeprecatedPaintLayer*> clippingAncestors; |
| + |
| + // TODO(trchen): Needs to add referrals to reuse existing transform/clip nodes. |
| + DeprecatedPaintLayer* currentLayer = child->layer(); |
| + while (currentLayer && currentLayer != &m_paintLayer) { |
| + EPosition position = currentLayer->layoutObject()->style()->position(); |
| + ASSERT(position != FixedPosition); |
| + |
| + DeprecatedPaintLayer* container; |
|
pdr.
2015/08/25 20:47:55
DeprecatedPaintLayer* container = nullptr;
(pointe
trchen
2015/08/26 07:39:04
Done.
|
| + 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->layer(), *context, paintingInfo, paintFlags); |
| + } |
| +} |
| + |
| // FIXME: inline this. |
| static bool paintForFixedRootBackground(const DeprecatedPaintLayer* layer, PaintLayerFlags paintFlags) |
| { |
| @@ -476,6 +566,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, 0, 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); |