Remove lazy scrollinfo hoisting introduced in bug 1193557. (bug 1209278 part 2, r=mstange)

--HG--
extra : rebase_source : 004d42f760364cd18e16125fb04f5d22cba2d648
This commit is contained in:
David Anderson 2016-02-23 10:11:43 -08:00
parent a08042eef1
commit 6fba740086
4 changed files with 39 additions and 182 deletions

View File

@ -608,13 +608,13 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mUsedAGRBudget(0),
mDirtyRect(-1,-1,-1,-1),
mGlassDisplayItem(nullptr),
mPendingScrollInfoItems(nullptr),
mCommittedScrollInfoItems(nullptr),
mScrollInfoItemsForHoisting(nullptr),
mMode(aMode),
mCurrentScrollParentId(FrameMetrics::NULL_SCROLL_ID),
mCurrentScrollbarTarget(FrameMetrics::NULL_SCROLL_ID),
mCurrentScrollbarFlags(0),
mPerspectiveItemIndex(0),
mSVGEffectsBuildingDepth(0),
mIsBuildingScrollbar(false),
mCurrentScrollbarWillHaveLayer(false),
mBuildCaret(aBuildCaret),
@ -1366,27 +1366,35 @@ nsDisplayListBuilder::AddToAGRBudget(nsIFrame* aFrame)
return onBudget;
}
nsDisplayList*
nsDisplayListBuilder::EnterScrollInfoItemHoisting(nsDisplayList* aScrollInfoItemStorage)
void
nsDisplayListBuilder::EnterSVGEffectsContents(nsDisplayList* aHoistedItemsStorage)
{
MOZ_ASSERT(ShouldBuildScrollInfoItemsForHoisting());
nsDisplayList* old = mPendingScrollInfoItems;
mPendingScrollInfoItems = aScrollInfoItemStorage;
return old;
MOZ_ASSERT(mSVGEffectsBuildingDepth >= 0);
MOZ_ASSERT(aHoistedItemsStorage);
if (mSVGEffectsBuildingDepth == 0) {
MOZ_ASSERT(!mScrollInfoItemsForHoisting);
mScrollInfoItemsForHoisting = aHoistedItemsStorage;
}
mSVGEffectsBuildingDepth++;
}
void
nsDisplayListBuilder::LeaveScrollInfoItemHoisting(nsDisplayList* aScrollInfoItemStorage)
nsDisplayListBuilder::ExitSVGEffectsContents()
{
MOZ_ASSERT(ShouldBuildScrollInfoItemsForHoisting());
mPendingScrollInfoItems = aScrollInfoItemStorage;
mSVGEffectsBuildingDepth--;
MOZ_ASSERT(mSVGEffectsBuildingDepth >= 0);
MOZ_ASSERT(mScrollInfoItemsForHoisting);
if (mSVGEffectsBuildingDepth == 0) {
mScrollInfoItemsForHoisting = nullptr;
}
}
void
nsDisplayListBuilder::AppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLayer* aScrollInfoItem)
{
MOZ_ASSERT(ShouldBuildScrollInfoItemsForHoisting());
mPendingScrollInfoItems->AppendNewToTop(aScrollInfoItem);
MOZ_ASSERT(mScrollInfoItemsForHoisting);
mScrollInfoItemsForHoisting->AppendNewToTop(aScrollInfoItem);
}
void
@ -4894,7 +4902,6 @@ nsDisplayScrollInfoLayer::nsDisplayScrollInfoLayer(
, mScrollFrame(aScrollFrame)
, mScrolledFrame(aScrolledFrame)
, mScrollParentId(aBuilder->GetCurrentScrollParentId())
, mIgnoreIfCompositorSupportsBlending(false)
{
#ifdef NS_BUILD_REFCNT_LOGGING
MOZ_COUNT_CTOR(nsDisplayScrollInfoLayer);
@ -4918,14 +4925,6 @@ nsDisplayScrollInfoLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
// cannot be layerized, and so needs to scroll synchronously. To handle those
// cases, we still want to generate scrollinfo layers.
if (mIgnoreIfCompositorSupportsBlending) {
// This item was created pessimistically because, during display list
// building, we encountered a mix blend mode. If our layer manager
// supports compositing this mix blend mode, we don't actually need to
// create a scroll info layer.
return nullptr;
}
ContainerLayerParameters params = aContainerParameters;
if (mScrolledFrame->GetContent() &&
nsLayoutUtils::HasCriticalDisplayPort(mScrolledFrame->GetContent())) {
@ -4969,24 +4968,7 @@ nsDisplayScrollInfoLayer::ComputeFrameMetrics(Layer* aLayer,
return UniquePtr<FrameMetrics>(new FrameMetrics(metrics));
}
void
nsDisplayScrollInfoLayer::IgnoreIfCompositorSupportsBlending(BlendModeSet aBlendModes)
{
mContainedBlendModes += aBlendModes;
mIgnoreIfCompositorSupportsBlending = true;
}
void
nsDisplayScrollInfoLayer::UnsetIgnoreIfCompositorSupportsBlending()
{
mIgnoreIfCompositorSupportsBlending = false;
}
bool
nsDisplayScrollInfoLayer::ContainedInMixBlendMode() const
{
return mIgnoreIfCompositorSupportsBlending;
}
void
nsDisplayScrollInfoLayer::WriteDebugInfo(std::stringstream& aStream)

View File

@ -1056,26 +1056,11 @@ public:
*/
bool IsInWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);
void SetCommittedScrollInfoItemList(nsDisplayList* aScrollInfoItemStorage) {
mCommittedScrollInfoItems = aScrollInfoItemStorage;
}
nsDisplayList* CommittedScrollInfoItems() const {
return mCommittedScrollInfoItems;
}
bool ShouldBuildScrollInfoItemsForHoisting() const {
return IsPaintingToWindow();
}
void EnterSVGEffectsContents(nsDisplayList* aHoistedItemsStorage);
void ExitSVGEffectsContents();
// When building display lists for stacking contexts, we append scroll info
// items to a temporary list. If the stacking context would create an
// inactive layer, we commit these items to the final hoisted scroll items
// list. Otherwise, we propagate these items to the parent stacking
// context's list of pending scroll info items.
//
// EnterScrollInfoItemHoisting returns the parent stacking context's pending
// item list.
nsDisplayList* EnterScrollInfoItemHoisting(nsDisplayList* aScrollInfoItemStorage);
void LeaveScrollInfoItemHoisting(nsDisplayList* aScrollInfoItemStorage);
bool ShouldBuildScrollInfoItemsForHoisting() const
{ return mSVGEffectsBuildingDepth > 0; }
void AppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLayer* aScrollInfoItem);
@ -1242,14 +1227,12 @@ private:
LayoutDeviceIntRegion mWindowNoDraggingRegion;
// The display item for the Windows window glass background, if any
nsDisplayItem* mGlassDisplayItem;
// When encountering inactive layers, we need to hoist scroll info items
// above these layers so APZ can deliver events to content. Such scroll
// info items are considered "committed" to the final hoisting list. If
// no hoisting is needed immediately, it may be needed later if a blend
// mode is introduced in a higher stacking context, so we keep all scroll
// info items until the end of display list building.
nsDisplayList* mPendingScrollInfoItems;
nsDisplayList* mCommittedScrollInfoItems;
// A temporary list that we append scroll info items to while building
// display items for the contents of frames with SVG effects.
// Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
// This is a pointer and not a real nsDisplayList value because the
// nsDisplayList class is defined below this class, so we can't use it here.
nsDisplayList* mScrollInfoItemsForHoisting;
nsTArray<DisplayItemScrollClip*> mScrollClipsToDestroy;
nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy;
Mode mMode;
@ -1259,6 +1242,7 @@ private:
BlendModeSet mContainedBlendModes;
Preserves3DContext mPreserves3DCtx;
uint32_t mPerspectiveItemIndex;
int32_t mSVGEffectsBuildingDepth;
bool mIsBuildingScrollbar;
bool mCurrentScrollbarWillHaveLayer;
bool mBuildCaret;
@ -3717,20 +3701,10 @@ public:
mozilla::UniquePtr<FrameMetrics> ComputeFrameMetrics(Layer* aLayer,
const ContainerLayerParameters& aContainerParameters);
void IgnoreIfCompositorSupportsBlending(BlendModeSet aBlendModes);
void UnsetIgnoreIfCompositorSupportsBlending();
bool ContainedInMixBlendMode() const;
protected:
nsIFrame* mScrollFrame;
nsIFrame* mScrolledFrame;
ViewID mScrollParentId;
// If the only reason for the ScrollInfoLayer is a blend mode, the blend
// mode may be supported in the compositor. We track it here to determine
// if so during layer construction.
BlendModeSet mContainedBlendModes;
bool mIgnoreIfCompositorSupportsBlending;
};
/**

View File

@ -3262,11 +3262,6 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
/* aAllowCreateDisplayPort = */ true);
}
nsDisplayList hoistedScrollItemStorage;
if (builder.IsPaintingToWindow()) {
builder.SetCommittedScrollInfoItemList(&hoistedScrollItemStorage);
}
nsRegion visibleRegion;
if (aFlags & PAINT_WIDGET_LAYERS) {
// This layer tree will be reused, so we'll need to calculate it

View File

@ -1830,87 +1830,6 @@ public:
}
};
class AutoHoistScrollInfoItems
{
nsDisplayListBuilder& mBuilder;
nsDisplayList* mParentPendingList;
nsDisplayList mPendingList;
public:
explicit AutoHoistScrollInfoItems(nsDisplayListBuilder& aBuilder)
: mBuilder(aBuilder),
mParentPendingList(nullptr)
{
if (!mBuilder.ShouldBuildScrollInfoItemsForHoisting()) {
return;
}
mParentPendingList = mBuilder.EnterScrollInfoItemHoisting(&mPendingList);
}
~AutoHoistScrollInfoItems() {
if (!mParentPendingList) {
// If we have no parent stacking context, we will throw out any scroll
// info items that are pending (meaning, we can safely ignore them since
// the scrollable layers they represent will not be flattened).
return;
}
mParentPendingList->AppendToTop(&mPendingList);
mBuilder.LeaveScrollInfoItemHoisting(mParentPendingList);
}
// The current stacking context will definitely be flattened, so commit all
// pending scroll info items and make sure they will not be optimized away
// in the case they were also inside a compositor-supported mix-blend-mode.
void Commit() {
nsDisplayItem* iter = nullptr;
while ((iter = mPendingList.RemoveBottom()) != nullptr) {
MOZ_ASSERT(iter->GetType() == nsDisplayItem::TYPE_SCROLL_INFO_LAYER);
auto item = static_cast<nsDisplayScrollInfoLayer*>(iter);
item->UnsetIgnoreIfCompositorSupportsBlending();
mBuilder.CommittedScrollInfoItems()->AppendToTop(item);
}
}
// The current stacking context will only be flattened if the given mix-blend
// mode is not supported in the compositor. Annotate the scroll info items
// and keep them in the pending list.
void AnnotateForBlendModes(BlendModeSet aBlendModes) {
for (nsDisplayItem* iter = mPendingList.GetBottom(); iter; iter = iter->GetAbove()) {
MOZ_ASSERT(iter->GetType() == nsDisplayItem::TYPE_SCROLL_INFO_LAYER);
auto item = static_cast<nsDisplayScrollInfoLayer*>(iter);
item->IgnoreIfCompositorSupportsBlending(aBlendModes);
}
}
bool IsRootStackingContext() {
// We're only finished building the hoisted list if we have no parent
// stacking context.
return !mParentPendingList;
}
// Any scroll info items which contain a mix-blend mode are moved into the
// parent display list.
void Finish(nsDisplayList* aResultList) {
MOZ_ASSERT(IsRootStackingContext());
nsDisplayItem* iter = nullptr;
while ((iter = mPendingList.RemoveBottom()) != nullptr) {
MOZ_ASSERT(iter->GetType() == nsDisplayItem::TYPE_SCROLL_INFO_LAYER);
nsDisplayScrollInfoLayer *item = static_cast<decltype(item)>(iter);
if (!item->ContainedInMixBlendMode()) {
// Discard the item, it was not committed for having an SVG effect nor
// was it contained with a mix-blend mode.
item->~nsDisplayScrollInfoLayer();
continue;
}
aResultList->AppendToTop(item);
}
}
};
static void
CheckForApzAwareEventHandlers(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
{
@ -2085,13 +2004,13 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
inTransform = true;
}
AutoHoistScrollInfoItems hoistedScrollInfoItems(*aBuilder);
bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
nsRect dirtyRectOutsideSVGEffects = dirtyRect;
nsDisplayList hoistedScrollInfoItemsStorage;
if (usingSVGEffects) {
dirtyRect =
nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
}
bool useOpacity = HasVisualOpacity() && !nsSVGUtils::CanOptimizeOpacity(this);
@ -2236,6 +2155,10 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
/* List now emptied, so add the new list to the top. */
resultList.AppendNewToTop(
new (aBuilder) nsDisplaySVGEffects(aBuilder, this, &resultList));
// Also add the hoisted scroll info items. We need those for APZ scrolling
// because nsDisplaySVGEffects items can't build active layers.
aBuilder->ExitSVGEffectsContents();
resultList.AppendToTop(&hoistedScrollInfoItemsStorage);
}
else if (useOpacity && !resultList.IsEmpty() && !is3DContextRoot) {
/* If this element is the root of a preserve-3d context, then we want
@ -2354,25 +2277,8 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
*/
if (aBuilder->ContainsBlendMode()) {
resultList.AppendNewToTop(
new (aBuilder) nsDisplayBlendContainer(aBuilder, this, &resultList, aBuilder->ContainedBlendModes()));
}
if (aBuilder->ShouldBuildScrollInfoItemsForHoisting()) {
if (usingSVGEffects) {
// We know this stacking context will be flattened, so hoist any scroll
// info items we created.
hoistedScrollInfoItems.Commit();
} else if (aBuilder->ContainsBlendMode()) {
hoistedScrollInfoItems.AnnotateForBlendModes(aBuilder->ContainedBlendModes());
}
if (hoistedScrollInfoItems.IsRootStackingContext()) {
// If we're the root stacking context, no more mix-blend modes can be
// introduced and it's safe to hoist scroll info items.
resultList.AppendToTop(aBuilder->CommittedScrollInfoItems());
hoistedScrollInfoItems.Finish(&resultList);
}
resultList.AppendNewToTop(
new (aBuilder) nsDisplayBlendContainer(aBuilder, this, &resultList, aBuilder->ContainedBlendModes()));
}
/* If there's blending, wrap up the list in a blend-mode item. Note