Changeset 107836 in webkit


Ignore:
Timestamp:
Feb 15, 2012 1:57:02 PM (12 years ago)
Author:
mitz@apple.com
Message:

<rdar://problem/10870238> Box shadow drawing takes an unnecessarily slow code path in some single-shadow, opaque-background cases
https://bugs.webkit.org/show_bug.cgi?id=78728

In some cases, when there is only one normal box shadow, and the box has an opaque background,
it is possible to draw the box shadow by having the background cast it directly. This appears
to be faster than the generic code path that uses a separate drawing pass to cast the shadow,
clipping out the border box and the shadow-casting box.

Reviewed by Dave Hyatt.

No new tests, because behavior is unchanged.

  • rendering/InlineFlowBox.cpp:

(WebCore::InlineFlowBox::paintBoxDecorations): Changed to not paint normal box shadows if
they are going to be cast by the background.

  • rendering/RenderBox.cpp:

(WebCore::RenderBox::paintBoxDecorations): Ditto.

  • rendering/RenderBox.h: Made determineBackgroundBleedAvoidance() protected.
  • rendering/RenderBoxModelObject.cpp:

(WebCore::applyBoxShadowForBackground): Added this helper function, which applies the first
normal shadow from the given RenderStyle to the given GraphicsContext.
(WebCore::RenderBoxModelObject::paintFillLayerExtended): Added calls to
applyBoxShadowForBackground() before drawing the background color when needed.
(WebCore::RenderBoxModelObject::boxShadowShouldBeAppliedToBackground): Added. Returns true
in some of the cases where the box shadow can be cast by the background directly.

  • rendering/RenderBoxModelObject.h:
  • rendering/RenderFieldset.cpp:

(WebCore::RenderFieldset::paintBoxDecorations): Changed to not paint normal box shadows if
they are going to be cast by the background.

  • rendering/RenderTable.cpp:

(WebCore::RenderTable::paintBoxDecorations): Ditto.

  • rendering/RenderTableCell.cpp:

(WebCore::RenderTableCell::boxShadowShouldBeAppliedToBackground): Added this override that
always returns false, because table cells sometimes apply a clip before drawing the background.

  • rendering/RenderTableCell.h:
Location:
trunk/Source/WebCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r107833 r107836  
     12012-02-15  Dan Bernstein  <mitz@apple.com>
     2
     3        <rdar://problem/10870238> Box shadow drawing takes an unnecessarily slow code path in some single-shadow, opaque-background cases
     4        https://bugs.webkit.org/show_bug.cgi?id=78728
     5
     6        In some cases, when there is only one normal box shadow, and the box has an opaque background,
     7        it is possible to draw the box shadow by having the background cast it directly. This appears
     8        to be faster than the generic code path that uses a separate drawing pass to cast the shadow,
     9        clipping out the border box and the shadow-casting box.
     10
     11        Reviewed by Dave Hyatt.
     12
     13        No new tests, because behavior is unchanged.
     14
     15        * rendering/InlineFlowBox.cpp:
     16        (WebCore::InlineFlowBox::paintBoxDecorations): Changed to not paint normal box shadows if
     17        they are going to be cast by the background.
     18        * rendering/RenderBox.cpp:
     19        (WebCore::RenderBox::paintBoxDecorations): Ditto.
     20        * rendering/RenderBox.h: Made determineBackgroundBleedAvoidance() protected.
     21        * rendering/RenderBoxModelObject.cpp:
     22        (WebCore::applyBoxShadowForBackground): Added this helper function, which applies the first
     23        normal shadow from the given RenderStyle to the given GraphicsContext.
     24        (WebCore::RenderBoxModelObject::paintFillLayerExtended): Added calls to
     25        applyBoxShadowForBackground() before drawing the background color when needed.
     26        (WebCore::RenderBoxModelObject::boxShadowShouldBeAppliedToBackground): Added. Returns true
     27        in some of the cases where the box shadow can be cast by the background directly.
     28        * rendering/RenderBoxModelObject.h:
     29        * rendering/RenderFieldset.cpp:
     30        (WebCore::RenderFieldset::paintBoxDecorations): Changed to not paint normal box shadows if
     31        they are going to be cast by the background.
     32        * rendering/RenderTable.cpp:
     33        (WebCore::RenderTable::paintBoxDecorations): Ditto.
     34        * rendering/RenderTableCell.cpp:
     35        (WebCore::RenderTableCell::boxShadowShouldBeAppliedToBackground): Added this override that
     36        always returns false, because table cells sometimes apply a clip before drawing the background.
     37        * rendering/RenderTableCell.h:
     38
    1392012-02-15  Ojan Vafai  <ojan@chromium.org>
    240
  • trunk/Source/WebCore/rendering/InlineFlowBox.cpp

    r107461 r107836  
    12041204        LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size());
    12051205        // Shadow comes first and is behind the background and border.
    1206         paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
     1206        if (!boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone))
     1207            paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
    12071208
    12081209        Color c = styleToUse->visitedDependentColor(CSSPropertyBackgroundColor);
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r107461 r107836  
    918918    borderFitAdjust(paintRect);
    919919
     920    BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
     921
    920922    // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
    921923    // custom shadows of their own.
    922     paintBoxShadow(paintInfo, paintRect, style(), Normal);
    923 
    924     BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
     924    if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance))
     925        paintBoxShadow(paintInfo, paintRect, style(), Normal);
    925926
    926927    GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
  • trunk/Source/WebCore/rendering/RenderBox.h

    r107760 r107836  
    461461    void paintMaskImages(const PaintInfo&, const LayoutRect&);
    462462
     463    BackgroundBleedAvoidance determineBackgroundBleedAvoidance(GraphicsContext*) const;
     464
    463465#if PLATFORM(MAC)
    464466    void paintCustomHighlight(const LayoutPoint&, const AtomicString& type, bool behindText);
     
    505507    virtual void computePreferredLogicalWidths() { setPreferredLogicalWidthsDirty(false); }
    506508
    507     BackgroundBleedAvoidance determineBackgroundBleedAvoidance(GraphicsContext*) const;
    508 
    509509private:
    510510    // The width/height of the contents + borders + padding.  The x/y location is relative to our container (which is not always our parent).
  • trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp

    r107461 r107836  
    620620}
    621621
     622static void applyBoxShadowForBackground(GraphicsContext* context, RenderStyle* style)
     623{
     624    const ShadowData* boxShadow = style->boxShadow();
     625    while (boxShadow->style() != Normal)
     626        boxShadow = boxShadow->next();
     627
     628    FloatSize shadowOffset(boxShadow->x(), boxShadow->y());
     629    if (!boxShadow->isWebkitBoxShadow())
     630        context->setShadow(shadowOffset, boxShadow->blur(), boxShadow->color(), style->colorSpace());
     631    else
     632        context->setLegacyShadow(shadowOffset, boxShadow->blur(), boxShadow->color(), style->colorSpace());
     633}
     634
    622635void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& color, const FillLayer* bgLayer, const LayoutRect& rect,
    623636    BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSize& boxSize, CompositeOperator op, RenderObject* backgroundObject)
     
    669682        if (!colorVisible)
    670683            return;
     684
     685        bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppliedToBackground(bleedAvoidance);
     686        GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAppliedToBackground);
     687        if (boxShadowShouldBeAppliedToBackground)
     688            applyBoxShadowForBackground(context, style());
    671689
    672690        if (hasRoundedBorder && bleedAvoidance != BackgroundBleedUseTransparencyLayer) {
     
    779797    if (!bgLayer->next()) {
    780798        IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect));
    781         backgroundRect.intersect(paintInfo.rect);
     799        bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppliedToBackground(bleedAvoidance);
     800        if (!boxShadowShouldBeAppliedToBackground)
     801            backgroundRect.intersect(paintInfo.rect);
     802
    782803        // If we have an alpha and we are painting the root element, go ahead and blend with the base background color.
    783804        Color baseColor;
     
    788809                shouldClearBackground = true;
    789810        }
     811
     812        GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAppliedToBackground);
     813        if (boxShadowShouldBeAppliedToBackground)
     814            applyBoxShadowForBackground(context, style());
    790815
    791816        if (baseColor.alpha()) {
     
    25572582}
    25582583
     2584bool RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance) const
     2585{
     2586    if (bleedAvoidance != BackgroundBleedNone)
     2587        return false;
     2588
     2589    if (style()->hasAppearance())
     2590        return false;
     2591
     2592    const ShadowData* boxShadow = style()->boxShadow();
     2593    bool hasOneNormalBoxShadow = false;
     2594    for (const ShadowData* currentShadow = boxShadow; currentShadow; currentShadow = currentShadow->next()) {
     2595        if (currentShadow->style() != Normal)
     2596            continue;
     2597        if (hasOneNormalBoxShadow)
     2598            return false;
     2599        hasOneNormalBoxShadow = true;
     2600    }
     2601
     2602    if (!hasOneNormalBoxShadow)
     2603        return false;
     2604
     2605    Color backgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
     2606    if (!backgroundColor.isValid() || backgroundColor.alpha() < 255)
     2607        return false;
     2608
     2609    const FillLayer* lastBackgroundLayer = style()->backgroundLayers();
     2610    for (const FillLayer* next = lastBackgroundLayer->next(); next; )
     2611        lastBackgroundLayer = next;
     2612
     2613    if (lastBackgroundLayer->clip() != BorderFillBox)
     2614        return false;
     2615
     2616    if (hasOverflowClip() && lastBackgroundLayer->attachment() == LocalBackgroundAttachment)
     2617        return false;
     2618
     2619    return true;
     2620}
     2621
    25592622static inline LayoutRect areaCastingShadowInHole(const LayoutRect& holeRect, int shadowBlur, int shadowSpread, const LayoutSize& shadowOffset)
    25602623{
  • trunk/Source/WebCore/rendering/RenderBoxModelObject.h

    r107032 r107836  
    128128    void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox* = 0, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
    129129   
     130    virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance) const;
     131
    130132    // Overridden by subclasses to determine line height and baseline position.
    131133    virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
  • trunk/Source/WebCore/rendering/RenderFieldset.cpp

    r92998 r107836  
    141141        paintRect.setX(paintRect.x() + xOff);
    142142    }
    143    
    144     paintBoxShadow(paintInfo, paintRect, style(), Normal);
     143
     144    if (!boxShadowShouldBeAppliedToBackground(determineBackgroundBleedAvoidance(paintInfo.context)))
     145        paintBoxShadow(paintInfo, paintRect, style(), Normal);
    145146    paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect);
    146147    paintBoxShadow(paintInfo, paintRect, style(), Inset);
  • trunk/Source/WebCore/rendering/RenderTable.cpp

    r106479 r107836  
    618618    subtractCaptionRect(rect);
    619619
    620     paintBoxShadow(paintInfo, rect, style(), Normal);
     620    if (!boxShadowShouldBeAppliedToBackground(determineBackgroundBleedAvoidance(paintInfo.context)))
     621        paintBoxShadow(paintInfo, rect, style(), Normal);
    621622    paintBackground(paintInfo, rect);
    622623    paintBoxShadow(paintInfo, rect, style(), Inset);
  • trunk/Source/WebCore/rendering/RenderTableCell.cpp

    r105029 r107836  
    10691069}
    10701070
     1071bool RenderTableCell::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance) const
     1072{
     1073    return false;
     1074}
     1075
    10711076void RenderTableCell::scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged)
    10721077{
  • trunk/Source/WebCore/rendering/RenderTableCell.h

    r105029 r107836  
    152152    virtual void paintMask(PaintInfo&, const LayoutPoint&);
    153153
     154    virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance) const OVERRIDE;
     155
    154156    virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&) const;
    155157    virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
Note: See TracChangeset for help on using the changeset viewer.