Bug 1386483 - Set clip for each item in layers-free mode. r=kats
MozReview-Commit-ID: 3rYKLTyHAlM
--- a/gfx/layers/wr/ScrollingLayersHelper.cpp
+++ b/gfx/layers/wr/ScrollingLayersHelper.cpp
@@ -16,16 +16,17 @@ namespace mozilla {
namespace layers {
ScrollingLayersHelper::ScrollingLayersHelper(WebRenderLayer* aLayer,
wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aStackingContext)
: mLayer(aLayer)
, mBuilder(&aBuilder)
, mPushedLayerLocalClip(false)
+ , mItem(nullptr)
{
if (!mLayer->WrManager()->AsyncPanZoomEnabled()) {
// If APZ is disabled then we don't need to push the scrolling clips. We
// still want to push the layer's local clip though.
PushLayerLocalClip(aStackingContext);
return;
}
@@ -102,16 +103,34 @@ ScrollingLayersHelper::ScrollingLayersHe
Maybe<wr::WrClipId> clipId = mBuilder->TopmostClipId();
// Default to 0 if there is no ancestor, because 0 refers to the root scrollframe.
mBuilder->PushClipAndScrollInfo(scrollsWith.valueOr(0), clipId.ptrOr(nullptr));
} else {
PushLayerLocalClip(aStackingContext);
}
}
+ScrollingLayersHelper::ScrollingLayersHelper(nsDisplayItem* aItem,
+ wr::DisplayListBuilder& aBuilder,
+ const StackingContextHelper& aStackingContext)
+ : mLayer(nullptr)
+ , mBuilder(&aBuilder)
+ , mPushedLayerLocalClip(false)
+ , mItem(aItem)
+{
+ const DisplayItemClip& itemClip = aItem->GetClip();
+ if (itemClip.HasClip()) {
+ int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
+ LayerRect clip = ViewAs<LayerPixel>(
+ LayoutDeviceRect::FromAppUnits(itemClip.GetClipRect(), appUnitsPerDevPixel),
+ PixelCastJustification::MovingDownToChildren);
+ aBuilder.PushClip(aStackingContext.ToRelativeLayoutRect(clip), nullptr);
+ }
+}
+
void
ScrollingLayersHelper::PushLayerLocalClip(const StackingContextHelper& aStackingContext)
{
Layer* layer = mLayer->GetLayer();
Maybe<ParentLayerRect> clip;
if (const Maybe<ParentLayerIntRect>& rect = layer->GetClipRect()) {
clip = Some(IntRectToRect(rect.ref()));
} else if (layer->GetMaskLayer()) {
@@ -141,16 +160,25 @@ ScrollingLayersHelper::PushLayerClip(con
// TODO: check this transform is correct in all cases
mask = maskWrLayer->RenderMaskLayer(aSc, maskLayer->GetTransform());
}
mBuilder->PushClip(aSc.ToRelativeLayoutRect(clipRect), mask.ptrOr(nullptr));
}
ScrollingLayersHelper::~ScrollingLayersHelper()
{
+ if (mItem) {
+ // For layers-free mode;
+ const DisplayItemClip& itemClip = mItem->GetClip();
+ if (itemClip.HasClip()) {
+ mBuilder->PopClip();
+ }
+ return;
+ }
+
Layer* layer = mLayer->GetLayer();
if (!mLayer->WrManager()->AsyncPanZoomEnabled()) {
if (mPushedLayerLocalClip) {
mBuilder->PopClip();
}
return;
}
--- a/gfx/layers/wr/ScrollingLayersHelper.h
+++ b/gfx/layers/wr/ScrollingLayersHelper.h
@@ -21,24 +21,28 @@ class StackingContextHelper;
class WebRenderLayer;
class MOZ_RAII ScrollingLayersHelper
{
public:
ScrollingLayersHelper(WebRenderLayer* aLayer,
wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc);
+ ScrollingLayersHelper(nsDisplayItem* aItem,
+ wr::DisplayListBuilder& aBuilder,
+ const StackingContextHelper& aStackingContext);
~ScrollingLayersHelper();
private:
void PushLayerLocalClip(const StackingContextHelper& aStackingContext);
void PushLayerClip(const LayerClip& aClip,
const StackingContextHelper& aSc);
WebRenderLayer* mLayer;
wr::DisplayListBuilder* mBuilder;
bool mPushedLayerLocalClip;
+ nsDisplayItem* mItem;
};
} // namespace layers
} // namespace mozilla
#endif
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -260,19 +260,22 @@ WebRenderLayerManager::CreateWebRenderCo
// walking up their ASR chain when building scroll metadata.
if (forceNewLayerData) {
mAsrStack.push_back(asr);
}
}
// Note: this call to CreateWebRenderCommands can recurse back into
// this function if the |item| is a wrapper for a sublist.
- if (!item->CreateWebRenderCommands(aBuilder, aSc, mParentCommands, this,
- aDisplayListBuilder)) {
- PushItemAsImage(item, aBuilder, aSc, aDisplayListBuilder);
+ {
+ ScrollingLayersHelper clip(item, aBuilder, aSc);
+ if (!item->CreateWebRenderCommands(aBuilder, aSc, mParentCommands, this,
+ aDisplayListBuilder)) {
+ PushItemAsImage(item, aBuilder, aSc, aDisplayListBuilder);
+ }
}
if (apzEnabled && forceNewLayerData) {
// Pop the thing we pushed before the recursion, so the topmost item on
// the stack is enclosing display item's ASR (or the stack is empty)
mAsrStack.pop_back();
const ActiveScrolledRoot* stopAtAsr =
mAsrStack.empty() ? nullptr : mAsrStack.back();