⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 252716 in webkit


Ignore:
Timestamp:
Nov 20, 2019, 3:52:40 PM (7 years ago)
Author:
Alan Bujtas
Message:

Flexbox sizing logic triggers full repaint on the flex items.
https://bugs.webkit.org/show_bug.cgi?id=204380
<rdar://problem/57236404>

Reviewed by Simon Fraser.

Source/WebCore:

RenderFlexibleBox::applyStretchAlignmentToChild explicitly sets the child renderer's height to 0 before issuing layout on it.
This confuses the child's repaint logic and could trigger unnecessary repaints on complete subtrees.

Many ::layout functions plant a LayoutRepainter stack object to track and report paint invalidations.
It works as long as the renderer's geometry change happens within the scope of this LayoutRepainter.
When the parent (RenderFlexibleBox) mutates the renderer's geometry, the LayoutRepainter object sees
this already mutated state as the initial state and will happily issue repaints even when the final
geometry remains the same.

This patch addresses the redundant repaint by pushing the height reset from the parent down to the child, inside the LayoutRepainter scope.

  • rendering/RenderBlock.h: Restrict it to RenderBlock level for now. It might need to go all the way up to RenderBox.

(WebCore::RenderBlock::shouldResetChildLogicalHeightBeforeLayout const):

  • rendering/RenderBlockFlow.cpp:

(WebCore::RenderBlockFlow::layoutBlock):

  • rendering/RenderBlockFlow.h:
  • rendering/RenderBox.cpp:

(WebCore::RenderBox::resetLogicalHeightBeforeLayoutIfNeeded):

  • rendering/RenderBox.h:

(WebCore::RenderBox::shouldResetLogicalHeightBeforeLayout const):

  • rendering/RenderDeprecatedFlexibleBox.cpp:

(WebCore::RenderDeprecatedFlexibleBox::layoutBlock):

  • rendering/RenderFlexibleBox.cpp:

(WebCore::RenderFlexibleBox::layoutBlock):
(WebCore::RenderFlexibleBox::applyStretchAlignmentToChild):

  • rendering/RenderFlexibleBox.h:
  • rendering/RenderGrid.cpp:

(WebCore::RenderGrid::layoutBlock):

  • rendering/RenderGrid.h:
  • rendering/RenderTable.cpp:

(WebCore::RenderTable::layout):

  • rendering/RenderTable.h:

LayoutTests:

  • fast/repaint/align-items-change-expected.txt: progression.
Location:
trunk
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r252715 r252716  
     12019-11-20  Zalan Bujtas  <zalan@apple.com>
     2
     3        Flexbox sizing logic triggers full repaint on the flex items.
     4        https://bugs.webkit.org/show_bug.cgi?id=204380
     5        <rdar://problem/57236404>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * fast/repaint/align-items-change-expected.txt: progression.
     10
    1112019-11-20  Justin Fan  <justin_fan@apple.com>
    212
  • trunk/LayoutTests/fast/repaint/align-items-change-expected.txt

    r219315 r252716  
    22
    33(repaint rects
    4   (rect 0 52 100 300)
    5   (rect 0 51 100 1)
    6   (rect 100 52 100 300)
    7   (rect 100 51 100 1)
     4  (rect 0 154 100 198)
     5  (rect 0 153 100 1)
     6  (rect 100 204 100 148)
     7  (rect 100 203 100 1)
    88  (rect 0 52 200 300)
    99)
  • trunk/Source/WebCore/ChangeLog

    r252710 r252716  
     12019-11-20  Zalan Bujtas  <zalan@apple.com>
     2
     3        Flexbox sizing logic triggers full repaint on the flex items.
     4        https://bugs.webkit.org/show_bug.cgi?id=204380
     5        <rdar://problem/57236404>
     6
     7        Reviewed by Simon Fraser.
     8
     9        RenderFlexibleBox::applyStretchAlignmentToChild explicitly sets the child renderer's height to 0 before issuing layout on it.
     10        This confuses the child's repaint logic and could trigger unnecessary repaints on complete subtrees.
     11
     12        Many ::layout functions plant a LayoutRepainter stack object to track and report paint invalidations.
     13        It works as long as the renderer's geometry change happens within the scope of this LayoutRepainter.
     14        When the parent (RenderFlexibleBox) mutates the renderer's geometry, the LayoutRepainter object sees
     15        this already mutated state as the initial state and will happily issue repaints even when the final
     16        geometry remains the same.
     17
     18        This patch addresses the redundant repaint by pushing the height reset from the parent down to the child, inside the LayoutRepainter scope.
     19
     20        * rendering/RenderBlock.h: Restrict it to RenderBlock level for now. It might need to go all the way up to RenderBox.
     21        (WebCore::RenderBlock::shouldResetChildLogicalHeightBeforeLayout const):
     22        * rendering/RenderBlockFlow.cpp:
     23        (WebCore::RenderBlockFlow::layoutBlock):
     24        * rendering/RenderBlockFlow.h:
     25        * rendering/RenderBox.cpp:
     26        (WebCore::RenderBox::resetLogicalHeightBeforeLayoutIfNeeded):
     27        * rendering/RenderBox.h:
     28        (WebCore::RenderBox::shouldResetLogicalHeightBeforeLayout const):
     29        * rendering/RenderDeprecatedFlexibleBox.cpp:
     30        (WebCore::RenderDeprecatedFlexibleBox::layoutBlock):
     31        * rendering/RenderFlexibleBox.cpp:
     32        (WebCore::RenderFlexibleBox::layoutBlock):
     33        (WebCore::RenderFlexibleBox::applyStretchAlignmentToChild):
     34        * rendering/RenderFlexibleBox.h:
     35        * rendering/RenderGrid.cpp:
     36        (WebCore::RenderGrid::layoutBlock):
     37        * rendering/RenderGrid.h:
     38        * rendering/RenderTable.cpp:
     39        (WebCore::RenderTable::layout):
     40        * rendering/RenderTable.h:
     41
    1422019-11-20  Myles C. Maxfield  <mmaxfield@apple.com>
    243
  • trunk/Source/WebCore/rendering/RenderBlock.h

    r248517 r252716  
    316316    Optional<LayoutUnit> availableLogicalHeightForPercentageComputation() const;
    317317    bool hasDefiniteLogicalHeight() const;
    318    
     318
     319    virtual bool shouldResetChildLogicalHeightBeforeLayout(const RenderBox&) const { return false; }
     320
    319321protected:
    320322    RenderFragmentedFlow* locateEnclosingFragmentedFlow() const override;
  • trunk/Source/WebCore/rendering/RenderBlockFlow.cpp

    r250341 r252716  
    473473    // FIXME: should this start out as borderAndPaddingLogicalHeight() + scrollbarLogicalHeight(),
    474474    // for consistency with other render classes?
    475     setLogicalHeight(0);
     475    resetLogicalHeightBeforeLayoutIfNeeded();
    476476
    477477    bool pageLogicalHeightChanged = false;
  • trunk/Source/WebCore/rendering/RenderBlockFlow.h

    r250234 r252716  
    392392
    393393protected:
     394    bool shouldResetLogicalHeightBeforeLayout() const override { return true; }
     395
    394396    void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const override;
    395397   
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r252161 r252716  
    568568}
    569569
     570void RenderBox::resetLogicalHeightBeforeLayoutIfNeeded()
     571{
     572    if (shouldResetLogicalHeightBeforeLayout() || (is<RenderBlock>(parent()) && downcast<RenderBlock>(*parent()).shouldResetChildLogicalHeightBeforeLayout(*this)))
     573        setLogicalHeight(0_lu);
     574}
     575
    570576static void setupWheelEventMonitor(RenderLayer& layer)
    571577{
  • trunk/Source/WebCore/rendering/RenderBox.h

    r249222 r252716  
    655655    bool createsNewFormattingContext() const;
    656656
     657    virtual bool shouldResetLogicalHeightBeforeLayout() const { return false; }
     658    void resetLogicalHeightBeforeLayoutIfNeeded();
     659
    657660    virtual ItemPosition selfAlignmentNormalBehavior(const RenderBox* = nullptr) const { return ItemPosition::Stretch; }
    658661
  • trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp

    r246490 r252716  
    286286        LayoutStateMaintainer statePusher(*this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
    287287
     288        resetLogicalHeightBeforeLayoutIfNeeded();
    288289        preparePaginationBeforeBlockLayout(relayoutChildren);
    289290
  • trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp

    r252620 r252716  
    263263    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
    264264
     265    resetLogicalHeightBeforeLayoutIfNeeded();
    265266    m_relaidOutChildren.clear();
    266267   
     
    18401841            child.setOverrideContentLogicalHeight(desiredLogicalHeight - child.borderAndPaddingLogicalHeight());
    18411842        if (childNeedsRelayout) {
    1842             child.setLogicalHeight(0_lu);
     1843            SetForScope<bool> resetChildLogicalHeight(m_shouldResetChildLogicalHeightBeforeLayout, true);
    18431844            // We cache the child's intrinsic content logical height to avoid it being
    18441845            // reset to the stretched height.
    1845             // FIXME: This is fragile. RendertBoxes should be smart enough to
     1846            // FIXME: This is fragile. RenderBoxes should be smart enough to
    18461847            // determine their intrinsic content logical height correctly even when
    18471848            // there's an overrideHeight.
  • trunk/Source/WebCore/rendering/RenderFlexibleBox.h

    r252620 r252716  
    9292    void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const override;
    9393    void computePreferredLogicalWidths() override;
     94
     95    bool shouldResetChildLogicalHeightBeforeLayout(const RenderBox&) const override { return m_shouldResetChildLogicalHeightBeforeLayout; }
    9496
    9597private:
     
    212214    mutable SizeDefiniteness m_hasDefiniteHeight { SizeDefiniteness::Unknown };
    213215    bool m_inLayout { false };
     216    bool m_shouldResetChildLogicalHeightBeforeLayout { false };
    214217};
    215218
  • trunk/Source/WebCore/rendering/RenderGrid.cpp

    r248846 r252716  
    220220        }
    221221        m_baselineItemsCached = true;
    222         setLogicalHeight(0);
     222        resetLogicalHeightBeforeLayoutIfNeeded();
    223223        updateLogicalWidth();
    224224
  • trunk/Source/WebCore/rendering/RenderGrid.h

    r240333 r252716  
    187187    LayoutUnit translateRTLCoordinate(LayoutUnit) const;
    188188
     189    bool shouldResetLogicalHeightBeforeLayout() const override { return true; }
     190
    189191    Grid m_grid;
    190192
  • trunk/Source/WebCore/rendering/RenderTable.cpp

    r252161 r252716  
    434434        LayoutUnit oldLogicalWidth = logicalWidth();
    435435        LayoutUnit oldLogicalHeight = logicalHeight();
    436         setLogicalHeight(0);
     436        resetLogicalHeightBeforeLayoutIfNeeded();
    437437        updateLogicalWidth();
    438438
  • trunk/Source/WebCore/rendering/RenderTable.h

    r245868 r252716  
    362362    }
    363363
     364    bool shouldResetLogicalHeightBeforeLayout() const override { return true; }
     365
    364366    LayoutUnit m_hSpacing;
    365367    LayoutUnit m_vSpacing;
Note: See TracChangeset for help on using the changeset viewer.