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()); 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 void
ScrollingLayersHelper::BeginItem(nsDisplayItem* aItem, ScrollingLayersHelper::BeginItem(nsDisplayItem* aItem,
const StackingContextHelper& aStackingContext) 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(); int32_t auPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
// There are two ASR chains here that we need to be fully defined. One is the // 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. // the item's ASR. So for those cases we need to use the ClipAndScroll API.
bool needClipAndScroll = (leafmostId != scrollId); bool needClipAndScroll = (leafmostId != scrollId);
ItemClips clips;
// If we don't need a ClipAndScroll, ensure the item's ASR is at the top of // If we don't need a ClipAndScroll, ensure the item's ASR is at the top of
// the scroll stack // the scroll stack
if (!needClipAndScroll && mBuilder->TopmostScrollId() != scrollId) { if (!needClipAndScroll && mBuilder->TopmostScrollId() != scrollId) {
@ -376,15 +400,6 @@ ScrollingLayersHelper::RecurseAndDefineAsr(nsDisplayItem* aItem,
return ids; return ids;
} }
void
ScrollingLayersHelper::EndItem(nsDisplayItem* aItem)
{
MOZ_ASSERT(!mItemClipStack.empty());
ItemClips& clips = mItemClipStack.back();
clips.Unapply(mBuilder);
mItemClipStack.pop_back();
}
ScrollingLayersHelper::~ScrollingLayersHelper() ScrollingLayersHelper::~ScrollingLayersHelper()
{ {
MOZ_ASSERT(!mBuilder); MOZ_ASSERT(!mBuilder);
@ -392,6 +407,13 @@ ScrollingLayersHelper::~ScrollingLayersHelper()
MOZ_ASSERT(mItemClipStack.empty()); MOZ_ASSERT(mItemClipStack.empty());
} }
ScrollingLayersHelper::ItemClips::ItemClips(const ActiveScrolledRoot* aAsr,
const DisplayItemClipChain* aChain)
: mAsr(aAsr)
, mChain(aChain)
{
}
void void
ScrollingLayersHelper::ItemClips::Apply(wr::DisplayListBuilder* aBuilder) 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 layers
} // namespace mozilla } // namespace mozilla

View File

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

View File

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