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); |
} |
} |