Changeset 200279 in webkit


Ignore:
Timestamp:
Apr 29, 2016, 7:55:01 PM (9 years ago)
Author:
Simon Fraser
Message:

Clean up GraphicsContext use in RenderLayer::paintLayerContents()
https://bugs.webkit.org/show_bug.cgi?id=157193

Reviewed by Zalan Bujtas.

Make the lifetime of the temporary GraphicsContext used to paint filters more explicit
by putting it in an inner scope.

Make currentContext a reference.

transparencyLayerContext was a confusing name (it doens't mean we've started a
transparency layer), so just use "context" to refer to the original context. When
passed to other functions, this is called "contextForTransparencyLayer".

No longer leaves "context" as a null pointer if filterPainter->filterContext() returns
a null pointer. It's unclear if this ever happened.

  • rendering/FilterEffectRenderer.cpp:

(WebCore::FilterEffectRendererHelper::filterContext):

  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::beginTransparencyLayers):
(WebCore::RenderLayer::applyFilters):
(WebCore::RenderLayer::paintLayerContents):
(WebCore::RenderLayer::paintBackgroundForFragments):
(WebCore::RenderLayer::paintForegroundForFragments):

  • rendering/RenderLayer.h:
Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r200276 r200279  
     12016-04-29  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Clean up GraphicsContext use in RenderLayer::paintLayerContents()
     4        https://bugs.webkit.org/show_bug.cgi?id=157193
     5
     6        Reviewed by Zalan Bujtas.
     7
     8        Make the lifetime of the temporary GraphicsContext used to paint filters more explicit
     9        by putting it in an inner scope.
     10       
     11        Make currentContext a reference.
     12       
     13        transparencyLayerContext was a confusing name (it doens't mean we've started a
     14        transparency layer), so just use "context" to refer to the original context. When
     15        passed to other functions, this is called "contextForTransparencyLayer".
     16       
     17        No longer leaves "context" as a null pointer if filterPainter->filterContext() returns
     18        a null pointer. It's unclear if this ever happened.
     19
     20        * rendering/FilterEffectRenderer.cpp:
     21        (WebCore::FilterEffectRendererHelper::filterContext):
     22        * rendering/RenderLayer.cpp:
     23        (WebCore::RenderLayer::beginTransparencyLayers):
     24        (WebCore::RenderLayer::applyFilters):
     25        (WebCore::RenderLayer::paintLayerContents):
     26        (WebCore::RenderLayer::paintBackgroundForFragments):
     27        (WebCore::RenderLayer::paintForegroundForFragments):
     28        * rendering/RenderLayer.h:
     29
    1302016-04-29  Joseph Pecoraro  <pecoraro@apple.com>
    231
  • trunk/Source/WebCore/rendering/FilterEffectRenderer.cpp

    r192140 r200279  
    388388{
    389389    if (!m_haveFilterEffect)
    390         return 0;
     390        return nullptr;
    391391
    392392    FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r200261 r200279  
    18201820
    18211821#ifdef REVEAL_TRANSPARENCY_LAYERS
    1822         context->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f));
    1823         context->fillRect(pixelSnappedClipRect);
     1822        context.setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f));
     1823        context.fillRect(pixelSnappedClipRect);
    18241824#endif
    18251825    }
     
    41974197}
    41984198
    4199 GraphicsContext& RenderLayer::applyFilters(FilterEffectRendererHelper* filterPainter, GraphicsContext& originalContext, LayerPaintingInfo& paintingInfo, LayerFragments& layerFragments)
     4199void RenderLayer::applyFilters(FilterEffectRendererHelper* filterPainter, GraphicsContext& originalContext, LayerPaintingInfo& paintingInfo, LayerFragments& layerFragments)
    42004200{
    42014201    ASSERT(filterPainter->hasStartedFilterEffect());
     
    42064206    filterPainter->applyFilterEffect(originalContext);
    42074207    restoreClip(originalContext, paintingInfo.paintDirtyRect, backgroundRect);
    4208     return originalContext;
    42094208}
    42104209
     
    42404239}
    42414240
    4242 void RenderLayer::paintLayerContents(GraphicsContext& originalContext, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
     4241void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
    42434242{
    42444243    ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
     
    42824281    // things on the scrolling thread.
    42834282    bool didQuantizeFonts = true;
    4284     bool needToAdjustSubpixelQuantization = setupFontSubpixelQuantization(originalContext, didQuantizeFonts);
     4283    bool needToAdjustSubpixelQuantization = setupFontSubpixelQuantization(context, didQuantizeFonts);
    42854284
    42864285    // Apply clip-path to context.
    42874286    LayoutSize columnAwareOffsetFromRoot = offsetFromRoot;
    4288     if (renderer().flowThreadContainingBlock() && (renderer().hasClipPath() || hasFilterThatIsPainting(originalContext, paintFlags)))
     4287    if (renderer().flowThreadContainingBlock() && (renderer().hasClipPath() || hasFilterThatIsPainting(context, paintFlags)))
    42894288        columnAwareOffsetFromRoot = toLayoutSize(convertToLayerCoords(paintingInfo.rootLayer, LayoutPoint(), AdjustForColumns));
    42904289
    42914290    bool hasClipPath = false;
    42924291    if (shouldApplyClipPath(paintingInfo.paintBehavior, localPaintFlags))
    4293         hasClipPath = setupClipPath(originalContext, paintingInfo, columnAwareOffsetFromRoot, rootRelativeBounds, rootRelativeBoundsComputed);
     4292        hasClipPath = setupClipPath(context, paintingInfo, columnAwareOffsetFromRoot, rootRelativeBounds, rootRelativeBoundsComputed);
    42944293
    42954294    LayerPaintingInfo localPaintingInfo(paintingInfo);
    4296 
    4297     GraphicsContext* context = &originalContext;
    4298     GraphicsContext& transparencyLayerContext = originalContext;
    4299     std::unique_ptr<FilterEffectRendererHelper> filterPainter = setupFilters(*context, localPaintingInfo, paintFlags, columnAwareOffsetFromRoot, rootRelativeBounds, rootRelativeBoundsComputed);
    4300     if (filterPainter) {
    4301         context = filterPainter->filterContext();
    4302         if (context != &transparencyLayerContext && haveTransparency) {
    4303             // 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 with the wrong context.
    4304             beginTransparencyLayers(transparencyLayerContext, localPaintingInfo, paintingInfo.paintDirtyRect);
    4305         }
    4306     }
    4307 
    4308     // If this layer's renderer is a child of the subtreePaintRoot, we render unconditionally, which
    4309     // is done by passing a nil subtreePaintRoot down to our renderer (as if no subtreePaintRoot was ever set).
    4310     // Otherwise, our renderer tree may or may not contain the subtreePaintRoot root, so we pass that root along
    4311     // so it will be tested against as we descend through the renderers.
    4312     RenderObject* subtreePaintRootForRenderer = nullptr;
    4313     if (localPaintingInfo.subtreePaintRoot && !renderer().isDescendantOf(localPaintingInfo.subtreePaintRoot))
    4314         subtreePaintRootForRenderer = localPaintingInfo.subtreePaintRoot;
    4315 
    4316     if (localPaintingInfo.overlapTestRequests && isSelfPaintingLayer)
    4317         performOverlapTests(*localPaintingInfo.overlapTestRequests, localPaintingInfo.rootLayer, this);
    43184295
    43194296    bool selectionAndBackgroundsOnly = localPaintingInfo.paintBehavior & PaintBehaviorSelectionAndBackgroundsOnly;
    43204297    bool selectionOnly = localPaintingInfo.paintBehavior & PaintBehaviorSelectionOnly;
    4321    
    4322     PaintBehavior paintBehavior = PaintBehaviorNormal;
    4323     if (localPaintFlags & PaintLayerPaintingSkipRootBackground)
    4324         paintBehavior |= PaintBehaviorSkipRootBackground;
    4325     else if (localPaintFlags & PaintLayerPaintingRootBackgroundOnly)
    4326         paintBehavior |= PaintBehaviorRootBackgroundOnly;
    4327 
    43284298    LayerFragments layerFragments;
    4329     LayoutRect paintDirtyRect = localPaintingInfo.paintDirtyRect;
    4330     if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
    4331         // Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment, as well as whether or not the content of each
    4332         // fragment should paint. If the parent's filter dictates full repaint to ensure proper filter effect,
    4333         // use the overflow clip as dirty rect, instead of no clipping. It maintains proper clipping for overflow::scroll.
    4334         if (!paintingInfo.clipToDirtyRect && renderer().hasOverflowClip()) {
    4335             // We can turn clipping back by requesting full repaint for the overflow area.
    4336             localPaintingInfo.clipToDirtyRect = true;
    4337             paintDirtyRect = selfClipRect();
    4338         }
    4339         collectFragments(layerFragments, localPaintingInfo.rootLayer, paintDirtyRect, ExcludeCompositedPaginatedLayers,
    4340             (localPaintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize,
    4341             (isPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, offsetFromRoot);
    4342         updatePaintingInfoForFragments(layerFragments, localPaintingInfo, localPaintFlags, shouldPaintContent, offsetFromRoot);
    4343     }
    4344    
    4345     if (isPaintingCompositedBackground) {
    4346         // Paint only the backgrounds for all of the fragments of the layer.
    4347         if (shouldPaintContent && !selectionOnly)
    4348             paintBackgroundForFragments(layerFragments, *context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
    4349                 localPaintingInfo, paintBehavior, subtreePaintRootForRenderer);
    4350     }
    4351 
    4352     // Now walk the sorted list of children with negative z-indices.
    4353     if ((isPaintingScrollingContent && isPaintingOverflowContents) || (!isPaintingScrollingContent && isPaintingCompositedBackground))
    4354         paintList(negZOrderList(), *context, localPaintingInfo, localPaintFlags);
    4355    
    4356     if (isPaintingCompositedForeground) {
    4357         if (shouldPaintContent)
    4358             paintForegroundForFragments(layerFragments, *context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
    4359                 localPaintingInfo, paintBehavior, subtreePaintRootForRenderer, selectionOnly || selectionAndBackgroundsOnly);
    4360     }
    4361 
    4362     if (shouldPaintOutline)
    4363         paintOutlineForFragments(layerFragments, *context, localPaintingInfo, paintBehavior, subtreePaintRootForRenderer);
    4364 
    4365     if (isPaintingCompositedForeground) {
    4366         // Paint any child layers that have overflow.
    4367         paintList(m_normalFlowList.get(), *context, localPaintingInfo, localPaintFlags);
    4368    
    4369         // Now walk the sorted list of children with positive z-indices.
    4370         paintList(posZOrderList(), *context, localPaintingInfo, localPaintFlags);
    4371 
    4372         // Paint the fixed elements from flow threads.
    4373         paintFixedLayersInNamedFlows(*context, localPaintingInfo, localPaintFlags);
     4299    RenderObject* subtreePaintRootForRenderer = nullptr;
     4300
     4301    { // Scope for currentContext.
     4302        std::unique_ptr<FilterEffectRendererHelper> filterPainter = setupFilters(context, localPaintingInfo, paintFlags, columnAwareOffsetFromRoot, rootRelativeBounds, rootRelativeBoundsComputed);
     4303
     4304        GraphicsContext* filterContext = filterPainter ? filterPainter->filterContext() : nullptr;
     4305        if (filterContext && haveTransparency) {
     4306            // 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 with the wrong context.
     4307            beginTransparencyLayers(context, localPaintingInfo, paintingInfo.paintDirtyRect);
     4308        }
     4309        GraphicsContext& currentContext = filterContext ? *filterContext : context;
     4310
     4311        // If this layer's renderer is a child of the subtreePaintRoot, we render unconditionally, which
     4312        // is done by passing a nil subtreePaintRoot down to our renderer (as if no subtreePaintRoot was ever set).
     4313        // Otherwise, our renderer tree may or may not contain the subtreePaintRoot root, so we pass that root along
     4314        // so it will be tested against as we descend through the renderers.
     4315        if (localPaintingInfo.subtreePaintRoot && !renderer().isDescendantOf(localPaintingInfo.subtreePaintRoot))
     4316            subtreePaintRootForRenderer = localPaintingInfo.subtreePaintRoot;
     4317
     4318        if (localPaintingInfo.overlapTestRequests && isSelfPaintingLayer)
     4319            performOverlapTests(*localPaintingInfo.overlapTestRequests, localPaintingInfo.rootLayer, this);
     4320
     4321        PaintBehavior paintBehavior = PaintBehaviorNormal;
     4322        if (localPaintFlags & PaintLayerPaintingSkipRootBackground)
     4323            paintBehavior |= PaintBehaviorSkipRootBackground;
     4324        else if (localPaintFlags & PaintLayerPaintingRootBackgroundOnly)
     4325            paintBehavior |= PaintBehaviorRootBackgroundOnly;
     4326
     4327        LayoutRect paintDirtyRect = localPaintingInfo.paintDirtyRect;
     4328        if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
     4329            // Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment, as well as whether or not the content of each
     4330            // fragment should paint. If the parent's filter dictates full repaint to ensure proper filter effect,
     4331            // use the overflow clip as dirty rect, instead of no clipping. It maintains proper clipping for overflow::scroll.
     4332            if (!paintingInfo.clipToDirtyRect && renderer().hasOverflowClip()) {
     4333                // We can turn clipping back by requesting full repaint for the overflow area.
     4334                localPaintingInfo.clipToDirtyRect = true;
     4335                paintDirtyRect = selfClipRect();
     4336            }
     4337            collectFragments(layerFragments, localPaintingInfo.rootLayer, paintDirtyRect, ExcludeCompositedPaginatedLayers,
     4338                (localPaintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize,
     4339                (isPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, offsetFromRoot);
     4340            updatePaintingInfoForFragments(layerFragments, localPaintingInfo, localPaintFlags, shouldPaintContent, offsetFromRoot);
     4341        }
    43744342       
    4375         // If this is a region, paint its contents via the flow thread's layer.
    4376         if (shouldPaintContent)
    4377             paintFlowThreadIfRegionForFragments(layerFragments, *context, localPaintingInfo, localPaintFlags);
    4378     }
    4379 
    4380     if (isPaintingOverlayScrollbars && hasScrollbars())
    4381         paintOverflowControlsForFragments(layerFragments, *context, localPaintingInfo);
    4382 
    4383     if (filterPainter) {
    4384         context = &applyFilters(filterPainter.get(), transparencyLayerContext, localPaintingInfo, layerFragments);
    4385         filterPainter = nullptr;
    4386     }
    4387    
    4388     // Make sure that we now use the original transparency context.
    4389     ASSERT(&transparencyLayerContext == context);
    4390 
     4343        if (isPaintingCompositedBackground) {
     4344            // Paint only the backgrounds for all of the fragments of the layer.
     4345            if (shouldPaintContent && !selectionOnly) {
     4346                paintBackgroundForFragments(layerFragments, currentContext, context, paintingInfo.paintDirtyRect, haveTransparency,
     4347                    localPaintingInfo, paintBehavior, subtreePaintRootForRenderer);
     4348            }
     4349        }
     4350
     4351        // Now walk the sorted list of children with negative z-indices.
     4352        if ((isPaintingScrollingContent && isPaintingOverflowContents) || (!isPaintingScrollingContent && isPaintingCompositedBackground))
     4353            paintList(negZOrderList(), currentContext, localPaintingInfo, localPaintFlags);
     4354       
     4355        if (isPaintingCompositedForeground) {
     4356            if (shouldPaintContent) {
     4357                paintForegroundForFragments(layerFragments, currentContext, context, paintingInfo.paintDirtyRect, haveTransparency,
     4358                    localPaintingInfo, paintBehavior, subtreePaintRootForRenderer, selectionOnly || selectionAndBackgroundsOnly);
     4359            }
     4360        }
     4361
     4362        if (shouldPaintOutline)
     4363            paintOutlineForFragments(layerFragments, currentContext, localPaintingInfo, paintBehavior, subtreePaintRootForRenderer);
     4364
     4365        if (isPaintingCompositedForeground) {
     4366            // Paint any child layers that have overflow.
     4367            paintList(m_normalFlowList.get(), currentContext, localPaintingInfo, localPaintFlags);
     4368       
     4369            // Now walk the sorted list of children with positive z-indices.
     4370            paintList(posZOrderList(), currentContext, localPaintingInfo, localPaintFlags);
     4371
     4372            // Paint the fixed elements from flow threads.
     4373            paintFixedLayersInNamedFlows(currentContext, localPaintingInfo, localPaintFlags);
     4374           
     4375            // If this is a region, paint its contents via the flow thread's layer.
     4376            if (shouldPaintContent)
     4377                paintFlowThreadIfRegionForFragments(layerFragments, currentContext, localPaintingInfo, localPaintFlags);
     4378        }
     4379
     4380        if (isPaintingOverlayScrollbars && hasScrollbars())
     4381            paintOverflowControlsForFragments(layerFragments, currentContext, localPaintingInfo);
     4382
     4383        if (filterContext) {
     4384            applyFilters(filterPainter.get(), context, localPaintingInfo, layerFragments);
     4385            filterPainter = nullptr;
     4386        }
     4387    }
     4388   
    43914389    if (shouldPaintContent && !(selectionOnly || selectionAndBackgroundsOnly)) {
    43924390        if (shouldPaintMask(paintingInfo.paintBehavior, localPaintFlags)) {
    43934391            // Paint the mask for the fragments.
    4394             paintMaskForFragments(layerFragments, *context, localPaintingInfo, subtreePaintRootForRenderer);
     4392            paintMaskForFragments(layerFragments, context, localPaintingInfo, subtreePaintRootForRenderer);
    43954393        }
    43964394
    43974395        if (!(paintFlags & PaintLayerPaintingCompositingMaskPhase) && (paintFlags & PaintLayerPaintingCompositingClipPathPhase)) {
    43984396            // Re-use paintChildClippingMaskForFragments to paint black for the compositing clipping mask.
    4399             paintChildClippingMaskForFragments(layerFragments, *context, localPaintingInfo, subtreePaintRootForRenderer);
     4397            paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, subtreePaintRootForRenderer);
    44004398        }
    44014399       
    44024400        if ((localPaintFlags & PaintLayerPaintingChildClippingMaskPhase)) {
    44034401            // Paint the border radius mask for the fragments.
    4404             paintChildClippingMaskForFragments(layerFragments, *context, localPaintingInfo, subtreePaintRootForRenderer);
     4402            paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, subtreePaintRootForRenderer);
    44054403        }
    44064404    }
     
    44084406    // End our transparency layer
    44094407    if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) {
    4410         context->endTransparencyLayer();
    4411         context->restore();
     4408        context.endTransparencyLayer();
     4409        context.restore();
    44124410        m_usedTransparency = false;
    44134411    }
     
    44154413    // Re-set this to whatever it was before we painted the layer.
    44164414    if (needToAdjustSubpixelQuantization)
    4417         context->setShouldSubpixelQuantizeFonts(didQuantizeFonts);
     4415        context.setShouldSubpixelQuantizeFonts(didQuantizeFonts);
    44184416
    44194417    if (hasClipPath)
    4420         context->restore();
     4418        context.restore();
    44214419}
    44224420
     
    46644662}
    46654663
    4666 void RenderLayer::paintBackgroundForFragments(const LayerFragments& layerFragments, GraphicsContext& context, GraphicsContext& transparencyLayerContext,
     4664void RenderLayer::paintBackgroundForFragments(const LayerFragments& layerFragments, GraphicsContext& context, GraphicsContext& contextForTransparencyLayer,
    46674665    const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior,
    46684666    RenderObject* subtreePaintRootForRenderer)
     
    46744672        // Begin transparency layers lazily now that we know we have to paint something.
    46754673        if (haveTransparency)
    4676             beginTransparencyLayers(transparencyLayerContext, localPaintingInfo, transparencyPaintDirtyRect);
     4674            beginTransparencyLayers(contextForTransparencyLayer, localPaintingInfo, transparencyPaintDirtyRect);
    46774675   
    46784676        if (localPaintingInfo.clipToDirtyRect) {
     
    46924690}
    46934691
    4694 void RenderLayer::paintForegroundForFragments(const LayerFragments& layerFragments, GraphicsContext& context, GraphicsContext& transparencyLayerContext,
     4692void RenderLayer::paintForegroundForFragments(const LayerFragments& layerFragments, GraphicsContext& context, GraphicsContext& contextForTransparencyLayer,
    46954693    const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior,
    46964694    RenderObject* subtreePaintRootForRenderer, bool selectionOnly)
     
    47004698        for (const auto& fragment : layerFragments) {
    47014699            if (fragment.shouldPaintContent && !fragment.foregroundRect.isEmpty()) {
    4702                 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo, transparencyPaintDirtyRect);
     4700                beginTransparencyLayers(contextForTransparencyLayer, localPaintingInfo, transparencyPaintDirtyRect);
    47034701                break;
    47044702            }
  • trunk/Source/WebCore/rendering/RenderLayer.h

    r200116 r200279  
    787787    bool hasFilterThatIsPainting(GraphicsContext&, PaintLayerFlags) const;
    788788    std::unique_ptr<FilterEffectRendererHelper> setupFilters(GraphicsContext&, LayerPaintingInfo&, PaintLayerFlags, const LayoutSize& offsetFromRoot, LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed);
    789     GraphicsContext& applyFilters(FilterEffectRendererHelper*, GraphicsContext& originalContext, LayerPaintingInfo&, LayerFragments&);
     789    void applyFilters(FilterEffectRendererHelper*, GraphicsContext& originalContext, LayerPaintingInfo&, LayerFragments&);
    790790
    791791    void paintLayer(GraphicsContext&, const LayerPaintingInfo&, PaintLayerFlags);
Note: See TracChangeset for help on using the changeset viewer.