Backed out changeset b134d587690d (bug 1787623) for causing reftest failures on filter-basic-01.svg. CLOSED TREE

This commit is contained in:
Marian-Vasile Laza 2022-09-04 17:56:37 +03:00
Родитель 9f8436d1ca
Коммит 5907792df1
13 изменённых файлов: 137 добавлений и 176 удалений

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

@ -8246,20 +8246,25 @@ bool nsDisplayBackdropFilters::CreateWebRenderCommands(
const StackingContextHelper& aSc, RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) {
WrFiltersHolder wrFilters;
Maybe<nsRect> filterClip;
const ComputedStyle& style = mStyle ? *mStyle : *mFrame->Style();
auto filterChain = style.StyleEffects()->mBackdropFilters.AsSpan();
bool initialized = true;
if (!SVGIntegrationUtils::CreateWebRenderCSSFilters(filterChain, mFrame,
wrFilters) &&
!SVGIntegrationUtils::BuildWebRenderFilters(mFrame, filterChain,
wrFilters, initialized)) {
// TODO: If painting backdrop-filters on the content side is implemented,
// consider returning false to fall back to that.
wrFilters = {};
!SVGIntegrationUtils::BuildWebRenderFilters(
mFrame, filterChain, wrFilters, filterClip, initialized)) {
if (mStyle) {
// TODO(bug 1769223): Support fallback backdrop-filters in the root
// code-path.
return true;
}
return false;
}
if (!initialized) {
wrFilters = {};
// draw nothing
return true;
}
nsCSSRendering::ImageLayerClipState clip;
@ -8359,41 +8364,33 @@ bool nsDisplayFilters::CreateWebRenderCommands(
wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc, RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) {
float auPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
WrFiltersHolder wrFilters;
const ComputedStyle& style = mStyle ? *mStyle : *mFrame->Style();
auto filterChain = style.StyleEffects()->mFilters.AsSpan();
Maybe<nsRect> filterClip;
bool initialized = true;
auto filterChain = mStyle ? mStyle->StyleEffects()->mFilters.AsSpan()
: mFrame->StyleEffects()->mFilters.AsSpan();
if (!SVGIntegrationUtils::CreateWebRenderCSSFilters(filterChain, mFrame,
wrFilters) &&
!SVGIntegrationUtils::BuildWebRenderFilters(mFrame, filterChain,
wrFilters, initialized)) {
!SVGIntegrationUtils::BuildWebRenderFilters(
mFrame, filterChain, wrFilters, filterClip, initialized)) {
if (mStyle) {
// TODO(bug 1769223): Support fallback filters in the root code-path,
// perhaps. For now treat it the same way as invalid filters.
wrFilters = {};
} else {
// Draw using fallback.
return false;
// TODO(bug 1769223): Support fallback filters in the root code-path.
return true;
}
return false;
}
if (!initialized) {
// https://drafts.fxtf.org/filter-effects/#typedef-filter-url:
//
// If the filter references a non-existent object or the referenced object
// is not a filter element, then the whole filter chain is ignored. No
// filter is applied to the object.
//
// Note that other engines have a weird discrepancy between SVG and HTML
// content here, but the spec is clear.
wrFilters = {};
// draw nothing
return true;
}
uint64_t clipChainId;
if (wrFilters.post_filters_clip) {
if (filterClip) {
auto devPxRect = LayoutDeviceRect::FromAppUnits(
wrFilters.post_filters_clip.value() + ToReferenceFrame(),
mFrame->PresContext()->AppUnitsPerDevPixel());
filterClip.value() + ToReferenceFrame(), auPerDevPixel);
auto clipId =
aBuilder.DefineRectClip(Nothing(), wr::ToLayoutRect(devPxRect));
clipChainId = aBuilder.DefineClipChain({clipId}, true).id;

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

@ -8,5 +8,6 @@
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=407463 -->
<rect x="0%" y="0%" width="100%" height="100%" fill="lime" filter="url(#null)"/>
<rect x="0%" y="0%" width="100%" height="100%" fill="lime"/>
<rect x="0%" y="0%" width="100%" height="100%" fill="red" filter="url(#null)"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 363 B

После

Ширина:  |  Высота:  |  Размер: 426 B

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

@ -120,9 +120,10 @@ static mozilla::wr::ComponentTransferFuncType FuncTypeToWr(uint8_t aFuncType) {
bool FilterInstance::BuildWebRenderFilters(nsIFrame* aFilteredFrame,
Span<const StyleFilter> aFilters,
WrFiltersHolder& aWrFilters,
Maybe<nsRect>& aPostFilterClip,
bool& aInitialized) {
bool status = BuildWebRenderFiltersImpl(aFilteredFrame, aFilters, aWrFilters,
aInitialized);
aPostFilterClip, aInitialized);
if (!status) {
aFilteredFrame->PresContext()->Document()->SetUseCounter(
eUseCounter_custom_WrFilterFallback);
@ -134,6 +135,7 @@ bool FilterInstance::BuildWebRenderFilters(nsIFrame* aFilteredFrame,
bool FilterInstance::BuildWebRenderFiltersImpl(nsIFrame* aFilteredFrame,
Span<const StyleFilter> aFilters,
WrFiltersHolder& aWrFilters,
Maybe<nsRect>& aPostFilterClip,
bool& aInitialized) {
aWrFilters.filters.Clear();
aWrFilters.filter_datas.Clear();
@ -366,12 +368,36 @@ bool FilterInstance::BuildWebRenderFiltersImpl(nsIFrame* aFilteredFrame,
}
if (finalClip) {
aWrFilters.post_filters_clip =
Some(instance.FilterSpaceToFrameSpace(finalClip.value()));
aPostFilterClip = Some(instance.FilterSpaceToFrameSpace(finalClip.value()));
}
return true;
}
nsRegion FilterInstance::GetPostFilterDirtyArea(
nsIFrame* aFilteredFrame, const nsRegion& aPreFilterDirtyRegion) {
if (aPreFilterDirtyRegion.IsEmpty()) {
return nsRegion();
}
gfxMatrix tm = SVGUtils::GetCanvasTM(aFilteredFrame);
auto filterChain = aFilteredFrame->StyleEffects()->mFilters.AsSpan();
UniquePtr<UserSpaceMetrics> metrics =
UserSpaceMetricsForFrame(aFilteredFrame);
// Hardcode InputIsTainted to true because we don't want JS to be able to
// read the rendered contents of aFilteredFrame.
FilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(),
*metrics, filterChain, /* InputIsTainted */ true,
nullptr, tm, nullptr, &aPreFilterDirtyRegion);
if (!instance.IsInitialized()) {
return nsRegion();
}
// We've passed in the source's dirty area so the instance knows about it.
// Now we can ask the instance to compute the area of the filter output
// that's dirty.
return instance.ComputePostFilterDirtyRegion();
}
nsRegion FilterInstance::GetPreFilterNeededArea(
nsIFrame* aFilteredFrame, const nsRegion& aPostFilterDirtyRegion) {
gfxMatrix tm = SVGUtils::GetCanvasTM(aFilteredFrame);
@ -392,8 +418,8 @@ nsRegion FilterInstance::GetPreFilterNeededArea(
return instance.ComputeSourceNeededRect();
}
Maybe<nsRect> FilterInstance::GetPostFilterBounds(
nsIFrame* aFilteredFrame, const gfxRect* aOverrideBBox,
nsRect FilterInstance::GetPostFilterBounds(nsIFrame* aFilteredFrame,
const gfxRect* aOverrideBBox,
const nsRect* aPreFilterBounds) {
MOZ_ASSERT(!aFilteredFrame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT) ||
!aFilteredFrame->HasAnyStateBits(NS_FRAME_IS_NONDISPLAY),
@ -417,10 +443,10 @@ Maybe<nsRect> FilterInstance::GetPostFilterBounds(
nullptr, tm, nullptr, preFilterRegionPtr,
aPreFilterBounds, aOverrideBBox);
if (!instance.IsInitialized()) {
return Nothing();
return nsRect();
}
return Some(instance.ComputePostFilterExtents());
return instance.ComputePostFilterExtents();
}
FilterInstance::FilterInstance(

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

@ -123,8 +123,8 @@ class FilterInstance {
* @param aPreFilterBounds The pre-filter ink overflow rect of
* aFilteredFrame, if non-null.
*/
static Maybe<nsRect> GetPostFilterBounds(
nsIFrame* aFilteredFrame, const gfxRect* aOverrideBBox = nullptr,
static nsRect GetPostFilterBounds(nsIFrame* aFilteredFrame,
const gfxRect* aOverrideBBox = nullptr,
const nsRect* aPreFilterBounds = nullptr);
/**
@ -136,7 +136,8 @@ class FilterInstance {
static bool BuildWebRenderFilters(
nsIFrame* aFilteredFrame,
mozilla::Span<const mozilla::StyleFilter> aFilters,
WrFiltersHolder& aWrFilters, bool& aInitialized);
WrFiltersHolder& aWrFilters, mozilla::Maybe<nsRect>& aPostFilterClip,
bool& aInitialized);
private:
/**
@ -177,7 +178,8 @@ class FilterInstance {
static bool BuildWebRenderFiltersImpl(
nsIFrame* aFilteredFrame,
mozilla::Span<const mozilla::StyleFilter> aFilters,
WrFiltersHolder& aWrFilters, bool& aInitialized);
WrFiltersHolder& aWrFilters, mozilla::Maybe<nsRect>& aPostFilterClip,
bool& aInitialized);
/**
* Returns true if the filter instance was created successfully.

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

@ -391,17 +391,54 @@ nsRect SVGIntegrationUtils::ComputePostEffectsInkOverflowRect(
AppUnitsPerCSSPixel());
overrideBBox.RoundOut();
Maybe<nsRect> overflowRect =
nsRect overflowRect =
FilterInstance::GetPostFilterBounds(firstFrame, &overrideBBox);
if (!overflowRect) {
return aPreEffectsOverflowRect;
}
// Return overflowRect relative to aFrame, rather than "user space":
return overflowRect.value() -
return overflowRect -
(aFrame->GetOffsetTo(firstFrame) + firstFrameToBoundingBox);
}
nsIntRegion SVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(
nsIFrame* aFrame, const nsPoint& aToReferenceFrame,
const nsIntRegion& aInvalidRegion) {
if (aInvalidRegion.IsEmpty()) {
return nsIntRect();
}
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
// If we have any filters to observe then we should have started doing that
// during reflow/ComputeFrameEffectsRect, so we use GetFiltersIfObserving
// here to avoid needless work (or masking bugs by setting up observers at
// the wrong time).
if (!aFrame->StyleEffects()->HasFilters() ||
SVGObserverUtils::GetFiltersIfObserving(firstFrame, nullptr) ==
SVGObserverUtils::eHasRefsSomeInvalid) {
return aInvalidRegion;
}
int32_t appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
// Convert aInvalidRegion into bounding box frame space in app units:
nsPoint toBoundingBox =
aFrame->GetOffsetTo(firstFrame) + GetOffsetToBoundingBox(firstFrame);
// The initial rect was relative to the reference frame, so we need to
// remove that offset to get a rect relative to the current frame.
toBoundingBox -= aToReferenceFrame;
nsRegion preEffectsRegion =
aInvalidRegion.ToAppUnits(appUnitsPerDevPixel).MovedBy(toBoundingBox);
// Adjust the dirty area for effects, and shift it back to being relative to
// the reference frame.
nsRegion result =
FilterInstance::GetPostFilterDirtyArea(firstFrame, preEffectsRegion)
.MovedBy(-toBoundingBox);
// Return the result, in pixels relative to the reference frame.
return result.ToOutsidePixels(appUnitsPerDevPixel);
}
nsRect SVGIntegrationUtils::GetRequiredSourceForInvalidArea(
nsIFrame* aFrame, const nsRect& aDirtyRect) {
nsIFrame* firstFrame =
@ -1084,17 +1121,20 @@ bool SVGIntegrationUtils::CreateWebRenderCSSFilters(
bool SVGIntegrationUtils::BuildWebRenderFilters(
nsIFrame* aFilteredFrame, Span<const StyleFilter> aFilters,
WrFiltersHolder& aWrFilters, bool& aInitialized) {
return FilterInstance::BuildWebRenderFilters(aFilteredFrame, aFilters,
aWrFilters, aInitialized);
WrFiltersHolder& aWrFilters, Maybe<nsRect>& aPostFilterClip,
bool& aInitialized) {
return FilterInstance::BuildWebRenderFilters(
aFilteredFrame, aFilters, aWrFilters, aPostFilterClip, aInitialized);
}
bool SVGIntegrationUtils::CanCreateWebRenderFiltersForFrame(nsIFrame* aFrame) {
WrFiltersHolder wrFilters;
Maybe<nsRect> filterClip;
auto filterChain = aFrame->StyleEffects()->mFilters.AsSpan();
bool initialized = true;
return CreateWebRenderCSSFilters(filterChain, aFrame, wrFilters) ||
BuildWebRenderFilters(aFrame, filterChain, wrFilters, initialized);
BuildWebRenderFilters(aFrame, filterChain, wrFilters, filterClip,
initialized);
}
bool SVGIntegrationUtils::UsesSVGEffectsNotSupportedInCompositor(

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

@ -25,7 +25,6 @@ struct nsSize;
struct WrFiltersHolder {
nsTArray<mozilla::wr::FilterOp> filters;
nsTArray<mozilla::wr::WrFilterData> filter_datas;
mozilla::Maybe<nsRect> post_filters_clip;
// This exists just to own the values long enough for them to be copied into
// rust.
nsTArray<nsTArray<float>> values;
@ -116,6 +115,22 @@ class SVGIntegrationUtils final {
static nsRect ComputePostEffectsInkOverflowRect(
nsIFrame* aFrame, const nsRect& aPreEffectsOverflowRect);
/**
* Used to adjust the area of a frame that needs to be invalidated to take
* account of SVG effects.
*
* @param aFrame The effects frame.
* @param aToReferenceFrame The offset (in app units) from aFrame to its
* reference display item.
* @param aInvalidRegion The pre-effects invalid region in pixels relative to
* the reference display item.
* @return The post-effects invalid rect in pixels relative to the reference
* display item.
*/
static nsIntRegion AdjustInvalidAreaForSVGEffects(
nsIFrame* aFrame, const nsPoint& aToReferenceFrame,
const nsIntRegion& aInvalidRegion);
/**
* Figure out which area of the source is needed given an area to
* repaint
@ -208,6 +223,7 @@ class SVGIntegrationUtils final {
static bool BuildWebRenderFilters(nsIFrame* aFilteredFrame,
Span<const StyleFilter> aFilters,
WrFiltersHolder& aWrFilters,
Maybe<nsRect>& aPostFilterClip,
bool& aInitialized);
/**

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

@ -127,8 +127,7 @@ nsRect SVGUtils::GetPostFilterInkOverflowRect(nsIFrame* aFrame,
return aPreFilterRect;
}
return FilterInstance::GetPostFilterBounds(aFrame, nullptr, &aPreFilterRect)
.valueOr(aPreFilterRect);
return FilterInstance::GetPostFilterBounds(aFrame, nullptr, &aPreFilterRect);
}
bool SVGUtils::OuterSVGIsCallingReflowSVG(nsIFrame* aFrame) {

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

@ -0,0 +1,2 @@
[effect-reference-delete.html]
expected: FAIL

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

@ -1,25 +0,0 @@
<!doctype html>
<meta charset="utf-8">
<title>Invalid backdrop-filter doesn't cause element to disappear</title>
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty">
<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#typedef-filter-value-list">
<link rel="match" href="filter-invalid-ref.html">
<style>
div, rect {
width: 100px;
height: 100px;
backdrop-filter: url(#not-found);
}
div {
background-color: blue;
}
rect {
fill: purple;
}
</style>
<div></div>
<svg>
<rect></rect>
</svg>

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

@ -1,27 +0,0 @@
<!doctype html>
<meta charset="utf-8">
<title>Maybe-unsupported backdrop-filter doesn't cause element to disappear</title>
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="help" href="https://drafts.fxtf.org/filter-effects/#BackdropFilterProperty">
<link rel="mismatch" href="/css/reference/blank.html">
<style>
div {
width: 100px;
height: 100px;
border: 5px solid green;
backdrop-filter: url(#from-svg);
}
</style>
<div></div>
<svg>
<defs>
<filter id="from-svg">
<feGaussianBlur in="BackgroundImage" stdDeviation="20" result="blur" />
<feMerge>
<feMergeNode in="SourceGraphic" />
<feMergeNode in="blur" />
</feMerge>
</filter>
</defs>
</svg>

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

@ -1,19 +0,0 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS Test Reference</title>
<style>
div, rect {
width: 100px;
height: 100px;
}
div {
background-color: blue;
}
rect {
fill: purple;
}
</style>
<div></div>
<svg>
<rect></rect>
</svg>

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

@ -1,24 +0,0 @@
<!doctype html>
<meta charset="utf-8">
<title>Invalid filter draws unfiltered frame</title>
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="help" href="https://drafts.fxtf.org/filter-effects/#typedef-filter-url">
<link rel="match" href="filter-invalid-ref.html">
<style>
div, rect {
width: 100px;
height: 100px;
filter: url(#not-found);
}
div {
background-color: blue;
}
rect {
fill: purple;
}
</style>
<div></div>
<svg>
<rect></rect>
</svg>

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

@ -1,27 +0,0 @@
<!doctype html>
<meta charset="utf-8">
<title>Unsupported filter draws unfiltered frame</title>
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="help" href="https://drafts.fxtf.org/filter-effects/#FilterProperty">
<link rel="mismatch" href="/css/reference/blank.html">
<style>
div {
width: 100px;
height: 100px;
border: 5px solid green;
filter: url(#from-svg);
}
</style>
<div></div>
<svg>
<defs>
<filter id="from-svg">
<feGaussianBlur in="BackgroundImage" stdDeviation="20" result="blur" />
<feMerge>
<feMergeNode in="SourceGraphic" />
<feMergeNode in="blur" />
</feMerge>
</filter>
</defs>
</svg>