Title: [286765] trunk/Source/WebCore
Revision
286765
Author
s...@apple.com
Date
2021-12-08 22:39:26 -0800 (Wed, 08 Dec 2021)

Log Message

[GPU Process] [Filters] Make Filter::apply() and FilterEffect:apply() take FilterImageVector for the inputs
https://bugs.webkit.org/show_bug.cgi?id=233973
rdar://86248999

Reviewed by Cameron McCormack.

This is a step towards removing the dependency on the input effects. This
step is required to make encoding/decoding the FilterEffect just be
sending or receiving its primitive data.

In this patch:

-- The sourceImage and sourceImageRect arguments to Filter::apply() are
   used to create a FilterImage. This will be the input to the SourceGraphic.

-- The members m_sourceImage and m_sourceImageRect of Filter are removed.

-- CSSFilter::apply() loops through its functions and uses the result
   of every function as the input to the next one. The initial input is
   the sourceImage. And the result of the last function is the returned
   FilterImage.

-- SVGFilter::apply() loops through its _expression_. It uses a stack of
   FilterImageVector to keep track of the inputs while applying each
   FilterEffect. Every FilterEffect is asked to takeInputs() from this
   stack. The result of applying the FilterEffect is pushed on this stack.
   The stack should have a single FilterImage when finishing the loop.
   This item is the result of applying the Filter.

-- FilterEffect::transformInputsColorSpace() was added to transform the
   input FilterImageVector to the operating color space of FilterEffect.
   It is overridden by FEDisplacementMap which does not transform the
   color space of the first input FilterImage.

-- FilterEffect::correctPremultipliedInputs() was added to correct the
   premultiplied pixels of the inputs FilterImageVector. We do not need
   to do this correction if the FilterEffect we apply is arithmetic
   composite filter. Otherwise we need to correct the FilterImage of any
   arithmetic composite filter in the FilterImageVector.

-- No need for totalNumberFilterEffects(). This count is the size of the
   SVGFilter _expression_.

* platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm:
(WebCore::SourceGraphicCoreImageApplier::apply const):
* platform/graphics/filters/FEBlend.h:
* platform/graphics/filters/FEComposite.h:
* platform/graphics/filters/FEDisplacementMap.cpp:
(WebCore::FEDisplacementMap::calculateImageRect const):
(WebCore::FEDisplacementMap::transformInputsColorSpace const):
(WebCore::FEDisplacementMap::transformResultColorSpace): Deleted.
* platform/graphics/filters/FEDisplacementMap.h:
* platform/graphics/filters/FEFlood.h:
* platform/graphics/filters/FEMerge.h:
* platform/graphics/filters/FETurbulence.h:
* platform/graphics/filters/Filter.cpp:
(WebCore::Filter::apply):
* platform/graphics/filters/Filter.h:
(WebCore::Filter::sourceImageRect const): Deleted.
(WebCore::Filter::setSourceImageRect): Deleted.
(WebCore::Filter::sourceImage const): Deleted.
(WebCore::Filter::setSourceImage): Deleted.
* platform/graphics/filters/FilterEffect.cpp:
(WebCore::FilterEffect::takeImageInputs const):
(WebCore::FilterEffect::calculateImageRect const):
(WebCore::FilterEffect::transformInputsColorSpace const):
(WebCore::FilterEffect::correctPremultipliedInputs const):
(WebCore::FilterEffect::apply):
(WebCore::FilterEffect::inputEffect const):
(WebCore::FilterEffect::inputFilterImages const): Deleted.
(WebCore::FilterEffect::correctPremultipliedResultIfNeeded): Deleted.
(WebCore::FilterEffect::transformResultColorSpace): Deleted.
* platform/graphics/filters/FilterEffect.h:
(WebCore::FilterEffect::filterImage const):
(WebCore::FilterEffect::numberOfEffectInputs const):
(WebCore::FilterEffect::numberOfImageInputs const):
(WebCore::FilterEffect::resultIsValidPremultiplied const):
(WebCore::FilterEffect::mayProduceInvalidPremultipliedPixels const): Deleted.
(WebCore::FilterEffect::correctFilterResultIfNeeded): Deleted.
(WebCore::FilterEffect::transformResultColorSpace): Deleted.
* platform/graphics/filters/FilterFunction.h:
(WebCore::FilterFunction::apply):
* platform/graphics/filters/FilterImage.cpp:
(WebCore::FilterImage::create):
(WebCore::FilterImage::FilterImage):
(WebCore::FilterImage::correctPremultipliedPixelBuffer):
* platform/graphics/filters/FilterImage.h:
* platform/graphics/filters/SourceAlpha.cpp:
(WebCore::SourceAlpha::calculateImageRect const): Deleted.
* platform/graphics/filters/SourceAlpha.h:
* platform/graphics/filters/SourceGraphic.cpp:
(WebCore::SourceGraphic::calculateImageRect const): Deleted.
* platform/graphics/filters/SourceGraphic.h:
* platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp:
(WebCore::SourceGraphicSoftwareApplier::apply const):
* rendering/CSSFilter.cpp:
(WebCore::CSSFilter::apply):
* rendering/CSSFilter.h:
* svg/graphics/filters/SVGFEImage.h:
* svg/graphics/filters/SVGFilter.cpp:
(WebCore::SVGFilter::apply):
* svg/graphics/filters/SVGFilter.h:
* svg/graphics/filters/SVGFilterBuilder.cpp:
(WebCore::SVGFilterBuilder::buildFilterEffects):
(WebCore::SVGFilterBuilder::buildExpression const):
(WebCore::collectEffects): Deleted.
(WebCore::totalNumberFilterEffects): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (286764 => 286765)


--- trunk/Source/WebCore/ChangeLog	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/ChangeLog	2021-12-09 06:39:26 UTC (rev 286765)
@@ -1,3 +1,113 @@
+2021-12-08  Said Abou-Hallawa  <s...@apple.com>
+
+        [GPU Process] [Filters] Make Filter::apply() and FilterEffect:apply() take FilterImageVector for the inputs
+        https://bugs.webkit.org/show_bug.cgi?id=233973
+        rdar://86248999
+
+        Reviewed by Cameron McCormack.
+
+        This is a step towards removing the dependency on the input effects. This 
+        step is required to make encoding/decoding the FilterEffect just be
+        sending or receiving its primitive data.
+
+        In this patch:
+
+        -- The sourceImage and sourceImageRect arguments to Filter::apply() are
+           used to create a FilterImage. This will be the input to the SourceGraphic.
+
+        -- The members m_sourceImage and m_sourceImageRect of Filter are removed.
+
+        -- CSSFilter::apply() loops through its functions and uses the result
+           of every function as the input to the next one. The initial input is
+           the sourceImage. And the result of the last function is the returned
+           FilterImage.
+
+        -- SVGFilter::apply() loops through its _expression_. It uses a stack of
+           FilterImageVector to keep track of the inputs while applying each
+           FilterEffect. Every FilterEffect is asked to takeInputs() from this 
+           stack. The result of applying the FilterEffect is pushed on this stack.
+           The stack should have a single FilterImage when finishing the loop.
+           This item is the result of applying the Filter.
+
+        -- FilterEffect::transformInputsColorSpace() was added to transform the
+           input FilterImageVector to the operating color space of FilterEffect.
+           It is overridden by FEDisplacementMap which does not transform the
+           color space of the first input FilterImage.
+
+        -- FilterEffect::correctPremultipliedInputs() was added to correct the
+           premultiplied pixels of the inputs FilterImageVector. We do not need
+           to do this correction if the FilterEffect we apply is arithmetic
+           composite filter. Otherwise we need to correct the FilterImage of any
+           arithmetic composite filter in the FilterImageVector.
+
+        -- No need for totalNumberFilterEffects(). This count is the size of the
+           SVGFilter _expression_.
+
+        * platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm:
+        (WebCore::SourceGraphicCoreImageApplier::apply const):
+        * platform/graphics/filters/FEBlend.h:
+        * platform/graphics/filters/FEComposite.h:
+        * platform/graphics/filters/FEDisplacementMap.cpp:
+        (WebCore::FEDisplacementMap::calculateImageRect const):
+        (WebCore::FEDisplacementMap::transformInputsColorSpace const):
+        (WebCore::FEDisplacementMap::transformResultColorSpace): Deleted.
+        * platform/graphics/filters/FEDisplacementMap.h:
+        * platform/graphics/filters/FEFlood.h:
+        * platform/graphics/filters/FEMerge.h:
+        * platform/graphics/filters/FETurbulence.h:
+        * platform/graphics/filters/Filter.cpp:
+        (WebCore::Filter::apply):
+        * platform/graphics/filters/Filter.h:
+        (WebCore::Filter::sourceImageRect const): Deleted.
+        (WebCore::Filter::setSourceImageRect): Deleted.
+        (WebCore::Filter::sourceImage const): Deleted.
+        (WebCore::Filter::setSourceImage): Deleted.
+        * platform/graphics/filters/FilterEffect.cpp:
+        (WebCore::FilterEffect::takeImageInputs const):
+        (WebCore::FilterEffect::calculateImageRect const):
+        (WebCore::FilterEffect::transformInputsColorSpace const):
+        (WebCore::FilterEffect::correctPremultipliedInputs const):
+        (WebCore::FilterEffect::apply):
+        (WebCore::FilterEffect::inputEffect const):
+        (WebCore::FilterEffect::inputFilterImages const): Deleted.
+        (WebCore::FilterEffect::correctPremultipliedResultIfNeeded): Deleted.
+        (WebCore::FilterEffect::transformResultColorSpace): Deleted.
+        * platform/graphics/filters/FilterEffect.h:
+        (WebCore::FilterEffect::filterImage const):
+        (WebCore::FilterEffect::numberOfEffectInputs const):
+        (WebCore::FilterEffect::numberOfImageInputs const):
+        (WebCore::FilterEffect::resultIsValidPremultiplied const):
+        (WebCore::FilterEffect::mayProduceInvalidPremultipliedPixels const): Deleted.
+        (WebCore::FilterEffect::correctFilterResultIfNeeded): Deleted.
+        (WebCore::FilterEffect::transformResultColorSpace): Deleted.
+        * platform/graphics/filters/FilterFunction.h:
+        (WebCore::FilterFunction::apply):
+        * platform/graphics/filters/FilterImage.cpp:
+        (WebCore::FilterImage::create):
+        (WebCore::FilterImage::FilterImage):
+        (WebCore::FilterImage::correctPremultipliedPixelBuffer):
+        * platform/graphics/filters/FilterImage.h:
+        * platform/graphics/filters/SourceAlpha.cpp:
+        (WebCore::SourceAlpha::calculateImageRect const): Deleted.
+        * platform/graphics/filters/SourceAlpha.h:
+        * platform/graphics/filters/SourceGraphic.cpp:
+        (WebCore::SourceGraphic::calculateImageRect const): Deleted.
+        * platform/graphics/filters/SourceGraphic.h:
+        * platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp:
+        (WebCore::SourceGraphicSoftwareApplier::apply const):
+        * rendering/CSSFilter.cpp:
+        (WebCore::CSSFilter::apply):
+        * rendering/CSSFilter.h:
+        * svg/graphics/filters/SVGFEImage.h:
+        * svg/graphics/filters/SVGFilter.cpp:
+        (WebCore::SVGFilter::apply):
+        * svg/graphics/filters/SVGFilter.h:
+        * svg/graphics/filters/SVGFilterBuilder.cpp:
+        (WebCore::SVGFilterBuilder::buildFilterEffects):
+        (WebCore::SVGFilterBuilder::buildExpression const):
+        (WebCore::collectEffects): Deleted.
+        (WebCore::totalNumberFilterEffects): Deleted.
+
 2021-12-08  Patrick Griffis  <pgrif...@igalia.com>
 
         CSP: Skip whitespace at beginning of policy header

Modified: trunk/Source/WebCore/platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm	2021-12-09 06:39:26 UTC (rev 286765)
@@ -28,15 +28,16 @@
 
 #if USE(CORE_IMAGE)
 
-#import "Filter.h"
 #import "FilterImage.h"
 #import "PlatformImageBuffer.h"
 
 namespace WebCore {
 
-bool SourceGraphicCoreImageApplier::apply(const Filter& filter, const FilterImageVector&, FilterImage& result) const
+bool SourceGraphicCoreImageApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) const
 {
-    auto sourceImage = filter.sourceImage();
+    auto& input = inputs[0].get();
+
+    auto sourceImage = input.imageBuffer();
     if (!sourceImage)
         return false;
 

Modified: trunk/Source/WebCore/platform/graphics/filters/FEBlend.h (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FEBlend.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEBlend.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -41,6 +41,8 @@
 private:
     FEBlend(BlendMode);
 
+    unsigned numberOfEffectInputs() const override { return 2; }
+    
     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
 
     void platformApplyNEON(unsigned char* srcPixelArrayA, unsigned char* srcPixelArrayB, unsigned char* dstPixelArray,

Modified: trunk/Source/WebCore/platform/graphics/filters/FEComposite.h (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FEComposite.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEComposite.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -63,9 +63,11 @@
 private:
     FEComposite(const CompositeOperationType&, float k1, float k2, float k3, float k4);
 
+    unsigned numberOfEffectInputs() const override { return 2; }
+
     FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
 
-    bool mayProduceInvalidPremultipliedPixels() const override { return m_type == FECOMPOSITE_OPERATOR_ARITHMETIC; }
+    bool resultIsValidPremultiplied() const override { return m_type != FECOMPOSITE_OPERATOR_ARITHMETIC; }
 
     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
 

Modified: trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp	2021-12-09 06:39:26 UTC (rev 286765)
@@ -68,6 +68,11 @@
     return true;
 }
 
+FloatRect FEDisplacementMap::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect& primitiveSubregion) const
+{
+    return filter.maxEffectRect(primitiveSubregion);
+}
+
 const DestinationColorSpace& FEDisplacementMap::resultColorSpace(const FilterImageVector& inputs) const
 {
     // Spec: The 'color-interpolation-filters' property only applies to the 'in2' source image
@@ -77,18 +82,13 @@
     return inputs[0]->colorSpace();
 }
 
-void FEDisplacementMap::transformResultColorSpace(FilterEffect* in, const int index)
+void FEDisplacementMap::transformInputsColorSpace(const FilterImageVector& inputs) const
 {
     // Do not transform the first primitive input, as per the spec.
-    if (index)
-        in->transformResultColorSpace(operatingColorSpace());
+    ASSERT(inputs.size() == 2);
+    inputs[1]->transformToColorSpace(operatingColorSpace());
 }
 
-FloatRect FEDisplacementMap::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect& primitiveSubregion) const
-{
-    return filter.maxEffectRect(primitiveSubregion);
-}
-
 std::unique_ptr<FilterEffectApplier> FEDisplacementMap::createApplier(const Filter&) const
 {
     return FilterEffectApplier::create<FEDisplacementMapSoftwareApplier>(*this);

Modified: trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -54,11 +54,13 @@
 private:
     FEDisplacementMap(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float);
 
-    const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const override;
-    void transformResultColorSpace(FilterEffect*, const int) override;
+    unsigned numberOfEffectInputs() const override { return 2; }
 
     FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
 
+    const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const override;
+    void transformInputsColorSpace(const FilterImageVector& inputs) const override;
+
     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
 
     WTF::TextStream& externalRepresentation(WTF::TextStream&, FilterRepresentation) const override;

Modified: trunk/Source/WebCore/platform/graphics/filters/FEFlood.h (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FEFlood.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEFlood.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -49,6 +49,8 @@
 private:
     FEFlood(const Color& floodColor, float floodOpacity);
 
+    unsigned numberOfEffectInputs() const override { return 0; }
+
     FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
 
     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;

Modified: trunk/Source/WebCore/platform/graphics/filters/FEMerge.h (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FEMerge.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEMerge.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -30,6 +30,8 @@
 public:
     WEBCORE_EXPORT static Ref<FEMerge> create(unsigned numberOfEffectInputs);
 
+    unsigned numberOfEffectInputs() const override { return m_numberOfEffectInputs; }
+
     template<class Encoder> void encode(Encoder&) const;
     template<class Decoder> static std::optional<Ref<FEMerge>> decode(Decoder&);
 

Modified: trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -63,6 +63,8 @@
 private:
     FETurbulence(TurbulenceType, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles);
 
+    unsigned numberOfEffectInputs() const override { return 0; }
+
     FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
 
     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;

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


--- trunk/Source/WebCore/platform/graphics/filters/Filter.cpp	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/Filter.cpp	2021-12-09 06:39:26 UTC (rev 286765)
@@ -83,13 +83,20 @@
 
 RefPtr<FilterImage> Filter::apply(ImageBuffer* sourceImage, const FloatRect& sourceImageRect)
 {
-    setSourceImage(sourceImage);
-    setSourceImageRect(sourceImageRect);
+    RefPtr<FilterImage> input;
 
-    auto result = apply();
+    if (sourceImage) {
+        auto absoluteSourceImageRect = enclosingIntRect(scaledByFilterScale(sourceImageRect));
+        input = FilterImage::create(m_filterRegion, sourceImageRect, absoluteSourceImageRect, Ref { *sourceImage });
+        if (!input)
+            return nullptr;
+    }
+
+    auto result = apply(input.get());
     if (!result)
-        return { };
+        return nullptr;
 
+    result->correctPremultipliedPixelBuffer();
     result->transformToColorSpace(DestinationColorSpace::SRGB());
     return result;
 }

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


--- trunk/Source/WebCore/platform/graphics/filters/Filter.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/Filter.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -44,15 +44,9 @@
     FloatSize filterScale() const { return m_filterScale; }
     void setFilterScale(const FloatSize& filterScale) { m_filterScale = filterScale; }
 
-    FloatRect sourceImageRect() const { return m_sourceImageRect; }
-    void setSourceImageRect(const FloatRect& sourceImageRect) { m_sourceImageRect = sourceImageRect; }
-
     FloatRect filterRegion() const { return m_filterRegion; }
     void setFilterRegion(const FloatRect& filterRegion) { m_filterRegion = filterRegion; }
 
-    ImageBuffer* sourceImage() const { return m_sourceImage.get(); }
-    void setSourceImage(RefPtr<ImageBuffer>&& sourceImage) { m_sourceImage = WTFMove(sourceImage); }
-
     ClipOperation clipOperation() const { return m_clipOperation; }
     void setClipOperation(ClipOperation clipOperation) { m_clipOperation = clipOperation; }
 
@@ -68,8 +62,8 @@
     virtual RefPtr<FilterEffect> lastEffect() const = 0;
 
     bool clampFilterRegionIfNeeded();
-    
-    virtual RefPtr<FilterImage> apply() = 0;
+
+    virtual RefPtr<FilterImage> apply(FilterImage* sourceImage) = 0;
     WEBCORE_EXPORT RefPtr<FilterImage> apply(ImageBuffer* sourceImage, const FloatRect& sourceImageRect);
 
 protected:
@@ -81,10 +75,6 @@
     FloatSize m_filterScale;
     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;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp	2021-12-09 06:39:26 UTC (rev 286765)
@@ -33,12 +33,20 @@
 
 namespace WebCore {
 
-FloatRect FilterEffect::calculateImageRect(const Filter& filter, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const
+FilterImageVector FilterEffect::takeImageInputs(FilterImageVector& stack) const
 {
-    FloatRect imageRect;
-    for (auto& input : inputs)
-        imageRect.unite(input->imageRect());
-    return filter.clipToMaxEffectRect(imageRect, primitiveSubregion);
+    unsigned inputsSize = numberOfImageInputs();
+    ASSERT(stack.size() >= inputsSize);
+    if (!inputsSize)
+        return { };
+
+    Vector<Ref<FilterImage>> inputs;
+    inputs.reserveInitialCapacity(inputsSize);
+
+    for (; inputsSize; --inputsSize)
+        inputs.uncheckedAppend(stack.takeLast());
+
+    return inputs;
 }
 
 FloatRect FilterEffect::calculatePrimitiveSubregion(const Filter& filter, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& geometry) const
@@ -68,51 +76,60 @@
     return primitiveSubregion;
 }
 
-FilterEffect* FilterEffect::inputEffect(unsigned number) const
+FloatRect FilterEffect::calculateImageRect(const Filter& filter, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const
 {
-    ASSERT_WITH_SECURITY_IMPLICATION(number < m_inputEffects.size());
-    return m_inputEffects.at(number).get();
+    FloatRect imageRect;
+    for (auto& input : inputs)
+        imageRect.unite(input->imageRect());
+    return filter.clipToMaxEffectRect(imageRect, primitiveSubregion);
 }
 
-bool FilterEffect::apply(const Filter& filter, const std::optional<FilterEffectGeometry>& geometry)
+void FilterEffect::transformInputsColorSpace(const FilterImageVector& inputs) const
 {
-    if (hasResult())
-        return true;
+    for (auto& input : inputs)
+        input->transformToColorSpace(operatingColorSpace());
+}
 
-    unsigned size = m_inputEffects.size();
-    for (unsigned i = 0; i < size; ++i) {
-        FilterEffect* in = m_inputEffects.at(i).get();
+void FilterEffect::correctPremultipliedInputs(const FilterImageVector& inputs) const
+{
+    // Correct any invalid pixels, if necessary, in the result of a filter operation.
+    // This method is used to ensure valid pixel values on filter inputs and the final result.
+    // Only the arithmetic composite filter ever needs to perform correction.
+    for (auto& input : inputs)
+        input->correctPremultipliedPixelBuffer();
+}
 
-        // Convert input results to the current effect's color space.
-        ASSERT(in->hasResult());
-        transformResultColorSpace(in, i);
-    }
+RefPtr<FilterImage> FilterEffect::apply(const Filter& filter, FilterImage& input)
+{
+    return apply(filter, FilterImageVector { Ref { input } });
+}
 
-    if (!mayProduceInvalidPremultipliedPixels()) {
-        for (auto& in : m_inputEffects)
-            in->correctPremultipliedResultIfNeeded();
-    }
+RefPtr<FilterImage> FilterEffect::apply(const Filter& filter, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& geometry)
+{
+    ASSERT(inputs.size() == numberOfImageInputs());
 
-    auto inputFilterImages = this->inputFilterImages();
+    if (m_filterImage)
+        return m_filterImage;
 
-    auto primitiveSubregion = calculatePrimitiveSubregion(filter, inputFilterImages, geometry);
-    auto imageRect = calculateImageRect(filter, inputFilterImages, primitiveSubregion);
+    auto primitiveSubregion = calculatePrimitiveSubregion(filter, inputs, geometry);
+    auto imageRect = calculateImageRect(filter, inputs, primitiveSubregion);
     auto absoluteImageRect = enclosingIntRect(filter.scaledByFilterScale(imageRect));
 
     if (absoluteImageRect.isEmpty() || ImageBuffer::sizeNeedsClamping(absoluteImageRect.size()))
-        return false;
+        return nullptr;
     
-    auto isAlphaImage = resultIsAlphaImage(inputFilterImages);
-    auto imageColorSpace = resultColorSpace(inputFilterImages);
+    auto isAlphaImage = resultIsAlphaImage(inputs);
+    auto isValidPremultiplied = resultIsValidPremultiplied();
+    auto imageColorSpace = resultColorSpace(inputs);
 
-    m_filterImage = FilterImage::create(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, filter.renderingMode(), imageColorSpace);
-    if (!m_filterImage)
-        return false;
-
     auto applier = createApplier(filter);
     if (!applier)
-        return false;
+        return nullptr;
 
+    m_filterImage = FilterImage::create(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, isValidPremultiplied, filter.renderingMode(), imageColorSpace);
+    if (!m_filterImage)
+        return nullptr;
+
     LOG_WITH_STREAM(Filters, stream
         << "FilterEffect " << filterName() << " " << this << " apply():"
         << "\n  filterPrimitiveSubregion " << primitiveSubregion
@@ -120,9 +137,22 @@
         << "\n  maxEffectRect " << filter.maxEffectRect(primitiveSubregion)
         << "\n  filter scale " << filter.filterScale());
 
-    return applier->apply(filter, inputFilterImages, *m_filterImage);
+    transformInputsColorSpace(inputs);
+    if (isValidPremultiplied)
+        correctPremultipliedInputs(inputs);
+
+    if (!applier->apply(filter, inputs, *m_filterImage))
+        m_filterImage = nullptr;
+
+    return m_filterImage;
 }
 
+FilterEffect* FilterEffect::inputEffect(unsigned number) const
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(number < m_inputEffects.size());
+    return m_inputEffects.at(number).get();
+}
+
 void FilterEffect::clearResult()
 {
     m_filterImage = nullptr;
@@ -137,30 +167,6 @@
         effect->clearResultsRecursive();
 }
 
-FilterImageVector FilterEffect::inputFilterImages() const
-{
-    FilterImageVector filterImages;
-
-    for (auto& inputEffect : m_inputEffects)
-        filterImages.append(*inputEffect->filterImage());
-
-    return filterImages;
-}
-
-void FilterEffect::correctPremultipliedResultIfNeeded()
-{
-    if (!hasResult() || !mayProduceInvalidPremultipliedPixels())
-        return;
-    m_filterImage->correctPremultipliedPixelBuffer();
-}
-
-void FilterEffect::transformResultColorSpace(const DestinationColorSpace& destinationColorSpace)
-{
-    if (!hasResult())
-        return;
-    m_filterImage->transformToColorSpace(destinationColorSpace);
-}
-
 TextStream& FilterEffect::externalRepresentation(TextStream& ts, FilterRepresentation representation) const
 {
     // FIXME: We should dump the subRegions of the filter primitives here later. This isn't

Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -40,21 +40,21 @@
 class FilterEffectGeometry;
 
 class FilterEffect : public FilterFunction {
+    using FilterFunction::apply;
+
 public:
     void clearResult() override;
     void clearResultsRecursive();
     bool hasResult() const { return m_filterImage; }
 
-    FilterImage* filterImage() const { return m_filterImage.get(); }
+    RefPtr<FilterImage> filterImage() const { return m_filterImage; }
+    FilterImageVector takeImageInputs(FilterImageVector& stack) const;
 
     FilterEffectVector& inputEffects() { return m_inputEffects; }
     FilterEffect* inputEffect(unsigned) const;
-    unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
 
-    void transformResultColorSpace(const DestinationColorSpace&);
+    RefPtr<FilterImage> apply(const Filter&, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& = std::nullopt);
 
-    bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) override;
-
     const DestinationColorSpace& operatingColorSpace() const { return m_operatingColorSpace; }
     virtual void setOperatingColorSpace(const DestinationColorSpace& colorSpace) { m_operatingColorSpace = colorSpace; }
 
@@ -63,29 +63,28 @@
 protected:
     using FilterFunction::FilterFunction;
 
-    virtual bool mayProduceInvalidPremultipliedPixels() const { return false; }
+    virtual unsigned numberOfEffectInputs() const { return 1; }
+    unsigned numberOfImageInputs() const { return filterType() == FilterEffect::Type::SourceGraphic ? 1 : numberOfEffectInputs(); }
 
-    void correctPremultipliedResultIfNeeded();
+    FloatRect calculatePrimitiveSubregion(const Filter&, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>&) const;
 
-    // Correct any invalid pixels, if necessary, in the result of a filter operation.
-    // This method is used to ensure valid pixel values on filter inputs and the final result.
-    // Only the arithmetic composite filter ever needs to perform correction.
-    virtual void correctFilterResultIfNeeded() { }
-
-    virtual void transformResultColorSpace(FilterEffect* in, const int) { in->transformResultColorSpace(m_operatingColorSpace); }
-
-    FilterImageVector inputFilterImages() const;
-    
-    FloatRect calculatePrimitiveSubregion(const Filter&, const FilterImageVector&, const std::optional<FilterEffectGeometry>&) const;
-
     virtual FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const;
 
     // Solid black image with different alpha values.
     virtual bool resultIsAlphaImage(const FilterImageVector&) const { return false; }
+
+    virtual bool resultIsValidPremultiplied() const { return true; }
+
     virtual const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const { return m_operatingColorSpace; }
 
+    virtual void transformInputsColorSpace(const FilterImageVector& inputs) const;
+    
+    void correctPremultipliedInputs(const FilterImageVector& inputs) const;
+
     virtual std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const = 0;
 
+    RefPtr<FilterImage> apply(const Filter&, FilterImage& input) override;
+
     FilterEffectVector m_inputEffects;
 
     RefPtr<FilterImage> m_filterImage;

Modified: trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -26,6 +26,8 @@
 #pragma once
 
 #include "FilterEffectGeometry.h"
+#include "FilterImage.h"
+#include "FilterImageVector.h"
 #include "FloatRect.h"
 #include "IntRectExtent.h"
 #include <wtf/RefCounted.h>
@@ -94,7 +96,7 @@
     virtual bool supportsCoreImageRendering() const { return false; }
 #endif
 
-    virtual bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) { return false; }
+    virtual RefPtr<FilterImage> apply(const Filter&, FilterImage&) { return nullptr; }
     virtual IntOutsets outsets() const { return { }; }
     virtual void clearResult() { }
 

Modified: trunk/Source/WebCore/platform/graphics/filters/FilterImage.cpp (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FilterImage.cpp	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterImage.cpp	2021-12-09 06:39:26 UTC (rev 286765)
@@ -38,22 +38,38 @@
 
 namespace WebCore {
 
-RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
+RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
 {
     ASSERT(!ImageBuffer::sizeNeedsClamping(absoluteImageRect.size()));
-    return adoptRef(new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, renderingMode, colorSpace));
+    return adoptRef(new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, isValidPremultiplied, renderingMode, colorSpace));
 }
 
-FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
+RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&& imageBuffer)
+{
+    return adoptRef(*new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, WTFMove(imageBuffer)));
+}
+
+FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
     : m_primitiveSubregion(primitiveSubregion)
     , m_imageRect(imageRect)
     , m_absoluteImageRect(absoluteImageRect)
     , m_isAlphaImage(isAlphaImage)
+    , m_isValidPremultiplied(isValidPremultiplied)
     , m_renderingMode(renderingMode)
     , m_colorSpace(colorSpace)
 {
 }
 
+FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&& imageBuffer)
+    : m_primitiveSubregion(primitiveSubregion)
+    , m_imageRect(imageRect)
+    , m_absoluteImageRect(absoluteImageRect)
+    , m_renderingMode(imageBuffer->renderingMode())
+    , m_colorSpace(imageBuffer->colorSpace())
+    , m_imageBuffer(WTFMove(imageBuffer))
+{
+}
+
 FloatRect FilterImage::maxEffectRect(const Filter& filter) const
 {
     return filter.maxEffectRect(m_primitiveSubregion);
@@ -281,7 +297,7 @@
 void FilterImage::correctPremultipliedPixelBuffer()
 {
     // Must operate on pre-multiplied results; other formats cannot have invalid pixels.
-    if (!m_premultipliedPixelBuffer)
+    if (!m_premultipliedPixelBuffer || m_isValidPremultiplied)
         return;
 
     Uint8ClampedArray& imageArray = m_premultipliedPixelBuffer->data();

Modified: trunk/Source/WebCore/platform/graphics/filters/FilterImage.h (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/FilterImage.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterImage.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -45,7 +45,8 @@
 
 class FilterImage : public RefCounted<FilterImage> {
 public:
-    static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode, const DestinationColorSpace&);
+    static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode, const DestinationColorSpace&);
+    static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&&);
 
     // The return values are in filter coordinates.
     FloatRect primitiveSubregion() const { return m_primitiveSubregion; }
@@ -76,7 +77,8 @@
 #endif
 
 private:
-    FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode, const DestinationColorSpace&);
+    FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode, const DestinationColorSpace&);
+    FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&&);
 
     std::optional<PixelBuffer>& pixelBufferSlot(AlphaPremultiplication);
 
@@ -93,6 +95,7 @@
     IntRect m_absoluteImageRect;
 
     bool m_isAlphaImage { false };
+    bool m_isValidPremultiplied { true };
     RenderingMode m_renderingMode;
     DestinationColorSpace m_colorSpace;
 

Modified: trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp	2021-12-09 06:39:26 UTC (rev 286765)
@@ -48,11 +48,6 @@
     inputEffects().append(&sourceEffect);
 }
 
-FloatRect SourceAlpha::calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect&) const
-{
-    return inputs[0]->imageRect();
-}
-
 std::unique_ptr<FilterEffectApplier> SourceAlpha::createApplier(const Filter&) const
 {
     return FilterEffectApplier::create<SourceAlphaSoftwareApplier>(*this);

Modified: trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.h (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -35,8 +35,6 @@
     SourceAlpha();
     explicit SourceAlpha(FilterEffect&);
 
-    FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
-
     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
 
     WTF::TextStream& externalRepresentation(WTF::TextStream&, FilterRepresentation) const override;

Modified: trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp	2021-12-09 06:39:26 UTC (rev 286765)
@@ -41,11 +41,6 @@
 {
 }
 
-FloatRect SourceGraphic::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect&) const
-{
-    return filter.sourceImageRect();
-}
-
 std::unique_ptr<FilterEffectApplier> SourceGraphic::createApplier(const Filter& filter) const
 {
 #if USE(CORE_IMAGE)

Modified: trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.h (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -38,7 +38,7 @@
     bool supportsCoreImageRendering() const override { return true; }
 #endif
 
-    FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
+    unsigned numberOfEffectInputs() const override { return 0; }
 
     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
 

Modified: trunk/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp (286764 => 286765)


--- trunk/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp	2021-12-09 06:39:26 UTC (rev 286765)
@@ -21,17 +21,17 @@
 #include "config.h"
 #include "SourceGraphicSoftwareApplier.h"
 
-#include "Filter.h"
 #include "GraphicsContext.h"
 #include "ImageBuffer.h"
-#include "SourceGraphic.h"
 
 namespace WebCore {
 
-bool SourceGraphicSoftwareApplier::apply(const Filter& filter, const FilterImageVector&, FilterImage& result) const
+bool SourceGraphicSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) const
 {
+    auto& input = inputs[0].get();
+
     auto resultImage = result.imageBuffer();
-    auto sourceImage = filter.sourceImage();
+    auto sourceImage = input.imageBuffer();
     if (!resultImage || !sourceImage)
         return false;
 

Modified: trunk/Source/WebCore/rendering/CSSFilter.cpp (286764 => 286765)


--- trunk/Source/WebCore/rendering/CSSFilter.cpp	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/rendering/CSSFilter.cpp	2021-12-09 06:39:26 UTC (rev 286765)
@@ -368,15 +368,20 @@
         function->clearResult();
 }
 
-RefPtr<FilterImage> CSSFilter::apply()
+RefPtr<FilterImage> CSSFilter::apply(FilterImage* sourceImage)
 {
+    if (!sourceImage)
+        return nullptr;
+    
+    RefPtr<FilterImage> result = sourceImage;
+
     for (auto& function : m_functions) {
-        if (function->isSVGFilter())
-            downcast<SVGFilter>(function.ptr())->setSourceImageRect(sourceImageRect());
-        if (!function->apply(*this))
+        result = function->apply(*this, *result);
+        if (!result)
             return nullptr;
     }
-    return lastEffect()->filterImage();
+
+    return result;
 }
 
 void CSSFilter::setFilterRegion(const FloatRect& filterRegion)

Modified: trunk/Source/WebCore/rendering/CSSFilter.h (286764 => 286765)


--- trunk/Source/WebCore/rendering/CSSFilter.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/rendering/CSSFilter.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -56,7 +56,7 @@
     IntOutsets outsets() const final;
 
     void clearIntermediateResults();
-    RefPtr<FilterImage> apply() final;
+    RefPtr<FilterImage> apply(FilterImage* sourceImage) final;
 
 private:
     CSSFilter(RenderingMode, const FloatSize& filterScale, ClipOperation, bool hasFilterThatMovesPixels, bool hasFilterThatShouldBeRestrictedBySecurityOrigin);

Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h (286764 => 286765)


--- trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -47,6 +47,8 @@
 private:
     FEImage(SourceImage&&, const FloatRect& sourceImageRect, const SVGPreserveAspectRatioValue&);
 
+    unsigned numberOfEffectInputs() const override { return 0; }
+
     // FEImage results are always in DestinationColorSpace::SRGB()
     void setOperatingColorSpace(const DestinationColorSpace&) override { }
 

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


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp	2021-12-09 06:39:26 UTC (rev 286765)
@@ -117,20 +117,51 @@
     return m_expression.last().effect.ptr();
 }
 
-bool SVGFilter::apply(const Filter& filter, const std::optional<FilterEffectGeometry>&)
+RefPtr<FilterImage> SVGFilter::apply(const Filter&, FilterImage& sourceImage)
 {
-    setSourceImage({ filter.sourceImage() });
-    return apply();
+    return apply(&sourceImage);
 }
 
-RefPtr<FilterImage> SVGFilter::apply()
+RefPtr<FilterImage> SVGFilter::apply(FilterImage* sourceImage)
 {
     ASSERT(!m_expression.isEmpty());
+
+    FilterImageVector stack;
+
     for (auto& term : m_expression) {
-        if (!term.effect->apply(*this, term.geometry))
+        auto& effect = term.effect;
+        auto geometry = term.geometry;
+
+        if (effect->filterType() == FilterEffect::Type::SourceGraphic) {
+            if (auto result = effect->filterImage()) {
+                stack.append(result.releaseNonNull());
+                continue;
+            }
+
+            if (!sourceImage)
+                return nullptr;
+
+            // Add sourceImage as an input to the SourceGraphic.
+            stack.append(Ref { *sourceImage });
+        }
+
+        // Need to remove the inputs here in case the effect already has a result.
+        auto inputs = effect->takeImageInputs(stack);
+
+        if (auto result = effect->filterImage()) {
+            stack.append(result.releaseNonNull());
+            continue;
+        }
+
+        auto result = term.effect->apply(*this, inputs, geometry);
+        if (!result)
             return nullptr;
+
+        stack.append(result.releaseNonNull());
     }
-    return lastEffect()->filterImage();
+    
+    ASSERT(stack.size() == 1);
+    return stack.takeLast();
 }
 
 IntOutsets SVGFilter::outsets() const

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


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h	2021-12-09 06:39:26 UTC (rev 286765)
@@ -48,7 +48,7 @@
     
     RefPtr<FilterEffect> lastEffect() const final;
 
-    RefPtr<FilterImage> apply() final;
+    RefPtr<FilterImage> apply(FilterImage* sourceImage) final;
 
     WTF::TextStream& externalRepresentation(WTF::TextStream&, FilterRepresentation) const final;
 
@@ -63,7 +63,7 @@
 #endif
     FloatSize resolvedSize(const FloatSize&) const final;
 
-    bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) final;
+    RefPtr<FilterImage> apply(const Filter&, FilterImage& sourceImage) final;
     IntOutsets outsets() const final;
     void clearResult() final;
 

Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp (286764 => 286765)


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp	2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp	2021-12-09 06:39:26 UTC (rev 286765)
@@ -34,6 +34,9 @@
 
 namespace WebCore {
 
+static constexpr unsigned maxTotalNumberFilterEffects = 100;
+static constexpr unsigned maxCountChildNodes = 200;
+
 void SVGFilterBuilder::setupBuiltinEffects(Ref<FilterEffect> sourceGraphic)
 {
     m_builtinEffects.add(SourceGraphic::effectName(), sourceGraphic.ptr());
@@ -76,28 +79,8 @@
 }
 #endif
 
-static unsigned collectEffects(const FilterEffect* effect, HashSet<const FilterEffect*>& allEffects)
-{
-    allEffects.add(effect);
-    unsigned size = effect->numberOfEffectInputs();
-    for (unsigned i = 0; i < size; ++i) {
-        FilterEffect* in = effect->inputEffect(i);
-        collectEffects(in, allEffects);
-    }
-    return allEffects.size();
-}
-
-static unsigned totalNumberFilterEffects(const FilterEffect& lastEffect)
-{
-    HashSet<const FilterEffect*> allEffects;
-    return collectEffects(&lastEffect, allEffects);
-}
-
 RefPtr<FilterEffect> SVGFilterBuilder::buildFilterEffects(SVGFilterElement& filterElement)
 {
-    static constexpr unsigned maxCountChildNodes = 200;
-    static constexpr unsigned maxTotalNumberFilterEffects = 100;
-
     if (filterElement.countChildNodes() > maxCountChildNodes)
         return nullptr;
 
@@ -124,10 +107,8 @@
         add(effectElement.result(), effect);
     }
 
-    if (!effect || totalNumberFilterEffects(*effect) > maxTotalNumberFilterEffects) {
+    if (!effect)
         clearEffects();
-        return nullptr;
-    }
 
     return effect;
 }
@@ -240,6 +221,9 @@
     if (!buildEffectExpression(m_lastEffect, stack, 0, _expression_))
         return false;
 
+    if (_expression_.size() > maxTotalNumberFilterEffects)
+        return false;
+
     _expression_.reverse();
     _expression_.shrinkToFit();
     return true;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to