зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1765525 - Fix gecko DL creation for backdrop-filters with clips r=gfx-reviewers,lsalzman
Change to derive from nsDisplayEffectsBase, since the backdrop-filter can still have a visual bounds (and effect) even if the child stacking context has no items. Also use the same approach to get the bounding rect and implement GetBounds as nsDisplayFilters uses. Differential Revision: https://phabricator.services.mozilla.com/D145295
This commit is contained in:
Родитель
2d73405522
Коммит
7dfd66fe8a
|
@ -2225,7 +2225,21 @@ impl<'a> SceneBuilder<'a> {
|
|||
return;
|
||||
}
|
||||
|
||||
let stacking_context = self.sc_stack.pop().unwrap();
|
||||
let mut stacking_context = self.sc_stack.pop().unwrap();
|
||||
|
||||
// If this stacking context has requested that clip masks get applied
|
||||
// to individual child elements, remove the blit reason. Since the picture
|
||||
// will still exist as a pass-through with a clip-chain, that clip
|
||||
// will be applied implicitly to the primitive inside the stacking
|
||||
// context. It's required for correctness for backdrop-filters
|
||||
// that have a clip-mask applied to them. In this case, Gecko supplies
|
||||
// a surrounding stacking context with clip-mask, which WR thinks is
|
||||
// the backdrop root without this optimization. In future, we should
|
||||
// change the way Geck supplies clip-masks on primitives so that this
|
||||
// isn't necessary.
|
||||
if stacking_context.flags.contains(StackingContextFlags::APPLY_CLIPS_TO_ITEMS) {
|
||||
stacking_context.blit_reason = BlitReason::empty();
|
||||
}
|
||||
|
||||
// If the stacking context is a blend container, and if we're at the top level
|
||||
// of the stacking context tree, we can make this blend container into a tile
|
||||
|
|
|
@ -948,6 +948,9 @@ bitflags! {
|
|||
/// If true, this stacking context is a blend container than contains
|
||||
/// mix-blend-mode children (and should thus be isolated).
|
||||
const IS_BLEND_CONTAINER = 1 << 1;
|
||||
/// If true, apply clip masks from this stacking context to individual items
|
||||
/// instead of the overall stacking context
|
||||
const APPLY_CLIPS_TO_ITEMS = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
root:
|
||||
items:
|
||||
- type: rect
|
||||
bounds: 0 0 256 256
|
||||
color: red
|
||||
- type: rect
|
||||
bounds: 64 64 128 128
|
||||
color: cyan
|
|
@ -0,0 +1,25 @@
|
|||
# Ensure that a backdrop-filter enclosed by a stacking context with
|
||||
# a clip-mask can select the correct backdrop root
|
||||
---
|
||||
root:
|
||||
items:
|
||||
- type: clip
|
||||
bounds: [64, 64, 128, 128]
|
||||
id: 2
|
||||
image-mask:
|
||||
image: solid-color(255,255,255,255,128,128)
|
||||
rect: [64, 64, 128, 128]
|
||||
repeat: false
|
||||
- type: stacking-context
|
||||
backdrop-root: true
|
||||
items:
|
||||
- type: rect
|
||||
bounds: 0 0 256 256
|
||||
color: red
|
||||
- type: stacking-context
|
||||
clip-node: 2
|
||||
apply-clips-to-items: true
|
||||
items:
|
||||
- type: backdrop-filter
|
||||
bounds: 0 0 256 256
|
||||
filters: invert(1)
|
|
@ -64,6 +64,7 @@ fuzzy(1,1) platform(linux,mac) == svg-filter-drop-shadow-perspective.yaml svg-fi
|
|||
#== backdrop-filter-basic.yaml backdrop-filter-basic-ref.yaml
|
||||
#platform(linux,mac) == backdrop-filter-perspective.yaml backdrop-filter-perspective.png
|
||||
#== backdrop-filter-on-child-surface.yaml backdrop-filter-on-child-surface-ref.yaml
|
||||
#== backdrop-filter-clip-mask.yaml backdrop-filter-clip-mask-ref.yaml
|
||||
#platform(linux,mac) == backdrop-filter-across-tiles.yaml backdrop-filter-across-tiles.png
|
||||
#platform(linux,mac) == backdrop-filter-chain.yaml backdrop-filter-chain.png
|
||||
#platform(linux,mac) == backdrop-filter-overlap.yaml backdrop-filter-overlap.png
|
||||
|
|
|
@ -2026,6 +2026,7 @@ impl YamlFrameReader {
|
|||
.unwrap_or(RasterSpace::Screen);
|
||||
let is_backdrop_root = yaml["backdrop-root"].as_bool().unwrap_or(false);
|
||||
let is_blend_container = yaml["blend-container"].as_bool().unwrap_or(false);
|
||||
let apply_clips_to_items = yaml["apply-clips-to-items"].as_bool().unwrap_or(false);
|
||||
|
||||
if is_root {
|
||||
if let Some(vector) = yaml["scroll-offset"].as_vector() {
|
||||
|
@ -2047,6 +2048,7 @@ impl YamlFrameReader {
|
|||
let mut flags = StackingContextFlags::empty();
|
||||
flags.set(StackingContextFlags::IS_BACKDROP_ROOT, is_backdrop_root);
|
||||
flags.set(StackingContextFlags::IS_BLEND_CONTAINER, is_blend_container);
|
||||
flags.set(StackingContextFlags::APPLY_CLIPS_TO_ITEMS, apply_clips_to_items);
|
||||
|
||||
dl.push_stacking_context(
|
||||
bounds.min,
|
||||
|
|
|
@ -3601,10 +3601,8 @@ void nsIFrame::BuildDisplayListForStackingContext(
|
|||
|
||||
if (usingBackdropFilter) {
|
||||
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
|
||||
nsRect backdropRect =
|
||||
GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this);
|
||||
resultList.AppendNewToTop<nsDisplayBackdropFilters>(
|
||||
aBuilder, this, &resultList, backdropRect);
|
||||
resultList.AppendNewToTop<nsDisplayBackdropFilters>(aBuilder, this,
|
||||
&resultList);
|
||||
ct.TrackContainer(resultList.GetTop());
|
||||
}
|
||||
|
||||
|
@ -3646,7 +3644,7 @@ void nsIFrame::BuildDisplayListForStackingContext(
|
|||
: containerItemASR;
|
||||
/* List now emptied, so add the new list to the top. */
|
||||
resultList.AppendNewToTop<nsDisplayMasksAndClipPaths>(
|
||||
aBuilder, this, &resultList, maskASR);
|
||||
aBuilder, this, &resultList, maskASR, usingBackdropFilter);
|
||||
ct.TrackContainer(resultList.GetTop());
|
||||
}
|
||||
|
||||
|
|
|
@ -7853,8 +7853,9 @@ static void ComputeMaskGeometry(PaintFramesParams& aParams) {
|
|||
|
||||
nsDisplayMasksAndClipPaths::nsDisplayMasksAndClipPaths(
|
||||
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList,
|
||||
const ActiveScrolledRoot* aActiveScrolledRoot)
|
||||
: nsDisplayEffectsBase(aBuilder, aFrame, aList, aActiveScrolledRoot, true) {
|
||||
const ActiveScrolledRoot* aActiveScrolledRoot, bool aApplyClipToChildren)
|
||||
: nsDisplayEffectsBase(aBuilder, aFrame, aList, aActiveScrolledRoot, true),
|
||||
mApplyClipToChildren(aApplyClipToChildren) {
|
||||
MOZ_COUNT_CTOR(nsDisplayMasksAndClipPaths);
|
||||
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
|
@ -8195,6 +8196,9 @@ bool nsDisplayMasksAndClipPaths::CreateWebRenderCommands(
|
|||
wr::StackingContextParams params;
|
||||
params.clip = wr::WrStackingContextClip::ClipId(*clip);
|
||||
params.opacity = opacity.ptrOr(nullptr);
|
||||
if (mApplyClipToChildren) {
|
||||
params.flags |= wr::StackingContextFlags::APPLY_CLIPS_TO_ITEMS;
|
||||
}
|
||||
layer.emplace(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder, params,
|
||||
bounds);
|
||||
sc = layer.ptr();
|
||||
|
@ -8317,20 +8321,23 @@ bool nsDisplayBackdropFilters::CreateWebRenderCommands(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool snap;
|
||||
nsRect bounds = GetBounds(aDisplayListBuilder, &snap);
|
||||
|
||||
nsCSSRendering::ImageLayerClipState clip;
|
||||
nsCSSRendering::GetImageLayerClip(
|
||||
mFrame->StyleBackground()->BottomLayer(), mFrame, *mFrame->StyleBorder(),
|
||||
mBackdropRect, mBackdropRect, false,
|
||||
mFrame->PresContext()->AppUnitsPerDevPixel(), &clip);
|
||||
bounds, bounds, false, mFrame->PresContext()->AppUnitsPerDevPixel(),
|
||||
&clip);
|
||||
|
||||
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
|
||||
mBackdropRect, mFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
LayoutDeviceRect deviceBounds = LayoutDeviceRect::FromAppUnits(
|
||||
bounds, mFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
|
||||
wr::ComplexClipRegion region =
|
||||
wr::ToComplexClipRegion(clip.mBGClipArea, clip.mRadii,
|
||||
mFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
|
||||
aBuilder.PushBackdropFilter(wr::ToLayoutRect(bounds), region,
|
||||
aBuilder.PushBackdropFilter(wr::ToLayoutRect(deviceBounds), region,
|
||||
wrFilters.filters, wrFilters.filter_datas,
|
||||
!BackfaceIsHidden());
|
||||
|
||||
|
@ -8340,8 +8347,8 @@ bool nsDisplayBackdropFilters::CreateWebRenderCommands(
|
|||
StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
|
||||
params);
|
||||
|
||||
nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
|
||||
aDisplayListBuilder);
|
||||
nsDisplayEffectsBase::CreateWebRenderCommands(aBuilder, aResources, sc,
|
||||
aManager, aDisplayListBuilder);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -5871,11 +5871,13 @@ class nsDisplayMasksAndClipPaths : public nsDisplayEffectsBase {
|
|||
public:
|
||||
nsDisplayMasksAndClipPaths(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList,
|
||||
const ActiveScrolledRoot* aActiveScrolledRoot);
|
||||
const ActiveScrolledRoot* aActiveScrolledRoot,
|
||||
bool aApplyClipToChildren);
|
||||
nsDisplayMasksAndClipPaths(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayMasksAndClipPaths& aOther)
|
||||
: nsDisplayEffectsBase(aBuilder, aOther),
|
||||
mDestRects(aOther.mDestRects.Clone()) {
|
||||
mDestRects(aOther.mDestRects.Clone()),
|
||||
mApplyClipToChildren(aOther.mApplyClipToChildren) {
|
||||
MOZ_COUNT_CTOR(nsDisplayMasksAndClipPaths);
|
||||
}
|
||||
|
||||
|
@ -5940,6 +5942,7 @@ class nsDisplayMasksAndClipPaths : public nsDisplayEffectsBase {
|
|||
NS_DISPLAY_ALLOW_CLONING()
|
||||
|
||||
nsTArray<nsRect> mDestRects;
|
||||
bool mApplyClipToChildren;
|
||||
};
|
||||
|
||||
class nsDisplayBackdropRootContainer : public nsDisplayWrapList {
|
||||
|
@ -5970,12 +5973,12 @@ class nsDisplayBackdropRootContainer : public nsDisplayWrapList {
|
|||
bool CreatesStackingContextHelper() override { return true; }
|
||||
};
|
||||
|
||||
class nsDisplayBackdropFilters : public nsDisplayWrapList {
|
||||
class nsDisplayBackdropFilters : public nsDisplayEffectsBase {
|
||||
public:
|
||||
nsDisplayBackdropFilters(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList, const nsRect& aBackdropRect)
|
||||
: nsDisplayWrapList(aBuilder, aFrame, aList),
|
||||
mBackdropRect(aBackdropRect) {
|
||||
nsDisplayList* aList)
|
||||
: nsDisplayEffectsBase(aBuilder, aFrame, aList),
|
||||
mBounds(aFrame->GetPaddingRectRelativeToSelf()) {
|
||||
MOZ_COUNT_CTOR(nsDisplayBackdropFilters);
|
||||
}
|
||||
|
||||
|
@ -5997,10 +6000,16 @@ class nsDisplayBackdropFilters : public nsDisplayWrapList {
|
|||
return !aBuilder->IsPaintingForWebRender();
|
||||
}
|
||||
|
||||
nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override {
|
||||
*aSnap = false;
|
||||
|
||||
return mBounds + ToReferenceFrame();
|
||||
}
|
||||
|
||||
bool CreatesStackingContextHelper() override { return true; }
|
||||
|
||||
private:
|
||||
nsRect mBackdropRect;
|
||||
nsRect mBounds;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче