Changeset 95852 in webkit


Ignore:
Timestamp:
Sep 23, 2011 12:56:21 PM (13 years ago)
Author:
jchaffraix@webkit.org
Message:

Redrawing dirty parts of a large table is very slow
https://bugs.webkit.org/show_bug.cgi?id=64546

Patch by Konstantin Scheglov <scheglov@google.com> on 2011-09-23
Reviewed by David Hyatt.

Source/WebCore:

Move CollapsedBorderValues into RenderTable.h.
Calculate collapsed borders only once and re-use during paintObject().
Invalidate cache when cell, row, row group, col, col group or table border is changed.

Tests: fast/table/border-collapsing/cached-cell-append.html

fast/table/border-collapsing/cached-cell-remove.html
fast/table/border-collapsing/cached-change-cell-border-color.html
fast/table/border-collapsing/cached-change-cell-border-width.html
fast/table/border-collapsing/cached-change-col-border-color.html
fast/table/border-collapsing/cached-change-col-border-width.html
fast/table/border-collapsing/cached-change-colgroup-border-color.html
fast/table/border-collapsing/cached-change-colgroup-border-width.html
fast/table/border-collapsing/cached-change-row-border-color.html
fast/table/border-collapsing/cached-change-row-border-width.html
fast/table/border-collapsing/cached-change-table-border-color.html
fast/table/border-collapsing/cached-change-table-border-width.html
fast/table/border-collapsing/cached-change-tbody-border-color.html
fast/table/border-collapsing/cached-change-tbody-border-width.html

  • rendering/RenderTable.cpp:

(WebCore::RenderTable::RenderTable):
(WebCore::RenderTable::styleDidChange): Invalidate cache on border change.
(WebCore::RenderTable::layout): Invalidate cache if layout changed.
(WebCore::RenderTable::recalcCollapsedBorders): Ensures that cache is valid.
(WebCore::RenderTable::paintObject): Use cached collapsed borders.

  • rendering/RenderTable.h:

(WebCore::RenderTable::invalidateCollapsedBorders): Accessor to mark cache invalid.
(WebCore::RenderTable::currentBorderValue): Rename to use word "value".

  • rendering/RenderTableCell.cpp:

(WebCore::RenderTableCell::styleDidChange): If border changed, invalidate cache.

Rename to use word "value".
(WebCore::addBorderStyle):
(WebCore::RenderTableCell::collectBorderValues):
(WebCore::compareBorderValuesForQSort):
(WebCore::RenderTableCell::sortBorderValues):
(WebCore::RenderTableCell::paintCollapsedBorder):

  • rendering/RenderTableCell.h:

If border changed, invalidate cache.

  • rendering/RenderTableCol.cpp:

(WebCore::RenderTableCol::styleDidChange):

  • rendering/RenderTableCol.h:
  • rendering/RenderTableRow.cpp:

(WebCore::RenderTableRow::styleDidChange):

  • rendering/RenderTableSection.cpp:

(WebCore::RenderTableSection::styleDidChange):

LayoutTests:

Tests for invalidating collapsed borders cache.

  • fast/table/border-collapsing/cached-cell-append-expected.png: Added.
  • fast/table/border-collapsing/cached-cell-append-expected.txt: Added.
  • fast/table/border-collapsing/cached-cell-append.html: Added.
  • fast/table/border-collapsing/cached-cell-remove-expected.png: Added.
  • fast/table/border-collapsing/cached-cell-remove-expected.txt: Added.
  • fast/table/border-collapsing/cached-cell-remove.html: Added.
  • fast/table/border-collapsing/cached-change-cell-border-color-expected.png: Added.
  • fast/table/border-collapsing/cached-change-cell-border-color-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-cell-border-color.html: Added.
  • fast/table/border-collapsing/cached-change-cell-border-width-expected.png: Added.
  • fast/table/border-collapsing/cached-change-cell-border-width-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-cell-border-width.html: Added.
  • fast/table/border-collapsing/cached-change-col-border-color-expected.png: Added.
  • fast/table/border-collapsing/cached-change-col-border-color-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-col-border-color.html: Added.
  • fast/table/border-collapsing/cached-change-col-border-width-expected.png: Added.
  • fast/table/border-collapsing/cached-change-col-border-width-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-col-border-width.html: Added.
  • fast/table/border-collapsing/cached-change-colgroup-border-color-expected.png: Added.
  • fast/table/border-collapsing/cached-change-colgroup-border-color-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-colgroup-border-color.html: Added.
  • fast/table/border-collapsing/cached-change-colgroup-border-width-expected.png: Added.
  • fast/table/border-collapsing/cached-change-colgroup-border-width-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-colgroup-border-width.html: Added.
  • fast/table/border-collapsing/cached-change-row-border-color-expected.png: Added.
  • fast/table/border-collapsing/cached-change-row-border-color-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-row-border-color.html: Added.
  • fast/table/border-collapsing/cached-change-row-border-width-expected.png: Added.
  • fast/table/border-collapsing/cached-change-row-border-width-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-row-border-width.html: Added.
  • fast/table/border-collapsing/cached-change-table-border-color-expected.png: Added.
  • fast/table/border-collapsing/cached-change-table-border-color-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-table-border-color.html: Added.
  • fast/table/border-collapsing/cached-change-table-border-width-expected.png: Added.
  • fast/table/border-collapsing/cached-change-table-border-width-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-table-border-width.html: Added.
  • fast/table/border-collapsing/cached-change-tbody-border-color-expected.png: Added.
  • fast/table/border-collapsing/cached-change-tbody-border-color-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-tbody-border-color.html: Added.
  • fast/table/border-collapsing/cached-change-tbody-border-width-expected.png: Added.
  • fast/table/border-collapsing/cached-change-tbody-border-width-expected.txt: Added.
  • fast/table/border-collapsing/cached-change-tbody-border-width.html: Added.
Location:
trunk
Files:
47 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r95845 r95852  
     12011-09-23  Konstantin Scheglov  <scheglov@google.com>
     2
     3        Redrawing dirty parts of a large table is very slow
     4        https://bugs.webkit.org/show_bug.cgi?id=64546
     5
     6        Reviewed by David Hyatt.
     7
     8        Tests for invalidating collapsed borders cache.
     9
     10        * fast/table/border-collapsing/cached-cell-append-expected.png: Added.
     11        * fast/table/border-collapsing/cached-cell-append-expected.txt: Added.
     12        * fast/table/border-collapsing/cached-cell-append.html: Added.
     13        * fast/table/border-collapsing/cached-cell-remove-expected.png: Added.
     14        * fast/table/border-collapsing/cached-cell-remove-expected.txt: Added.
     15        * fast/table/border-collapsing/cached-cell-remove.html: Added.
     16        * fast/table/border-collapsing/cached-change-cell-border-color-expected.png: Added.
     17        * fast/table/border-collapsing/cached-change-cell-border-color-expected.txt: Added.
     18        * fast/table/border-collapsing/cached-change-cell-border-color.html: Added.
     19        * fast/table/border-collapsing/cached-change-cell-border-width-expected.png: Added.
     20        * fast/table/border-collapsing/cached-change-cell-border-width-expected.txt: Added.
     21        * fast/table/border-collapsing/cached-change-cell-border-width.html: Added.
     22        * fast/table/border-collapsing/cached-change-col-border-color-expected.png: Added.
     23        * fast/table/border-collapsing/cached-change-col-border-color-expected.txt: Added.
     24        * fast/table/border-collapsing/cached-change-col-border-color.html: Added.
     25        * fast/table/border-collapsing/cached-change-col-border-width-expected.png: Added.
     26        * fast/table/border-collapsing/cached-change-col-border-width-expected.txt: Added.
     27        * fast/table/border-collapsing/cached-change-col-border-width.html: Added.
     28        * fast/table/border-collapsing/cached-change-colgroup-border-color-expected.png: Added.
     29        * fast/table/border-collapsing/cached-change-colgroup-border-color-expected.txt: Added.
     30        * fast/table/border-collapsing/cached-change-colgroup-border-color.html: Added.
     31        * fast/table/border-collapsing/cached-change-colgroup-border-width-expected.png: Added.
     32        * fast/table/border-collapsing/cached-change-colgroup-border-width-expected.txt: Added.
     33        * fast/table/border-collapsing/cached-change-colgroup-border-width.html: Added.
     34        * fast/table/border-collapsing/cached-change-row-border-color-expected.png: Added.
     35        * fast/table/border-collapsing/cached-change-row-border-color-expected.txt: Added.
     36        * fast/table/border-collapsing/cached-change-row-border-color.html: Added.
     37        * fast/table/border-collapsing/cached-change-row-border-width-expected.png: Added.
     38        * fast/table/border-collapsing/cached-change-row-border-width-expected.txt: Added.
     39        * fast/table/border-collapsing/cached-change-row-border-width.html: Added.
     40        * fast/table/border-collapsing/cached-change-table-border-color-expected.png: Added.
     41        * fast/table/border-collapsing/cached-change-table-border-color-expected.txt: Added.
     42        * fast/table/border-collapsing/cached-change-table-border-color.html: Added.
     43        * fast/table/border-collapsing/cached-change-table-border-width-expected.png: Added.
     44        * fast/table/border-collapsing/cached-change-table-border-width-expected.txt: Added.
     45        * fast/table/border-collapsing/cached-change-table-border-width.html: Added.
     46        * fast/table/border-collapsing/cached-change-tbody-border-color-expected.png: Added.
     47        * fast/table/border-collapsing/cached-change-tbody-border-color-expected.txt: Added.
     48        * fast/table/border-collapsing/cached-change-tbody-border-color.html: Added.
     49        * fast/table/border-collapsing/cached-change-tbody-border-width-expected.png: Added.
     50        * fast/table/border-collapsing/cached-change-tbody-border-width-expected.txt: Added.
     51        * fast/table/border-collapsing/cached-change-tbody-border-width.html: Added.
     52
    1532011-09-23  Jochen Eisinger  <jochen@chromium.org>
    254
  • trunk/Source/WebCore/ChangeLog

    r95849 r95852  
     12011-09-23  Konstantin Scheglov  <scheglov@google.com>
     2
     3        Redrawing dirty parts of a large table is very slow
     4        https://bugs.webkit.org/show_bug.cgi?id=64546
     5
     6        Reviewed by David Hyatt.
     7
     8        Move CollapsedBorderValues into RenderTable.h.
     9        Calculate collapsed borders only once and re-use during paintObject().
     10        Invalidate cache when cell, row, row group, col, col group or table border is changed.
     11
     12        Tests: fast/table/border-collapsing/cached-cell-append.html
     13               fast/table/border-collapsing/cached-cell-remove.html
     14               fast/table/border-collapsing/cached-change-cell-border-color.html
     15               fast/table/border-collapsing/cached-change-cell-border-width.html
     16               fast/table/border-collapsing/cached-change-col-border-color.html
     17               fast/table/border-collapsing/cached-change-col-border-width.html
     18               fast/table/border-collapsing/cached-change-colgroup-border-color.html
     19               fast/table/border-collapsing/cached-change-colgroup-border-width.html
     20               fast/table/border-collapsing/cached-change-row-border-color.html
     21               fast/table/border-collapsing/cached-change-row-border-width.html
     22               fast/table/border-collapsing/cached-change-table-border-color.html
     23               fast/table/border-collapsing/cached-change-table-border-width.html
     24               fast/table/border-collapsing/cached-change-tbody-border-color.html
     25               fast/table/border-collapsing/cached-change-tbody-border-width.html
     26
     27        * rendering/RenderTable.cpp:
     28        (WebCore::RenderTable::RenderTable):
     29        (WebCore::RenderTable::styleDidChange): Invalidate cache on border change.
     30        (WebCore::RenderTable::layout): Invalidate cache if layout changed.
     31        (WebCore::RenderTable::recalcCollapsedBorders): Ensures that cache is valid.
     32        (WebCore::RenderTable::paintObject): Use cached collapsed borders.
     33        * rendering/RenderTable.h:
     34        (WebCore::RenderTable::invalidateCollapsedBorders): Accessor to mark cache invalid.
     35        (WebCore::RenderTable::currentBorderValue): Rename to use word "value".
     36        * rendering/RenderTableCell.cpp:
     37        (WebCore::RenderTableCell::styleDidChange): If border changed, invalidate cache.
     38
     39        Rename to use word "value".
     40        (WebCore::addBorderStyle):
     41        (WebCore::RenderTableCell::collectBorderValues):
     42        (WebCore::compareBorderValuesForQSort):
     43        (WebCore::RenderTableCell::sortBorderValues):
     44        (WebCore::RenderTableCell::paintCollapsedBorder):
     45        * rendering/RenderTableCell.h:
     46       
     47        If border changed, invalidate cache.
     48        * rendering/RenderTableCol.cpp:
     49        (WebCore::RenderTableCol::styleDidChange):
     50        * rendering/RenderTableCol.h:
     51        * rendering/RenderTableRow.cpp:
     52        (WebCore::RenderTableRow::styleDidChange):
     53        * rendering/RenderTableSection.cpp:
     54        (WebCore::RenderTableSection::styleDidChange):
     55
    1562011-09-23  Mark Hahnenberg  <mhahnenberg@apple.com>
    257
  • trunk/Source/WebCore/rendering/RenderTable.cpp

    r95671 r95852  
    5555    , m_firstBody(0)
    5656    , m_currentBorder(0)
     57    , m_collapsedBordersValid(false)
    5758    , m_hasColElements(false)
    58     , m_needsSectionRecalc(0)
     59    , m_needsSectionRecalc(false)
    5960    , m_hSpacing(0)
    6061    , m_vSpacing(0)
     
    9293            m_tableLayout = adoptPtr(new AutoTableLayout(this));
    9394    }
     95
     96    // If border was changed, invalidate collapsed borders cache.
     97    if (!needsLayout() && oldStyle && oldStyle->border() != style()->border())
     98        invalidateCollapsedBorders();
    9499}
    95100
     
    397402    updateLayerTransform();
    398403
     404    // Layout was changed, so probably borders too.
     405    invalidateCollapsedBorders();
     406
    399407    computeOverflow(clientLogicalBottom());
    400408
     
    415423    setNeedsLayout(false);
    416424}
     425
     426// Collect all the unique border values that we want to paint in a sorted list.
     427void RenderTable::recalcCollapsedBorders()
     428{
     429    if (m_collapsedBordersValid)
     430        return;
     431    m_collapsedBordersValid = true;
     432    m_collapsedBorders.clear();
     433    RenderObject* stop = nextInPreOrderAfterChildren();
     434    for (RenderObject* o = firstChild(); o && o != stop; o = o->nextInPreOrder()) {
     435        if (o->isTableCell())
     436            toRenderTableCell(o)->collectBorderValues(m_collapsedBorders);
     437    }
     438    RenderTableCell::sortBorderValues(m_collapsedBorders);
     439}
     440
    417441
    418442void RenderTable::addOverflowFromChildren()
     
    506530   
    507531    if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
    508         // Collect all the unique border styles that we want to paint in a sorted list.  Once we
    509         // have all the styles sorted, we then do individual passes, painting each style of border
    510         // from lowest precedence to highest precedence.
     532        recalcCollapsedBorders();
     533        // Using our cached sorted styles, we then do individual passes,
     534        // painting each style of border from lowest precedence to highest precedence.
    511535        info.phase = PaintPhaseCollapsedTableBorders;
    512         RenderTableCell::CollapsedBorderStyles borderStyles;
    513         RenderObject* stop = nextInPreOrderAfterChildren();
    514         for (RenderObject* o = firstChild(); o && o != stop; o = o->nextInPreOrder()) {
    515             if (o->isTableCell())
    516                 toRenderTableCell(o)->collectBorderStyles(borderStyles);
    517         }
    518         RenderTableCell::sortBorderStyles(borderStyles);
    519         size_t count = borderStyles.size();
     536        size_t count = m_collapsedBorders.size();
    520537        for (size_t i = 0; i < count; ++i) {
    521             m_currentBorder = &borderStyles[i];
     538            m_currentBorder = &m_collapsedBorders[i];
    522539            for (RenderObject* child = firstChild(); child; child = child->nextSibling())
    523540                if (child->isTableSection()) {
  • trunk/Source/WebCore/rendering/RenderTable.h

    r94776 r95852  
    2727
    2828#include "CSSPropertyNames.h"
     29#include "CollapsedBorderValue.h"
    2930#include "RenderBlock.h"
    3031#include <wtf/Vector.h>
     
    3233namespace WebCore {
    3334
    34 class CollapsedBorderValue;
    3535class RenderTableCol;
    3636class RenderTableCell;
     
    201201    RenderTableCell* cellAfter(const RenderTableCell*) const;
    202202 
    203     const CollapsedBorderValue* currentBorderStyle() const { return m_currentBorder; }
     203    typedef Vector<CollapsedBorderValue> CollapsedBorderValues;
     204    void invalidateCollapsedBorders()
     205    {
     206        m_collapsedBordersValid = false;
     207        m_collapsedBorders.clear();
     208    }
     209    const CollapsedBorderValue* currentBorderValue() const { return m_currentBorder; }
    204210   
    205211    bool hasSections() const { return m_head || m_foot || m_firstBody; }
     
    246252    void subtractCaptionRect(LayoutRect&) const;
    247253
     254    void recalcCollapsedBorders();
    248255    void recalcCaption(RenderBlock*) const;
    249256    void recalcSections() const;
     
    260267    OwnPtr<TableLayout> m_tableLayout;
    261268
     269    CollapsedBorderValues m_collapsedBorders;
    262270    const CollapsedBorderValue* m_currentBorder;
     271    bool m_collapsedBordersValid : 1;
    263272   
    264273    mutable bool m_hasColElements : 1;
  • trunk/Source/WebCore/rendering/RenderTableCell.cpp

    r95777 r95852  
    318318    RenderBlock::styleDidChange(diff, oldStyle);
    319319    setHasBoxDecorations(true);
     320
     321    // If border was changed, notify table.
     322    if (parent()) {
     323        RenderTable* table = this->table();
     324        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout()&& oldStyle && oldStyle->border() != style()->border())
     325            table->invalidateCollapsedBorders();
     326    }
    320327}
    321328
     
    872879};
    873880
    874 static void addBorderStyle(RenderTableCell::CollapsedBorderStyles& borderStyles, CollapsedBorderValue borderValue)
     881static void addBorderStyle(RenderTable::CollapsedBorderValues& borderValues,
     882                           CollapsedBorderValue borderValue)
    875883{
    876884    if (!borderValue.exists())
    877885        return;
    878     size_t count = borderStyles.size();
     886    size_t count = borderValues.size();
    879887    for (size_t i = 0; i < count; ++i)
    880         if (borderStyles[i] == borderValue)
     888        if (borderValues[i] == borderValue)
    881889            return;
    882     borderStyles.append(borderValue);
    883 }
    884 
    885 void RenderTableCell::collectBorderStyles(CollapsedBorderStyles& borderStyles) const
    886 {
    887     addBorderStyle(borderStyles, collapsedStartBorder());
    888     addBorderStyle(borderStyles, collapsedEndBorder());
    889     addBorderStyle(borderStyles, collapsedBeforeBorder());
    890     addBorderStyle(borderStyles, collapsedAfterBorder());
    891 }
    892 
    893 static int compareBorderStylesForQSort(const void* pa, const void* pb)
     890    borderValues.append(borderValue);
     891}
     892
     893void RenderTableCell::collectBorderValues(RenderTable::CollapsedBorderValues& borderValues) const
     894{
     895    addBorderStyle(borderValues, collapsedStartBorder());
     896    addBorderStyle(borderValues, collapsedEndBorder());
     897    addBorderStyle(borderValues, collapsedBeforeBorder());
     898    addBorderStyle(borderValues, collapsedAfterBorder());
     899}
     900
     901static int compareBorderValuesForQSort(const void* pa, const void* pb)
    894902{
    895903    const CollapsedBorderValue* a = static_cast<const CollapsedBorderValue*>(pa);
     
    900908}
    901909
    902 void RenderTableCell::sortBorderStyles(CollapsedBorderStyles& borderStyles)
    903 {
    904     qsort(borderStyles.data(), borderStyles.size(), sizeof(CollapsedBorderValue),
    905         compareBorderStylesForQSort);
     910void RenderTableCell::sortBorderValues(RenderTable::CollapsedBorderValues& borderValues)
     911{
     912    qsort(borderValues.data(), borderValues.size(), sizeof(CollapsedBorderValue),
     913        compareBorderValuesForQSort);
    906914}
    907915
    908916void RenderTableCell::paintCollapsedBorder(GraphicsContext* graphicsContext, const LayoutRect& paintRect)
    909917{
    910     if (!table()->currentBorderStyle() || graphicsContext->paintingDisabled())
     918    if (!table()->currentBorderValue() || graphicsContext->paintingDisabled())
    911919        return;
    912920   
     
    948956   
    949957    for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) {
    950         if (border->borderValue == *table()->currentBorderStyle())
     958        if (border->borderValue == *table()->currentBorderValue())
    951959            drawLineForBoxSide(graphicsContext, border->x1, border->y1, border->x2, border->y2, border->side,
    952960                               border->borderValue.color(), border->style, 0, 0, antialias);
  • trunk/Source/WebCore/rendering/RenderTableCell.h

    r95573 r95852  
    8787    CollapsedBorderValue collapsedBottomBorder() const;
    8888
    89     typedef Vector<CollapsedBorderValue, 100> CollapsedBorderStyles;
    90     void collectBorderStyles(CollapsedBorderStyles&) const;
    91     static void sortBorderStyles(CollapsedBorderStyles&);
     89    void collectBorderValues(RenderTable::CollapsedBorderValues&) const;
     90    static void sortBorderValues(RenderTable::CollapsedBorderValues&);
    9291
    9392    virtual void updateFromElement();
  • trunk/Source/WebCore/rendering/RenderTableCol.cpp

    r92992 r95852  
    4343    setInline(true); // our object is not Inline
    4444    updateFromElement();
     45}
     46
     47void RenderTableCol::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
     48{
     49    RenderBox::styleDidChange(diff, oldStyle);
     50
     51    // If border was changed, notify table.
     52    if (parent()) {
     53        RenderTable* table = this->table();
     54        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
     55            table->invalidateCollapsedBorders();
     56    }
    4557}
    4658
  • trunk/Source/WebCore/rendering/RenderTableCol.h

    r92252 r95852  
    6060    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
    6161
     62    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
     63
    6264    RenderTable* table() const;
    6365
  • trunk/Source/WebCore/rendering/RenderTableRow.cpp

    r95671 r95852  
    7979    if (parent())
    8080        updateBeforeAndAfterContent();
     81
     82    // If border was changed, notify table.
     83    if (parent()) {
     84        RenderTable* table = this->table();
     85        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
     86            table->invalidateCollapsedBorders();
     87    }
    8188}
    8289
  • trunk/Source/WebCore/rendering/RenderTableSection.cpp

    r95671 r95852  
    8282    RenderBox::styleDidChange(diff, oldStyle);
    8383    propagateStyleToAnonymousChildren();
     84
     85    // If border was changed, notify table.
     86    RenderTable* table = this->table();
     87    if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
     88        table->invalidateCollapsedBorders();
    8489}
    8590
Note: See TracChangeset for help on using the changeset viewer.