Bug 1367906: Cache the presence of rounded corners upon style changes. r=dbaron r=mattwoodrow
Profiling indicates a significant amount of time is spent during displaylist building accessing style information in order to detect border radii. This is a cost that for frames with no border radii only needs to be paid when the style changes.
Since nsIFrame still has 16 bits available for storing data without growing it in size, this patch recomputes whether there are border radii upon DidGetStyleContext and stores that information in one of these unused bits.
MozReview-Commit-ID: 4Jm29qUwXq3
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -973,16 +973,18 @@ nsFrame::DidSetStyleContext(nsStyleConte
// bidi algorithm, we need to call |SetBidiEnabled| on the pres
// context before reflow starts. See bug 115921.
if (StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
PresContext()->SetBidiEnabled();
}
RemoveStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS |
NS_FRAME_SIMPLE_DISPLAYLIST);
+
+ mMayHaveRoundedCorners = true;
}
void
nsIFrame::ReparentFrameViewTo(nsViewManager* aViewManager,
nsView* aNewParentView,
nsView* aOldParentView)
{
if (HasView()) {
@@ -1547,16 +1549,21 @@ nsIFrame::OutsetBorderRadii(nscoord aRad
}
}
}
/* virtual */ bool
nsIFrame::GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
Sides aSkipSides, nscoord aRadii[8]) const
{
+ if (!mMayHaveRoundedCorners) {
+ memset(aRadii, 0, sizeof(nscoord) * 8);
+ return false;
+ }
+
if (IsThemed()) {
// When we're themed, the native theme code draws the border and
// background, and therefore it doesn't make sense to tell other
// code that's interested in border-radius that we have any radii.
//
// In an ideal world, we might have a way for the them to tell us an
// border radius, but since we don't, we're better off assuming
// zero.
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -610,16 +610,17 @@ public:
: mRect()
, mContent(nullptr)
, mStyleContext(nullptr)
, mParent(nullptr)
, mNextSibling(nullptr)
, mPrevSibling(nullptr)
, mState(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY)
, mType(aType)
+ , mMayHaveRoundedCorners(false)
{
mozilla::PodZero(&mOverflow);
}
nsPresContext* PresContext() const {
return StyleContext()->PresContext();
}
@@ -3897,16 +3898,19 @@ protected:
} mOverflow;
/** @see GetWritingMode() */
mozilla::WritingMode mWritingMode;
/** The type of the frame. */
mozilla::LayoutFrameType mType;
+ bool mMayHaveRoundedCorners : 1;
+ // There should be a 15-bit gap left here.
+
// Helpers
/**
* Can we stop inside this frame when we're skipping non-rendered whitespace?
* @param aForward [in] Are we moving forward (or backward) in content order.
* @param aOffset [in/out] At what offset into the frame to start looking.
* on output - what offset was reached (whether or not we found a place to stop).
* @return STOP: An appropriate offset was found within this frame,
* and is given by aOffset.