Chromium Code Reviews| 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); |
| } |
| } |