Changeset 81802 in webkit
- Timestamp:
- Mar 23, 2011 1:39:53 PM (13 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r81799 r81802 1 2011-03-23 David Hyatt <hyatt@apple.com> 2 3 Reviewed by Dan Bernstein. 4 5 https://bugs.webkit.org/show_bug.cgi?id=56909 6 7 Add a simplified normal flow layout path optimization for overflow recomputation 8 and for positioned objects inside relative positioned containers. 9 10 Currently there is an optimized code path for positioned objects, but as soon as 11 we encounter a normal flow object in the containing block chain, we lose the 12 optimization. 13 14 This patch adds a new type of style difference called SimplifiedLayout that is 15 returned when only overflow needs to be recomputed. Whenever opacity changes or 16 a transform changes, this is the hint returned now instead of a full layout. 17 18 In addition, when positioned objects need layout and start marking up the 19 containing block chain, we now propagate the fact that the layout is simplified 20 all the way up to the root, even when we encounter normal flow containing 21 blocks. 22 23 The layoutOnlyPositionedObjects function has been renamed to simplifiedLayout() 24 and is now used for all of these cases (in addition to what it handled before). 25 26 No new tests, since existing tests covered this very well (especially the opacity 27 and transforms repaint tests in fast/repaint). 28 29 * rendering/RenderBlock.cpp: 30 (WebCore::RenderBlock::layoutBlock): 31 (WebCore::RenderBlock::simplifiedNormalFlowLayout): 32 (WebCore::RenderBlock::simplifiedLayout): 33 * rendering/RenderBlock.h: 34 * rendering/RenderBox.cpp: 35 (WebCore::RenderBox::styleDidChange): 36 * rendering/RenderBoxModelObject.cpp: 37 (WebCore::RenderBoxModelObject::styleWillChange): 38 * rendering/RenderFlexibleBox.cpp: 39 (WebCore::RenderFlexibleBox::layoutBlock): 40 * rendering/RenderObject.cpp: 41 (WebCore::RenderObject::RenderObject): 42 (WebCore::RenderObject::adjustStyleDifference): 43 (WebCore::RenderObject::setStyle): 44 (WebCore::RenderObject::styleDidChange): 45 * rendering/RenderObject.h: 46 (WebCore::RenderObject::needsLayout): 47 (WebCore::RenderObject::needsPositionedMovementLayoutOnly): 48 (WebCore::RenderObject::needsSimplifiedNormalFlowLayout): 49 (WebCore::RenderObject::setNeedsLayout): 50 (WebCore::RenderObject::setChildNeedsLayout): 51 (WebCore::RenderObject::setNeedsSimplifiedNormalFlowLayout): 52 (WebCore::RenderObject::markContainingBlocksForLayout): 53 * rendering/RenderTable.cpp: 54 (WebCore::RenderTable::layout): 55 * rendering/style/RenderStyle.cpp: 56 (WebCore::RenderStyle::diff): 57 * rendering/style/RenderStyleConstants.h: 58 * rendering/svg/RenderSVGText.cpp: 59 (WebCore::RenderSVGText::layout): 60 1 61 2011-03-23 Tyler Close <tjclose@chromium.org> 2 62 -
trunk/Source/WebCore/rendering/RenderBlock.cpp
r81794 r81802 35 35 #include "HTMLNames.h" 36 36 #include "HitTestResult.h" 37 #include "InlineIterator.h" 37 38 #include "InlineTextBox.h" 38 39 #include "PaintInfo.h" … … 1133 1134 return; // cause us to come in here. Just bail. 1134 1135 1135 if (!relayoutChildren && layoutOnlyPositionedObjects())1136 if (!relayoutChildren && simplifiedLayout()) 1136 1137 return; 1137 1138 … … 2077 2078 } 2078 2079 2079 bool RenderBlock::layoutOnlyPositionedObjects() 2080 { 2081 if (!posChildNeedsLayout() || normalChildNeedsLayout() || selfNeedsLayout()) 2080 void RenderBlock::simplifiedNormalFlowLayout() 2081 { 2082 if (childrenInline()) { 2083 ListHashSet<RootInlineBox*> lineBoxes; 2084 bool endOfInline = false; 2085 RenderObject* o = bidiFirst(this, 0, false); 2086 while (o) { 2087 if (!o->isPositioned() && (o->isReplaced() || o->isFloating())) { 2088 o->layoutIfNeeded(); 2089 if (toRenderBox(o)->inlineBoxWrapper()) { 2090 RootInlineBox* box = toRenderBox(o)->inlineBoxWrapper()->root(); 2091 lineBoxes.add(box); 2092 } 2093 } else if (o->isText() || (o->isRenderInline() && !endOfInline)) 2094 o->setNeedsLayout(false); 2095 o = bidiNext(this, o, 0, false, &endOfInline); 2096 } 2097 2098 // FIXME: Glyph overflow will get lost in this case, but not really a big deal. 2099 GlyphOverflowAndFallbackFontsMap textBoxDataMap; 2100 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); it != lineBoxes.end(); ++it) { 2101 RootInlineBox* box = *it; 2102 box->computeOverflow(box->lineTop(), box->lineBottom(), document()->inNoQuirksMode(), textBoxDataMap); 2103 } 2104 } else { 2105 for (RenderBox* box = firstChildBox(); box; box = box->nextSiblingBox()) { 2106 if (!box->isPositioned()) 2107 box->layoutIfNeeded(); 2108 } 2109 } 2110 } 2111 2112 bool RenderBlock::simplifiedLayout() 2113 { 2114 if ((!posChildNeedsLayout() && !needsSimplifiedNormalFlowLayout()) || normalChildNeedsLayout() || selfNeedsLayout()) 2082 2115 return false; 2083 2116 2084 2117 LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode()); 2085 2118 2086 2119 if (needsPositionedMovementLayout()) { 2087 2120 tryLayoutDoingPositionedMovementOnly(); … … 2090 2123 } 2091 2124 2092 // All we have to is lay out our positioned objects. 2093 layoutPositionedObjects(false); 2125 // Lay out positioned descendants or objects that just need to recompute overflow. 2126 if (needsSimplifiedNormalFlowLayout()) 2127 simplifiedNormalFlowLayout(); 2128 2129 // Lay out our positioned objects if our positioned child bit is set. 2130 if (posChildNeedsLayout()) 2131 layoutPositionedObjects(false); 2094 2132 2095 2133 // Recompute our overflow information. -
trunk/Source/WebCore/rendering/RenderBlock.h
r81746 r81802 298 298 299 299 virtual bool hasLineIfEmpty() const; 300 bool layoutOnlyPositionedObjects(); 300 301 bool simplifiedLayout(); 302 void simplifiedNormalFlowLayout(); 301 303 302 304 void computeOverflow(int oldClientAfterEdge, bool recomputeFloats = false); -
trunk/Source/WebCore/rendering/RenderBox.cpp
r81786 r81802 289 289 RenderBoxModelObject::styleDidChange(diff, oldStyle); 290 290 291 if (needsLayout() && oldStyle && (oldStyle->logicalHeight().isPercent() || oldStyle->logicalMinHeight().isPercent() || oldStyle->logicalMaxHeight().isPercent())) 292 RenderBlock::removePercentHeightDescendant(this); 291 if (needsLayout() && oldStyle) { 292 if (oldStyle && (oldStyle->logicalHeight().isPercent() || oldStyle->logicalMinHeight().isPercent() || oldStyle->logicalMaxHeight().isPercent())) 293 RenderBlock::removePercentHeightDescendant(this); 294 295 // Normally we can do optimized positioning layout for absolute/fixed positioned objects. There is one special case, however, which is 296 // when the positioned object's margin-before is changed. In this case the parent has to get a layout in order to run margin collapsing 297 // to determine the new static position. 298 if (isPositioned() && style()->hasStaticBlockPosition(isHorizontalWritingMode()) && oldStyle->marginBefore() != style()->marginBefore() 299 && parent() && !parent()->normalChildNeedsLayout()) 300 parent()->setChildNeedsLayout(true); 301 } 293 302 294 303 // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the -
trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp
r81716 r81802 304 304 } 305 305 306 if (diff == StyleDifferenceLayout ) {306 if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) { 307 307 // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could 308 308 // end up being destroyed. -
trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp
r79930 r81802 210 210 ASSERT(needsLayout()); 211 211 212 if (!relayoutChildren && layoutOnlyPositionedObjects())212 if (!relayoutChildren && simplifiedLayout()) 213 213 return; 214 214 -
trunk/Source/WebCore/rendering/RenderObject.cpp
r81747 r81802 192 192 , m_normalChildNeedsLayout(false) 193 193 , m_posChildNeedsLayout(false) 194 , m_needsSimplifiedNormalFlowLayout(false) 194 195 , m_preferredLogicalWidthsDirty(false) 195 196 , m_floating(false) … … 1687 1688 // hence the !isText() check. 1688 1689 // FIXME: when transforms are taken into account for overflow, we will need to do a layout. 1689 if (!isText() && (!hasLayer() || !toRenderBoxModelObject(this)->layer()->isComposited())) 1690 diff = StyleDifferenceLayout; 1691 else if (diff < StyleDifferenceRecompositeLayer) 1690 if (!isText() && (!hasLayer() || !toRenderBoxModelObject(this)->layer()->isComposited())) { 1691 if (!hasLayer()) 1692 diff = StyleDifferenceLayout; // FIXME: Do this for now since SimplifiedLayout cannot handle updating floating objects lists. 1693 else if (diff < StyleDifferenceSimplifiedLayout) 1694 diff = StyleDifferenceSimplifiedLayout; 1695 } else if (diff < StyleDifferenceRecompositeLayer) 1692 1696 diff = StyleDifferenceRecompositeLayer; 1693 1697 } … … 1768 1772 else if (updatedDiff == StyleDifferenceLayoutPositionedMovementOnly) 1769 1773 setNeedsPositionedMovementLayout(); 1774 else if (updatedDiff == StyleDifferenceSimplifiedLayout) 1775 setNeedsSimplifiedNormalFlowLayout(); 1770 1776 } 1771 1777 … … 1881 1887 return; 1882 1888 1883 if (diff == StyleDifferenceLayout ) {1889 if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) { 1884 1890 RenderCounter::rendererStyleChanged(this, oldStyle, m_style.get()); 1885 1891 … … 1892 1898 markContainingBlocksForLayout(); 1893 1899 1894 setNeedsLayoutAndPrefWidthsRecalc(); 1900 if (diff == StyleDifferenceLayout) 1901 setNeedsLayoutAndPrefWidthsRecalc(); 1902 else 1903 setNeedsSimplifiedNormalFlowLayout(); 1895 1904 } else if (diff == StyleDifferenceLayoutPositionedMovementOnly) 1896 1905 setNeedsPositionedMovementLayout(); -
trunk/Source/WebCore/rendering/RenderObject.h
r81747 r81802 416 416 bool mustRepaintBackgroundOrBorder() const; 417 417 bool hasBackground() const { return style()->hasBackground(); } 418 bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout || m_needs PositionedMovementLayout; }418 bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout || m_needsSimplifiedNormalFlowLayout || m_needsPositionedMovementLayout; } 419 419 bool selfNeedsLayout() const { return m_needsLayout; } 420 420 bool needsPositionedMovementLayout() const { return m_needsPositionedMovementLayout; } 421 bool needsPositionedMovementLayoutOnly() const { return m_needsPositionedMovementLayout && !m_needsLayout && !m_normalChildNeedsLayout && !m_posChildNeedsLayout ; }421 bool needsPositionedMovementLayoutOnly() const { return m_needsPositionedMovementLayout && !m_needsLayout && !m_normalChildNeedsLayout && !m_posChildNeedsLayout && !m_needsSimplifiedNormalFlowLayout; } 422 422 bool posChildNeedsLayout() const { return m_posChildNeedsLayout; } 423 bool needsSimplifiedNormalFlowLayout() const { return m_needsSimplifiedNormalFlowLayout; } 423 424 bool normalChildNeedsLayout() const { return m_normalChildNeedsLayout; } 424 425 … … 489 490 void setChildNeedsLayout(bool b, bool markParents = true); 490 491 void setNeedsPositionedMovementLayout(); 492 void setNeedsSimplifiedNormalFlowLayout(); 491 493 void setPreferredLogicalWidthsDirty(bool, bool markParents = true); 492 494 void invalidateContainerPreferredLogicalWidths(); … … 847 849 bool m_normalChildNeedsLayout : 1; 848 850 bool m_posChildNeedsLayout : 1; 851 bool m_needsSimplifiedNormalFlowLayout : 1; 849 852 bool m_preferredLogicalWidthsDirty : 1; 850 853 bool m_floating : 1; … … 932 935 m_everHadLayout = true; 933 936 m_posChildNeedsLayout = false; 937 m_needsSimplifiedNormalFlowLayout = false; 934 938 m_normalChildNeedsLayout = false; 935 939 m_needsPositionedMovementLayout = false; … … 947 951 } else { 948 952 m_posChildNeedsLayout = false; 953 m_needsSimplifiedNormalFlowLayout = false; 949 954 m_normalChildNeedsLayout = false; 950 955 m_needsPositionedMovementLayout = false; … … 956 961 bool alreadyNeededLayout = needsLayout(); 957 962 m_needsPositionedMovementLayout = true; 963 if (!alreadyNeededLayout) { 964 markContainingBlocksForLayout(); 965 if (hasLayer()) 966 setLayerNeedsFullRepaint(); 967 } 968 } 969 970 inline void RenderObject::setNeedsSimplifiedNormalFlowLayout() 971 { 972 bool alreadyNeededLayout = needsLayout(); 973 m_needsSimplifiedNormalFlowLayout = true; 958 974 if (!alreadyNeededLayout) { 959 975 markContainingBlocksForLayout(); … … 983 999 RenderObject* last = this; 984 1000 1001 bool simplifiedNormalFlowLayout = needsSimplifiedNormalFlowLayout() && !selfNeedsLayout() && !normalChildNeedsLayout(); 1002 985 1003 while (o) { 986 1004 // Don't mark the outermost object of an unrooted subtree. That object will be … … 990 1008 return; 991 1009 if (!last->isText() && (last->style()->position() == FixedPosition || last->style()->position() == AbsolutePosition)) { 992 if (last->style()->top().isAuto() && last->style()->bottom().isAuto()) {993 RenderObject* parent = last->parent();994 if (!parent->normalChildNeedsLayout()) {995 parent->setChildNeedsLayout(true, false);996 if (parent != newRoot)997 parent->markContainingBlocksForLayout(scheduleRelayout, newRoot);998 }999 }1000 1010 if (o->m_posChildNeedsLayout) 1001 1011 return; 1002 1012 o->m_posChildNeedsLayout = true; 1013 simplifiedNormalFlowLayout = true; 1014 ASSERT(!o->isSetNeedsLayoutForbidden()); 1015 } else if (simplifiedNormalFlowLayout) { 1016 if (o->m_needsSimplifiedNormalFlowLayout) 1017 return; 1018 o->m_needsSimplifiedNormalFlowLayout = true; 1003 1019 ASSERT(!o->isSetNeedsLayoutForbidden()); 1004 1020 } else { -
trunk/Source/WebCore/rendering/RenderTable.cpp
r81304 r81802 262 262 ASSERT(needsLayout()); 263 263 264 if ( layoutOnlyPositionedObjects())264 if (simplifiedLayout()) 265 265 return; 266 266 -
trunk/Source/WebCore/rendering/style/RenderStyle.cpp
r81684 r81802 486 486 return StyleDifferenceLayout; 487 487 488 if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE)) 489 return StyleDifferenceLayout; 490 488 491 if ((rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1) || 489 492 (rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1)) { 490 // FIXME: We should add an optimized form of layout that just recomputes visual overflow. 493 // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet. 494 // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need 495 // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line). 496 // In addition we need to solve the floating object issue when layers come and go. Right now 497 // a full layout is necessary to keep floating object lists sane. 491 498 return StyleDifferenceLayout; 492 499 } 493 500 494 if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))495 return StyleDifferenceLayout;496 497 501 #if ENABLE(SVG) 498 502 // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes. … … 512 516 return StyleDifferenceLayoutPositionedMovementOnly; 513 517 514 // FIXME: We will need to do a bit of work in RenderObject/Box::setStyle before we 515 // can stop doing a layout when relative positioned objects move. In particular, we'll need 516 // to update scrolling positions and figure out how to do a repaint properly of the updated layer. 517 //if (other->position() == RelativePosition) 518 // return RepaintLayer; 519 //else 520 return StyleDifferenceLayout; 518 // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet. 519 // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need 520 // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line). 521 return StyleDifferenceLayout; 521 522 } else if (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex() || 522 523 visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip) -
trunk/Source/WebCore/rendering/style/RenderStyleConstants.h
r80151 r81802 52 52 StyleDifferenceRepaintLayer, 53 53 StyleDifferenceLayoutPositionedMovementOnly, 54 StyleDifferenceSimplifiedLayout, 54 55 StyleDifferenceLayout 55 56 }; -
trunk/Source/WebCore/rendering/svg/RenderSVGText.cpp
r77485 r81802 135 135 // All if branches that could cause early exit in RenderBlocks layoutBlock() method are turned into assertions. 136 136 ASSERT(!isInline()); 137 ASSERT(! layoutOnlyPositionedObjects());137 ASSERT(!simplifiedLayout()); 138 138 ASSERT(!scrollsOverflow()); 139 139 ASSERT(!hasControlClip());
Note: See TracChangeset
for help on using the changeset viewer.