mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-27 02:43:07 +00:00
Bug 1405359 - Make ScrollingLayersHelper a more stateful class. r=jrmuizel
This makes ScrollingLayersHelper a non-RAII type class, and instead adds methods to notify it of when we start processing a new transaction or a new display item within the transaction. This patch has no functional changes, it's non-obvious refactoring. MozReview-Commit-ID: 3yq9sPiHMge --HG-- extra : rebase_source : 286423f56de59211e320f015cb1004a1e98332b8
This commit is contained in:
parent
7feb6820bd
commit
1ef110fd03
@ -5,21 +5,41 @@
|
|||||||
|
|
||||||
#include "mozilla/layers/ScrollingLayersHelper.h"
|
#include "mozilla/layers/ScrollingLayersHelper.h"
|
||||||
|
|
||||||
|
#include "DisplayItemClipChain.h"
|
||||||
#include "FrameMetrics.h"
|
#include "FrameMetrics.h"
|
||||||
#include "mozilla/layers/StackingContextHelper.h"
|
#include "mozilla/layers/StackingContextHelper.h"
|
||||||
#include "mozilla/webrender/WebRenderAPI.h"
|
#include "mozilla/webrender/WebRenderAPI.h"
|
||||||
|
#include "nsDisplayList.h"
|
||||||
#include "UnitTransforms.h"
|
#include "UnitTransforms.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
ScrollingLayersHelper::ScrollingLayersHelper(nsDisplayItem* aItem,
|
ScrollingLayersHelper::ScrollingLayersHelper()
|
||||||
wr::DisplayListBuilder& aBuilder,
|
: mBuilder(nullptr)
|
||||||
const StackingContextHelper& aStackingContext,
|
{
|
||||||
WebRenderCommandBuilder::ClipIdMap& aCache,
|
}
|
||||||
bool aApzEnabled)
|
|
||||||
: mBuilder(&aBuilder)
|
void
|
||||||
, mCache(aCache)
|
ScrollingLayersHelper::BeginBuild(wr::DisplayListBuilder& aBuilder)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!mBuilder);
|
||||||
|
mBuilder = &aBuilder;
|
||||||
|
MOZ_ASSERT(mCache.empty());
|
||||||
|
MOZ_ASSERT(mItemClipStack.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ScrollingLayersHelper::EndBuild()
|
||||||
|
{
|
||||||
|
mBuilder = nullptr;
|
||||||
|
mCache.clear();
|
||||||
|
MOZ_ASSERT(mItemClipStack.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ScrollingLayersHelper::BeginItem(nsDisplayItem* aItem,
|
||||||
|
const StackingContextHelper& aStackingContext)
|
||||||
{
|
{
|
||||||
int32_t auPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
|
int32_t auPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
|
||||||
|
|
||||||
@ -58,16 +78,17 @@ ScrollingLayersHelper::ScrollingLayersHelper(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) {
|
||||||
MOZ_ASSERT(leafmostId == scrollId); // because !needClipAndScroll
|
MOZ_ASSERT(leafmostId == scrollId); // because !needClipAndScroll
|
||||||
mItemClips.mScrollId = Some(scrollId);
|
clips.mScrollId = Some(scrollId);
|
||||||
}
|
}
|
||||||
// And ensure the leafmost clip, if scrolled by that ASR, is at the top of the
|
// And ensure the leafmost clip, if scrolled by that ASR, is at the top of the
|
||||||
// stack.
|
// stack.
|
||||||
if (ids.second && aItem->GetClipChain()->mASR == leafmostASR) {
|
if (ids.second && aItem->GetClipChain()->mASR == leafmostASR) {
|
||||||
mItemClips.mClipId = ids.second;
|
clips.mClipId = ids.second;
|
||||||
}
|
}
|
||||||
// If we need the ClipAndScroll, we want to replace the topmost scroll layer
|
// If we need the ClipAndScroll, we want to replace the topmost scroll layer
|
||||||
// with the item's ASR but preseve the topmost clip (which is scrolled by
|
// with the item's ASR but preseve the topmost clip (which is scrolled by
|
||||||
@ -76,14 +97,15 @@ ScrollingLayersHelper::ScrollingLayersHelper(nsDisplayItem* aItem,
|
|||||||
// If mClipId is set that means we want to push it such that it's going
|
// If mClipId is set that means we want to push it such that it's going
|
||||||
// to be the TopmostClipId(), but we haven't actually pushed it yet.
|
// to be the TopmostClipId(), but we haven't actually pushed it yet.
|
||||||
// But we still want to take that instead of the actual current TopmostClipId().
|
// But we still want to take that instead of the actual current TopmostClipId().
|
||||||
Maybe<wr::WrClipId> clipId = mItemClips.mClipId;
|
Maybe<wr::WrClipId> clipId = clips.mClipId;
|
||||||
if (!clipId) {
|
if (!clipId) {
|
||||||
clipId = mBuilder->TopmostClipId();
|
clipId = mBuilder->TopmostClipId();
|
||||||
}
|
}
|
||||||
mItemClips.mClipAndScroll = Some(std::make_pair(scrollId, clipId));
|
clips.mClipAndScroll = Some(std::make_pair(scrollId, clipId));
|
||||||
}
|
}
|
||||||
|
|
||||||
mItemClips.Apply(mBuilder);
|
clips.Apply(mBuilder);
|
||||||
|
mItemClipStack.push_back(clips);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Maybe<FrameMetrics::ViewID>, Maybe<wr::WrClipId>>
|
std::pair<Maybe<FrameMetrics::ViewID>, Maybe<wr::WrClipId>>
|
||||||
@ -354,9 +376,20 @@ 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()
|
||||||
{
|
{
|
||||||
mItemClips.Unapply(mBuilder);
|
MOZ_ASSERT(!mBuilder);
|
||||||
|
MOZ_ASSERT(mCache.empty());
|
||||||
|
MOZ_ASSERT(mItemClipStack.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -7,10 +7,12 @@
|
|||||||
#define GFX_SCROLLINGLAYERSHELPER_H
|
#define GFX_SCROLLINGLAYERSHELPER_H
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/layers/WebRenderCommandBuilder.h"
|
|
||||||
|
class nsDisplayItem;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
struct ActiveScrolledRoot;
|
||||||
struct DisplayItemClipChain;
|
struct DisplayItemClipChain;
|
||||||
|
|
||||||
namespace wr {
|
namespace wr {
|
||||||
@ -22,14 +24,17 @@ namespace layers {
|
|||||||
struct FrameMetrics;
|
struct FrameMetrics;
|
||||||
class StackingContextHelper;
|
class StackingContextHelper;
|
||||||
|
|
||||||
class MOZ_RAII ScrollingLayersHelper
|
class ScrollingLayersHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScrollingLayersHelper(nsDisplayItem* aItem,
|
ScrollingLayersHelper();
|
||||||
wr::DisplayListBuilder& aBuilder,
|
|
||||||
const StackingContextHelper& aStackingContext,
|
void BeginBuild(wr::DisplayListBuilder& aBuilder);
|
||||||
WebRenderCommandBuilder::ClipIdMap& aCache,
|
void EndBuild();
|
||||||
bool aApzEnabled);
|
|
||||||
|
void BeginItem(nsDisplayItem* aItem,
|
||||||
|
const StackingContextHelper& aStackingContext);
|
||||||
|
void EndItem(nsDisplayItem* aItem);
|
||||||
~ScrollingLayersHelper();
|
~ScrollingLayersHelper();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -54,8 +59,20 @@ private:
|
|||||||
int32_t aAppUnitsPerDevPixel,
|
int32_t aAppUnitsPerDevPixel,
|
||||||
const StackingContextHelper& aSc);
|
const StackingContextHelper& aSc);
|
||||||
|
|
||||||
|
// Note: two DisplayItemClipChain* A and B might actually be "equal" (as per
|
||||||
|
// DisplayItemClipChain::Equal(A, B)) even though they are not the same pointer
|
||||||
|
// (A != B). In this hopefully-rare case, they will get separate entries
|
||||||
|
// in this map when in fact we could collapse them. However, to collapse
|
||||||
|
// them involves writing a custom hash function for the pointer type such that
|
||||||
|
// A and B hash to the same things whenever DisplayItemClipChain::Equal(A, B)
|
||||||
|
// is true, and that will incur a performance penalty for all the hashmap
|
||||||
|
// operations, so is probably not worth it. With the current code we might
|
||||||
|
// end up creating multiple clips in WR that are effectively identical but
|
||||||
|
// have separate clip ids. Hopefully this won't happen very often.
|
||||||
|
typedef std::unordered_map<const DisplayItemClipChain*, wr::WrClipId> ClipIdMap;
|
||||||
|
|
||||||
wr::DisplayListBuilder* mBuilder;
|
wr::DisplayListBuilder* mBuilder;
|
||||||
WebRenderCommandBuilder::ClipIdMap& mCache;
|
ClipIdMap mCache;
|
||||||
|
|
||||||
struct ItemClips {
|
struct ItemClips {
|
||||||
Maybe<FrameMetrics::ViewID> mScrollId;
|
Maybe<FrameMetrics::ViewID> mScrollId;
|
||||||
@ -66,7 +83,7 @@ private:
|
|||||||
void Unapply(wr::DisplayListBuilder* aBuilder);
|
void Unapply(wr::DisplayListBuilder* aBuilder);
|
||||||
};
|
};
|
||||||
|
|
||||||
ItemClips mItemClips;
|
std::vector<ItemClips> mItemClipStack;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
|
@ -64,6 +64,7 @@ WebRenderCommandBuilder::BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder
|
|||||||
MOZ_ASSERT(mLayerScrollData.empty());
|
MOZ_ASSERT(mLayerScrollData.empty());
|
||||||
mLastCanvasDatas.Clear();
|
mLastCanvasDatas.Clear();
|
||||||
mLastAsr = nullptr;
|
mLastAsr = nullptr;
|
||||||
|
mScrollingHelper.BeginBuild(aBuilder);
|
||||||
|
|
||||||
{
|
{
|
||||||
StackingContextHelper pageRootSc(sc, aBuilder);
|
StackingContextHelper pageRootSc(sc, aBuilder);
|
||||||
@ -94,7 +95,7 @@ WebRenderCommandBuilder::BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder
|
|||||||
aScrollData.AddLayerData(*i);
|
aScrollData.AddLayerData(*i);
|
||||||
}
|
}
|
||||||
mLayerScrollData.clear();
|
mLayerScrollData.clear();
|
||||||
mClipIdCache.clear();
|
mScrollingHelper.EndBuild();
|
||||||
|
|
||||||
// Remove the user data those are not displayed on the screen and
|
// Remove the user data those are not displayed on the screen and
|
||||||
// also reset the data to unused for next transaction.
|
// also reset the data to unused for next transaction.
|
||||||
@ -213,16 +214,14 @@ WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(nsDisplayList* a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // ensure the scope of ScrollingLayersHelper is maintained
|
mScrollingHelper.BeginItem(item, aSc);
|
||||||
ScrollingLayersHelper clip(item, aBuilder, aSc, mClipIdCache, apzEnabled);
|
// Note: this call to CreateWebRenderCommands can recurse back into
|
||||||
|
// this function if the |item| is a wrapper for a sublist.
|
||||||
// Note: this call to CreateWebRenderCommands can recurse back into
|
if (!item->CreateWebRenderCommands(aBuilder, aResources, aSc, mManager,
|
||||||
// this function if the |item| is a wrapper for a sublist.
|
aDisplayListBuilder)) {
|
||||||
if (!item->CreateWebRenderCommands(aBuilder, aResources, aSc, mManager,
|
PushItemAsImage(item, aBuilder, aResources, aSc, aDisplayListBuilder);
|
||||||
aDisplayListBuilder)) {
|
|
||||||
PushItemAsImage(item, aBuilder, aResources, aSc, aDisplayListBuilder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
mScrollingHelper.EndItem(item);
|
||||||
|
|
||||||
if (apzEnabled) {
|
if (apzEnabled) {
|
||||||
if (forceNewLayerData) {
|
if (forceNewLayerData) {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#define GFX_WEBRENDERCOMMANDBUILDER_H
|
#define GFX_WEBRENDERCOMMANDBUILDER_H
|
||||||
|
|
||||||
#include "mozilla/webrender/WebRenderAPI.h"
|
#include "mozilla/webrender/WebRenderAPI.h"
|
||||||
|
#include "mozilla/layers/ScrollingLayersHelper.h"
|
||||||
#include "mozilla/layers/WebRenderMessages.h"
|
#include "mozilla/layers/WebRenderMessages.h"
|
||||||
#include "mozilla/layers/WebRenderScrollData.h"
|
#include "mozilla/layers/WebRenderScrollData.h"
|
||||||
#include "mozilla/layers/WebRenderUserData.h"
|
#include "mozilla/layers/WebRenderUserData.h"
|
||||||
@ -145,22 +146,9 @@ public:
|
|||||||
return res.forget();
|
return res.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
// Note: two DisplayItemClipChain* A and B might actually be "equal" (as per
|
|
||||||
// DisplayItemClipChain::Equal(A, B)) even though they are not the same pointer
|
|
||||||
// (A != B). In this hopefully-rare case, they will get separate entries
|
|
||||||
// in this map when in fact we could collapse them. However, to collapse
|
|
||||||
// them involves writing a custom hash function for the pointer type such that
|
|
||||||
// A and B hash to the same things whenever DisplayItemClipChain::Equal(A, B)
|
|
||||||
// is true, and that will incur a performance penalty for all the hashmap
|
|
||||||
// operations, so is probably not worth it. With the current code we might
|
|
||||||
// end up creating multiple clips in WR that are effectively identical but
|
|
||||||
// have separate clip ids. Hopefully this won't happen very often.
|
|
||||||
typedef std::unordered_map<const DisplayItemClipChain*, wr::WrClipId> ClipIdMap;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WebRenderLayerManager* mManager;
|
WebRenderLayerManager* mManager;
|
||||||
ClipIdMap mClipIdCache;
|
ScrollingLayersHelper mScrollingHelper;
|
||||||
|
|
||||||
// These fields are used to save a copy of the display list for
|
// These fields are used to save a copy of the display list for
|
||||||
// empty transactions in layers-free mode.
|
// empty transactions in layers-free mode.
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "mozilla/gfx/DrawEventRecorder.h"
|
#include "mozilla/gfx/DrawEventRecorder.h"
|
||||||
#include "mozilla/layers/CompositorBridgeChild.h"
|
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||||
#include "mozilla/layers/IpcResourceUpdateQueue.h"
|
#include "mozilla/layers/IpcResourceUpdateQueue.h"
|
||||||
#include "mozilla/layers/ScrollingLayersHelper.h"
|
|
||||||
#include "mozilla/layers/StackingContextHelper.h"
|
#include "mozilla/layers/StackingContextHelper.h"
|
||||||
#include "mozilla/layers/TextureClient.h"
|
#include "mozilla/layers/TextureClient.h"
|
||||||
#include "mozilla/layers/WebRenderBridgeChild.h"
|
#include "mozilla/layers/WebRenderBridgeChild.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user