Bug 1768986 - Remove nsDisplayBackdropRoot r=gfx-reviewers,lsalzman

It's not possible to implement backdrop-filter with gecko adding
explicit boundaries for backdrop roots, since backdrop filters
can sample from a backdrop in a parent iframe. In this case, the
parent display list (in one process) doesn't see a backdrop filter,
so no root display item is added, even if there is a child display
list (in another process) that has a backdrop-filter.

This patch just removes the existing backdrop-filter root display
items from Gecko. A follow up patch will add implicit backdrop
root handling inside WR itself, where we have access to all of the
display lists.

Differential Revision: https://phabricator.services.mozilla.com/D146148
This commit is contained in:
Glenn Watson 2022-05-15 22:42:22 +00:00
parent cebe610723
commit 63d7dcbcd1
5 changed files with 1 additions and 218 deletions

View File

@ -3693,41 +3693,6 @@ class MOZ_RAII AutoContainsBlendModeCapturer {
}
};
// This is an equivalent to the AutoContainsBlendModeCapturer helper class
// above but for backdrop filters.
class MOZ_RAII AutoContainsBackdropFilterCapturer {
nsDisplayListBuilder& mBuilder;
bool mSavedContainsBackdropFilter;
public:
explicit AutoContainsBackdropFilterCapturer(nsDisplayListBuilder& aBuilder)
: mBuilder(aBuilder),
mSavedContainsBackdropFilter(aBuilder.ContainsBackdropFilter()) {
mBuilder.SetContainsBackdropFilter(false);
}
bool CaptureContainsBackdropFilter() {
// "Capture" the flag by extracting and clearing the ContainsBackdropFilter
// flag on the builder.
bool capturedBackdropFilter = mBuilder.ContainsBackdropFilter();
mBuilder.SetContainsBackdropFilter(false);
return capturedBackdropFilter;
}
~AutoContainsBackdropFilterCapturer() {
// If CaptureContainsBackdropFilter() was called, the descendant filter was
// "captured" and so uncapturedContainsBackdropFilter will be false. If
// CaptureContainsBackdropFilter() wasn't called, then no capture occurred,
// and uncapturedContainsBackdropFilter may be true if there was a
// descendant filter. In that case, we set the flag on the DL builder so
// that we restore state to what it would have been without this RAII class
// on the stack.
bool uncapturedContainsBackdropFilter = mBuilder.ContainsBackdropFilter();
mBuilder.SetContainsBackdropFilter(mSavedContainsBackdropFilter ||
uncapturedContainsBackdropFilter);
}
};
// Finds the max z-index of the items in aList that meet the following
// conditions
// 1) have z-index auto or z-index >= 0.
@ -3947,7 +3912,6 @@ void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsDisplayListCollection set(aBuilder);
AutoContainsBlendModeCapturer blendCapture(*aBuilder);
AutoContainsBackdropFilterCapturer backdropFilterCapture(*aBuilder);
bool willBuildAsyncZoomContainer =
mWillBuildScrollableLayer && aBuilder->ShouldBuildAsyncZoomContainer() &&
@ -4191,7 +4155,6 @@ void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
if (rootStyleFrame->StyleEffects()->HasBackdropFilters() &&
rootStyleFrame->IsVisibleForPainting()) {
SerializeList();
aBuilder->SetContainsBackdropFilter(true);
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
nsRect backdropRect = mOuter->GetRectRelativeToSelf() +
aBuilder->ToReferenceFrame(mOuter);
@ -4238,31 +4201,6 @@ void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
}
if (backdropFilterCapture.CaptureContainsBackdropFilter()) {
// The async zoom contents contain a backdrop-filter, so let's wrap all
// those contents into a backdrop root container, and then wrap the
// backdrop container in the async zoom container. Otherwise the
// backdrop-root container ends up outside the zoom container which
// results in blend failure for WebRender.
rootResultList.AppendNewToTop<nsDisplayBackdropRootContainer>(
aBuilder, mOuter, &rootResultList,
aBuilder->CurrentActiveScrolledRoot());
// Backdrop root containers can be created or omitted during partial
// updates depending on the dirty rect. So we basically can't do partial
// updates if there's a backdrop root container involved. There is
// equivalent code to this in the BuildDisplayListForStackingContext
// function as well, with a more detailed comment explaining things
// better.
if (aBuilder->IsRetainingDisplayList()) {
if (aBuilder->IsPartialUpdate()) {
aBuilder->SetPartialBuildFailed(true);
} else {
aBuilder->SetDisablePartialUpdates(true);
}
}
}
mozilla::layers::FrameMetrics::ViewID viewID =
nsLayoutUtils::FindOrCreateIDFor(mScrolledFrame->GetContent());

View File

@ -2651,41 +2651,6 @@ inline static bool IsSVGContentWithCSSClip(const nsIFrame* aFrame) {
nsGkAtoms::foreignObject);
}
bool nsIFrame::FormsBackdropRoot() const {
// Check if this is a root frame.
if (!GetParent()) {
return true;
}
const auto& style = *Style();
const auto& effects = *style.StyleEffects();
// Check for filter effects.
if (!style.IsRootElementStyle()) {
if (effects.HasFilters() || effects.HasBackdropFilters()) {
return true;
}
}
if (effects.HasMixBlendMode()) {
return true;
}
// Check for opacity.
const auto& disp = *style.StyleDisplay();
if (HasOpacity(&disp, &effects)) {
return true;
}
// Check for mask or clip path.
const auto& svgReset = *style.StyleSVGReset();
if (svgReset.HasMask() || svgReset.HasClipPath()) {
return true;
}
// TODO(cbrewster): Check will-change attributes
return false;
}
Maybe<nsRect> nsIFrame::GetClipPropClipRect(const nsStyleDisplay* aDisp,
const nsStyleEffects* aEffects,
const nsSize& aSize) const {
@ -2849,30 +2814,6 @@ class AutoSaveRestoreContainsBlendMode {
}
};
class AutoSaveRestoreContainsBackdropFilter {
nsDisplayListBuilder& mBuilder;
bool mSavedContainsBackdropFilter;
public:
explicit AutoSaveRestoreContainsBackdropFilter(nsDisplayListBuilder& aBuilder)
: mBuilder(aBuilder),
mSavedContainsBackdropFilter(aBuilder.ContainsBackdropFilter()) {}
/**
* This is called if a stacking context which does not form a backdrop root
* contains a descendent with a backdrop filter. In this case we need to
* delegate backdrop root creation to the next parent in the tree until we hit
* the nearest backdrop root ancestor.
*/
void DelegateUp(bool aContainsBackdropFilter) {
mSavedContainsBackdropFilter = aContainsBackdropFilter;
}
~AutoSaveRestoreContainsBackdropFilter() {
mBuilder.SetContainsBackdropFilter(mSavedContainsBackdropFilter);
}
};
static void CheckForApzAwareEventHandlers(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame) {
if (aBuilder->GetAncestorHasApzAwareEventHandler()) {
@ -3236,12 +3177,6 @@ void nsIFrame::BuildDisplayListForStackingContext(
bool usingBackdropFilter = effects->HasBackdropFilters() &&
IsVisibleForPainting() &&
!style.IsRootElementStyle();
if (usingBackdropFilter) {
aBuilder->SetContainsBackdropFilter(true);
}
AutoSaveRestoreContainsBackdropFilter autoRestoreBackdropFilter(*aBuilder);
aBuilder->SetContainsBackdropFilter(false);
nsRect visibleRectOutsideTransform = visibleRect;
nsDisplayTransform::PrerenderInfo prerenderInfo;
@ -3444,7 +3379,6 @@ void nsIFrame::BuildDisplayListForStackingContext(
nsDisplayListCollection set(aBuilder);
Maybe<nsRect> clipForMask;
bool insertBackdropRoot;
{
DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
nsDisplayListBuilder::AutoInTransformSetter inTransformSetter(aBuilder,
@ -3490,9 +3424,6 @@ void nsIFrame::BuildDisplayListForStackingContext(
aBuilder->Check();
aBuilder->DisplayCaret(this, set.Outlines());
insertBackdropRoot =
aBuilder->ContainsBackdropFilter() && FormsBackdropRoot();
// Blend modes are a real pain for retained display lists. We build a blend
// container item if the built list contains any blend mode items within
// the current stacking context. This can change without an invalidation
@ -3511,7 +3442,7 @@ void nsIFrame::BuildDisplayListForStackingContext(
// to remove any existing content that isn't wrapped in the blend container,
// and then we need to build content infront/behind the blend container
// to get correct positioning during merging.
if ((insertBackdropRoot || aBuilder->ContainsBlendMode()) &&
if ((aBuilder->ContainsBlendMode()) &&
aBuilder->IsRetainingDisplayList()) {
if (aBuilder->IsPartialUpdate()) {
aBuilder->SetPartialBuildFailed(true);
@ -3521,13 +3452,6 @@ void nsIFrame::BuildDisplayListForStackingContext(
}
}
// If a child contains a backdrop filter, but this stacking context does not
// form a backdrop root, we need to propogate up the tree until we find an
// ancestor that does form a backdrop root.
if (!insertBackdropRoot && aBuilder->ContainsBackdropFilter()) {
autoRestoreBackdropFilter.DelegateUp(true);
}
if (aBuilder->IsBackgroundOnly()) {
set.BlockBorderBackgrounds()->DeleteAll(aBuilder);
set.Floats()->DeleteAll(aBuilder);
@ -3579,14 +3503,6 @@ void nsIFrame::BuildDisplayListForStackingContext(
createdContainer = true;
}
if (insertBackdropRoot) {
DisplayListClipState::AutoSaveRestore backdropRootContainerClipState(
aBuilder);
resultList.AppendNewToTop<nsDisplayBackdropRootContainer>(
aBuilder, this, &resultList, containerItemASR);
createdContainer = true;
}
if (usingBackdropFilter) {
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
nsRect backdropRect =

View File

@ -1951,12 +1951,6 @@ class nsIFrame : public nsQueryFrame {
virtual bool IsSVGTransformed(Matrix* aOwnTransforms = nullptr,
Matrix* aFromParentTransforms = nullptr) const;
/**
* Return true if this frame should form a backdrop root container.
* See: https://drafts.fxtf.org/filter-effects-2/#BackdropRootTriggers
*/
bool FormsBackdropRoot() const;
/**
* Returns whether this frame will attempt to extend the 3d transforms of its
* children. This requires transform-style: preserve-3d, as well as no

View File

@ -693,7 +693,6 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mPartialBuildFailed(false),
mIsInActiveDocShell(false),
mBuildAsyncZoomContainer(false),
mContainsBackdropFilter(false),
mIsRelativeToLayoutViewport(false),
mUseOverlayScrollbars(false),
mAlwaysLayerizeScrollbars(false) {
@ -8272,30 +8271,6 @@ void nsDisplayMasksAndClipPaths::PrintEffects(nsACString& aTo) {
}
#endif
void nsDisplayBackdropRootContainer::Paint(nsDisplayListBuilder* aBuilder,
gfxContext* aCtx) {
aCtx->GetDrawTarget()->PushLayer(false, 1.0, nullptr, gfx::Matrix());
GetChildren()->Paint(aBuilder, aCtx,
mFrame->PresContext()->AppUnitsPerDevPixel());
aCtx->GetDrawTarget()->PopLayer();
}
bool nsDisplayBackdropRootContainer::CreateWebRenderCommands(
wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc, RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) {
wr::StackingContextParams params;
params.flags |= wr::StackingContextFlags::IS_BACKDROP_ROOT;
params.clip =
wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId());
StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
params);
nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
aDisplayListBuilder);
return true;
}
bool nsDisplayBackdropFilters::CreateWebRenderCommands(
wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc, RenderRootStateManager* aManager,

View File

@ -1490,17 +1490,6 @@ class nsDisplayListBuilder {
}
bool ContainsBlendMode() const { return mContainsBlendMode; }
/**
* mContainsBackdropFilter is true if we proccessed a display item that
* has a backdrop filter set. We track this so we can insert a
* nsDisplayBackdropRootContainer in the stacking context of the nearest
* ancestor that forms a backdrop root.
*/
void SetContainsBackdropFilter(bool aContainsBackdropFilter) {
mContainsBackdropFilter = aContainsBackdropFilter;
}
bool ContainsBackdropFilter() const { return mContainsBackdropFilter; }
DisplayListClipState& ClipState() { return mClipState; }
const ActiveScrolledRoot* CurrentActiveScrolledRoot() {
return mCurrentActiveScrolledRoot;
@ -1918,7 +1907,6 @@ class nsDisplayListBuilder {
bool mPartialBuildFailed;
bool mIsInActiveDocShell;
bool mBuildAsyncZoomContainer;
bool mContainsBackdropFilter;
bool mIsRelativeToLayoutViewport;
bool mUseOverlayScrollbars;
bool mAlwaysLayerizeScrollbars;
@ -5946,34 +5934,6 @@ class nsDisplayMasksAndClipPaths : public nsDisplayEffectsBase {
nsTArray<nsRect> mDestRects;
};
class nsDisplayBackdropRootContainer : public nsDisplayWrapList {
public:
nsDisplayBackdropRootContainer(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot)
: nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot, true) {
MOZ_COUNT_CTOR(nsDisplayBackdropRootContainer);
}
MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropRootContainer)
NS_DISPLAY_DECL_NAME("BackdropRootContainer", TYPE_BACKDROP_ROOT_CONTAINER)
void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
bool CreateWebRenderCommands(
wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
layers::RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
return !aBuilder->IsPaintingForWebRender();
}
bool CreatesStackingContextHelper() override { return true; }
};
class nsDisplayBackdropFilters : public nsDisplayWrapList {
public:
nsDisplayBackdropFilters(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,