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

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: stripped localPaintingInfo cleanup and fixed-pos workarounds Created 5 years, 3 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 b3e1e59e9bcc5775b3d71277d7e553ac160d19c4..2202aecab95d1c6ad84411cdcb2394a1dc0eb684 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"
@@ -230,7 +231,10 @@ DeprecatedPaintLayerPainter::PaintResult DeprecatedPaintLayerPainter::paintLayer
m_paintLayer.stackingNode()->updateLayerListsIfNeeded();
LayoutPoint offsetFromRoot;
- m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
+ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
+ m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot, DeprecatedPaintLayer::ExcludeScroll);
+ else
+ m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
if (m_paintLayer.compositingState() == PaintsIntoOwnBacking)
offsetFromRoot.move(m_paintLayer.subpixelAccumulation());
@@ -272,10 +276,19 @@ DeprecatedPaintLayerPainter::PaintResult DeprecatedPaintLayerPainter::paintLayer
// 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)
+ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
+ // TODO(trchen): Need to handle layer fragmentation.
chrishtr 2015/09/17 18:07:53 How hard will this be? We need a clear plan for it
+ 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, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, localPaintingInfo.subPixelAccumulation);
- else
+ } else {
m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, localPaintingInfo.subPixelAccumulation);
+ }
if (shouldPaintContent) {
// TODO(wangxianzhu): This is for old slow scrolling. Implement similar optimization for slimming paint v2.
shouldPaintContent = atLeastOneFragmentIntersectsDamageRect(layerFragments, localPaintingInfo, paintFlags, offsetFromRoot);
@@ -350,6 +363,9 @@ DeprecatedPaintLayerPainter::PaintResult DeprecatedPaintLayerPainter::paintLayer
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();
}
@@ -473,6 +489,9 @@ DeprecatedPaintLayerPainter::PaintResult DeprecatedPaintLayerPainter::paintChild
LayerListMutationDetector mutationChecker(m_paintLayer.stackingNode());
#endif
+ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
+ return paintChildrenWithFullScrollClipChain(childrenToVisit, context, paintingInfo, paintFlags);
+
IntSize scrollOffsetAccumulation = paintingInfo.scrollOffsetAccumulation;
if (m_paintLayer.layoutObject()->hasOverflowClip())
scrollOffsetAccumulation += m_paintLayer.layoutBox()->scrolledContentOffset();
@@ -499,6 +518,90 @@ DeprecatedPaintLayerPainter::PaintResult DeprecatedPaintLayerPainter::paintChild
return result;
}
+static DeprecatedPaintLayerPainter::PaintResult recursivelyScrollAndPaintChildLayer(Vector<DeprecatedPaintLayer*>& clippingAncestors, DeprecatedPaintLayer& child, GraphicsContext& context, const DeprecatedPaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, DeprecatedPaintLayer* paintOffsetBase, LayoutPoint paintOffset)
chrishtr 2015/09/17 00:53:46 This looks like a bottom-up approach: when encount
trchen 2015/09/17 01:56:04 Only up to the nearest self-painting ancestor. i.e
+{
+ ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
+ if (clippingAncestors.isEmpty())
+ return DeprecatedPaintLayerPainter(child).paintLayer(&context, paintingInfo, paintFlags);
+ DeprecatedPaintLayer* layer = clippingAncestors.last();
+ clippingAncestors.removeLast();
+
+ ASSERT(layer->layoutObject()->hasOverflowClip() && layer->layoutObject()->isBox());
+ layer->convertToLayerCoords(paintOffsetBase, paintOffset, DeprecatedPaintLayer::ExcludeScroll);
+ LayerDescendantClipRecorder clipRecorder(context, *layer->layoutBox(), paintOffset);
+#if ENABLE(ASSERT)
+ // We want to calculate the current layer position relative to the painting root.
+ // The conversion above reduces time complexity but is logically incorrect.
+ // For example if we have layers A, B, C where layer A is the grandparent of layer C,
+ // we want to first convert from space C->B then B->A. What we do above is actually
+ // convert from space B->A first then C->B. It works because we assume the conversions
+ // are all linear translation thus commutative.
+ LayoutPoint expectedPaintOffset = toLayoutPoint(paintingInfo.subPixelAccumulation);
+ layer->convertToLayerCoords(paintingInfo.rootLayer, expectedPaintOffset, DeprecatedPaintLayer::ExcludeScroll);
+ ASSERT(paintOffset == expectedPaintOffset);
+#endif
+
+ IntSize scrollOffset = layer->layoutBox()->scrolledContentOffset();
+ Optional<ScrollRecorder> scrollRecorder;
+ if (layer->scrollsOverflow() || !scrollOffset.isZero())
+ scrollRecorder.emplace(context, *layer->layoutObject(), PaintPhaseBlockBackground, scrollOffset);
+ return recursivelyScrollAndPaintChildLayer(clippingAncestors, child, context, paintingInfo, paintFlags, layer, paintOffset);
+}
+
+static void collectClippingLayersBetween(Vector<DeprecatedPaintLayer*> &clippingAncestors, DeprecatedPaintLayer* layer, DeprecatedPaintLayer* ancestor)
chrishtr 2015/09/17 00:53:46 This function is doing almost (exactly?) the same
trchen 2015/09/17 01:56:04 Yep. Albeit we don't try to collapse clip rects ri
+{
+ while (layer && layer != ancestor) {
+ EPosition position = layer->layoutObject()->style()->position();
+ ASSERT(position != FixedPosition);
+
+ DeprecatedPaintLayer* container = nullptr;
+ if (position == AbsolutePosition) {
+ bool ranPastThisLayer;
+ container = layer->enclosingPositionedAncestor(ancestor, &ranPastThisLayer);
+ if (ranPastThisLayer)
+ break;
+ } else {
+ container = layer->parent();
+ }
+ if (!container)
+ break;
+
+ if (container->layoutObject()->hasOverflowClip())
chrishtr 2015/09/17 18:07:53 What about css clip and clip-path?
+ clippingAncestors.append(container);
+
+ layer = container;
+ }
+}
+
+// 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.
+DeprecatedPaintLayerPainter::PaintResult DeprecatedPaintLayerPainter::paintChildrenWithFullScrollClipChain(unsigned childrenToVisit, GraphicsContext* context, const DeprecatedPaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
chrishtr 2015/09/22 18:32:56 Let's implement an optimization here: between pain
+{
+ PaintResult result = FullyPainted;
+ 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) {
+ // TODO(trchen): Fixed position needs to be implemented here.
chrishtr 2015/09/17 18:07:53 We need a plan for how to do it before committing
chrishtr 2015/09/22 18:32:56 On reflection, I think fixed position shouldn't be
+ if (DeprecatedPaintLayerPainter(*child).paintLayer(context, paintingInfo, paintFlags) == MaybeNotFullyPainted)
+ result = MaybeNotFullyPainted;
+ continue;
+ }
+
+ Vector<DeprecatedPaintLayer*> clippingAncestors;
+ collectClippingLayersBetween(clippingAncestors, child, &m_paintLayer);
+ if (recursivelyScrollAndPaintChildLayer(clippingAncestors, *child, *context, paintingInfo, paintFlags, paintingInfo.rootLayer, toLayoutPoint(paintingInfo.subPixelAccumulation)) == MaybeNotFullyPainted)
+ result = MaybeNotFullyPainted;
+ }
+ return result;
+}
+
// FIXME: inline this.
static bool paintForFixedRootBackground(const DeprecatedPaintLayer* layer, PaintLayerFlags paintFlags)
{
@@ -536,6 +639,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);

Powered by Google App Engine
This is Rietveld 408576698