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

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

Issue 653303003: Generalize paint chunks to clips, and implement clips in LayerPainter. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fixed Created 6 years, 2 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
« no previous file with comments | « Source/core/paint/LayerPainter.h ('k') | Source/core/paint/ViewDisplayList.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/paint/LayerPainter.cpp
diff --git a/Source/core/paint/LayerPainter.cpp b/Source/core/paint/LayerPainter.cpp
index d00ce6861dcc3d923586b85163ba3eb9cb1e601f..fc8a9c5e4e0afb314093268067ba926f3c756d31 100644
--- a/Source/core/paint/LayerPainter.cpp
+++ b/Source/core/paint/LayerPainter.cpp
@@ -88,6 +88,11 @@ void LayerPainter::paintLayer(GraphicsContext* context, const LayerPaintingInfo&
return;
}
+ PaintClipRecorder paintClipRecorder(&m_renderLayer, ClipDisplayItem::LayerParent);
+ PaintClipRecorder* paintClipRecorderPtr = 0;
+ if (RuntimeEnabledFeatures::slimmingPaintEnabled())
+ paintClipRecorderPtr = &paintClipRecorder;
+
// Make sure the parent's clip rects have been calculated.
ClipRect clipRect = paintingInfo.paintDirtyRect;
if (m_renderLayer.parent()) {
@@ -98,14 +103,14 @@ void LayerPainter::paintLayer(GraphicsContext* context, const LayerPaintingInfo&
clipRect.intersect(paintingInfo.paintDirtyRect);
// Push the parent coordinate space's clip.
- LayerPainter(*m_renderLayer.parent()).clipToRect(paintingInfo, context, clipRect, paintFlags);
+ LayerPainter(*m_renderLayer.parent()).clipToRect(paintingInfo, context, clipRect, paintFlags, paintClipRecorderPtr);
}
paintLayerByApplyingTransform(context, paintingInfo, paintFlags);
// Restore the clip.
if (m_renderLayer.parent())
- LayerPainter(*m_renderLayer.parent()).restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
+ LayerPainter(*m_renderLayer.parent()).restoreClip(context, paintingInfo.paintDirtyRect, clipRect, paintClipRecorderPtr);
return;
}
@@ -265,6 +270,11 @@ void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint
updatePaintingInfoForFragments(layerFragments, localPaintingInfo, paintFlags, shouldPaintContent, &offsetFromRoot);
}
+ PaintClipRecorder filterPaintClipRecorder(&m_renderLayer, ClipDisplayItem::LayerFilter);
+ PaintClipRecorder* filterPaintClipRecorderPtr = 0;
+ if (RuntimeEnabledFeatures::slimmingPaintEnabled())
+ filterPaintClipRecorderPtr = &filterPaintClipRecorder;
+
if (haveFilterEffect) {
ASSERT(m_renderLayer.filterInfo());
@@ -276,18 +286,19 @@ void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint
// If we have a filter and transparency, we have to eagerly start a transparency layer here, rather than risk a child layer lazily starts one after filter processing.
beginTransparencyLayers(context, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior);
}
+
// We'll handle clipping to the dirty rect before filter rasterization.
// Filter processing will automatically expand the clip rect and the offscreen to accommodate any filter outsets.
// FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved.
ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect;
- clipToRect(localPaintingInfo, context, backgroundRect, paintFlags);
+ clipToRect(localPaintingInfo, context, backgroundRect, paintFlags, filterPaintClipRecorderPtr);
// Subsequent code should not clip to the dirty rect, since we've already
// done it above, and doing it later will defeat the outsets.
localPaintingInfo.clipToDirtyRect = false;
haveFilterEffect = m_renderLayer.filterRenderer()->beginFilterEffect(context, rootRelativeBounds);
if (!haveFilterEffect) {
// If the the filter failed to start, undo the clip immediately
- restoreClip(context, localPaintingInfo.paintDirtyRect, backgroundRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, backgroundRect, filterPaintClipRecorderPtr);
}
}
@@ -343,7 +354,7 @@ void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint
// FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved.
ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect;
m_renderLayer.filterRenderer()->endFilterEffect(context);
- restoreClip(context, localPaintingInfo.paintDirtyRect, backgroundRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, backgroundRect, filterPaintClipRecorderPtr);
}
if (shouldPaintMask)
@@ -381,43 +392,59 @@ static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLaye
}
void LayerPainter::clipToRect(const LayerPaintingInfo& localPaintingInfo, GraphicsContext* context, const ClipRect& clipRect,
- PaintLayerFlags paintFlags, BorderRadiusClippingRule rule)
+ PaintLayerFlags paintFlags, PaintClipRecorder* paintClipRecorder, BorderRadiusClippingRule rule)
{
if (clipRect.rect() == localPaintingInfo.paintDirtyRect && !clipRect.hasRadius())
return;
- context->save();
- context->clip(pixelSnappedIntRect(clipRect.rect()));
- if (!clipRect.hasRadius())
- return;
+ IntRect pixelSnappedRect = pixelSnappedIntRect(clipRect.rect());
- // If the clip rect has been tainted by a border radius, then we have to walk up our layer chain applying the clips from
- // any layers with overflow. The condition for being able to apply these clips is that the overflow object be in our
- // containing block chain so we check that also.
- for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? &m_renderLayer : m_renderLayer.parent(); layer; layer = layer->parent()) {
- // Composited scrolling layers handle border-radius clip in the compositor via a mask layer. We do not
- // want to apply a border-radius clip to the layer contents itself, because that would require re-rastering
- // every frame to update the clip. We only want to make sure that the mask layer is properly clipped so
- // that it can in turn clip the scrolled contents in the compositor.
- if (layer->needsCompositedScrolling() && !(paintFlags & PaintLayerPaintingChildClippingMaskPhase))
- break;
+ if (paintClipRecorder) {
leviw_travelin_and_unemployed 2014/10/15 18:51:39 Putting this if everywhere that calls clip seems u
+ paintClipRecorder->setClipRect(pixelSnappedRect);
+ } else {
+ context->save();
+ context->clip(pixelSnappedIntRect(clipRect.rect()));
+ }
- if (layer->renderer()->hasOverflowClip() && layer->renderer()->style()->hasBorderRadius() && inContainingBlockChain(&m_renderLayer, layer)) {
- LayoutPoint delta;
- layer->convertToLayerCoords(localPaintingInfo.rootLayer, delta);
- context->clipRoundedRect(layer->renderer()->style()->getRoundedInnerBorderFor(LayoutRect(delta, layer->size())));
- }
+ if (clipRect.hasRadius()) {
+ // If the clip rect has been tainted by a border radius, then we have to walk up our layer chain applying the clips from
+ // any layers with overflow. The condition for being able to apply these clips is that the overflow object be in our
+ // containing block chain so we check that also.
+ for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? &m_renderLayer : m_renderLayer.parent(); layer; layer = layer->parent()) {
+ // Composited scrolling layers handle border-radius clip in the compositor via a mask layer. We do not
+ // want to apply a border-radius clip to the layer contents itself, because that would require re-rastering
+ // every frame to update the clip. We only want to make sure that the mask layer is properly clipped so
+ // that it can in turn clip the scrolled contents in the compositor.
+ if (layer->needsCompositedScrolling() && !(paintFlags & PaintLayerPaintingChildClippingMaskPhase))
+ break;
- if (layer == localPaintingInfo.rootLayer)
- break;
+ if (layer->renderer()->hasOverflowClip() && layer->renderer()->style()->hasBorderRadius() && inContainingBlockChain(&m_renderLayer, layer)) {
+ LayoutPoint delta;
+ layer->convertToLayerCoords(localPaintingInfo.rootLayer, delta);
+ RoundedRect roundedRect = layer->renderer()->style()->getRoundedInnerBorderFor(LayoutRect(delta, layer->size()));
+ if (paintClipRecorder)
+ paintClipRecorder->addRoundedRectClip(roundedRect);
+ else
+ context->clipRoundedRect(roundedRect);
+ }
+
+ if (layer == localPaintingInfo.rootLayer)
+ break;
+ }
}
+
+ if (paintClipRecorder)
leviw_travelin_and_unemployed 2014/10/15 18:51:39 Why is it okay to unbalance this with the calls to
+ paintClipRecorder->endClip();
}
-void LayerPainter::restoreClip(GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect)
+void LayerPainter::restoreClip(GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect, PaintClipRecorder* paintClipRecorder = 0)
{
if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius())
return;
- context->restore();
+ if (paintClipRecorder)
+ paintClipRecorder->endClip();
+ else
+ context->restore();
}
void LayerPainter::updatePaintingInfoForFragments(LayerFragments& fragments, const LayerPaintingInfo& localPaintingInfo, PaintLayerFlags localPaintFlags,
@@ -512,11 +539,17 @@ static inline LayoutSize subPixelAccumulationIfNeeded(const LayoutSize& subPixel
void LayerPainter::paintOverflowControlsForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo, PaintLayerFlags paintFlags)
{
for (size_t i = 0; i < layerFragments.size(); ++i) {
+ PaintClipRecorder paintClipRecorder(&m_renderLayer, ClipDisplayItem::LayerOverflowControls);
+ PaintClipRecorder* paintClipRecorderPtr = 0;
+ if (RuntimeEnabledFeatures::slimmingPaintEnabled())
+ paintClipRecorderPtr = &paintClipRecorder;
+
const LayerFragment& fragment = layerFragments.at(i);
- clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags);
+
+ clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags, paintClipRecorderPtr);
if (RenderLayerScrollableArea* scrollableArea = m_renderLayer.scrollableArea())
scrollableArea->paintOverflowControls(context, roundedIntPoint(toPoint(fragment.layerBounds.location() - m_renderLayer.renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, m_renderLayer.compositingState()))), pixelSnappedIntRect(fragment.backgroundRect.rect()), true);
- restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect, paintClipRecorderPtr);
}
}
@@ -665,6 +698,11 @@ void LayerPainter::paintBackgroundForFragments(const LayerFragments& layerFragme
RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags)
{
for (size_t i = 0; i < layerFragments.size(); ++i) {
+ PaintClipRecorder paintClipRecorder(&m_renderLayer, ClipDisplayItem::LayerBackground);
+ PaintClipRecorder* paintClipRecorderPtr = 0;
+ if (RuntimeEnabledFeatures::slimmingPaintEnabled())
+ paintClipRecorderPtr = &paintClipRecorder;
+
const LayerFragment& fragment = layerFragments.at(i);
if (!fragment.shouldPaintContent)
continue;
@@ -676,7 +714,7 @@ void LayerPainter::paintBackgroundForFragments(const LayerFragments& layerFragme
if (localPaintingInfo.clipToDirtyRect) {
// Paint our background first, before painting any child layers.
// Establish the clip used to paint our background.
- clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
+ clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags, paintClipRecorderPtr, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
}
// Paint the background.
@@ -685,7 +723,7 @@ void LayerPainter::paintBackgroundForFragments(const LayerFragments& layerFragme
m_renderLayer.renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - m_renderLayer.renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, m_renderLayer.compositingState())));
if (localPaintingInfo.clipToDirtyRect)
- restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect, paintClipRecorderPtr);
}
}
@@ -704,10 +742,15 @@ void LayerPainter::paintForegroundForFragments(const LayerFragments& layerFragme
}
}
+ PaintClipRecorder paintClipRecorder(&m_renderLayer, ClipDisplayItem::LayerForeground);
+ PaintClipRecorder* paintClipRecorderPtr = 0;
+ if (RuntimeEnabledFeatures::slimmingPaintEnabled())
+ paintClipRecorderPtr = &paintClipRecorder;
+
// Optimize clipping for the single fragment case.
bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() == 1 && layerFragments[0].shouldPaintContent && !layerFragments[0].foregroundRect.isEmpty();
if (shouldClip)
- clipToRect(localPaintingInfo, context, layerFragments[0].foregroundRect, paintFlags);
+ clipToRect(localPaintingInfo, context, layerFragments[0].foregroundRect, paintFlags, paintClipRecorderPtr);
// We have to loop through every fragment multiple times, since we have to issue paint invalidations in each specific phase in order for
// interleaving of the fragments to work properly.
@@ -721,7 +764,7 @@ void LayerPainter::paintForegroundForFragments(const LayerFragments& layerFragme
}
if (shouldClip)
- restoreClip(context, localPaintingInfo.paintDirtyRect, layerFragments[0].foregroundRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, layerFragments[0].foregroundRect, paintClipRecorderPtr);
}
void LayerPainter::paintForegroundForFragmentsWithPhase(PaintPhase phase, const LayerFragments& layerFragments, GraphicsContext* context,
@@ -734,14 +777,36 @@ void LayerPainter::paintForegroundForFragmentsWithPhase(PaintPhase phase, const
if (!fragment.shouldPaintContent || fragment.foregroundRect.isEmpty())
continue;
+ // Note: this method only clips when there is more than one fragment.
+ ClipDisplayItem::ClipType clipType = (ClipDisplayItem::ClipType)0;
+ if (RuntimeEnabledFeatures::slimmingPaintEnabled()) {
+ switch (phase) {
+ case PaintPhaseFloat:
+ clipType = ClipDisplayItem::LayerFragmentFloat;
+ break;
+ case PaintPhaseForeground:
+ clipType = ClipDisplayItem::LayerFragmentForeground;
+ break;
+ case PaintPhaseChildOutlines:
+ clipType = ClipDisplayItem::LayerFragmentChildOutline;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+ PaintClipRecorder paintClipRecorder(&m_renderLayer, clipType);
+ PaintClipRecorder* paintClipRecorderPtr = 0;
+ if (RuntimeEnabledFeatures::slimmingPaintEnabled())
+ paintClipRecorderPtr = &paintClipRecorder;
+
if (shouldClip)
- clipToRect(localPaintingInfo, context, fragment.foregroundRect, paintFlags);
+ clipToRect(localPaintingInfo, context, fragment.foregroundRect, paintFlags, paintClipRecorderPtr);
PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.foregroundRect.rect()), phase, paintBehavior, paintingRootForRenderer, 0, localPaintingInfo.rootLayer->renderer());
m_renderLayer.renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - m_renderLayer.renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, m_renderLayer.compositingState())));
if (shouldClip)
- restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect, paintClipRecorderPtr);
}
}
@@ -753,11 +818,16 @@ void LayerPainter::paintOutlineForFragments(const LayerFragments& layerFragments
if (fragment.outlineRect.isEmpty())
continue;
+ PaintClipRecorder paintClipRecorder(&m_renderLayer, ClipDisplayItem::LayerFragmentOutline);
+ PaintClipRecorder* paintClipRecorderPtr = 0;
+ if (RuntimeEnabledFeatures::slimmingPaintEnabled())
+ paintClipRecorderPtr = &paintClipRecorder;
+
// Paint our own outline
PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.outlineRect.rect()), PaintPhaseSelfOutline, paintBehavior, paintingRootForRenderer, 0, localPaintingInfo.rootLayer->renderer());
- clipToRect(localPaintingInfo, context, fragment.outlineRect, paintFlags, DoNotIncludeSelfForBorderRadius);
+ clipToRect(localPaintingInfo, context, fragment.outlineRect, paintFlags, paintClipRecorderPtr, DoNotIncludeSelfForBorderRadius);
m_renderLayer.renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - m_renderLayer.renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, m_renderLayer.compositingState())));
- restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.outlineRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.outlineRect, paintClipRecorderPtr);
}
}
@@ -769,8 +839,13 @@ void LayerPainter::paintMaskForFragments(const LayerFragments& layerFragments, G
if (!fragment.shouldPaintContent)
continue;
+ PaintClipRecorder paintClipRecorder(&m_renderLayer, ClipDisplayItem::LayerFragmentMask);
+ PaintClipRecorder* paintClipRecorderPtr = 0;
+ if (RuntimeEnabledFeatures::slimmingPaintEnabled())
+ paintClipRecorderPtr = &paintClipRecorder;
+
if (localPaintingInfo.clipToDirtyRect)
- clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
+ clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags, paintClipRecorderPtr, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
// Paint the mask.
// FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info.
@@ -778,7 +853,7 @@ void LayerPainter::paintMaskForFragments(const LayerFragments& layerFragments, G
m_renderLayer.renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - m_renderLayer.renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, m_renderLayer.compositingState())));
if (localPaintingInfo.clipToDirtyRect)
- restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect, paintClipRecorderPtr);
}
}
@@ -790,15 +865,20 @@ void LayerPainter::paintChildClippingMaskForFragments(const LayerFragments& laye
if (!fragment.shouldPaintContent)
continue;
+ PaintClipRecorder paintClipRecorder(&m_renderLayer, ClipDisplayItem::LayerFragmentClippingMask);
+ PaintClipRecorder* paintClipRecorderPtr = 0;
+ if (RuntimeEnabledFeatures::slimmingPaintEnabled())
+ paintClipRecorderPtr = &paintClipRecorder;
+
if (localPaintingInfo.clipToDirtyRect)
- clipToRect(localPaintingInfo, context, fragment.foregroundRect, paintFlags, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
+ clipToRect(localPaintingInfo, context, fragment.foregroundRect, paintFlags, paintClipRecorderPtr, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
// Paint the the clipped mask.
PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseClippingMask, PaintBehaviorNormal, paintingRootForRenderer, 0, localPaintingInfo.rootLayer->renderer());
m_renderLayer.renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - m_renderLayer.renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, m_renderLayer.compositingState())));
if (localPaintingInfo.clipToDirtyRect)
- restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect, paintClipRecorderPtr);
}
}
@@ -841,9 +921,14 @@ void LayerPainter::paintTransformedLayerIntoFragments(GraphicsContext* context,
clipRect.intersect(parentClipRect);
}
- LayerPainter(*m_renderLayer.parent()).clipToRect(paintingInfo, context, clipRect, paintFlags);
+ PaintClipRecorder paintClipRecorder(&m_renderLayer, ClipDisplayItem::LayerFragmentParent);
+ PaintClipRecorder* paintClipRecorderPtr = 0;
+ if (RuntimeEnabledFeatures::slimmingPaintEnabled())
+ paintClipRecorderPtr = &paintClipRecorder;
+
+ LayerPainter(*m_renderLayer.parent()).clipToRect(paintingInfo, context, clipRect, paintFlags, paintClipRecorderPtr);
paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset);
- LayerPainter(*m_renderLayer.parent()).restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
+ LayerPainter(*m_renderLayer.parent()).restoreClip(context, paintingInfo.paintDirtyRect, clipRect, paintClipRecorderPtr);
}
}
« no previous file with comments | « Source/core/paint/LayerPainter.h ('k') | Source/core/paint/ViewDisplayList.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698