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

Unified Diff: Source/core/paint/DeprecatedPaintLayerPainter.cpp

Issue 1284203004: Generate scroll/clip display item hierarchy for SPv2 (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: still long way to go Created 5 years, 4 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 side-by-side diff with in-line comments
Download patch
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);

Powered by Google App Engine
This is Rietveld 408576698