--- a/gfx/layers/wr/ScrollingLayersHelper.cpp
+++ b/gfx/layers/wr/ScrollingLayersHelper.cpp
@@ -119,44 +119,48 @@ ScrollingLayersHelper::BeginItem(nsDispl
// generated while processing aItem. However those display items only care
// about the topmost clip on the stack. If that were all we cared about we
// would only need to push one thing here and we would be done. However, we
// also care about the ScrollingLayersHelper instance that might be created
// for nested display items, in the case where aItem is a wrapper item. The
// nested ScrollingLayersHelper may rely on things like TopmostScrollId and
// TopmostClipId, so now we need to push at most two things onto the stack.
- FrameMetrics::ViewID leafmostId = ids.first.valueOr(FrameMetrics::NULL_SCROLL_ID);
- FrameMetrics::ViewID scrollId = aItem->GetActiveScrolledRoot()
+ Maybe<wr::WrScrollId> leafmostId = ids.first;
+ FrameMetrics::ViewID viewId = aItem->GetActiveScrolledRoot()
? aItem->GetActiveScrolledRoot()->GetViewId()
: FrameMetrics::NULL_SCROLL_ID;
+ Maybe<wr::WrScrollId> scrollId =
+ mBuilder->GetScrollIdForDefinedScrollLayer(viewId);
+ MOZ_ASSERT(scrollId.isSome());
+
// If the leafmost ASR is not the same as the item's ASR then we are dealing
// with a case where the item's clip chain is scrolled by something other than
// the item's ASR. So for those cases we need to use the ClipAndScroll API.
bool needClipAndScroll = (leafmostId != scrollId);
// The other scenario where we need to push a ClipAndScroll is when we are
// in a nested display item where the enclosing item pushed a ClipAndScroll,
// and our clip chain extends from that item's clip chain. To check this we
// want to make sure that (a) we are inside a ClipAndScroll, and (b) nothing
// else was pushed onto mBuilder's stack since that ClipAndScroll.
if (!needClipAndScroll &&
mBuilder->TopmostScrollId() == scrollId &&
!mBuilder->TopmostIsClip()) {
if (auto cs = EnclosingClipAndScroll()) {
- MOZ_ASSERT(cs->first == scrollId);
+ MOZ_ASSERT(cs->first == *scrollId);
needClipAndScroll = true;
}
}
// 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) {
MOZ_ASSERT(leafmostId == scrollId); // because !needClipAndScroll
- clips.mScrollId = Some(scrollId);
+ clips.mScrollId = scrollId;
}
// And ensure the leafmost clip, if scrolled by that ASR, is at the top of the
// stack.
if (ids.second && clip->mASR == leafmostASR) {
clips.mClipId = ids.second;
}
// 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
@@ -164,26 +168,27 @@ ScrollingLayersHelper::BeginItem(nsDispl
if (needClipAndScroll) {
// 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.
// But we still want to take that instead of the actual current TopmostClipId().
Maybe<wr::WrClipId> clipId = clips.mClipId;
if (!clipId) {
clipId = mBuilder->TopmostClipId();
}
- clips.mClipAndScroll = Some(std::make_pair(scrollId, clipId));
+
+ clips.mClipAndScroll = Some(std::make_pair(*scrollId, clipId));
}
clips.Apply(mBuilder);
mItemClipStack.push_back(clips);
SLH_LOG("done setup for %p\n", aItem);
}
-std::pair<Maybe<FrameMetrics::ViewID>, Maybe<wr::WrClipId>>
+std::pair<Maybe<wr::WrScrollId>, Maybe<wr::WrClipId>>
ScrollingLayersHelper::DefineClipChain(nsDisplayItem* aItem,
const ActiveScrolledRoot* aAsr,
const DisplayItemClipChain* aChain,
int32_t aAppUnitsPerDevPixel,
const StackingContextHelper& aStackingContext)
{
// This is the main entry point for defining the clip chain for a display
// item. This function recursively walks up the ASR chain and the display
@@ -222,27 +227,27 @@ ScrollingLayersHelper::DefineClipChain(n
return RecurseAndDefineAsr(aItem, aAsr, aChain, aAppUnitsPerDevPixel, aStackingContext);
}
MOZ_ASSERT(!aChain && !aAsr);
return std::make_pair(Nothing(), Nothing());
}
-std::pair<Maybe<FrameMetrics::ViewID>, Maybe<wr::WrClipId>>
+std::pair<Maybe<wr::WrScrollId>, Maybe<wr::WrClipId>>
ScrollingLayersHelper::RecurseAndDefineClip(nsDisplayItem* aItem,
const ActiveScrolledRoot* aAsr,
const DisplayItemClipChain* aChain,
int32_t aAppUnitsPerDevPixel,
const StackingContextHelper& aSc)
{
MOZ_ASSERT(aChain);
// This will hold our return value
- std::pair<Maybe<FrameMetrics::ViewID>, Maybe<wr::WrClipId>> ids;
+ std::pair<Maybe<wr::WrScrollId>, Maybe<wr::WrClipId>> ids;
if (mBuilder->HasExtraClip()) {
// We can't use the clip cache directly. However if there's an out-of-band clip that
// was pushed on top of aChain, we should return the id for that OOB clip,
// so that anything we want to define as a descendant of aChain we actually
// end up defining as a descendant of the OOB clip.
ids.second = mBuilder->GetCacheOverride(aChain);
} else {
@@ -250,19 +255,18 @@ ScrollingLayersHelper::RecurseAndDefineC
auto it = cache.find(aChain);
if (it != cache.end()) {
ids.second = Some(it->second);
}
}
if (ids.second) {
// If we've already got an id for this clip, we can early-exit
if (aAsr) {
- FrameMetrics::ViewID scrollId = aAsr->GetViewId();
- MOZ_ASSERT(mBuilder->IsScrollLayerDefined(scrollId));
- ids.first = Some(scrollId);
+ ids.first = mBuilder->GetScrollIdForDefinedScrollLayer(aAsr->GetViewId());
+ MOZ_ASSERT(ids.first);
}
return ids;
}
// If not, recurse to ensure all the ancestors are defined
auto ancestorIds = DefineClipChain(
aItem, aAsr, aChain->mParent, aAppUnitsPerDevPixel, aSc);
ids = ancestorIds;
@@ -289,17 +293,18 @@ ScrollingLayersHelper::RecurseAndDefineC
} else {
// But if the ASRs are different, this is the outermost clip that's
// still inside aAsr, and we need to make it a child of aAsr rather
// than aChain->mParent.
ancestorIds.second = Nothing();
}
} else {
MOZ_ASSERT(!ancestorIds.second);
- FrameMetrics::ViewID scrollId = aChain->mASR ? aChain->mASR->GetViewId() : FrameMetrics::NULL_SCROLL_ID;
+ FrameMetrics::ViewID viewId = aChain->mASR ? aChain->mASR->GetViewId() : FrameMetrics::NULL_SCROLL_ID;
+ auto scrollId = mBuilder->GetScrollIdForDefinedScrollLayer(viewId);
if (mBuilder->TopmostScrollId() == scrollId) {
if (mBuilder->TopmostIsClip()) {
// If aChain->mASR is already the topmost scroll layer on the stack, but
// but there was another clip pushed *on top* of that ASR, then that clip
// shares the ASR, and we need to make our clip a child of that clip, which
// in turn will already be a descendant of the correct ASR.
// This covers the cases where e.g. the Gecko display list has nested items,
// and the clip chain on the nested item implicitly extends from the clip
@@ -318,17 +323,17 @@ ScrollingLayersHelper::RecurseAndDefineC
// item had a clip scrolled by a different ASR than the item itself),
// then we have need to propagate that behaviour as well. For example if
// the enclosing display item pushed a ClipAndScroll with (scrollid=S,
// clipid=C), then then clip we're defining here (call it D) needs to be
// defined as a child of C, and we'll need to push the ClipAndScroll
// (S, D) for this item. This hunk of code ensures that we define D
// as a child of C, and when we set the needClipAndScroll flag elsewhere
// in this file we make sure to set it for this scenario.
- MOZ_ASSERT(cs->first == scrollId);
+ MOZ_ASSERT(Some(cs->first) == scrollId);
ancestorIds.first = Nothing();
ancestorIds.second = cs->second;
}
}
}
// At most one of the ancestor pair should be defined here, and the one that
// is defined will be the parent clip for the new clip that we're defining.
MOZ_ASSERT(!(ancestorIds.first && ancestorIds.second));
@@ -345,32 +350,32 @@ ScrollingLayersHelper::RecurseAndDefineC
if (!mBuilder->HasExtraClip()) {
mCacheStack.back()[aChain] = clipId;
}
ids.second = Some(clipId);
return ids;
}
-std::pair<Maybe<FrameMetrics::ViewID>, Maybe<wr::WrClipId>>
+std::pair<Maybe<wr::WrScrollId>, Maybe<wr::WrClipId>>
ScrollingLayersHelper::RecurseAndDefineAsr(nsDisplayItem* aItem,
const ActiveScrolledRoot* aAsr,
const DisplayItemClipChain* aChain,
int32_t aAppUnitsPerDevPixel,
const StackingContextHelper& aSc)
{
MOZ_ASSERT(aAsr);
// This will hold our return value
- std::pair<Maybe<FrameMetrics::ViewID>, Maybe<wr::WrClipId>> ids;
+ std::pair<Maybe<wr::WrScrollId>, Maybe<wr::WrClipId>> ids;
- FrameMetrics::ViewID scrollId = aAsr->GetViewId();
- if (mBuilder->IsScrollLayerDefined(scrollId)) {
+ FrameMetrics::ViewID viewId = aAsr->GetViewId();
+ if (auto scrollId = mBuilder->GetScrollIdForDefinedScrollLayer(viewId)) {
// If we've already defined this scroll layer before, we can early-exit
- ids.first = Some(scrollId);
+ ids.first = scrollId;
if (aChain) {
if (mBuilder->HasExtraClip()) {
ids.second = mBuilder->GetCacheOverride(aChain);
} else {
const ClipIdMap& cache = mCacheStack.back();
auto it = cache.find(aChain);
// If |it == cache.end()| here then we have run into a case where the
// scroll layer was previously defined with a specific parent clip, and
@@ -440,17 +445,19 @@ ScrollingLayersHelper::RecurseAndDefineA
// However, when we get the scrollable rect from the FrameMetrics, the origin
// has nothing to do with the position of the frame but instead represents
// the minimum allowed scroll offset of the scrollable content. While APZ
// uses this to clamp the scroll position, we don't need to send this to
// WebRender at all. Instead, we take the position from the composition
// bounds.
contentRect.MoveTo(clipBounds.TopLeft());
- mBuilder->DefineScrollLayer(scrollId, ancestorIds.first, ancestorIds.second,
+ auto scrollId = mBuilder->DefineScrollLayer(viewId,
+ ancestorIds.first,
+ ancestorIds.second,
aSc.ToRelativeLayoutRect(contentRect),
aSc.ToRelativeLayoutRect(clipBounds));
ids.first = Some(scrollId);
return ids;
}
const DisplayItemClipChain*
--- a/gfx/layers/wr/ScrollingLayersHelper.h
+++ b/gfx/layers/wr/ScrollingLayersHelper.h
@@ -42,33 +42,33 @@ public:
void BeginList(const StackingContextHelper& aStackingContext);
void EndList(const StackingContextHelper& aStackingContext);
void BeginItem(nsDisplayItem* aItem,
const StackingContextHelper& aStackingContext);
~ScrollingLayersHelper();
private:
- typedef std::pair<FrameMetrics::ViewID, Maybe<wr::WrClipId>> ClipAndScroll;
+ typedef std::pair<wr::WrScrollId, Maybe<wr::WrClipId>> ClipAndScroll;
- std::pair<Maybe<FrameMetrics::ViewID>, Maybe<wr::WrClipId>>
+ std::pair<Maybe<wr::WrScrollId>, Maybe<wr::WrClipId>>
DefineClipChain(nsDisplayItem* aItem,
const ActiveScrolledRoot* aAsr,
const DisplayItemClipChain* aChain,
int32_t aAppUnitsPerDevPixel,
const StackingContextHelper& aStackingContext);
- std::pair<Maybe<FrameMetrics::ViewID>, Maybe<wr::WrClipId>>
+ std::pair<Maybe<wr::WrScrollId>, Maybe<wr::WrClipId>>
RecurseAndDefineClip(nsDisplayItem* aItem,
const ActiveScrolledRoot* aAsr,
const DisplayItemClipChain* aChain,
int32_t aAppUnitsPerDevPixel,
const StackingContextHelper& aSc);
- std::pair<Maybe<FrameMetrics::ViewID>, Maybe<wr::WrClipId>>
+ std::pair<Maybe<wr::WrScrollId>, Maybe<wr::WrClipId>>
RecurseAndDefineAsr(nsDisplayItem* aItem,
const ActiveScrolledRoot* aAsr,
const DisplayItemClipChain* aChain,
int32_t aAppUnitsPerDevPixel,
const StackingContextHelper& aSc);
const DisplayItemClipChain* ExtendChain(const DisplayItemClipChain* aClip);
Maybe<ClipAndScroll> EnclosingClipAndScroll() const;
@@ -90,17 +90,17 @@ private:
struct ItemClips {
ItemClips(const ActiveScrolledRoot* aAsr,
const DisplayItemClipChain* aChain);
const ActiveScrolledRoot* mAsr;
const DisplayItemClipChain* mChain;
- Maybe<FrameMetrics::ViewID> mScrollId;
+ Maybe<wr::WrScrollId> mScrollId;
Maybe<wr::WrClipId> mClipId;
Maybe<ClipAndScroll> mClipAndScroll;
void Apply(wr::DisplayListBuilder* aBuilder);
void Unapply(wr::DisplayListBuilder* aBuilder);
bool HasSameInputs(const ItemClips& aOther);
};
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -777,35 +777,39 @@ DisplayListBuilder::PushStackingContext(
void
DisplayListBuilder::PopStackingContext()
{
WRDL_LOG("PopStackingContext\n", mWrState);
wr_dp_pop_stacking_context(mWrState);
}
wr::WrClipId
-DisplayListBuilder::DefineClip(const Maybe<layers::FrameMetrics::ViewID>& aAncestorScrollId,
+DisplayListBuilder::DefineClip(const Maybe<wr::WrScrollId>& aAncestorScrollId,
const Maybe<wr::WrClipId>& aAncestorClipId,
const wr::LayoutRect& aClipRect,
const nsTArray<wr::ComplexClipRegion>* aComplex,
const wr::WrImageMask* aMask)
{
+ const uint64_t* ancestorScrollId = nullptr;
+ if (aAncestorScrollId) {
+ ancestorScrollId = &(aAncestorScrollId.ref().id);
+ }
const uint64_t* ancestorClipId = nullptr;
if (aAncestorClipId) {
ancestorClipId = &(aAncestorClipId.ref().id);
}
uint64_t clip_id = wr_dp_define_clip(mWrState,
- aAncestorScrollId.ptrOr(nullptr), ancestorClipId,
+ ancestorScrollId, ancestorClipId,
aClipRect,
aComplex ? aComplex->Elements() : nullptr,
aComplex ? aComplex->Length() : 0,
aMask);
WRDL_LOG("DefineClip id=%" PRIu64 " as=%s ac=%s r=%s m=%p b=%s complex=%zu\n", mWrState,
clip_id,
- aAncestorScrollId ? Stringify(aAncestorScrollId.ref()).c_str() : "(nil)",
+ aAncestorScrollId ? Stringify(aAncestorScrollId.ref().id).c_str() : "(nil)",
aAncestorClipId ? Stringify(aAncestorClipId.ref().id).c_str() : "(nil)",
Stringify(aClipRect).c_str(), aMask,
aMask ? Stringify(aMask->rect).c_str() : "none",
aComplex ? aComplex->Length() : 0);
return wr::WrClipId { clip_id };
}
void
@@ -927,80 +931,95 @@ DisplayListBuilder::PushStickyFrame(cons
void
DisplayListBuilder::PopStickyFrame(const DisplayItemClipChain* aParent)
{
WRDL_LOG("PopSticky\n", mWrState);
PopCacheOverride(aParent);
wr_dp_pop_clip(mWrState);
}
-bool
-DisplayListBuilder::IsScrollLayerDefined(layers::FrameMetrics::ViewID aScrollId) const
+Maybe<wr::WrScrollId>
+DisplayListBuilder::GetScrollIdForDefinedScrollLayer(layers::FrameMetrics::ViewID aViewId) const
{
- return mScrollIdsDefined.find(aScrollId) != mScrollIdsDefined.end();
+ if (aViewId == layers::FrameMetrics::NULL_SCROLL_ID) {
+ return Some(wr::WrScrollId { 0 });
+ }
+
+ auto it = mScrollIds.find(aViewId);
+ if (it == mScrollIds.end()) {
+ return Nothing();
+ }
+
+ return Some(it->second);
}
-void
-DisplayListBuilder::DefineScrollLayer(const layers::FrameMetrics::ViewID& aScrollId,
- const Maybe<layers::FrameMetrics::ViewID>& aAncestorScrollId,
+wr::WrScrollId
+DisplayListBuilder::DefineScrollLayer(const layers::FrameMetrics::ViewID& aViewId,
+ const Maybe<wr::WrScrollId>& aAncestorScrollId,
const Maybe<wr::WrClipId>& aAncestorClipId,
const wr::LayoutRect& aContentRect,
const wr::LayoutRect& aClipRect)
{
WRDL_LOG("DefineScrollLayer id=%" PRIu64 " as=%s ac=%s co=%s cl=%s\n", mWrState,
- aScrollId,
- aAncestorScrollId ? Stringify(aAncestorScrollId.ref()).c_str() : "(nil)",
+ aViewId,
+ aAncestorScrollId ? Stringify(aAncestorScrollId.ref().id).c_str() : "(nil)",
aAncestorClipId ? Stringify(aAncestorClipId.ref().id).c_str() : "(nil)",
Stringify(aContentRect).c_str(), Stringify(aClipRect).c_str());
- auto it = mScrollIdsDefined.insert(aScrollId);
- if (it.second) {
- // An insertion took place, which means we haven't defined aScrollId before.
- // So let's define it now.
- const uint64_t* ancestorClipId = nullptr;
- if (aAncestorClipId) {
- ancestorClipId = &(aAncestorClipId.ref().id);
- }
- wr_dp_define_scroll_layer(mWrState, aScrollId, aAncestorScrollId.ptrOr(nullptr),
- ancestorClipId, aContentRect, aClipRect);
+ auto it = mScrollIds.find(aViewId);
+ if (it != mScrollIds.end()) {
+ return it->second;
}
+
+ // We haven't defined aViewId before, so let's define it now.
+ uint64_t numericScrollId = wr_dp_define_scroll_layer(
+ mWrState,
+ aViewId,
+ aAncestorScrollId ? &(aAncestorScrollId->id) : nullptr,
+ aAncestorClipId ? &(aAncestorClipId->id) : nullptr,
+ aContentRect,
+ aClipRect);
+ auto wrScrollId = wr::WrScrollId { numericScrollId };
+ mScrollIds[aViewId] = wrScrollId;
+ return wrScrollId;
}
void
-DisplayListBuilder::PushScrollLayer(const layers::FrameMetrics::ViewID& aScrollId)
+DisplayListBuilder::PushScrollLayer(const wr::WrScrollId& aScrollId)
{
- WRDL_LOG("PushScrollLayer id=%" PRIu64 "\n", mWrState, aScrollId);
- wr_dp_push_scroll_layer(mWrState, aScrollId);
+ WRDL_LOG("PushScrollLayer id=%" PRIu64 "\n", mWrState, aScrollId.id);
+ wr_dp_push_scroll_layer(mWrState, aScrollId.id);
mClipStack.push_back(wr::ScrollOrClipId(aScrollId));
}
void
DisplayListBuilder::PopScrollLayer()
{
- MOZ_ASSERT(mClipStack.back().is<layers::FrameMetrics::ViewID>());
- WRDL_LOG("PopScrollLayer id=%" PRIu64 "\n", mWrState, mClipStack.back().as<layers::FrameMetrics::ViewID>());
+ MOZ_ASSERT(mClipStack.back().is<wr::WrScrollId>());
+ WRDL_LOG("PopScrollLayer id=%" PRIu64 "\n", mWrState,
+ mClipStack.back().as<wr::WrScrollId>().id);
mClipStack.pop_back();
wr_dp_pop_scroll_layer(mWrState);
}
void
-DisplayListBuilder::PushClipAndScrollInfo(const layers::FrameMetrics::ViewID& aScrollId,
+DisplayListBuilder::PushClipAndScrollInfo(const wr::WrScrollId& aScrollId,
const wr::WrClipId* aClipId)
{
- WRDL_LOG("PushClipAndScroll s=%" PRIu64 " c=%s\n", mWrState, aScrollId,
+ WRDL_LOG("PushClipAndScroll s=%" PRIu64 " c=%s\n", mWrState, aScrollId.id,
aClipId ? Stringify(aClipId->id).c_str() : "none");
- wr_dp_push_clip_and_scroll_info(mWrState, aScrollId,
+ wr_dp_push_clip_and_scroll_info(mWrState, aScrollId.id,
aClipId ? &(aClipId->id) : nullptr);
mClipStack.push_back(wr::ScrollOrClipId(aScrollId));
}
void
DisplayListBuilder::PopClipAndScrollInfo()
{
- MOZ_ASSERT(mClipStack.back().is<layers::FrameMetrics::ViewID>());
+ MOZ_ASSERT(mClipStack.back().is<wr::WrScrollId>());
WRDL_LOG("PopClipAndScroll\n", mWrState);
mClipStack.pop_back();
wr_dp_pop_clip_and_scroll_info(mWrState);
}
void
DisplayListBuilder::PushRect(const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip,
@@ -1287,25 +1306,25 @@ DisplayListBuilder::TopmostClipId()
for (auto it = mClipStack.crbegin(); it != mClipStack.crend(); it++) {
if (it->is<wr::WrClipId>()) {
return Some(it->as<wr::WrClipId>());
}
}
return Nothing();
}
-layers::FrameMetrics::ViewID
+Maybe<wr::WrScrollId>
DisplayListBuilder::TopmostScrollId()
{
for (auto it = mClipStack.crbegin(); it != mClipStack.crend(); it++) {
- if (it->is<layers::FrameMetrics::ViewID>()) {
- return it->as<layers::FrameMetrics::ViewID>();
+ if (it->is<wr::WrScrollId>()) {
+ return Some(it->as<wr::WrScrollId>());
}
}
- return layers::FrameMetrics::NULL_SCROLL_ID;
+ return Nothing();
}
bool
DisplayListBuilder::TopmostIsClip()
{
if (mClipStack.empty()) {
return false;
}
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -249,17 +249,17 @@ public:
const gfx::Matrix4x4* aTransform,
wr::TransformStyle aTransformStyle,
const gfx::Matrix4x4* aPerspective,
const wr::MixBlendMode& aMixBlendMode,
const nsTArray<wr::WrFilterOp>& aFilters,
bool aIsBackfaceVisible);
void PopStackingContext();
- wr::WrClipId DefineClip(const Maybe<layers::FrameMetrics::ViewID>& aAncestorScrollId,
+ wr::WrClipId DefineClip(const Maybe<wr::WrScrollId>& aAncestorScrollId,
const Maybe<wr::WrClipId>& aAncestorClipId,
const wr::LayoutRect& aClipRect,
const nsTArray<wr::ComplexClipRegion>* aComplex = nullptr,
const wr::WrImageMask* aMask = nullptr);
void PushClip(const wr::WrClipId& aClipId, const DisplayItemClipChain* aParent = nullptr);
void PopClip(const DisplayItemClipChain* aParent = nullptr);
Maybe<wr::WrClipId> GetCacheOverride(const DisplayItemClipChain* aParent);
@@ -270,26 +270,26 @@ public:
const float* aLeftMargin,
const StickyOffsetBounds& aVerticalBounds,
const StickyOffsetBounds& aHorizontalBounds,
const wr::LayoutVector2D& aAppliedOffset);
void PushStickyFrame(const wr::WrStickyId& aStickyId,
const DisplayItemClipChain* aParent);
void PopStickyFrame(const DisplayItemClipChain* aParent);
- bool IsScrollLayerDefined(layers::FrameMetrics::ViewID aScrollId) const;
- void DefineScrollLayer(const layers::FrameMetrics::ViewID& aScrollId,
- const Maybe<layers::FrameMetrics::ViewID>& aAncestorScrollId,
- const Maybe<wr::WrClipId>& aAncestorClipId,
- const wr::LayoutRect& aContentRect, // TODO: We should work with strongly typed rects
- const wr::LayoutRect& aClipRect);
- void PushScrollLayer(const layers::FrameMetrics::ViewID& aScrollId);
+ Maybe<wr::WrScrollId> GetScrollIdForDefinedScrollLayer(layers::FrameMetrics::ViewID aViewId) const;
+ wr::WrScrollId DefineScrollLayer(const layers::FrameMetrics::ViewID& aViewId,
+ const Maybe<wr::WrScrollId>& aAncestorScrollId,
+ const Maybe<wr::WrClipId>& aAncestorClipId,
+ const wr::LayoutRect& aContentRect, // TODO: We should work with strongly typed rects
+ const wr::LayoutRect& aClipRect);
+ void PushScrollLayer(const wr::WrScrollId& aScrollId);
void PopScrollLayer();
- void PushClipAndScrollInfo(const layers::FrameMetrics::ViewID& aScrollId,
+ void PushClipAndScrollInfo(const wr::WrScrollId& aScrollId,
const wr::WrClipId* aClipId);
void PopClipAndScrollInfo();
void PushRect(const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip,
bool aIsBackfaceVisible,
const wr::ColorF& aColor);
@@ -430,17 +430,17 @@ public:
const wr::BorderRadius& aBorderRadius,
const wr::BoxShadowClipMode& aClipMode);
// Returns the clip id that was most recently pushed with PushClip and that
// has not yet been popped with PopClip. Return Nothing() if the clip stack
// is empty.
Maybe<wr::WrClipId> TopmostClipId();
// Same as TopmostClipId() but for scroll layers.
- layers::FrameMetrics::ViewID TopmostScrollId();
+ Maybe<wr::WrScrollId> TopmostScrollId();
// If the topmost item on the stack is a clip or a scroll layer
bool TopmostIsClip();
// Set the hit-test info to be used for all display items until the next call
// to SetHitTestInfo or ClearHitTestInfo.
void SetHitTestInfo(const layers::FrameMetrics::ViewID& aScrollId,
gfx::CompositorHitTestInfo aHitInfo);
// Clears the hit-test info so that subsequent display items will not have it.
@@ -462,17 +462,17 @@ protected:
// Track the stack of clip ids and scroll layer ids that have been pushed
// (by PushClip and PushScrollLayer/PushClipAndScrollInfo, respectively) and
// haven't yet been popped.
std::vector<wr::ScrollOrClipId> mClipStack;
// Track each scroll id that we encountered. We use this structure to
// ensure that we don't define a particular scroll layer multiple times,
// as that results in undefined behaviour in WR.
- std::unordered_set<layers::FrameMetrics::ViewID> mScrollIdsDefined;
+ std::unordered_map<layers::FrameMetrics::ViewID, wr::WrScrollId> mScrollIds;
// A map that holds the cache overrides creates by "out of band" clips, i.e.
// clips that are generated by display items but that ScrollingLayersHelper
// doesn't know about. These are called "cache overrides" because while we're
// inside one of these clips, the WR clip stack is different from what
// ScrollingLayersHelper thinks it actually is (because of the out-of-band
// clip that was pushed onto the stack) and so ScrollingLayersHelper cannot
// use its clip cache as-is. Instead, any time ScrollingLayersHelper wants
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -747,37 +747,48 @@ static inline wr::WrFilterOpType ToWrFil
return wr::WrFilterOpType::DropShadow;
}
MOZ_ASSERT_UNREACHABLE("Tried to convert unknown filter type.");
return wr::WrFilterOpType::Grayscale;
}
// Corresponds to an "internal" webrender clip id. That is, a
// ClipId::Clip(x,pipeline_id) maps to a WrClipId{x}. We use a struct wrapper
-// instead of a typedef so that this is a distinct type from FrameMetrics::ViewID
-// and the compiler will catch accidental conversions between the two.
+// instead of a typedef so that this is a distinct type from ids generated
+// by scroll and position:sticky nodes and the compiler will catch accidental
+// conversions between them.
struct WrClipId {
uint64_t id;
bool operator==(const WrClipId& other) const {
return id == other.id;
}
};
+// Corresponds to a clip id for for a scroll frame in webrender. Similar
+// to WrClipId but a separate struct so we don't get them mixed up in C++.
+struct WrScrollId {
+ uint64_t id;
+
+ bool operator==(const WrScrollId& other) const {
+ return id == other.id;
+ }
+};
+
// Corresponds to a clip id for a position:sticky clip in webrender. Similar
// to WrClipId but a separate struct so we don't get them mixed up in C++.
struct WrStickyId {
uint64_t id;
bool operator==(const WrStickyId& other) const {
return id == other.id;
}
};
-typedef Variant<layers::FrameMetrics::ViewID, WrClipId> ScrollOrClipId;
+typedef Variant<WrScrollId, WrClipId> ScrollOrClipId;
enum class WebRenderError : int8_t {
INITIALIZE = 0,
MAKE_CURRENT,
RENDER,
Sentinel /* this must be last for serialization purposes. */
};
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -984,18 +984,18 @@ pub extern "C" fn wr_transaction_update_
#[no_mangle]
pub extern "C" fn wr_transaction_scroll_layer(
txn: &mut Transaction,
pipeline_id: WrPipelineId,
scroll_id: u64,
new_scroll_origin: LayoutPoint
) {
assert!(unsafe { is_in_compositor_thread() });
- let clip_id = ClipId::new(scroll_id, pipeline_id);
- txn.scroll_node_with_id(new_scroll_origin, clip_id, ScrollClamping::NoClamping);
+ let scroll_id = IdType::ExternalScrollId(ExternalScrollId(scroll_id, pipeline_id));
+ txn.scroll_node_with_id(new_scroll_origin, scroll_id, ScrollClamping::NoClamping);
}
#[no_mangle]
pub extern "C" fn wr_resource_updates_add_image(
resources: &mut ResourceUpdates,
image_key: WrImageKey,
descriptor: &WrImageDescriptor,
bytes: &mut WrVecU8,
@@ -1453,21 +1453,21 @@ pub extern "C" fn wr_dp_pop_stacking_con
fn make_scroll_info(state: &mut WrState,
scroll_id: Option<&u64>,
clip_id: Option<&u64>)
-> Option<ClipAndScrollInfo> {
if let Some(&sid) = scroll_id {
if let Some(&cid) = clip_id {
Some(ClipAndScrollInfo::new(
- ClipId::new(sid, state.pipeline_id),
+ ClipId::Clip(sid, state.pipeline_id),
ClipId::Clip(cid, state.pipeline_id)))
} else {
Some(ClipAndScrollInfo::simple(
- ClipId::new(sid, state.pipeline_id)))
+ ClipId::Clip(sid, state.pipeline_id)))
}
} else if let Some(&cid) = clip_id {
Some(ClipAndScrollInfo::simple(
ClipId::Clip(cid, state.pipeline_id)))
} else {
None
}
}
@@ -1487,20 +1487,20 @@ pub extern "C" fn wr_dp_define_clip(stat
unsafe { ancestor_scroll_id.as_ref() },
unsafe { ancestor_clip_id.as_ref() });
let complex_slice = make_slice(complex, complex_count);
let complex_iter = complex_slice.iter().cloned();
let mask : Option<ImageMask> = unsafe { mask.as_ref() }.map(|x| x.into());
let clip_id = if info.is_some() {
- state.frame_builder.dl_builder.define_clip_with_parent(None,
+ state.frame_builder.dl_builder.define_clip_with_parent(
info.unwrap().scroll_node_id, clip_rect, complex_iter, mask)
} else {
- state.frame_builder.dl_builder.define_clip(None, clip_rect, complex_iter, mask)
+ state.frame_builder.dl_builder.define_clip(clip_rect, complex_iter, mask)
};
// return the u64 id value from inside the ClipId::Clip(..)
match clip_id {
ClipId::Clip(id, pipeline_id) => {
assert!(pipeline_id == state.pipeline_id);
id
},
_ => panic!("Got unexpected clip id type"),
@@ -1528,17 +1528,17 @@ pub extern "C" fn wr_dp_define_sticky_fr
bottom_margin: *const f32,
left_margin: *const f32,
vertical_bounds: StickyOffsetBounds,
horizontal_bounds: StickyOffsetBounds,
applied_offset: LayoutVector2D)
-> u64 {
assert!(unsafe { is_in_main_thread() });
let clip_id = state.frame_builder.dl_builder.define_sticky_frame(
- None, content_rect, SideOffsets2D::new(
+ content_rect, SideOffsets2D::new(
unsafe { top_margin.as_ref() }.cloned(),
unsafe { right_margin.as_ref() }.cloned(),
unsafe { bottom_margin.as_ref() }.cloned(),
unsafe { left_margin.as_ref() }.cloned()
),
vertical_bounds, horizontal_bounds, applied_offset);
match clip_id {
ClipId::Clip(id, pipeline_id) => {
@@ -1550,40 +1550,59 @@ pub extern "C" fn wr_dp_define_sticky_fr
}
#[no_mangle]
pub extern "C" fn wr_dp_define_scroll_layer(state: &mut WrState,
scroll_id: u64,
ancestor_scroll_id: *const u64,
ancestor_clip_id: *const u64,
content_rect: LayoutRect,
- clip_rect: LayoutRect) {
+ clip_rect: LayoutRect)
+ -> u64 {
assert!(unsafe { is_in_main_thread() });
let info = make_scroll_info(state,
unsafe { ancestor_scroll_id.as_ref() },
unsafe { ancestor_clip_id.as_ref() });
- let clip_id = ClipId::new(scroll_id, state.pipeline_id);
- if info.is_some() {
+ let new_id = if info.is_some() {
state.frame_builder.dl_builder.define_scroll_frame_with_parent(
- Some(clip_id), info.unwrap().scroll_node_id, content_rect,
- clip_rect, vec![], None, ScrollSensitivity::Script);
+ info.unwrap().scroll_node_id,
+ Some(ExternalScrollId(scroll_id, state.pipeline_id)),
+ content_rect,
+ clip_rect,
+ vec![],
+ None,
+ ScrollSensitivity::Script
+ )
} else {
state.frame_builder.dl_builder.define_scroll_frame(
- Some(clip_id), content_rect, clip_rect, vec![], None,
- ScrollSensitivity::Script);
+ Some(ExternalScrollId(scroll_id, state.pipeline_id)),
+ content_rect,
+ clip_rect,
+ vec![],
+ None,
+ ScrollSensitivity::Script
+ )
};
+
+ match new_id {
+ ClipId::Clip(id, pipeline_id) => {
+ assert!(pipeline_id == state.pipeline_id);
+ id
+ },
+ _ => panic!("Got unexpected clip id type"),
+ }
}
#[no_mangle]
pub extern "C" fn wr_dp_push_scroll_layer(state: &mut WrState,
scroll_id: u64) {
debug_assert!(unsafe { is_in_main_thread() });
- let clip_id = ClipId::new(scroll_id, state.pipeline_id);
+ let clip_id = ClipId::Clip(scroll_id, state.pipeline_id);
state.frame_builder.dl_builder.push_clip_id(clip_id);
}
#[no_mangle]
pub extern "C" fn wr_dp_pop_scroll_layer(state: &mut WrState) {
debug_assert!(unsafe { is_in_main_thread() });
state.frame_builder.dl_builder.pop_clip_id();
}
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -1054,22 +1054,22 @@ uint64_t wr_dp_define_clip(WrState *aSta
const uint64_t *aAncestorClipId,
LayoutRect aClipRect,
const ComplexClipRegion *aComplex,
size_t aComplexCount,
const WrImageMask *aMask)
WR_FUNC;
WR_INLINE
-void wr_dp_define_scroll_layer(WrState *aState,
- uint64_t aScrollId,
- const uint64_t *aAncestorScrollId,
- const uint64_t *aAncestorClipId,
- LayoutRect aContentRect,
- LayoutRect aClipRect)
+uint64_t wr_dp_define_scroll_layer(WrState *aState,
+ uint64_t aScrollId,
+ const uint64_t *aAncestorScrollId,
+ const uint64_t *aAncestorClipId,
+ LayoutRect aContentRect,
+ LayoutRect aClipRect)
WR_FUNC;
WR_INLINE
uint64_t wr_dp_define_sticky_frame(WrState *aState,
LayoutRect aContentRect,
const float *aTopMargin,
const float *aRightMargin,
const float *aBottomMargin,