Title: [286546] trunk
Revision
286546
Author
[email protected]
Date
2021-12-06 10:20:43 -0800 (Mon, 06 Dec 2021)

Log Message

[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.

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:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (286545 => 286546)


--- trunk/LayoutTests/ChangeLog	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/LayoutTests/ChangeLog	2021-12-06 18:20:43 UTC (rev 286546)
@@ -1,3 +1,14 @@
+2021-12-06  Said Abou-Hallawa  <[email protected]>
+
+        [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  <[email protected]>
 
         CSS animation sorting may crash due to AnimationList copy upon CSS Animation removal

Modified: trunk/LayoutTests/TestExpectations (286545 => 286546)


--- trunk/LayoutTests/TestExpectations	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/LayoutTests/TestExpectations	2021-12-06 18:20:43 UTC (rev 286546)
@@ -5163,19 +5163,3 @@
 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 ]

Modified: trunk/Source/WebCore/ChangeLog (286545 => 286546)


--- trunk/Source/WebCore/ChangeLog	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/ChangeLog	2021-12-06 18:20:43 UTC (rev 286546)
@@ -1,3 +1,63 @@
+2021-12-06  Said Abou-Hallawa  <[email protected]>
+        [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  <[email protected]>
 
         WKWebpagePreferences._activeContentRuleListActionPatterns should be an NSDictionary of identifier to allowed patterns

Modified: trunk/Source/WebCore/css/CSSFilterImageValue.cpp (286545 => 286546)


--- trunk/Source/WebCore/css/CSSFilterImageValue.cpp	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/css/CSSFilterImageValue.cpp	2021-12-06 18:20:43 UTC (rev 286546)
@@ -124,12 +124,12 @@
     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;
 

Modified: trunk/Source/WebCore/platform/graphics/filters/Filter.cpp (286545 => 286546)


--- trunk/Source/WebCore/platform/graphics/filters/Filter.cpp	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/platform/graphics/filters/Filter.cpp	2021-12-06 18:20:43 UTC (rev 286546)
@@ -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)
 {
 }
 

Modified: trunk/Source/WebCore/platform/graphics/filters/Filter.h (286545 => 286546)


--- trunk/Source/WebCore/platform/graphics/filters/Filter.h	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/platform/graphics/filters/Filter.h	2021-12-06 18:20:43 UTC (rev 286546)
@@ -77,19 +77,17 @@
 
 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

Modified: trunk/Source/WebCore/rendering/CSSFilter.cpp (286545 => 286546)


--- trunk/Source/WebCore/rendering/CSSFilter.cpp	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/rendering/CSSFilter.cpp	2021-12-06 18:20:43 UTC (rev 286546)
@@ -44,12 +44,17 @@
 
 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)
@@ -57,8 +62,8 @@
     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 @@
     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 @@
     }
 
     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 @@
             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 @@
     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,6 +371,8 @@
 RefPtr<FilterImage> CSSFilter::apply()
 {
     for (auto& function : m_functions) {
+        if (function->isSVGFilter())
+            downcast<SVGFilter>(function.ptr())->setSourceImageRect(sourceImageRect());
         if (!function->apply(*this))
             return nullptr;
     }
@@ -384,27 +379,16 @@
     return lastEffect()->filterImage();
 }
 
-LayoutRect CSSFilter::computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect)
+void CSSFilter::setFilterRegion(const FloatRect& filterRegion)
 {
-    // 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;
-}
+    Filter::setFilterRegion(filterRegion);
 
-void CSSFilter::setSourceImageRect(const FloatRect& sourceImageRect)
-{
-    Filter::setFilterRegion(sourceImageRect);
-    Filter::setSourceImageRect(sourceImageRect);
-
     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

Modified: trunk/Source/WebCore/rendering/CSSFilter.h (286545 => 286546)


--- trunk/Source/WebCore/rendering/CSSFilter.h	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/rendering/CSSFilter.h	2021-12-06 18:20:43 UTC (rev 286546)
@@ -42,13 +42,12 @@
 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 @@
     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;

Modified: trunk/Source/WebCore/rendering/RenderLayerFilters.cpp (286545 => 286546)


--- trunk/Source/WebCore/rendering/RenderLayerFilters.cpp	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/rendering/RenderLayerFilters.cpp	2021-12-06 18:20:43 UTC (rev 286546)
@@ -121,7 +121,7 @@
     // If the filter fails to build, remove it from the layer. It will still attempt to
     // go through regular processing (e.g. compositing), but never apply anything.
     // FIXME: this rebuilds the entire effects chain even if the filter style didn't change.
-    m_filter = CSSFilter::create(renderer.style().filter(), renderingMode, scaleFactor, Filter::ClipOperation::Unite);
+    m_filter = CSSFilter::create(renderer, renderer.style().filter(), renderingMode, FloatSize { scaleFactor, scaleFactor }, Filter::ClipOperation::Unite, m_targetBoundingBox);
 }
 
 GraphicsContext* RenderLayerFilters::inputContext()
@@ -129,10 +129,10 @@
     return m_sourceImage ? &m_sourceImage->context() : nullptr;
 }
 
-void RenderLayerFilters::allocateBackingStore(const GraphicsContext& targetContext)
+void RenderLayerFilters::allocateBackingStoreIfNeeded(const GraphicsContext& targetContext)
 {
     auto& filter = *m_filter;
-    auto logicalSize = filter.scaledByFilterScale(filter.sourceImageRect().size());
+    auto logicalSize = filter.scaledByFilterScale(m_filterRegion.size());
 
     if (!m_sourceImage || m_sourceImage->logicalSize() != logicalSize) {
 #if USE(DIRECT2D)
@@ -151,42 +151,59 @@
     if (!m_filter)
         return nullptr;
 
-    auto& filter = *m_filter;
-    auto filterSourceRect = filter.computeSourceImageRectForDirtyRect(filterBoxRect, dirtyRect);
-    if (filterSourceRect.isEmpty())
+    // Calculate targetBoundingBox since it will be used if the filter is created.
+    auto targetBoundingBox = intersection(filterBoxRect, dirtyRect);
+    if (targetBoundingBox.isEmpty())
         return nullptr;
 
-    bool hasUpdatedBackingStore = filter.updateBackingStoreRect(filterSourceRect);
+    if (m_targetBoundingBox != targetBoundingBox) {
+        m_targetBoundingBox = targetBoundingBox;
+        // FIXME: this rebuilds the entire effects chain even if the filter style didn't change.
+        m_filter = CSSFilter::create(renderer, renderer.style().filter(), m_filter->renderingMode(), m_filter->filterScale(), Filter::ClipOperation::Unite, m_targetBoundingBox);
+    }
 
-    // FIXME: this call should be moved to CSSFilter::create() when FilterEffect does not store its geometry.
-    if (hasUpdatedBackingStore || !m_filter->lastEffect()) {
-        // If the filter fails to build, remove it from the layer. It will still attempt to
-        // go through regular processing (e.g. compositing), but never apply anything.
-        if (!m_filter->buildFilterFunctions(renderer, renderer.style().filter()))
-            return nullptr;
+    if (!m_filter)
+        return nullptr;
+
+    auto& filter = *m_filter;
+    
+    // For CSSFilter, filterRegion = targetBoundingBox + filter->outsets()
+    auto filterRegion = targetBoundingBox;
+    if (filter.hasFilterThatMovesPixels()) {
+        filterRegion += filter.outsets();
+        filterRegion.intersect(filterBoxRect);
     }
 
+    if (filterRegion.isEmpty())
+        return nullptr;
+
+    // For CSSFilter, sourceImageRect = filterRegion.
+    bool hasUpdatedBackingStore = false;
+    if (m_filterRegion != filterRegion) {
+        m_filterRegion = filterRegion;
+        hasUpdatedBackingStore = true;
+    }
+
     if (!filter.hasFilterThatMovesPixels())
         m_repaintRect = dirtyRect;
     else {
         if (hasUpdatedBackingStore)
-            m_repaintRect = filterSourceRect;
+            m_repaintRect = filterRegion;
         else {
             m_repaintRect = dirtyRect;
             m_repaintRect.unite(layerRepaintRect);
-            m_repaintRect.intersect(filterSourceRect);
+            m_repaintRect.intersect(filterRegion);
         }
     }
-    m_paintOffset = filterSourceRect.location();
+
+    m_paintOffset = filterRegion.location();
     resetDirtySourceRect();
 
-    filter.clampFilterRegionIfNeeded();
+    filter.setFilterRegion(m_filterRegion);
+    allocateBackingStoreIfNeeded(destinationContext);
 
-    if (hasUpdatedBackingStore)
-        allocateBackingStore(destinationContext);
-
     auto* sourceGraphicsContext = inputContext();
-    if (!sourceGraphicsContext || filter.filterRegion().isEmpty() || ImageBuffer::sizeNeedsClamping(filter.filterRegion().size()))
+    if (!sourceGraphicsContext)
         return nullptr;
 
     // Translate the context so that the contents of the layer is captured in the offscreen memory buffer.
@@ -207,7 +224,7 @@
 
     auto& filter = *m_filter;
 
-    destinationContext.drawFilteredImageBuffer(m_sourceImage.get(), filter.sourceImageRect(), filter);
+    destinationContext.drawFilteredImageBuffer(m_sourceImage.get(), m_filterRegion, filter);
     filter.clearIntermediateResults();
 
     LOG_WITH_STREAM(Filters, stream << "RenderLayerFilters " << this << " applyFilterEffect done\n");

Modified: trunk/Source/WebCore/rendering/RenderLayerFilters.h (286545 => 286546)


--- trunk/Source/WebCore/rendering/RenderLayerFilters.h	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/rendering/RenderLayerFilters.h	2021-12-06 18:20:43 UTC (rev 286546)
@@ -70,7 +70,7 @@
     void notifyFinished(CachedResource&, const NetworkLoadMetrics&) final;
     void resetDirtySourceRect() { m_dirtySourceRect = LayoutRect(); }
     GraphicsContext* inputContext();
-    void allocateBackingStore(const GraphicsContext& targetContext);
+    void allocateBackingStoreIfNeeded(const GraphicsContext& targetContext);
 
     RenderLayer& m_layer;
 
@@ -77,6 +77,8 @@
     Vector<RefPtr<Element>> m_internalSVGReferences;
     Vector<CachedResourceHandle<CachedSVGDocument>> m_externalSVGReferences;
 
+    LayoutRect m_targetBoundingBox;
+    FloatRect m_filterRegion;
     RefPtr<ImageBuffer> m_sourceImage;
     RefPtr<CSSFilter> m_filter;
     LayoutRect m_dirtySourceRect;

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp (286545 => 286546)


--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp	2021-12-06 18:20:43 UTC (rev 286546)
@@ -129,7 +129,7 @@
 
     // Create the SVGFilter object.
     filterData->builder = makeUnique<SVGFilterBuilder>();
-    filterData->filter = SVGFilter::create(filterElement(), *filterData->builder, renderingMode, filterScale, filterData->drawingRegion, filterData->boundaries, targetBoundingBox);
+    filterData->filter = SVGFilter::create(filterElement(), *filterData->builder, renderingMode, filterScale, filterData->boundaries, targetBoundingBox);
     if (!filterData->filter) {
         m_rendererFilterDataMap.remove(&renderer);
         return false;

Modified: trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp (286545 => 286546)


--- trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp	2021-12-06 18:20:43 UTC (rev 286546)
@@ -431,7 +431,7 @@
         FloatRect dummyRect;
         FloatSize dummyScale(1, 1);
         SVGFilterBuilder builder;
-        auto dummyFilter = SVGFilter::create(filter.filterElement(), builder, RenderingMode::Unaccelerated, dummyScale, dummyRect, dummyRect, dummyRect);
+        auto dummyFilter = SVGFilter::create(filter.filterElement(), builder, RenderingMode::Unaccelerated, dummyScale, dummyRect, dummyRect);
         if (dummyFilter) {
             TextStream::IndentScope indentScope(ts);
 

Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp (286545 => 286546)


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp	2021-12-06 18:20:43 UTC (rev 286546)
@@ -29,19 +29,19 @@
 
 namespace WebCore {
 
-RefPtr<SVGFilter> SVGFilter::create(SVGFilterElement& filterElement, SVGFilterBuilder& builder, RenderingMode renderingMode, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, ClipOperation clipOperation, FilterEffect& previousEffect)
+RefPtr<SVGFilter> SVGFilter::create(SVGFilterElement& filterElement, SVGFilterBuilder& builder, RenderingMode renderingMode, const FloatSize& filterScale, ClipOperation clipOperation, const FloatRect& targetBoundingBox, FilterEffect& previousEffect)
 {
-    return create(filterElement, builder, renderingMode, filterScale, sourceImageRect, filterRegion, clipOperation, filterRegion, &previousEffect);
+    return create(filterElement, builder, renderingMode, filterScale, clipOperation, targetBoundingBox, targetBoundingBox, &previousEffect);
 }
 
-RefPtr<SVGFilter> SVGFilter::create(SVGFilterElement& filterElement, SVGFilterBuilder& builder, RenderingMode renderingMode, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, const FloatRect& targetBoundingBox)
+RefPtr<SVGFilter> SVGFilter::create(SVGFilterElement& filterElement, SVGFilterBuilder& builder, RenderingMode renderingMode, const FloatSize& filterScale, const FloatRect& filterRegion, const FloatRect& targetBoundingBox)
 {
-    return create(filterElement, builder, renderingMode, filterScale, sourceImageRect, filterRegion, ClipOperation::Intersect, targetBoundingBox, nullptr);
+    return create(filterElement, builder, renderingMode, filterScale, ClipOperation::Intersect, filterRegion, targetBoundingBox, nullptr);
 }
 
-RefPtr<SVGFilter> SVGFilter::create(SVGFilterElement& filterElement, SVGFilterBuilder& builder, RenderingMode renderingMode, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, ClipOperation clipOperation, const FloatRect& targetBoundingBox, FilterEffect* previousEffect)
+RefPtr<SVGFilter> SVGFilter::create(SVGFilterElement& filterElement, SVGFilterBuilder& builder, RenderingMode renderingMode, const FloatSize& filterScale, ClipOperation clipOperation, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, FilterEffect* previousEffect)
 {
-    auto filter = adoptRef(*new SVGFilter(renderingMode, filterScale, sourceImageRect, filterRegion, clipOperation, targetBoundingBox, filterElement.primitiveUnits()));
+    auto filter = adoptRef(*new SVGFilter(renderingMode, filterScale, clipOperation, filterRegion, targetBoundingBox, filterElement.primitiveUnits()));
 
     if (!previousEffect)
         builder.setupBuiltinEffects(SourceGraphic::create());
@@ -71,8 +71,8 @@
     return filter;
 }
 
-SVGFilter::SVGFilter(RenderingMode renderingMode, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, ClipOperation clipOperation, const FloatRect& targetBoundingBox, SVGUnitTypes::SVGUnitType primitiveUnits)
-    : Filter(Filter::Type::SVGFilter, renderingMode, filterScale, sourceImageRect, filterRegion, clipOperation)
+SVGFilter::SVGFilter(RenderingMode renderingMode, const FloatSize& filterScale, ClipOperation clipOperation, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, SVGUnitTypes::SVGUnitType primitiveUnits)
+    : Filter(Filter::Type::SVGFilter, renderingMode, filterScale, clipOperation, filterRegion)
     , m_targetBoundingBox(targetBoundingBox)
     , m_primitiveUnits(primitiveUnits)
 {

Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h (286545 => 286546)


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h	2021-12-06 17:46:01 UTC (rev 286545)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h	2021-12-06 18:20:43 UTC (rev 286546)
@@ -36,9 +36,9 @@
 
 class SVGFilter final : public Filter {
 public:
-    static RefPtr<SVGFilter> create(SVGFilterElement&, SVGFilterBuilder&, RenderingMode, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, ClipOperation, FilterEffect& previousEffect);
-    static RefPtr<SVGFilter> create(SVGFilterElement&, SVGFilterBuilder&, RenderingMode, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, const FloatRect& targetBoundingBox);
-    static RefPtr<SVGFilter> create(SVGFilterElement&, SVGFilterBuilder&, RenderingMode, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, ClipOperation, const FloatRect& targetBoundingBox, FilterEffect* previousEffect);
+    static RefPtr<SVGFilter> create(SVGFilterElement&, SVGFilterBuilder&, RenderingMode, const FloatSize& filterScale, ClipOperation, const FloatRect& targetBoundingBox, FilterEffect& previousEffect);
+    static RefPtr<SVGFilter> create(SVGFilterElement&, SVGFilterBuilder&, RenderingMode, const FloatSize& filterScale, const FloatRect& filterRegion, const FloatRect& targetBoundingBox);
+    static RefPtr<SVGFilter> create(SVGFilterElement&, SVGFilterBuilder&, RenderingMode, const FloatSize& filterScale, ClipOperation, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, FilterEffect* previousEffect);
 
     FloatRect targetBoundingBox() const { return m_targetBoundingBox; }
 
@@ -47,7 +47,7 @@
     RefPtr<FilterImage> apply() final;
 
 private:
-    SVGFilter(RenderingMode, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, ClipOperation, const FloatRect& targetBoundingBox, SVGUnitTypes::SVGUnitType primitiveUnits);
+    SVGFilter(RenderingMode, const FloatSize& filterScale, ClipOperation, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, SVGUnitTypes::SVGUnitType primitiveUnits);
 
     // FIXME: Merge the effectBoundaries in the _expression_ node.
     void setExpression(FilterEffectVector&& _expression_) { m_expression = WTFMove(_expression_); }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to