Bug 1178765 - Part 3: Add backdrop-filter display items to Gecko r=mstange

Differential Revision: https://phabricator.services.mozilla.com/D39099

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Connor Brewster 2019-08-13 22:02:57 +00:00
Родитель dbce0f3810
Коммит 04d4ece0af
40 изменённых файлов: 539 добавлений и 129 удалений

Просмотреть файл

@ -1039,6 +1039,25 @@ void DisplayListBuilder::PushClearRectWithComplexRegion(
&spaceAndClip);
}
void DisplayListBuilder::PushBackdropFilter(
const wr::LayoutRect& aBounds, const wr::ComplexClipRegion& aRegion,
const nsTArray<wr::FilterOp>& aFilters,
const nsTArray<wr::WrFilterData>& aFilterDatas, bool aIsBackfaceVisible) {
wr::LayoutRect clip = MergeClipLeaf(aBounds);
WRDL_LOG("PushBackdropFilter b=%s c=%s\n", mWrState,
Stringify(aBounds).c_str(), Stringify(clip).c_str());
AutoTArray<wr::ComplexClipRegion, 1> clips;
clips.AppendElement(aRegion);
auto clipId = DefineClip(Nothing(), aBounds, &clips, nullptr);
auto spaceAndClip = WrSpaceAndClip{mCurrentSpaceAndClipChain.space, clipId};
wr_dp_push_backdrop_filter_with_parent_clip(
mWrState, aBounds, clip, aIsBackfaceVisible, &spaceAndClip,
aFilters.Elements(), aFilters.Length(), aFilterDatas.Elements(),
aFilterDatas.Length());
}
void DisplayListBuilder::PushLinearGradient(
const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
bool aIsBackfaceVisible, const wr::LayoutPoint& aStartPoint,

Просмотреть файл

@ -450,6 +450,12 @@ class DisplayListBuilder final {
void PushClearRectWithComplexRegion(const wr::LayoutRect& aBounds,
const wr::ComplexClipRegion& aRegion);
void PushBackdropFilter(const wr::LayoutRect& aBounds,
const wr::ComplexClipRegion& aRegion,
const nsTArray<wr::FilterOp>& aFilters,
const nsTArray<wr::WrFilterData>& aFilterDatas,
bool aIsBackfaceVisible);
void PushLinearGradient(const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
const wr::LayoutPoint& aStartPoint,

Просмотреть файл

@ -2432,6 +2432,60 @@ pub extern "C" fn wr_dp_push_rect_with_parent_clip(
);
}
#[no_mangle]
pub extern "C" fn wr_dp_push_backdrop_filter_with_parent_clip(
state: &mut WrState,
rect: LayoutRect,
clip: LayoutRect,
is_backface_visible: bool,
parent: &WrSpaceAndClip,
filters: *const FilterOp,
filter_count: usize,
filter_datas: *const WrFilterData,
filter_datas_count: usize,
) {
debug_assert!(unsafe { !is_in_render_thread() });
let c_filters = unsafe { make_slice(filters, filter_count) };
let filters : Vec<FilterOp> = c_filters.iter()
.map(|c_filter| { c_filter.clone() })
.collect();
let c_filter_datas = unsafe { make_slice(filter_datas, filter_datas_count) };
let filter_datas : Vec<FilterData> = c_filter_datas.iter().map(|c_filter_data| {
FilterData {
func_r_type: c_filter_data.funcR_type,
r_values: unsafe { make_slice(c_filter_data.R_values, c_filter_data.R_values_count).to_vec() },
func_g_type: c_filter_data.funcG_type,
g_values: unsafe { make_slice(c_filter_data.G_values, c_filter_data.G_values_count).to_vec() },
func_b_type: c_filter_data.funcB_type,
b_values: unsafe { make_slice(c_filter_data.B_values, c_filter_data.B_values_count).to_vec() },
func_a_type: c_filter_data.funcA_type,
a_values: unsafe { make_slice(c_filter_data.A_values, c_filter_data.A_values_count).to_vec() },
}
}).collect();
let space_and_clip = parent.to_webrender(state.pipeline_id);
let clip_rect = clip.intersection(&rect);
if clip_rect.is_none() { return; }
let prim_info = CommonItemProperties {
clip_rect: clip_rect.unwrap(),
clip_id: space_and_clip.clip_id,
spatial_id: space_and_clip.spatial_id,
is_backface_visible,
hit_info: state.current_tag,
};
state.frame_builder.dl_builder.push_backdrop_filter(
&prim_info,
&filters,
&filter_datas,
&[],
);
}
#[no_mangle]
pub extern "C" fn wr_dp_push_clear_rect(state: &mut WrState,
rect: LayoutRect,

Просмотреть файл

@ -2531,6 +2531,35 @@ inline static bool IsSVGContentWithCSSClip(const nsIFrame* aFrame) {
nsGkAtoms::foreignObject);
}
bool nsIFrame::FormsBackdropRoot(const nsStyleDisplay* aStyleDisplay,
const nsStyleEffects* aStyleEffects,
const nsStyleSVGReset* aStyleSVGReset) {
// Check if this is a root frame.
if (!GetParent()) {
return true;
}
// Check for filter effects.
if (aStyleEffects->HasFilters() || aStyleEffects->HasBackdropFilters() ||
aStyleEffects->HasMixBlendMode()) {
return true;
}
// Check for opacity.
if (HasOpacity(aStyleDisplay, aStyleEffects)) {
return true;
}
// Check for mask or clip path.
if (aStyleSVGReset->HasMask() || aStyleSVGReset->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 {
@ -3092,10 +3121,18 @@ void nsIFrame::BuildDisplayListForStackingContext(
}
}
bool usingFilter = StyleEffects()->HasFilters();
bool backdropFilterEnabled =
StaticPrefs::layout_css_backdrop_filter_enabled();
bool usingBackdropFilter =
backdropFilterEnabled && effects->HasBackdropFilters() &&
nsDisplayBackdropFilters::CanCreateWebRenderCommands(aBuilder, this);
bool usingFilter = effects->HasFilters();
bool usingMask = nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(this);
bool usingSVGEffects = usingFilter || usingMask;
bool formsBackdropRoot = backdropFilterEnabled &&
FormsBackdropRoot(disp, effects, StyleSVGReset());
nsRect visibleRectOutsideSVGEffects = visibleRect;
nsDisplayList hoistedScrollInfoItemsStorage;
if (usingSVGEffects) {
@ -3347,6 +3384,23 @@ void nsIFrame::BuildDisplayListForStackingContext(
ct.TrackContainer(resultList.GetTop());
}
if (formsBackdropRoot) {
DisplayListClipState::AutoSaveRestore backdropRootContainerClipState(
aBuilder);
resultList.AppendNewToTop<nsDisplayBackdropRootContainer>(
aBuilder, this, &resultList, containerItemASR);
ct.TrackContainer(resultList.GetTop());
}
if (usingBackdropFilter) {
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
nsRect backdropRect =
GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this);
resultList.AppendNewToTop<nsDisplayBackdropFilters>(
aBuilder, this, &resultList, backdropRect);
ct.TrackContainer(resultList.GetTop());
}
/* If there are any SVG effects, wrap the list up in an SVG effects item
* (which also handles CSS group opacity). Note that we create an SVG effects
* item even if resultList is empty, since a filter can produce graphical
@ -10779,7 +10833,8 @@ bool nsIFrame::IsStackingContext(const nsStyleDisplay* aStyleDisplay,
aStylePosition->mZIndex.IsInteger())) ||
(aStyleDisplay->mWillChange.bits &
StyleWillChangeBits_STACKING_CONTEXT) ||
aStyleDisplay->mIsolation != NS_STYLE_ISOLATION_AUTO;
aStyleDisplay->mIsolation != NS_STYLE_ISOLATION_AUTO ||
aStyleEffects->HasBackdropFilters();
}
bool nsIFrame::IsStackingContext() {

Просмотреть файл

@ -1808,6 +1808,14 @@ 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 nsStyleDisplay* aStyleDisplay,
const nsStyleEffects* aStyleEffects,
const nsStyleSVGReset* aStyleSvgReset);
/**
* Returns whether this frame will attempt to extend the 3d transforms of its
* children. This requires transform-style: preserve-3d, as well as no

Просмотреть файл

@ -7,6 +7,8 @@
DECLARE_DISPLAY_ITEM_TYPE(ALT_FEEDBACK, 0)
DECLARE_DISPLAY_ITEM_TYPE(ASYNC_ZOOM,
TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTAINER)
DECLARE_DISPLAY_ITEM_TYPE(BACKDROP_FILTER, TYPE_IS_CONTAINER)
DECLARE_DISPLAY_ITEM_TYPE(BACKDROP_ROOT_CONTAINER, TYPE_IS_CONTAINER)
DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND, TYPE_IS_CONTENTFUL)
DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND_COLOR, TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(BLEND_CONTAINER,

Просмотреть файл

@ -10188,6 +10188,185 @@ void nsDisplayMasksAndClipPaths::PrintEffects(nsACString& aTo) {
}
#endif
static float ClampStdDeviation(float aStdDeviation) {
// Cap software blur radius for performance reasons.
return std::min(std::max(0.0f, aStdDeviation), 100.0f);
}
static bool CreateWebRenderCSSFilters(Span<const StyleFilter> aFilters,
nsIFrame* aFrame,
WrFiltersHolder& aWrFilters) {
// All CSS filters are supported by WebRender. SVG filters are not fully
// supported, those use NS_STYLE_FILTER_URL and are handled separately.
// If there are too many filters to render, then just pretend that we
// succeeded, and don't render any of them.
if (aFilters.Length() >
StaticPrefs::gfx_webrender_max_filter_ops_per_chain()) {
return true;
}
aWrFilters.filters.SetCapacity(aFilters.Length());
auto& wrFilters = aWrFilters.filters;
for (const StyleFilter& filter : aFilters) {
switch (filter.tag) {
case StyleFilter::Tag::Brightness:
wrFilters.AppendElement(
wr::FilterOp::Brightness(filter.AsBrightness()));
break;
case StyleFilter::Tag::Contrast:
wrFilters.AppendElement(wr::FilterOp::Contrast(filter.AsContrast()));
break;
case StyleFilter::Tag::Grayscale:
wrFilters.AppendElement(wr::FilterOp::Grayscale(filter.AsGrayscale()));
break;
case StyleFilter::Tag::Invert:
wrFilters.AppendElement(wr::FilterOp::Invert(filter.AsInvert()));
break;
case StyleFilter::Tag::Opacity: {
float opacity = filter.AsOpacity();
wrFilters.AppendElement(wr::FilterOp::Opacity(
wr::PropertyBinding<float>::Value(opacity), opacity));
break;
}
case StyleFilter::Tag::Saturate:
wrFilters.AppendElement(wr::FilterOp::Saturate(filter.AsSaturate()));
break;
case StyleFilter::Tag::Sepia:
wrFilters.AppendElement(wr::FilterOp::Sepia(filter.AsSepia()));
break;
case StyleFilter::Tag::HueRotate: {
wrFilters.AppendElement(
wr::FilterOp::HueRotate(filter.AsHueRotate().ToDegrees()));
break;
}
case StyleFilter::Tag::Blur: {
// TODO(emilio): we should go directly from css pixels -> device pixels.
float appUnitsPerDevPixel =
aFrame->PresContext()->AppUnitsPerDevPixel();
wrFilters.AppendElement(mozilla::wr::FilterOp::Blur(
ClampStdDeviation(NSAppUnitsToFloatPixels(
filter.AsBlur().ToAppUnits(), appUnitsPerDevPixel))));
break;
}
case StyleFilter::Tag::DropShadow: {
float appUnitsPerDevPixel =
aFrame->PresContext()->AppUnitsPerDevPixel();
const StyleSimpleShadow& shadow = filter.AsDropShadow();
nscolor color = shadow.color.CalcColor(aFrame);
wr::Shadow wrShadow;
wrShadow.offset = {
NSAppUnitsToFloatPixels(shadow.horizontal.ToAppUnits(),
appUnitsPerDevPixel),
NSAppUnitsToFloatPixels(shadow.vertical.ToAppUnits(),
appUnitsPerDevPixel)};
wrShadow.blur_radius = NSAppUnitsToFloatPixels(shadow.blur.ToAppUnits(),
appUnitsPerDevPixel);
wrShadow.color = {NS_GET_R(color) / 255.0f, NS_GET_G(color) / 255.0f,
NS_GET_B(color) / 255.0f, NS_GET_A(color) / 255.0f};
wrFilters.AppendElement(wr::FilterOp::DropShadow(wrShadow));
break;
}
default:
return false;
}
}
return true;
}
already_AddRefed<Layer> nsDisplayBackdropRootContainer::BuildLayer(
nsDisplayListBuilder* aBuilder, LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) {
RefPtr<Layer> container = aManager->GetLayerBuilder()->BuildContainerLayerFor(
aBuilder, aManager, mFrame, this, &mList, aContainerParameters, nullptr);
if (!container) {
return nullptr;
}
return container.forget();
}
LayerState nsDisplayBackdropRootContainer::GetLayerState(
nsDisplayListBuilder* aBuilder, LayerManager* aManager,
const ContainerLayerParameters& aParameters) {
return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList,
GetAnimatedGeometryRoot());
}
bool nsDisplayBackdropRootContainer::CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) {
wr::StackingContextParams params;
params.is_backdrop_root = true;
params.clip =
wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId());
StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
params);
nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
aDisplayListBuilder);
return true;
}
/* static */
bool nsDisplayBackdropFilters::CanCreateWebRenderCommands(
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) {
WrFiltersHolder wrFilters;
Maybe<nsRect> filterClip;
auto filterChain = aFrame->StyleEffects()->mBackdropFilters.AsSpan();
return CreateWebRenderCSSFilters(filterChain, aFrame, wrFilters) ||
nsSVGIntegrationUtils::BuildWebRenderFilters(aFrame, filterChain,
wrFilters, filterClip);
}
bool nsDisplayBackdropFilters::CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) {
WrFiltersHolder wrFilters;
Maybe<nsRect> filterClip;
auto filterChain = mFrame->StyleEffects()->mBackdropFilters.AsSpan();
if (!CreateWebRenderCSSFilters(filterChain, mFrame, wrFilters) &&
!nsSVGIntegrationUtils::BuildWebRenderFilters(mFrame, filterChain,
wrFilters, filterClip)) {
return false;
}
nsCSSRendering::ImageLayerClipState clip;
nsCSSRendering::GetImageLayerClip(
mFrame->StyleBackground()->BottomLayer(), mFrame, *mFrame->StyleBorder(),
mBackdropRect, mBackdropRect, false,
mFrame->PresContext()->AppUnitsPerDevPixel(), &clip);
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
mBackdropRect, mFrame->PresContext()->AppUnitsPerDevPixel());
wr::LayoutRect roundedRect = wr::ToRoundedLayoutRect(bounds);
wr::ComplexClipRegion region =
wr::ToComplexClipRegion(clip.mBGClipArea, clip.mRadii,
mFrame->PresContext()->AppUnitsPerDevPixel());
aBuilder.PushBackdropFilter(roundedRect, region, wrFilters.filters,
wrFilters.filter_datas, !BackfaceIsHidden());
wr::StackingContextParams params;
params.clip =
wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId());
StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
params);
nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
aDisplayListBuilder);
return true;
}
/* static */
nsDisplayFilters::nsDisplayFilters(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayEffectsBase(aBuilder, aFrame, aList),
@ -10276,99 +10455,14 @@ void nsDisplayFilters::PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsDisplayFiltersGeometry::UpdateDrawResult(this, imgParams.result);
}
static float ClampStdDeviation(float aStdDeviation) {
// Cap software blur radius for performance reasons.
return std::min(std::max(0.0f, aStdDeviation), 100.0f);
}
bool nsDisplayFilters::CreateWebRenderCSSFilters(WrFiltersHolder& aWrFilters) {
// All CSS filters are supported by WebRender. SVG filters are not fully
// supported, those use NS_STYLE_FILTER_URL and are handled separately.
Span<const StyleFilter> filters = mFrame->StyleEffects()->mFilters.AsSpan();
// If there are too many filters to render, then just pretend that we
// succeeded, and don't render any of them.
if (filters.Length() >
StaticPrefs::gfx_webrender_max_filter_ops_per_chain()) {
return true;
}
aWrFilters.filters.SetCapacity(filters.Length());
auto& wrFilters = aWrFilters.filters;
for (const StyleFilter& filter : filters) {
switch (filter.tag) {
case StyleFilter::Tag::Brightness:
wrFilters.AppendElement(
wr::FilterOp::Brightness(filter.AsBrightness()));
break;
case StyleFilter::Tag::Contrast:
wrFilters.AppendElement(wr::FilterOp::Contrast(filter.AsContrast()));
break;
case StyleFilter::Tag::Grayscale:
wrFilters.AppendElement(wr::FilterOp::Grayscale(filter.AsGrayscale()));
break;
case StyleFilter::Tag::Invert:
wrFilters.AppendElement(wr::FilterOp::Invert(filter.AsInvert()));
break;
case StyleFilter::Tag::Opacity: {
float opacity = filter.AsOpacity();
wrFilters.AppendElement(wr::FilterOp::Opacity(
wr::PropertyBinding<float>::Value(opacity), opacity));
break;
}
case StyleFilter::Tag::Saturate:
wrFilters.AppendElement(wr::FilterOp::Saturate(filter.AsSaturate()));
break;
case StyleFilter::Tag::Sepia:
wrFilters.AppendElement(wr::FilterOp::Sepia(filter.AsSepia()));
break;
case StyleFilter::Tag::HueRotate: {
wrFilters.AppendElement(
wr::FilterOp::HueRotate(filter.AsHueRotate().ToDegrees()));
break;
}
case StyleFilter::Tag::Blur: {
// TODO(emilio): we should go directly from css pixels -> device pixels.
float appUnitsPerDevPixel =
mFrame->PresContext()->AppUnitsPerDevPixel();
wrFilters.AppendElement(mozilla::wr::FilterOp::Blur(
ClampStdDeviation(NSAppUnitsToFloatPixels(
filter.AsBlur().ToAppUnits(), appUnitsPerDevPixel))));
break;
}
case StyleFilter::Tag::DropShadow: {
float appUnitsPerDevPixel =
mFrame->PresContext()->AppUnitsPerDevPixel();
const StyleSimpleShadow& shadow = filter.AsDropShadow();
nscolor color = shadow.color.CalcColor(mFrame);
wr::Shadow wrShadow;
wrShadow.offset = {
NSAppUnitsToFloatPixels(shadow.horizontal.ToAppUnits(),
appUnitsPerDevPixel),
NSAppUnitsToFloatPixels(shadow.vertical.ToAppUnits(),
appUnitsPerDevPixel)};
wrShadow.blur_radius = NSAppUnitsToFloatPixels(shadow.blur.ToAppUnits(),
appUnitsPerDevPixel);
wrShadow.color = {NS_GET_R(color) / 255.0f, NS_GET_G(color) / 255.0f,
NS_GET_B(color) / 255.0f, NS_GET_A(color) / 255.0f};
wrFilters.AppendElement(wr::FilterOp::DropShadow(wrShadow));
break;
}
default:
return false;
}
}
return true;
}
bool nsDisplayFilters::CanCreateWebRenderCommands(
nsDisplayListBuilder* aBuilder) {
WrFiltersHolder wrFilters;
Maybe<nsRect> filterClip;
if (!CreateWebRenderCSSFilters(wrFilters) &&
!nsSVGIntegrationUtils::BuildWebRenderFilters(mFrame, wrFilters,
filterClip)) {
auto filterChain = mFrame->StyleEffects()->mFilters.AsSpan();
if (!CreateWebRenderCSSFilters(filterChain, mFrame, wrFilters) &&
!nsSVGIntegrationUtils::BuildWebRenderFilters(mFrame, filterChain,
wrFilters, filterClip)) {
return false;
}
return true;
@ -10384,9 +10478,10 @@ bool nsDisplayFilters::CreateWebRenderCommands(
WrFiltersHolder wrFilters;
Maybe<nsRect> filterClip;
if (!CreateWebRenderCSSFilters(wrFilters) &&
!nsSVGIntegrationUtils::BuildWebRenderFilters(mFrame, wrFilters,
filterClip)) {
auto filterChain = mFrame->StyleEffects()->mFilters.AsSpan();
if (!CreateWebRenderCSSFilters(filterChain, mFrame, wrFilters) &&
!nsSVGIntegrationUtils::BuildWebRenderFilters(mFrame, filterChain,
wrFilters, filterClip)) {
return false;
}

Просмотреть файл

@ -6688,6 +6688,77 @@ 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);
}
#ifdef NS_BUILD_REFCNT_LOGGING
~nsDisplayBackdropRootContainer() override {
MOZ_COUNT_DTOR(nsDisplayBackdropRootContainer);
}
#endif
NS_DISPLAY_DECL_NAME("BackdropRootContainer", TYPE_BACKDROP_ROOT_CONTAINER)
already_AddRefed<Layer> BuildLayer(
nsDisplayListBuilder* aBuilder, LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
LayerState GetLayerState(
nsDisplayListBuilder* aBuilder, LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
bool CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
return !aBuilder->IsPaintingForWebRender();
}
};
class nsDisplayBackdropFilters : public nsDisplayWrapList {
public:
nsDisplayBackdropFilters(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, const nsRect& aBackdropRect)
: nsDisplayWrapList(aBuilder, aFrame, aList),
mBackdropRect(aBackdropRect) {
MOZ_COUNT_CTOR(nsDisplayBackdropFilters);
}
#ifdef NS_BUILD_REFCNT_LOGGING
~nsDisplayBackdropFilters() override {
MOZ_COUNT_DTOR(nsDisplayBackdropFilters);
}
#endif
NS_DISPLAY_DECL_NAME("BackdropFilter", TYPE_BACKDROP_FILTER)
bool CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
static bool CanCreateWebRenderCommands(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame);
bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
return !aBuilder->IsPaintingForWebRender();
}
private:
nsRect mBackdropRect;
};
/**
* A display item to paint a stacking context with filter effects set by the
* stacking context root frame's style.
@ -6767,8 +6838,6 @@ class nsDisplayFilters : public nsDisplayEffectsBase {
nsDisplayListBuilder* aDisplayListBuilder) override;
bool CanCreateWebRenderCommands(nsDisplayListBuilder* aBuilder);
bool CreateWebRenderCSSFilters(WrFiltersHolder& wrFilters);
private:
NS_DISPLAY_ALLOW_CLONING()

Просмотреть файл

@ -3802,6 +3802,11 @@ nsChangeHint nsStyleEffects::CalcDifference(
hint |= nsChangeHint_RepaintFrame;
}
if (HasBackdropFilters() != aNewData.HasBackdropFilters()) {
// A change from/to being a containing block for position:fixed.
hint |= nsChangeHint_UpdateContainingBlock;
}
if (mBackdropFilters != aNewData.mBackdropFilters) {
hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
}

Просмотреть файл

@ -2376,6 +2376,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleEffects {
bool HasFilters() const { return !mFilters.IsEmpty(); }
bool HasBackdropFilters() const { return !mBackdropFilters.IsEmpty(); }
bool HasBoxShadowWithInset(bool aInset) const {
for (auto& shadow : mBoxShadow.AsSpan()) {
if (shadow.inset == aInset) {
@ -2385,6 +2387,10 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleEffects {
return false;
}
bool HasMixBlendMode() const {
return mMixBlendMode != NS_STYLE_BLEND_NORMAL;
}
mozilla::StyleOwnedSlice<mozilla::StyleFilter> mFilters;
mozilla::StyleOwnedSlice<mozilla::StyleBoxShadow> mBoxShadow;
mozilla::StyleOwnedSlice<mozilla::StyleFilter> mBackdropFilters;

Просмотреть файл

@ -135,7 +135,8 @@ bool nsStyleDisplay::IsFixedPosContainingBlockForNonSVGTextFrames(
return true;
}
return aStyle.StyleEffects()->HasFilters();
return aStyle.StyleEffects()->HasFilters() ||
aStyle.StyleEffects()->HasBackdropFilters();
}
bool nsStyleDisplay::

Просмотреть файл

@ -1706,7 +1706,8 @@ already_AddRefed<nsIURI> SVGObserverUtils::GetBaseURLForLocalRef(
already_AddRefed<URLAndReferrerInfo> SVGObserverUtils::GetFilterURI(
nsIFrame* aFrame, const StyleFilter& aFilter) {
MOZ_ASSERT(!aFrame->StyleEffects()->mFilters.IsEmpty());
MOZ_ASSERT(!aFrame->StyleEffects()->mFilters.IsEmpty() ||
!aFrame->StyleEffects()->mBackdropFilters.IsEmpty());
MOZ_ASSERT(aFilter.IsUrl());
return ResolveURLUsingLocalRef(aFrame, aFilter.AsUrl());
}

Просмотреть файл

@ -116,13 +116,13 @@ static mozilla::wr::ComponentTransferFuncType FuncTypeToWr(uint8_t aFuncType) {
}
bool nsFilterInstance::BuildWebRenderFilters(nsIFrame* aFilteredFrame,
Span<const StyleFilter> aFilters,
WrFiltersHolder& aWrFilters,
Maybe<nsRect>& aPostFilterClip) {
aWrFilters.filters.Clear();
aWrFilters.filter_datas.Clear();
aWrFilters.values.Clear();
auto filterChain = aFilteredFrame->StyleEffects()->mFilters.AsSpan();
UniquePtr<UserSpaceMetrics> metrics =
UserSpaceMetricsForFrame(aFilteredFrame);
@ -136,7 +136,7 @@ bool nsFilterInstance::BuildWebRenderFilters(nsIFrame* aFilteredFrame,
// read the rendered contents of aFilteredFrame.
bool inputIsTainted = true;
nsFilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(),
*metrics, filterChain, inputIsTainted, nullptr,
*metrics, aFilters, inputIsTainted, nullptr,
scaleMatrixInDevUnits, nullptr, nullptr, nullptr,
nullptr);

Просмотреть файл

@ -126,9 +126,10 @@ class nsFilterInstance {
* Try to build WebRender filters for a frame if the filters applied to it are
* supported.
*/
static bool BuildWebRenderFilters(nsIFrame* aFilteredFrame,
WrFiltersHolder& aWrFilters,
mozilla::Maybe<nsRect>& aPostFilterClip);
static bool BuildWebRenderFilters(
nsIFrame* aFilteredFrame,
mozilla::Span<const mozilla::StyleFilter> aFilters,
WrFiltersHolder& aWrFilters, mozilla::Maybe<nsRect>& aPostFilterClip);
private:
/**

Просмотреть файл

@ -160,8 +160,11 @@ bool nsSVGIntegrationUtils::UsingEffectsForFrame(const nsIFrame* aFrame) {
// checking the SDL prefs here, since we don't know if we're being called for
// painting or hit-testing anyway.
const nsStyleSVGReset* style = aFrame->StyleSVGReset();
return aFrame->StyleEffects()->HasFilters() || style->HasClipPath() ||
style->HasMask();
const nsStyleEffects* effects = aFrame->StyleEffects();
// TODO(cbrewster): remove backdrop-filter from this list once it is supported
// in preserve-3d cases.
return effects->HasFilters() || effects->HasBackdropFilters() ||
style->HasClipPath() || style->HasMask();
}
bool nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(
@ -1103,10 +1106,10 @@ void nsSVGIntegrationUtils::PaintFilter(const PaintFramesParams& aParams) {
}
bool nsSVGIntegrationUtils::BuildWebRenderFilters(
nsIFrame* aFilteredFrame, WrFiltersHolder& aWrFilters,
Maybe<nsRect>& aPostFilterClip) {
return nsFilterInstance::BuildWebRenderFilters(aFilteredFrame, aWrFilters,
aPostFilterClip);
nsIFrame* aFilteredFrame, Span<const StyleFilter> aFilters,
WrFiltersHolder& aWrFilters, Maybe<nsRect>& aPostFilterClip) {
return nsFilterInstance::BuildWebRenderFilters(aFilteredFrame, aFilters,
aWrFilters, aPostFilterClip);
}
class PaintFrameCallback : public gfxDrawingCallback {

Просмотреть файл

@ -209,9 +209,10 @@ class nsSVGIntegrationUtils final {
* Try to build WebRender filters for a frame if the filters applied to it are
* supported.
*/
static bool BuildWebRenderFilters(nsIFrame* aFilteredFrame,
WrFiltersHolder& aWrFilters,
mozilla::Maybe<nsRect>& aPostFilterClip);
static bool BuildWebRenderFilters(
nsIFrame* aFilteredFrame,
mozilla::Span<const mozilla::StyleFilter> aFilters,
WrFiltersHolder& aWrFilters, mozilla::Maybe<nsRect>& aPostFilterClip);
/**
* @param aRenderingContext the target rendering context in which the paint

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filter-basic-background-color.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=2426

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filter-basic-opacity-2.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=10894

Просмотреть файл

@ -0,0 +1,3 @@
[backdrop-filter-basic-opacity.html]
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=916

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filter-basic.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=2507

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filter-clipped.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=622

Просмотреть файл

@ -0,0 +1,3 @@
[backdrop-filter-edge-clipping.html]
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=5211

Просмотреть файл

@ -0,0 +1,3 @@
[backdrop-filter-edge-pixels.html]
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=3169

Просмотреть файл

@ -1,2 +1,4 @@
[backdrop-filter-fixed-clip.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filter-isolation-fixed.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=3623

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filter-isolation-isolate.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=3623

Просмотреть файл

@ -1,2 +1,4 @@
[backdrop-filter-isolation.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS

Просмотреть файл

@ -0,0 +1,3 @@
[backdrop-filter-paint-order.html]
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=5211

Просмотреть файл

@ -1,2 +1,4 @@
[backdrop-filter-plus-filter.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS

Просмотреть файл

@ -0,0 +1,3 @@
[backdrop-filter-plus-opacity.html]
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=625

Просмотреть файл

@ -0,0 +1,4 @@
[backdrop-filter-reference-filter.html]
expected:
if not webrender: PASS
if webrender: FAIL

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filter-update.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=622

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filters-brightness.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=2188

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filters-contrast.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=2029

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filters-grayscale.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=1508

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filters-hue-rotate.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=1942

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filters-invert.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=2029

Просмотреть файл

@ -0,0 +1,3 @@
[backdrop-filters-opacity.html]
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=1437

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filters-saturate.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=2206

Просмотреть файл

@ -1,2 +1,6 @@
[backdrop-filters-sepia.html]
expected: FAIL
expected:
if not webrender: FAIL
if webrender: PASS
fuzzy:
if os == "win" and webrender: maxDifference=92;totalPixels=1508