Bug 1405359 - Avoid pushing and popping identical clip stacks for adjacent display items. r=jrmuizel

Instead of unconditionally pushing and popping clips per display item,
this patch changes things so that for each recursive display list, we
create an ItemClips struct. We push this onto the stack when we enter
the display list, and pop it off at the end. For each display item, we
check to see if the clips would actually change compared to the previous
display item, and only do the pop/repush in that case.

MozReview-Commit-ID: GadIp2J8TrA

--HG--
extra : rebase_source : ba64c6b4659b8e51cab19b807088b9a50d71b85a
This commit is contained in:
Kartikaya Gupta 2017-10-24 16:15:00 -04:00
parent 1ef110fd03
commit 3bc78496af
3 changed files with 53 additions and 12 deletions

View File

@ -37,10 +37,35 @@ ScrollingLayersHelper::EndBuild()
MOZ_ASSERT(mItemClipStack.empty());
}
void
ScrollingLayersHelper::BeginList()
{
mItemClipStack.emplace_back(nullptr, nullptr);
}
void
ScrollingLayersHelper::EndList()
{
MOZ_ASSERT(!mItemClipStack.empty());
mItemClipStack.back().Unapply(mBuilder);
mItemClipStack.pop_back();
}
void
ScrollingLayersHelper::BeginItem(nsDisplayItem* aItem,
const StackingContextHelper& aStackingContext)
{
ItemClips clips(aItem->GetActiveScrolledRoot(), aItem->GetClipChain());
MOZ_ASSERT(!mItemClipStack.empty());
if (clips.HasSameInputs(mItemClipStack.back())) {
// Early-exit because if the clips are the same then we don't need to do
// do the work of popping the old stuff and then pushing it right back on
// for the new item.
return;
}
mItemClipStack.back().Unapply(mBuilder);
mItemClipStack.pop_back();
int32_t auPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
// There are two ASR chains here that we need to be fully defined. One is the
@ -78,7 +103,6 @@ ScrollingLayersHelper::BeginItem(nsDisplayItem* aItem,
// the item's ASR. So for those cases we need to use the ClipAndScroll API.
bool needClipAndScroll = (leafmostId != scrollId);
ItemClips clips;
// If we don't need a ClipAndScroll, ensure the item's ASR is at the top of
// the scroll stack
if (!needClipAndScroll && mBuilder->TopmostScrollId() != scrollId) {
@ -376,15 +400,6 @@ ScrollingLayersHelper::RecurseAndDefineAsr(nsDisplayItem* aItem,
return ids;
}
void
ScrollingLayersHelper::EndItem(nsDisplayItem* aItem)
{
MOZ_ASSERT(!mItemClipStack.empty());
ItemClips& clips = mItemClipStack.back();
clips.Unapply(mBuilder);
mItemClipStack.pop_back();
}
ScrollingLayersHelper::~ScrollingLayersHelper()
{
MOZ_ASSERT(!mBuilder);
@ -392,6 +407,13 @@ ScrollingLayersHelper::~ScrollingLayersHelper()
MOZ_ASSERT(mItemClipStack.empty());
}
ScrollingLayersHelper::ItemClips::ItemClips(const ActiveScrolledRoot* aAsr,
const DisplayItemClipChain* aChain)
: mAsr(aAsr)
, mChain(aChain)
{
}
void
ScrollingLayersHelper::ItemClips::Apply(wr::DisplayListBuilder* aBuilder)
{
@ -421,5 +443,12 @@ ScrollingLayersHelper::ItemClips::Unapply(wr::DisplayListBuilder* aBuilder)
}
}
bool
ScrollingLayersHelper::ItemClips::HasSameInputs(const ItemClips& aOther)
{
return mAsr == aOther.mAsr &&
mChain == aOther.mChain;
}
} // namespace layers
} // namespace mozilla

View File

@ -32,9 +32,11 @@ public:
void BeginBuild(wr::DisplayListBuilder& aBuilder);
void EndBuild();
void BeginList();
void EndList();
void BeginItem(nsDisplayItem* aItem,
const StackingContextHelper& aStackingContext);
void EndItem(nsDisplayItem* aItem);
~ScrollingLayersHelper();
private:
@ -75,12 +77,19 @@ private:
ClipIdMap mCache;
struct ItemClips {
ItemClips(const ActiveScrolledRoot* aAsr,
const DisplayItemClipChain* aChain);
const ActiveScrolledRoot* mAsr;
const DisplayItemClipChain* mChain;
Maybe<FrameMetrics::ViewID> mScrollId;
Maybe<wr::WrClipId> mClipId;
Maybe<std::pair<FrameMetrics::ViewID, Maybe<wr::WrClipId>>> mClipAndScroll;
void Apply(wr::DisplayListBuilder* aBuilder);
void Unapply(wr::DisplayListBuilder* aBuilder);
bool HasSameInputs(const ItemClips& aOther);
};
std::vector<ItemClips> mItemClipStack;

View File

@ -112,6 +112,8 @@ WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(nsDisplayList* a
wr::DisplayListBuilder& aBuilder,
wr::IpcResourceUpdateQueue& aResources)
{
mScrollingHelper.BeginList();
bool apzEnabled = mManager->AsyncPanZoomEnabled();
EventRegions eventRegions;
@ -221,7 +223,6 @@ WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(nsDisplayList* a
aDisplayListBuilder)) {
PushItemAsImage(item, aBuilder, aResources, aSc, aDisplayListBuilder);
}
mScrollingHelper.EndItem(item);
if (apzEnabled) {
if (forceNewLayerData) {
@ -259,6 +260,8 @@ WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(nsDisplayList* a
MOZ_ASSERT(!mLayerScrollData.empty());
mLayerScrollData.back().AddEventRegions(eventRegions);
}
mScrollingHelper.EndList();
}
Maybe<wr::ImageKey>