Skip to content
Permalink
Browse files
[GPU Process] (REGRESSION r285597): Set the filterRegion of the CSSFi…
…lter after it is created

https://bugs.webkit.org/show_bug.cgi?id=233849

Reviewed by Cameron McCormack.

Source/WebCore:

In this patch:

1. sourceImageRect is no longer passed as an argument to SVGFilter. It
   should be passed only when SVGFilter::apply() is called.

2. CSSFilter::create() will create and build the FilterFunctions from the
   FilterOperations. So we have to pass the targetBoundingBox since the
   FilterEffects will need it when calculating the outsets.

3. The steps in RenderLayerFilters::beginFilterEffect() are:
   a) Recreate the CSSFilter if the targetBoundingBox changes.
   b) Calculate the filterRegion = targetBoundingBox + outsets
   c) Clamp the filterRegion if needed. This will change the filterScale.
   d) Set sourceImageRect = filterRegion.
   e) Recreate the sourceImage if needed.
   f) setup the context for drawing the target renderer.

4. Managing the targetBoundingBox and the filterRegion is moved from
   CSSFilter to RenderLayerFilters.

* css/CSSFilterImageValue.cpp:
(WebCore::CSSFilterImageValue::image):
* platform/graphics/filters/Filter.cpp:
(WebCore::Filter::Filter):
* platform/graphics/filters/Filter.h:
(WebCore::Filter::Filter):
* rendering/CSSFilter.cpp:
(WebCore::CSSFilter::create):
(WebCore::CSSFilter::CSSFilter):
(WebCore::createSVGFilter):
(WebCore::CSSFilter::buildFilterFunctions):
(WebCore::CSSFilter::apply):
(WebCore::CSSFilter::setFilterRegion):
(WebCore::m_hasFilterThatShouldBeRestrictedBySecurityOrigin): Deleted.
(WebCore::CSSFilter::updateBackingStoreRect): Deleted.
(WebCore::CSSFilter::computeSourceImageRectForDirtyRect): Deleted.
(WebCore::CSSFilter::setSourceImageRect): Deleted.
* rendering/CSSFilter.h:
* rendering/RenderLayerFilters.cpp:
(WebCore::RenderLayerFilters::buildFilter):
(WebCore::RenderLayerFilters::allocateBackingStoreIfNeeded):
(WebCore::RenderLayerFilters::beginFilterEffect):
(WebCore::RenderLayerFilters::applyFilterEffect):
(WebCore::RenderLayerFilters::allocateBackingStore): Deleted.
* rendering/RenderLayerFilters.h:
* rendering/svg/RenderSVGResourceFilter.cpp:
(WebCore::RenderSVGResourceFilter::applyResource):
* rendering/svg/SVGRenderTreeAsText.cpp:
(WebCore::writeSVGResourceContainer):
* svg/graphics/filters/SVGFilter.cpp:
(WebCore::SVGFilter::create):
(WebCore::SVGFilter::SVGFilter):
* svg/graphics/filters/SVGFilter.h:

LayoutTests:

Unskip layout tests which were skipped in r285597.

* TestExpectations:



Canonical link: https://commits.webkit.org/244878@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@286546 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
shallawa committed Dec 6, 2021
1 parent cc3580d commit f27a530614db21c6de91b3803ac54187dac6e731
Showing 14 changed files with 162 additions and 118 deletions.
@@ -1,3 +1,14 @@
2021-12-06 Said Abou-Hallawa <said@apple.com>

[GPU Process] (REGRESSION r285597): Set the filterRegion of the CSSFilter after it is created
https://bugs.webkit.org/show_bug.cgi?id=233849

Reviewed by Cameron McCormack.

Unskip layout tests which were skipped in r285597.

* TestExpectations:

2021-12-04 Antoine Quint <graouts@webkit.org>

CSS animation sorting may crash due to AnimationList copy upon CSS Animation removal
@@ -5163,19 +5163,3 @@ imported/blink/http/tests/plugins [ Skip ]
imported/blink/plugins [ Skip ]
js/dom/reflect-set-onto-dom.html [ Skip ]
userscripts/user-script-plugin-document.html [ Skip ]

# These filter related failures should be fixed once webkit.org/b/232705 is resolved
webkit.org/b/232705 compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html [ Skip ]
webkit.org/b/232705 compositing/filters/sw-shadow-overlaps-hw-layer.html [ Skip ]
webkit.org/b/232705 compositing/filters/sw-shadow-overlaps-hw-shadow.html [ Skip ]
webkit.org/b/232705 css3/filters/effect-reference-delete.html [ Skip ]
webkit.org/b/232705 css3/filters/svg-blur-filter-clipped.html [ Skip ]
webkit.org/b/232705 fast/filter-image/background-filter-image.html [ Skip ]
webkit.org/b/232705 fast/filter-image/filter-image-blur.html [ Skip ]
webkit.org/b/232705 fast/filter-image/filter-image-svg.html [ Skip ]
webkit.org/b/232705 fast/filter-image/filter-image.html [ Skip ]
webkit.org/b/232705 imported/mozilla/svg/dynamic-filter-contents-01a.svg [ Skip ]
webkit.org/b/232705 imported/mozilla/svg/filters/feComposite-2.svg [ Skip ]
webkit.org/b/232705 imported/mozilla/svg/filters/feSpecularLighting-1.svg [ Skip ]
webkit.org/b/232705 svg/custom/resources-css-scaled.html [ Skip ]
webkit.org/b/232705 svg/filters/feLighting-clipped.svg [ Skip ]
@@ -1,3 +1,63 @@
2021-12-06 Said Abou-Hallawa <said@apple.com>
[GPU Process] (REGRESSION r285597): Set the filterRegion of the CSSFilter after it is created
https://bugs.webkit.org/show_bug.cgi?id=233849

Reviewed by Cameron McCormack.

In this patch:

1. sourceImageRect is no longer passed as an argument to SVGFilter. It
should be passed only when SVGFilter::apply() is called.

2. CSSFilter::create() will create and build the FilterFunctions from the
FilterOperations. So we have to pass the targetBoundingBox since the
FilterEffects will need it when calculating the outsets.

3. The steps in RenderLayerFilters::beginFilterEffect() are:
a) Recreate the CSSFilter if the targetBoundingBox changes.
b) Calculate the filterRegion = targetBoundingBox + outsets
c) Clamp the filterRegion if needed. This will change the filterScale.
d) Set sourceImageRect = filterRegion.
e) Recreate the sourceImage if needed.
f) setup the context for drawing the target renderer.

4. Managing the targetBoundingBox and the filterRegion is moved from
CSSFilter to RenderLayerFilters.

* css/CSSFilterImageValue.cpp:
(WebCore::CSSFilterImageValue::image):
* platform/graphics/filters/Filter.cpp:
(WebCore::Filter::Filter):
* platform/graphics/filters/Filter.h:
(WebCore::Filter::Filter):
* rendering/CSSFilter.cpp:
(WebCore::CSSFilter::create):
(WebCore::CSSFilter::CSSFilter):
(WebCore::createSVGFilter):
(WebCore::CSSFilter::buildFilterFunctions):
(WebCore::CSSFilter::apply):
(WebCore::CSSFilter::setFilterRegion):
(WebCore::m_hasFilterThatShouldBeRestrictedBySecurityOrigin): Deleted.
(WebCore::CSSFilter::updateBackingStoreRect): Deleted.
(WebCore::CSSFilter::computeSourceImageRectForDirtyRect): Deleted.
(WebCore::CSSFilter::setSourceImageRect): Deleted.
* rendering/CSSFilter.h:
* rendering/RenderLayerFilters.cpp:
(WebCore::RenderLayerFilters::buildFilter):
(WebCore::RenderLayerFilters::allocateBackingStoreIfNeeded):
(WebCore::RenderLayerFilters::beginFilterEffect):
(WebCore::RenderLayerFilters::applyFilterEffect):
(WebCore::RenderLayerFilters::allocateBackingStore): Deleted.
* rendering/RenderLayerFilters.h:
* rendering/svg/RenderSVGResourceFilter.cpp:
(WebCore::RenderSVGResourceFilter::applyResource):
* rendering/svg/SVGRenderTreeAsText.cpp:
(WebCore::writeSVGResourceContainer):
* svg/graphics/filters/SVGFilter.cpp:
(WebCore::SVGFilter::create):
(WebCore::SVGFilter::SVGFilter):
* svg/graphics/filters/SVGFilter.h:

2021-12-06 Alex Christensen <achristensen@webkit.org>

WKWebpagePreferences._activeContentRuleListActionPatterns should be an NSDictionary of identifier to allowed patterns
@@ -124,12 +124,12 @@ RefPtr<Image> CSSFilterImageValue::image(RenderElement& renderer, const FloatSiz
auto sourceImageRect = FloatRect { { }, size };
sourceImage->context().drawImage(*image, sourceImageRect);

auto cssFilter = CSSFilter::create(m_filterOperations, renderingMode);

cssFilter->setSourceImageRect(sourceImageRect);
if (!cssFilter->buildFilterFunctions(renderer, m_filterOperations))
auto cssFilter = CSSFilter::create(renderer, m_filterOperations, renderingMode, FloatSize { 1, 1 }, Filter::ClipOperation::Intersect, sourceImageRect);
if (!cssFilter)
return &Image::nullImage();

cssFilter->setFilterRegion(sourceImageRect);

if (auto image = sourceImage->filteredImage(*cssFilter))
return image;

@@ -32,21 +32,12 @@

namespace WebCore {

Filter::Filter(Filter::Type filterType, RenderingMode renderingMode, const FloatSize& filterScale, ClipOperation clipOperation)
Filter::Filter(Filter::Type filterType, RenderingMode renderingMode, const FloatSize& filterScale, ClipOperation clipOperation, const FloatRect& filterRegion)
: FilterFunction(filterType)
, m_renderingMode(renderingMode)
, m_filterScale(filterScale)
, m_clipOperation(clipOperation)
{
}

Filter::Filter(Filter::Type filterType, RenderingMode renderingMode, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, ClipOperation clipOperation)
: FilterFunction(filterType)
, m_renderingMode(renderingMode)
, m_filterScale(filterScale)
, m_sourceImageRect(sourceImageRect)
, m_filterRegion(filterRegion)
, m_clipOperation(clipOperation)
{
}

@@ -77,19 +77,17 @@ class Filter : public FilterFunction {

protected:
using FilterFunction::FilterFunction;
Filter(Filter::Type, RenderingMode, const FloatSize& filterScale, ClipOperation = ClipOperation::Intersect);
Filter(Filter::Type, RenderingMode, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, ClipOperation = ClipOperation::Intersect);
Filter(Filter::Type, RenderingMode, const FloatSize& filterScale, ClipOperation, const FloatRect& filterRegion = { });

private:
RenderingMode m_renderingMode;

FloatSize m_filterScale;
FloatRect m_sourceImageRect;
ClipOperation m_clipOperation;
FloatRect m_filterRegion;

// FIXME: these should not be members of Filter. They should be passed to Filter::apply().
FloatRect m_sourceImageRect;
RefPtr<ImageBuffer> m_sourceImage;

ClipOperation m_clipOperation;
};

} // namespace WebCore
@@ -44,21 +44,26 @@

namespace WebCore {

RefPtr<CSSFilter> CSSFilter::create(const FilterOperations& operations, RenderingMode renderingMode, float scaleFactor, ClipOperation clipOperation)
RefPtr<CSSFilter> CSSFilter::create(RenderElement& renderer, const FilterOperations& operations, RenderingMode renderingMode, const FloatSize& filterScale, ClipOperation clipOperation, const FloatRect& targetBoundingBox)
{
bool hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels();
bool hasFilterThatShouldBeRestrictedBySecurityOrigin = operations.hasFilterThatShouldBeRestrictedBySecurityOrigin();

return adoptRef(*new CSSFilter(renderingMode, scaleFactor, clipOperation, hasFilterThatMovesPixels, hasFilterThatShouldBeRestrictedBySecurityOrigin));
auto filter = adoptRef(*new CSSFilter(renderingMode, filterScale, clipOperation, hasFilterThatMovesPixels, hasFilterThatShouldBeRestrictedBySecurityOrigin));

if (!filter->buildFilterFunctions(renderer, operations, targetBoundingBox))
return nullptr;

return filter;
}

RefPtr<CSSFilter> CSSFilter::create(Vector<Ref<FilterFunction>>&& functions)
{
return adoptRef(new CSSFilter(WTFMove(functions)));
}

CSSFilter::CSSFilter(RenderingMode renderingMode, float scaleFactor, ClipOperation clipOperation, bool hasFilterThatMovesPixels, bool hasFilterThatShouldBeRestrictedBySecurityOrigin)
: Filter(Filter::Type::CSSFilter, renderingMode, FloatSize { scaleFactor, scaleFactor }, clipOperation)
CSSFilter::CSSFilter(RenderingMode renderingMode, const FloatSize& filterScale, ClipOperation clipOperation, bool hasFilterThatMovesPixels, bool hasFilterThatShouldBeRestrictedBySecurityOrigin)
: Filter(Filter::Type::CSSFilter, renderingMode, filterScale, clipOperation)
, m_hasFilterThatMovesPixels(hasFilterThatMovesPixels)
, m_hasFilterThatShouldBeRestrictedBySecurityOrigin(hasFilterThatShouldBeRestrictedBySecurityOrigin)
{
@@ -213,7 +218,7 @@ static RefPtr<FilterEffect> createSepiaEffect(const BasicColorMatrixFilterOperat
return FEColorMatrix::create(FECOLORMATRIX_TYPE_MATRIX, WTFMove(inputParameters));
}

static RefPtr<SVGFilter> createSVGFilter(CSSFilter& filter, const ReferenceFilterOperation& filterOperation, RenderElement& renderer, FilterEffect& previousEffect)
static RefPtr<SVGFilter> createSVGFilter(CSSFilter& filter, const ReferenceFilterOperation& filterOperation, RenderElement& renderer, const FloatRect& targetBoundingBox, FilterEffect& previousEffect)
{
auto& referencedSVGResources = renderer.ensureReferencedSVGResources();
auto* filterElement = referencedSVGResources.referencedFilterElement(renderer.document(), filterOperation);
@@ -227,10 +232,10 @@ static RefPtr<SVGFilter> createSVGFilter(CSSFilter& filter, const ReferenceFilte
}

SVGFilterBuilder builder;
return SVGFilter::create(*filterElement, builder, filter.renderingMode(), filter.filterScale(), filter.sourceImageRect(), filter.filterRegion(), filter.clipOperation(), previousEffect);
return SVGFilter::create(*filterElement, builder, filter.renderingMode(), filter.filterScale(), filter.clipOperation(), targetBoundingBox, previousEffect);
}

bool CSSFilter::buildFilterFunctions(RenderElement& renderer, const FilterOperations& operations)
bool CSSFilter::buildFilterFunctions(RenderElement& renderer, const FilterOperations& operations, const FloatRect& targetBoundingBox)
{
m_functions.clear();
m_outsets = { };
@@ -287,7 +292,7 @@ bool CSSFilter::buildFilterFunctions(RenderElement& renderer, const FilterOperat
break;

case FilterOperation::REFERENCE:
filter = createSVGFilter(*this, downcast<ReferenceFilterOperation>(*operation), renderer, *previousEffect);
filter = createSVGFilter(*this, downcast<ReferenceFilterOperation>(*operation), renderer, targetBoundingBox, *previousEffect);
effect = nullptr;
break;

@@ -330,18 +335,6 @@ bool CSSFilter::buildFilterFunctions(RenderElement& renderer, const FilterOperat
return true;
}

bool CSSFilter::updateBackingStoreRect(const FloatRect& filterRect)
{
if (filterRect.isEmpty() || ImageBuffer::sizeNeedsClamping(filterRect.size()))
return false;

if (filterRect == sourceImageRect())
return false;

setSourceImageRect(filterRect);
return true;
}

RefPtr<FilterEffect> CSSFilter::lastEffect() const
{
if (m_functions.isEmpty())
@@ -378,33 +371,24 @@ void CSSFilter::clearIntermediateResults()
RefPtr<FilterImage> CSSFilter::apply()
{
for (auto& function : m_functions) {
if (function->isSVGFilter())
downcast<SVGFilter>(function.ptr())->setSourceImageRect(sourceImageRect());
if (!function->apply(*this))
return nullptr;
}
return lastEffect()->filterImage();
}

LayoutRect CSSFilter::computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect)
{
// The result of this function is the area in the "filterBoxRect" that needs to be repainted, so that we fully cover the "dirtyRect".
auto rectForRepaint = dirtyRect;
if (hasFilterThatMovesPixels())
rectForRepaint += outsets();
rectForRepaint.intersect(filterBoxRect);
return rectForRepaint;
}

void CSSFilter::setSourceImageRect(const FloatRect& sourceImageRect)
void CSSFilter::setFilterRegion(const FloatRect& filterRegion)
{
Filter::setFilterRegion(sourceImageRect);
Filter::setSourceImageRect(sourceImageRect);
Filter::setFilterRegion(filterRegion);

for (auto& function : m_functions) {
if (function->isSVGFilter()) {
downcast<SVGFilter>(function.ptr())->setFilterRegion(sourceImageRect);
downcast<SVGFilter>(function.ptr())->setSourceImageRect(sourceImageRect);
}
if (function->isSVGFilter())
downcast<SVGFilter>(function.ptr())->setFilterRegion(filterRegion);
}

clampFilterRegionIfNeeded();
}

IntOutsets CSSFilter::outsets() const
@@ -42,13 +42,12 @@ class SourceGraphic;
class CSSFilter final : public Filter {
WTF_MAKE_FAST_ALLOCATED;
public:
static RefPtr<CSSFilter> create(const FilterOperations&, RenderingMode, float scaleFactor = 1, ClipOperation = ClipOperation::Intersect);
static RefPtr<CSSFilter> create(RenderElement&, const FilterOperations&, RenderingMode, const FloatSize& filterScale, ClipOperation, const FloatRect& targetBoundingBox);
WEBCORE_EXPORT static RefPtr<CSSFilter> create(Vector<Ref<FilterFunction>>&&);

const Vector<Ref<FilterFunction>>& functions() const { return m_functions; }

void setSourceImageRect(const FloatRect&);
bool buildFilterFunctions(RenderElement&, const FilterOperations&);
void setFilterRegion(const FloatRect&);

bool hasFilterThatMovesPixels() const { return m_hasFilterThatMovesPixels; }
bool hasFilterThatShouldBeRestrictedBySecurityOrigin() const { return m_hasFilterThatShouldBeRestrictedBySecurityOrigin; }
@@ -59,13 +58,11 @@ class CSSFilter final : public Filter {
void clearIntermediateResults();
RefPtr<FilterImage> apply() final;

bool updateBackingStoreRect(const FloatRect& filterRect);

LayoutRect computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect);

private:
CSSFilter(RenderingMode, float scaleFactor, ClipOperation, bool hasFilterThatMovesPixels, bool hasFilterThatShouldBeRestrictedBySecurityOrigin);
CSSFilter(RenderingMode, const FloatSize& filterScale, ClipOperation, bool hasFilterThatMovesPixels, bool hasFilterThatShouldBeRestrictedBySecurityOrigin);
CSSFilter(Vector<Ref<FilterFunction>>&&);

bool buildFilterFunctions(RenderElement&, const FilterOperations&, const FloatRect& targetBoundingBox);

#if USE(CORE_IMAGE)
bool supportsCoreImageRendering() const final;

0 comments on commit f27a530

Please sign in to comment.