[GPU Process] Make FilterEffect appliers take FilterImages in their apply() methods
https://bugs.webkit.org/show_bug.cgi?id=233487

Reviewed by Cameron McCormack.

Eventually the FilterImage will be removed from FilterEffect. So this is
a step towards making the FilterEffect hold the effect data only. To do
his change, FilterImage needs to hold two new members: primitiveSubregion
and isAlphaImage.

FilterEffect::setIsAlphaImage() is not needed and isAlphaImage() will be
a virtual function but it will be renamed resultIsAlphaImage(). The result
of this function will be stored in the result FilterImage.

FEGaussianBlurSoftwareApplier::apply() is the only user of isAlphaImage.

* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/filters/FEBlend.cpp:
(WebCore::FEBlend::platformApplySoftware):
* platform/graphics/filters/FEColorMatrix.cpp:
(WebCore::FEColorMatrix::resultIsAlphaImage const):
(WebCore::FEColorMatrix::platformApplySoftware):
* platform/graphics/filters/FEColorMatrix.h:
* platform/graphics/filters/FEComponentTransfer.cpp:
(WebCore::FEComponentTransfer::platformApplySoftware):
* platform/graphics/filters/FEComposite.cpp:
(WebCore::FEComposite::platformApplySoftware):
* platform/graphics/filters/FEConvolveMatrix.cpp:
(WebCore::FEConvolveMatrix::platformApplySoftware):
* platform/graphics/filters/FEDisplacementMap.cpp:
(WebCore::FEDisplacementMap::platformApplySoftware):
* platform/graphics/filters/FEDropShadow.cpp:
(WebCore::FEDropShadow::platformApplySoftware):
* platform/graphics/filters/FEFlood.cpp:
(WebCore::FEFlood::platformApplySoftware):
* platform/graphics/filters/FEGaussianBlur.cpp:
(WebCore::FEGaussianBlur::resultIsAlphaImage const):
(WebCore::FEGaussianBlur::platformApplySoftware):
* platform/graphics/filters/FEGaussianBlur.h:
* platform/graphics/filters/FELighting.cpp:
(WebCore::FELighting::platformApplySoftware):
* platform/graphics/filters/FEMerge.cpp:
(WebCore::FEMerge::platformApplySoftware):
* platform/graphics/filters/FEMorphology.cpp:
(WebCore::FEMorphology::resultIsAlphaImage const):
(WebCore::FEMorphology::platformApplySoftware):
* platform/graphics/filters/FEMorphology.h:
* platform/graphics/filters/FEOffset.cpp:
(WebCore::FEOffset::resultIsAlphaImage const):
(WebCore::FEOffset::platformApplySoftware):
* platform/graphics/filters/FEOffset.h:
* platform/graphics/filters/FETile.cpp:
(WebCore::FETile::resultIsAlphaImage const):
(WebCore::FETile::platformApplySoftware):
* platform/graphics/filters/FETile.h:
* platform/graphics/filters/FETurbulence.cpp:
(WebCore::FETurbulence::platformApplySoftware):
* platform/graphics/filters/Filter.h:
(WebCore::Filter::maxEffectRect const):
* platform/graphics/filters/FilterEffect.cpp:
(WebCore::FilterEffect::apply):
(WebCore::FilterEffect::inputFilterImages const):
(WebCore::FilterEffect::externalRepresentation const):
(WebCore::FilterEffect::createResult): Deleted.
(WebCore::FilterEffect::imageBufferResult): Deleted.
(WebCore::FilterEffect::pixelBufferResult): Deleted.
(WebCore::FilterEffect::getPixelBufferResult): Deleted.
(WebCore::FilterEffect::copyPixelBufferResult const): Deleted.
* platform/graphics/filters/FilterEffect.h:
(WebCore::FilterEffect::filterImage const):
(WebCore::FilterEffect::resultIsAlphaImage const):
(WebCore::FilterEffect::isAlphaImage const): Deleted.
(WebCore::FilterEffect::setIsAlphaImage): Deleted.
(WebCore::FilterEffect::normalizedFloats): Deleted.
* platform/graphics/filters/FilterEffectApplier.h:
* platform/graphics/filters/FilterImage.cpp:
(WebCore::FilterImage::create):
(WebCore::FilterImage::FilterImage):
* platform/graphics/filters/FilterImage.h:
(WebCore::FilterImage::primitiveSubregion const):
(WebCore::FilterImage::isAlphaImage const):
* platform/graphics/filters/FilterImageVector.h: Copied from Source/WebCore/platform/graphics/filters/FilterEffectApplier.h.
* platform/graphics/filters/SourceAlpha.cpp:
(WebCore::SourceAlpha::platformApplySoftware):
* platform/graphics/filters/SourceGraphic.cpp:
(WebCore::SourceGraphic::platformApplySoftware):
* platform/graphics/filters/software/FEBlendSoftwareApplier.cpp:
(WebCore::FEBlendSoftwareApplier::apply):
* platform/graphics/filters/software/FEBlendSoftwareApplier.h:
* platform/graphics/filters/software/FEColorMatrixSoftwareApplier.cpp:
(WebCore::FEColorMatrixSoftwareApplier::apply):
* platform/graphics/filters/software/FEColorMatrixSoftwareApplier.h:
* platform/graphics/filters/software/FEComponentTransferSoftwareApplier.cpp:
(WebCore::FEComponentTransferSoftwareApplier::apply):
* platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h:
* platform/graphics/filters/software/FECompositeSoftwareApplier.cpp:
(WebCore::FECompositeSoftwareApplier::applyArithmetic):
(WebCore::FECompositeSoftwareApplier::applyNonArithmetic):
(WebCore::FECompositeSoftwareApplier::apply):
* platform/graphics/filters/software/FECompositeSoftwareApplier.h:
* platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.cpp:
(WebCore::FEConvolveMatrixSoftwareApplier::apply):
* platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.h:
* platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.cpp:
(WebCore::FEDisplacementMapSoftwareApplier::apply):
* platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.h:
* platform/graphics/filters/software/FEDropShadowSoftwareApplier.cpp:
(WebCore::FEDropShadowSoftwareApplier::apply):
* platform/graphics/filters/software/FEDropShadowSoftwareApplier.h:
* platform/graphics/filters/software/FEFloodSoftwareApplier.cpp:
(WebCore::FEFloodSoftwareApplier::apply):
* platform/graphics/filters/software/FEFloodSoftwareApplier.h:
* platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.cpp:
(WebCore::FEGaussianBlurSoftwareApplier::apply):
* platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.h:
* platform/graphics/filters/software/FELightingSoftwareApplier.cpp:
(WebCore::FELightingSoftwareApplier::apply):
* platform/graphics/filters/software/FELightingSoftwareApplier.h:
* platform/graphics/filters/software/FEMergeSoftwareApplier.cpp:
(WebCore::FEMergeSoftwareApplier::apply):
* platform/graphics/filters/software/FEMergeSoftwareApplier.h:
* platform/graphics/filters/software/FEMorphologySoftwareApplier.cpp:
(WebCore::FEMorphologySoftwareApplier::apply):
* platform/graphics/filters/software/FEMorphologySoftwareApplier.h:
* platform/graphics/filters/software/FEOffsetSoftwareApplier.cpp:
(WebCore::FEOffsetSoftwareApplier::apply):
* platform/graphics/filters/software/FEOffsetSoftwareApplier.h:
* platform/graphics/filters/software/FETileSoftwareApplier.cpp:
(WebCore::FETileSoftwareApplier::apply):
* platform/graphics/filters/software/FETileSoftwareApplier.h:
* platform/graphics/filters/software/FETurbulenceSoftwareApplier.cpp:
(WebCore::FETurbulenceSoftwareApplier::apply):
* platform/graphics/filters/software/FETurbulenceSoftwareApplier.h:
* platform/graphics/filters/software/SourceAlphaSoftwareApplier.cpp:
(WebCore::SourceAlphaSoftwareApplier::apply):
* platform/graphics/filters/software/SourceAlphaSoftwareApplier.h:
* platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp:
(WebCore::SourceGraphicSoftwareApplier::apply):
* platform/graphics/filters/software/SourceGraphicSoftwareApplier.h:
* rendering/CSSFilter.cpp:
(WebCore::CSSFilter::output):
* rendering/svg/RenderSVGResourceFilter.cpp:
(WebCore::RenderSVGResourceFilter::postApplyResource):
* svg/graphics/filters/SVGFEImage.cpp:
(WebCore::FEImageSoftwareApplier::apply):
(WebCore::FEImage::platformApplySoftware):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@286164 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 2b2ff86..fa68ba3 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,152 @@
+2021-11-25  Said Abou-Hallawa  <said@apple.com>
+
+        [GPU Process] Make FilterEffect appliers take FilterImages in their apply() methods
+        https://bugs.webkit.org/show_bug.cgi?id=233487
+
+        Reviewed by Cameron McCormack.
+
+        Eventually the FilterImage will be removed from FilterEffect. So this is
+        a step towards making the FilterEffect hold the effect data only. To do 
+        his change, FilterImage needs to hold two new members: primitiveSubregion
+        and isAlphaImage.
+
+        FilterEffect::setIsAlphaImage() is not needed and isAlphaImage() will be
+        a virtual function but it will be renamed resultIsAlphaImage(). The result 
+        of this function will be stored in the result FilterImage.
+
+        FEGaussianBlurSoftwareApplier::apply() is the only user of isAlphaImage.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/graphics/filters/FEBlend.cpp:
+        (WebCore::FEBlend::platformApplySoftware):
+        * platform/graphics/filters/FEColorMatrix.cpp:
+        (WebCore::FEColorMatrix::resultIsAlphaImage const):
+        (WebCore::FEColorMatrix::platformApplySoftware):
+        * platform/graphics/filters/FEColorMatrix.h:
+        * platform/graphics/filters/FEComponentTransfer.cpp:
+        (WebCore::FEComponentTransfer::platformApplySoftware):
+        * platform/graphics/filters/FEComposite.cpp:
+        (WebCore::FEComposite::platformApplySoftware):
+        * platform/graphics/filters/FEConvolveMatrix.cpp:
+        (WebCore::FEConvolveMatrix::platformApplySoftware):
+        * platform/graphics/filters/FEDisplacementMap.cpp:
+        (WebCore::FEDisplacementMap::platformApplySoftware):
+        * platform/graphics/filters/FEDropShadow.cpp:
+        (WebCore::FEDropShadow::platformApplySoftware):
+        * platform/graphics/filters/FEFlood.cpp:
+        (WebCore::FEFlood::platformApplySoftware):
+        * platform/graphics/filters/FEGaussianBlur.cpp:
+        (WebCore::FEGaussianBlur::resultIsAlphaImage const):
+        (WebCore::FEGaussianBlur::platformApplySoftware):
+        * platform/graphics/filters/FEGaussianBlur.h:
+        * platform/graphics/filters/FELighting.cpp:
+        (WebCore::FELighting::platformApplySoftware):
+        * platform/graphics/filters/FEMerge.cpp:
+        (WebCore::FEMerge::platformApplySoftware):
+        * platform/graphics/filters/FEMorphology.cpp:
+        (WebCore::FEMorphology::resultIsAlphaImage const):
+        (WebCore::FEMorphology::platformApplySoftware):
+        * platform/graphics/filters/FEMorphology.h:
+        * platform/graphics/filters/FEOffset.cpp:
+        (WebCore::FEOffset::resultIsAlphaImage const):
+        (WebCore::FEOffset::platformApplySoftware):
+        * platform/graphics/filters/FEOffset.h:
+        * platform/graphics/filters/FETile.cpp:
+        (WebCore::FETile::resultIsAlphaImage const):
+        (WebCore::FETile::platformApplySoftware):
+        * platform/graphics/filters/FETile.h:
+        * platform/graphics/filters/FETurbulence.cpp:
+        (WebCore::FETurbulence::platformApplySoftware):
+        * platform/graphics/filters/Filter.h:
+        (WebCore::Filter::maxEffectRect const):
+        * platform/graphics/filters/FilterEffect.cpp:
+        (WebCore::FilterEffect::apply):
+        (WebCore::FilterEffect::inputFilterImages const):
+        (WebCore::FilterEffect::externalRepresentation const):
+        (WebCore::FilterEffect::createResult): Deleted.
+        (WebCore::FilterEffect::imageBufferResult): Deleted.
+        (WebCore::FilterEffect::pixelBufferResult): Deleted.
+        (WebCore::FilterEffect::getPixelBufferResult): Deleted.
+        (WebCore::FilterEffect::copyPixelBufferResult const): Deleted.
+        * platform/graphics/filters/FilterEffect.h:
+        (WebCore::FilterEffect::filterImage const):
+        (WebCore::FilterEffect::resultIsAlphaImage const):
+        (WebCore::FilterEffect::isAlphaImage const): Deleted.
+        (WebCore::FilterEffect::setIsAlphaImage): Deleted.
+        (WebCore::FilterEffect::normalizedFloats): Deleted.
+        * platform/graphics/filters/FilterEffectApplier.h:
+        * platform/graphics/filters/FilterImage.cpp:
+        (WebCore::FilterImage::create):
+        (WebCore::FilterImage::FilterImage):
+        * platform/graphics/filters/FilterImage.h:
+        (WebCore::FilterImage::primitiveSubregion const):
+        (WebCore::FilterImage::isAlphaImage const):
+        * platform/graphics/filters/FilterImageVector.h: Copied from Source/WebCore/platform/graphics/filters/FilterEffectApplier.h.
+        * platform/graphics/filters/SourceAlpha.cpp:
+        (WebCore::SourceAlpha::platformApplySoftware):
+        * platform/graphics/filters/SourceGraphic.cpp:
+        (WebCore::SourceGraphic::platformApplySoftware):
+        * platform/graphics/filters/software/FEBlendSoftwareApplier.cpp:
+        (WebCore::FEBlendSoftwareApplier::apply):
+        * platform/graphics/filters/software/FEBlendSoftwareApplier.h:
+        * platform/graphics/filters/software/FEColorMatrixSoftwareApplier.cpp:
+        (WebCore::FEColorMatrixSoftwareApplier::apply):
+        * platform/graphics/filters/software/FEColorMatrixSoftwareApplier.h:
+        * platform/graphics/filters/software/FEComponentTransferSoftwareApplier.cpp:
+        (WebCore::FEComponentTransferSoftwareApplier::apply):
+        * platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h:
+        * platform/graphics/filters/software/FECompositeSoftwareApplier.cpp:
+        (WebCore::FECompositeSoftwareApplier::applyArithmetic):
+        (WebCore::FECompositeSoftwareApplier::applyNonArithmetic):
+        (WebCore::FECompositeSoftwareApplier::apply):
+        * platform/graphics/filters/software/FECompositeSoftwareApplier.h:
+        * platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.cpp:
+        (WebCore::FEConvolveMatrixSoftwareApplier::apply):
+        * platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.h:
+        * platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.cpp:
+        (WebCore::FEDisplacementMapSoftwareApplier::apply):
+        * platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.h:
+        * platform/graphics/filters/software/FEDropShadowSoftwareApplier.cpp:
+        (WebCore::FEDropShadowSoftwareApplier::apply):
+        * platform/graphics/filters/software/FEDropShadowSoftwareApplier.h:
+        * platform/graphics/filters/software/FEFloodSoftwareApplier.cpp:
+        (WebCore::FEFloodSoftwareApplier::apply):
+        * platform/graphics/filters/software/FEFloodSoftwareApplier.h:
+        * platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.cpp:
+        (WebCore::FEGaussianBlurSoftwareApplier::apply):
+        * platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.h:
+        * platform/graphics/filters/software/FELightingSoftwareApplier.cpp:
+        (WebCore::FELightingSoftwareApplier::apply):
+        * platform/graphics/filters/software/FELightingSoftwareApplier.h:
+        * platform/graphics/filters/software/FEMergeSoftwareApplier.cpp:
+        (WebCore::FEMergeSoftwareApplier::apply):
+        * platform/graphics/filters/software/FEMergeSoftwareApplier.h:
+        * platform/graphics/filters/software/FEMorphologySoftwareApplier.cpp:
+        (WebCore::FEMorphologySoftwareApplier::apply):
+        * platform/graphics/filters/software/FEMorphologySoftwareApplier.h:
+        * platform/graphics/filters/software/FEOffsetSoftwareApplier.cpp:
+        (WebCore::FEOffsetSoftwareApplier::apply):
+        * platform/graphics/filters/software/FEOffsetSoftwareApplier.h:
+        * platform/graphics/filters/software/FETileSoftwareApplier.cpp:
+        (WebCore::FETileSoftwareApplier::apply):
+        * platform/graphics/filters/software/FETileSoftwareApplier.h:
+        * platform/graphics/filters/software/FETurbulenceSoftwareApplier.cpp:
+        (WebCore::FETurbulenceSoftwareApplier::apply):
+        * platform/graphics/filters/software/FETurbulenceSoftwareApplier.h:
+        * platform/graphics/filters/software/SourceAlphaSoftwareApplier.cpp:
+        (WebCore::SourceAlphaSoftwareApplier::apply):
+        * platform/graphics/filters/software/SourceAlphaSoftwareApplier.h:
+        * platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp:
+        (WebCore::SourceGraphicSoftwareApplier::apply):
+        * platform/graphics/filters/software/SourceGraphicSoftwareApplier.h:
+        * rendering/CSSFilter.cpp:
+        (WebCore::CSSFilter::output):
+        * rendering/svg/RenderSVGResourceFilter.cpp:
+        (WebCore::RenderSVGResourceFilter::postApplyResource):
+        * svg/graphics/filters/SVGFEImage.cpp:
+        (WebCore::FEImageSoftwareApplier::apply):
+        (WebCore::FEImage::platformApplySoftware):
+
 2021-11-25  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         Unreviewed. Fix GTK distcheck build
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index 0aca7c3..c6c24a4 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -10931,6 +10931,7 @@
 		72A13AD7274DE57800E2A88E /* SourceGraphicSoftwareApplier.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SourceGraphicSoftwareApplier.h; sourceTree = "<group>"; };
 		72B4EF74274E233300293C2F /* FEBlendSoftwareApplier.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FEBlendSoftwareApplier.h; sourceTree = "<group>"; };
 		72B4EF75274E233400293C2F /* FEBlendSoftwareApplier.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FEBlendSoftwareApplier.cpp; sourceTree = "<group>"; };
+		72B4EF7C274EE37F00293C2F /* FilterImageVector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FilterImageVector.h; sourceTree = "<group>"; };
 		72BAC3A423E17327008D741C /* ImageBufferBackend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageBufferBackend.cpp; sourceTree = "<group>"; };
 		72BAC3A523E17328008D741C /* ImageBufferBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageBufferBackend.h; sourceTree = "<group>"; };
 		72BAC3A623E17328008D741C /* PlatformImageBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformImageBuffer.h; sourceTree = "<group>"; };
@@ -26027,6 +26028,7 @@
 				7262D756272A174100C56A09 /* FilterFunction.h */,
 				72435EF5273D07670005E7EE /* FilterImage.cpp */,
 				72435EF4273D07670005E7EE /* FilterImage.h */,
+				72B4EF7C274EE37F00293C2F /* FilterImageVector.h */,
 				49ECEB631499790D00CDD3A4 /* FilterOperation.cpp */,
 				49ECEB641499790D00CDD3A4 /* FilterOperation.h */,
 				49ECEB651499790D00CDD3A4 /* FilterOperations.cpp */,
diff --git a/Source/WebCore/platform/graphics/filters/FEBlend.cpp b/Source/WebCore/platform/graphics/filters/FEBlend.cpp
index 29dcb0f..35cd655 100644
--- a/Source/WebCore/platform/graphics/filters/FEBlend.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEBlend.cpp
@@ -53,7 +53,7 @@
 
 bool FEBlend::platformApplySoftware(const Filter& filter)
 {
-    return FEBlendSoftwareApplier(*this).apply(filter, inputEffects());
+    return FEBlendSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 TextStream& FEBlend::externalRepresentation(TextStream& ts, RepresentationType representation) const
diff --git a/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp
index d685a14..5aa882a 100644
--- a/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -93,9 +93,14 @@
     return normalizedValues;
 }
 
+bool FEColorMatrix::resultIsAlphaImage() const
+{
+    return m_type == FECOLORMATRIX_TYPE_LUMINANCETOALPHA;
+}
+
 bool FEColorMatrix::platformApplySoftware(const Filter& filter)
 {
-    return FEColorMatrixSoftwareApplier(*this).apply(filter, inputEffects());
+    return FEColorMatrixSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 static TextStream& operator<<(TextStream& ts, const ColorMatrixType& type)
diff --git a/Source/WebCore/platform/graphics/filters/FEColorMatrix.h b/Source/WebCore/platform/graphics/filters/FEColorMatrix.h
index 5601eb0..e1ac688 100644
--- a/Source/WebCore/platform/graphics/filters/FEColorMatrix.h
+++ b/Source/WebCore/platform/graphics/filters/FEColorMatrix.h
@@ -52,6 +52,8 @@
 private:
     FEColorMatrix(ColorMatrixType, Vector<float>&&);
 
+    bool resultIsAlphaImage() const override;
+
     bool platformApplySoftware(const Filter&) override;
 
     WTF::TextStream& externalRepresentation(WTF::TextStream&, RepresentationType) const override;
diff --git a/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
index 86f9de1..bb5428a 100644
--- a/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
@@ -46,7 +46,7 @@
 
 bool FEComponentTransfer::platformApplySoftware(const Filter& filter)
 {
-    return FEComponentTransferSoftwareApplier(*this).apply(filter, inputEffects());
+    return FEComponentTransferSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 static TextStream& operator<<(TextStream& ts, ComponentTransferType type)
diff --git a/Source/WebCore/platform/graphics/filters/FEComposite.cpp b/Source/WebCore/platform/graphics/filters/FEComposite.cpp
index ef37e4c..5a48ea4 100644
--- a/Source/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -109,7 +109,7 @@
 
 bool FEComposite::platformApplySoftware(const Filter& filter)
 {
-    return FECompositeSoftwareApplier(*this).apply(filter, inputEffects());
+    return FECompositeSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 static TextStream& operator<<(TextStream& ts, const CompositeOperationType& type)
diff --git a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
index f78f057..ddbd95e 100644
--- a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
@@ -115,7 +115,7 @@
 
 bool FEConvolveMatrix::platformApplySoftware(const Filter& filter)
 {
-    return FEConvolveMatrixSoftwareApplier(*this).apply(filter, inputEffects());
+    return FEConvolveMatrixSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 static TextStream& operator<<(TextStream& ts, const EdgeModeType& type)
diff --git a/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp b/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
index f4d5f49..5adefd7 100644
--- a/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
@@ -85,7 +85,7 @@
 
 bool FEDisplacementMap::platformApplySoftware(const Filter& filter)
 {
-    return FEDisplacementMapSoftwareApplier(*this).apply(filter, inputEffects());
+    return FEDisplacementMapSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 static TextStream& operator<<(TextStream& ts, const ChannelSelectorType& type)
diff --git a/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp b/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp
index e966ddb..f5f5c60 100644
--- a/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp
@@ -68,7 +68,7 @@
 
 bool FEDropShadow::platformApplySoftware(const Filter& filter)
 {
-    return FEDropShadowSoftwareApplier(*this).apply(filter, inputEffects());
+    return FEDropShadowSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
     
 IntOutsets FEDropShadow::outsets() const
diff --git a/Source/WebCore/platform/graphics/filters/FEFlood.cpp b/Source/WebCore/platform/graphics/filters/FEFlood.cpp
index eaa78c3..a4814ee 100644
--- a/Source/WebCore/platform/graphics/filters/FEFlood.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEFlood.cpp
@@ -60,7 +60,7 @@
 
 bool FEFlood::platformApplySoftware(const Filter& filter)
 {
-    return FEFloodSoftwareApplier(*this).apply(filter, inputEffects());
+    return FEFloodSoftwareApplier(*this).apply(filter, { }, *filterImage());
 }
 
 TextStream& FEFlood::externalRepresentation(TextStream& ts, RepresentationType representation) const
diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
index 3bcc59f..ea9d333 100644
--- a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
@@ -125,17 +125,22 @@
     setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
 }
 
-bool FEGaussianBlur::platformApplySoftware(const Filter& filter)
-{
-    return FEGaussianBlurSoftwareApplier(*this).apply(filter, inputEffects());
-}
-
 IntOutsets FEGaussianBlur::outsets() const
 {
     IntSize outsetSize = calculateOutsetSize({ m_stdX, m_stdY });
     return { outsetSize.height(), outsetSize.width(), outsetSize.height(), outsetSize.width() };
 }
 
+bool FEGaussianBlur::resultIsAlphaImage() const
+{
+    return inputEffect(0)->resultIsAlphaImage();
+}
+
+bool FEGaussianBlur::platformApplySoftware(const Filter& filter)
+{
+    return FEGaussianBlurSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
+}
+
 TextStream& FEGaussianBlur::externalRepresentation(TextStream& ts, RepresentationType representation) const
 {
     ts << indent << "[feGaussianBlur";
diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h
index 9082264..4d4e020 100644
--- a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h
+++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h
@@ -51,6 +51,8 @@
 
     IntOutsets outsets() const override;
 
+    bool resultIsAlphaImage() const override;
+
     bool platformApplySoftware(const Filter&) override;
 
     WTF::TextStream& externalRepresentation(WTF::TextStream&, RepresentationType) const override;
diff --git a/Source/WebCore/platform/graphics/filters/FELighting.cpp b/Source/WebCore/platform/graphics/filters/FELighting.cpp
index ccde6eb..309df9e 100644
--- a/Source/WebCore/platform/graphics/filters/FELighting.cpp
+++ b/Source/WebCore/platform/graphics/filters/FELighting.cpp
@@ -83,7 +83,7 @@
 
 bool FELighting::platformApplySoftware(const Filter& filter)
 {
-    return FELightingSoftwareApplier(*this).apply(filter, inputEffects());
+    return FELightingSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/FEMerge.cpp b/Source/WebCore/platform/graphics/filters/FEMerge.cpp
index 3f3621c..0c4220f 100644
--- a/Source/WebCore/platform/graphics/filters/FEMerge.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEMerge.cpp
@@ -40,7 +40,7 @@
 
 bool FEMerge::platformApplySoftware(const Filter& filter)
 {
-    return FEMergeSoftwareApplier(*this).apply(filter, inputEffects());
+    return FEMergeSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 TextStream& FEMerge::externalRepresentation(TextStream& ts, RepresentationType representation) const
diff --git a/Source/WebCore/platform/graphics/filters/FEMorphology.cpp b/Source/WebCore/platform/graphics/filters/FEMorphology.cpp
index 1a22b50..b946e20 100644
--- a/Source/WebCore/platform/graphics/filters/FEMorphology.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEMorphology.cpp
@@ -79,9 +79,14 @@
     setAbsolutePaintRect(enclosingIntRect(paintRect));
 }
 
+bool FEMorphology::resultIsAlphaImage() const
+{
+    return inputEffect(0)->resultIsAlphaImage();
+}
+
 bool FEMorphology::platformApplySoftware(const Filter& filter)
 {
-    return FEMorphologySoftwareApplier(*this).apply(filter, inputEffects());
+    return FEMorphologySoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 static TextStream& operator<<(TextStream& ts, const MorphologyOperatorType& type)
diff --git a/Source/WebCore/platform/graphics/filters/FEMorphology.h b/Source/WebCore/platform/graphics/filters/FEMorphology.h
index 7193998..dbcdab6 100644
--- a/Source/WebCore/platform/graphics/filters/FEMorphology.h
+++ b/Source/WebCore/platform/graphics/filters/FEMorphology.h
@@ -50,6 +50,8 @@
 
     void determineAbsolutePaintRect(const Filter&) override;
 
+    bool resultIsAlphaImage() const override;
+
     bool platformApplySoftware(const Filter&) override;
 
     WTF::TextStream& externalRepresentation(WTF::TextStream&, RepresentationType) const override;
diff --git a/Source/WebCore/platform/graphics/filters/FEOffset.cpp b/Source/WebCore/platform/graphics/filters/FEOffset.cpp
index 52c9b9c..13a0c6f 100644
--- a/Source/WebCore/platform/graphics/filters/FEOffset.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEOffset.cpp
@@ -64,9 +64,14 @@
     setAbsolutePaintRect(enclosingIntRect(paintRect));
 }
 
+bool FEOffset::resultIsAlphaImage() const
+{
+    return inputEffect(0)->resultIsAlphaImage();
+}
+
 bool FEOffset::platformApplySoftware(const Filter& filter)
 {
-    return FEOffsetSoftwareApplier(*this).apply(filter, inputEffects());
+    return FEOffsetSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 TextStream& FEOffset::externalRepresentation(TextStream& ts, RepresentationType representation) const
diff --git a/Source/WebCore/platform/graphics/filters/FEOffset.h b/Source/WebCore/platform/graphics/filters/FEOffset.h
index 7ffc552..ed73f27 100644
--- a/Source/WebCore/platform/graphics/filters/FEOffset.h
+++ b/Source/WebCore/platform/graphics/filters/FEOffset.h
@@ -41,6 +41,8 @@
 
     void determineAbsolutePaintRect(const Filter&) override;
 
+    bool resultIsAlphaImage() const override;
+
     bool platformApplySoftware(const Filter&) override;
 
     WTF::TextStream& externalRepresentation(WTF::TextStream&, RepresentationType) const override;
diff --git a/Source/WebCore/platform/graphics/filters/FETile.cpp b/Source/WebCore/platform/graphics/filters/FETile.cpp
index 249cb87..5a0bce7 100644
--- a/Source/WebCore/platform/graphics/filters/FETile.cpp
+++ b/Source/WebCore/platform/graphics/filters/FETile.cpp
@@ -23,7 +23,6 @@
 #include "FETile.h"
 
 #include "FETileSoftwareApplier.h"
-#include "GraphicsContext.h"
 #include <wtf/text/TextStream.h>
 
 namespace WebCore {
@@ -38,9 +37,14 @@
 {
 }
 
+bool FETile::resultIsAlphaImage() const
+{
+    return inputEffect(0)->resultIsAlphaImage();
+}
+
 bool FETile::platformApplySoftware(const Filter& filter)
 {
-    return FETileSoftwareApplier(*this).apply(filter, inputEffects());
+    return FETileSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 TextStream& FETile::externalRepresentation(TextStream& ts, RepresentationType representation) const
diff --git a/Source/WebCore/platform/graphics/filters/FETile.h b/Source/WebCore/platform/graphics/filters/FETile.h
index 717b5c2..806aba3 100644
--- a/Source/WebCore/platform/graphics/filters/FETile.h
+++ b/Source/WebCore/platform/graphics/filters/FETile.h
@@ -35,6 +35,8 @@
 
     void determineAbsolutePaintRect(const Filter&) override { setAbsolutePaintRect(enclosingIntRect(maxEffectRect())); }
 
+    bool resultIsAlphaImage() const override;
+
     bool platformApplySoftware(const Filter&) override;
 
     WTF::TextStream& externalRepresentation(WTF::TextStream&, RepresentationType) const override;
diff --git a/Source/WebCore/platform/graphics/filters/FETurbulence.cpp b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp
index 3223af7..e4186a4 100644
--- a/Source/WebCore/platform/graphics/filters/FETurbulence.cpp
+++ b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp
@@ -97,7 +97,7 @@
 
 bool FETurbulence::platformApplySoftware(const Filter& filter)
 {
-    return FETurbulenceSoftwareApplier(*this).apply(filter, inputEffects());
+    return FETurbulenceSoftwareApplier(*this).apply(filter, { }, *filterImage());
 }
 
 static TextStream& operator<<(TextStream& ts, TurbulenceType type)
diff --git a/Source/WebCore/platform/graphics/filters/Filter.h b/Source/WebCore/platform/graphics/filters/Filter.h
index 884e788..cde81fb 100644
--- a/Source/WebCore/platform/graphics/filters/Filter.h
+++ b/Source/WebCore/platform/graphics/filters/Filter.h
@@ -53,6 +53,11 @@
     RenderingMode renderingMode() const { return m_renderingMode; }
     void setRenderingMode(RenderingMode renderingMode) { m_renderingMode = renderingMode; }
 
+    FloatRect maxEffectRect(const FloatRect& primitiveSubregion) const
+    {
+        return intersection(primitiveSubregion, m_filterRegion);
+    }
+
 protected:
     Filter(Filter::Type filterType, const FloatSize& filterScale)
         : FilterFunction(filterType)
diff --git a/Source/WebCore/platform/graphics/filters/FilterEffect.cpp b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
index aa10a7e..f330694 100644
--- a/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
+++ b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -158,20 +158,15 @@
         for (auto& in : m_inputEffects)
             in->correctPremultipliedResultIfNeeded();
     }
-    
-    if (!createResult())
+
+    m_filterImage = FilterImage::create(m_filterPrimitiveSubregion, m_absolutePaintRect, resultIsAlphaImage(), filter.renderingMode(), resultColorSpace());
+    if (!m_filterImage)
         return false;
 
     // Add platform specific apply functions here and return earlier.
     return platformApplySoftware(filter);
 }
 
-bool FilterEffect::createResult()
-{
-    m_filterImage = FilterImage::create(m_absolutePaintRect, RenderingMode::Unaccelerated, resultColorSpace());
-    return m_filterImage;
-}
-
 void FilterEffect::clearResult()
 {
     m_filterImage = nullptr;
@@ -186,30 +181,14 @@
         effect->clearResultsRecursive();
 }
 
-ImageBuffer* FilterEffect::imageBufferResult()
+FilterImageVector FilterEffect::inputFilterImages() const
 {
-    if (!hasResult())
-        return nullptr;
-    return m_filterImage->imageBuffer();
-}
+    FilterImageVector filterImages;
 
-PixelBuffer* FilterEffect::pixelBufferResult(AlphaPremultiplication alphaFormat)
-{
-    if (!hasResult())
-        return nullptr;
-    return m_filterImage->pixelBuffer(alphaFormat);
-}
+    for (auto& inputEffect : m_inputEffects)
+        filterImages.append(*inputEffect->filterImage());
 
-std::optional<PixelBuffer> FilterEffect::getPixelBufferResult(AlphaPremultiplication alphaFormat, const IntRect& sourceRect, std::optional<DestinationColorSpace> colorSpace)
-{
-    ASSERT(hasResult());
-    return m_filterImage->getPixelBuffer(alphaFormat, sourceRect, colorSpace);
-}
-
-void FilterEffect::copyPixelBufferResult(PixelBuffer& destinationPixelBuffer, const IntRect& sourceRect) const
-{
-    ASSERT(hasResult());
-    m_filterImage->copyPixelBuffer(destinationPixelBuffer, sourceRect);
+    return filterImages;
 }
 
 void FilterEffect::correctPremultipliedResultIfNeeded()
@@ -233,7 +212,7 @@
     
     if (representationType == RepresentationType::Debugging) {
         TextStream::IndentScope indentScope(ts);
-        ts.dumpProperty("alpha image", m_alphaImage);
+        ts.dumpProperty("alpha image", resultIsAlphaImage());
         ts.dumpProperty("operating colorspace", operatingColorSpace());
         ts.dumpProperty("result colorspace", resultColorSpace());
         ts << "\n" << indent;
diff --git a/Source/WebCore/platform/graphics/filters/FilterEffect.h b/Source/WebCore/platform/graphics/filters/FilterEffect.h
index 916bbe8..1f312c9 100644
--- a/Source/WebCore/platform/graphics/filters/FilterEffect.h
+++ b/Source/WebCore/platform/graphics/filters/FilterEffect.h
@@ -26,6 +26,7 @@
 #include "FilterEffectVector.h"
 #include "FilterFunction.h"
 #include "FilterImage.h"
+#include "FilterImageVector.h"
 #include "IntRect.h"
 #include <wtf/Vector.h>
 
@@ -40,16 +41,13 @@
 
 class FilterEffect : public FilterFunction {
 public:
-    bool createResult();
     void clearResult() override;
     void clearResultsRecursive();
-
     bool hasResult() const { return m_filterImage; }
 
-    ImageBuffer* imageBufferResult();
-    PixelBuffer* pixelBufferResult(AlphaPremultiplication);
-    std::optional<PixelBuffer> getPixelBufferResult(AlphaPremultiplication, const IntRect& sourceRect, std::optional<DestinationColorSpace> = std::nullopt);
-    void copyPixelBufferResult(PixelBuffer& destinationPixelBuffer, const IntRect& sourceRect) const;
+    FilterImage* filterImage() const { return m_filterImage.get(); }
+    FilterImageVector inputFilterImages() const;
+
     void correctPremultipliedResultIfNeeded();
 
     FilterEffectVector& inputEffects() { return m_inputEffects; }
@@ -62,10 +60,6 @@
     // Recurses on inputs.
     FloatRect determineFilterPrimitiveSubregion(const Filter&);
 
-    // Solid black image with different alpha values.
-    bool isAlphaImage() const { return m_alphaImage; }
-    void setIsAlphaImage(bool alphaImage) { m_alphaImage = alphaImage; }
-
     IntRect absolutePaintRect() const { return m_absolutePaintRect; }
     void setAbsolutePaintRect(const IntRect& absolutePaintRect) { m_absolutePaintRect = absolutePaintRect; }
 
@@ -114,19 +108,13 @@
     const DestinationColorSpace& operatingColorSpace() const { return m_operatingColorSpace; }
     virtual void setOperatingColorSpace(const DestinationColorSpace& colorSpace) { m_operatingColorSpace = colorSpace; }
 
+    // Solid black image with different alpha values.
+    virtual bool resultIsAlphaImage() const { return false; }
     virtual const DestinationColorSpace& resultColorSpace() const { return m_operatingColorSpace; }
 
     virtual void transformResultColorSpace(FilterEffect* in, const int) { in->transformResultColorSpace(m_operatingColorSpace); }
     void transformResultColorSpace(const DestinationColorSpace&);
     
-    static Vector<float> normalizedFloats(const Vector<float>& values)
-    {
-        Vector<float> normalizedValues(values.size());
-        for (size_t i = 0; i < values.size(); ++i)
-            normalizedValues[i] = normalizedFloat(values[i]);
-        return normalizedValues;
-    }
-
 protected:
     using FilterFunction::FilterFunction;
 
@@ -158,7 +146,6 @@
     // filterPrimitiveSubregion mapped to absolute coordinates before clipping.
     FloatRect m_absoluteUnclippedSubregion;
 
-    bool m_alphaImage { false };
     bool m_hasX { false };
     bool m_hasY { false };
     bool m_hasWidth { false };
diff --git a/Source/WebCore/platform/graphics/filters/FilterEffectApplier.h b/Source/WebCore/platform/graphics/filters/FilterEffectApplier.h
index f7a58d0..fe324f7 100644
--- a/Source/WebCore/platform/graphics/filters/FilterEffectApplier.h
+++ b/Source/WebCore/platform/graphics/filters/FilterEffectApplier.h
@@ -25,7 +25,7 @@
 
 #pragma once
 
-#include "FilterEffectVector.h"
+#include "FilterImageVector.h"
 
 namespace WebCore {
 
@@ -36,7 +36,7 @@
     FilterEffectApplier() = default;
     virtual ~FilterEffectApplier() = default;
     
-    virtual bool apply(const Filter&, const FilterEffectVector& inputs) = 0;
+    virtual bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) = 0;
 };
 
 template<typename FilterEffectType>
diff --git a/Source/WebCore/platform/graphics/filters/FilterImage.cpp b/Source/WebCore/platform/graphics/filters/FilterImage.cpp
index 8430258..7691678 100644
--- a/Source/WebCore/platform/graphics/filters/FilterImage.cpp
+++ b/Source/WebCore/platform/graphics/filters/FilterImage.cpp
@@ -37,14 +37,16 @@
 
 namespace WebCore {
 
-RefPtr<FilterImage> FilterImage::create(const IntRect& absoluteImageRect, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
+RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
 {
     ASSERT(!ImageBuffer::sizeNeedsClamping(absoluteImageRect.size()));
-    return adoptRef(new FilterImage(absoluteImageRect, renderingMode, colorSpace));
+    return adoptRef(new FilterImage(primitiveSubregion, absoluteImageRect, isAlphaImage, renderingMode, colorSpace));
 }
 
-FilterImage::FilterImage(const IntRect& absoluteImageRect, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
-    : m_absoluteImageRect(absoluteImageRect)
+FilterImage::FilterImage(const FloatRect& primitiveSubregion, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
+    : m_primitiveSubregion(primitiveSubregion)
+    , m_absoluteImageRect(absoluteImageRect)
+    , m_isAlphaImage(isAlphaImage)
     , m_renderingMode(renderingMode)
     , m_colorSpace(colorSpace)
 {
diff --git a/Source/WebCore/platform/graphics/filters/FilterImage.h b/Source/WebCore/platform/graphics/filters/FilterImage.h
index 272c3e0..93cdec8 100644
--- a/Source/WebCore/platform/graphics/filters/FilterImage.h
+++ b/Source/WebCore/platform/graphics/filters/FilterImage.h
@@ -38,10 +38,12 @@
 
 class FilterImage : public RefCounted<FilterImage> {
 public:
-    static RefPtr<FilterImage> create(const IntRect& absoluteImageRect, RenderingMode, const DestinationColorSpace&);
+    static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode, const DestinationColorSpace&);
 
+    FloatRect primitiveSubregion() const { return m_primitiveSubregion; }
     IntRect absoluteImageRect() const { return m_absoluteImageRect; }
 
+    bool isAlphaImage() const { return m_isAlphaImage; }
     RenderingMode renderingMode() const { return m_renderingMode; }
     const DestinationColorSpace& colorSpace() const { return m_colorSpace; }
 
@@ -55,14 +57,16 @@
     void transformToColorSpace(const DestinationColorSpace&);
 
 private:
-    FilterImage(const IntRect& absoluteImageRect, RenderingMode, const DestinationColorSpace&);
+    FilterImage(const FloatRect& primitiveSubregion, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode, const DestinationColorSpace&);
 
     std::optional<PixelBuffer>& pixelBufferSlot(AlphaPremultiplication);
 
     bool requiresPixelBufferColorSpaceConversion(std::optional<DestinationColorSpace>) const;
 
+    FloatRect m_primitiveSubregion;
     IntRect m_absoluteImageRect;
 
+    bool m_isAlphaImage { false };
     RenderingMode m_renderingMode;
     DestinationColorSpace m_colorSpace;
 
diff --git a/Source/WebCore/platform/graphics/filters/FilterImageVector.h b/Source/WebCore/platform/graphics/filters/FilterImageVector.h
new file mode 100644
index 0000000..6a75359
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FilterImageVector.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FilterImage;
+
+using FilterImageVector = Vector<Ref<FilterImage>>;
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp b/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp
index 018b576..bc5a255 100644
--- a/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp
+++ b/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp
@@ -47,7 +47,7 @@
 
 bool SourceAlpha::platformApplySoftware(const Filter& filter)
 {
-    return SourceAlphaSoftwareApplier(*this).apply(filter, inputEffects());
+    return SourceAlphaSoftwareApplier(*this).apply(filter, inputFilterImages(), *filterImage());
 }
 
 TextStream& SourceAlpha::externalRepresentation(TextStream& ts, RepresentationType) const
diff --git a/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp b/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp
index 349da0d..106f544 100644
--- a/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp
+++ b/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp
@@ -45,7 +45,7 @@
 
 bool SourceGraphic::platformApplySoftware(const Filter& filter)
 {
-    return SourceGraphicSoftwareApplier(*this).apply(filter, inputEffects());
+    return SourceGraphicSoftwareApplier(*this).apply(filter, { }, *filterImage());
 }
 
 TextStream& SourceGraphic::externalRepresentation(TextStream& ts, RepresentationType) const
diff --git a/Source/WebCore/platform/graphics/filters/software/FEBlendSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FEBlendSoftwareApplier.cpp
index b523a2b..4af777a 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEBlendSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FEBlendSoftwareApplier.cpp
@@ -34,23 +34,23 @@
 namespace WebCore {
 
 #if !HAVE(ARM_NEON_INTRINSICS)
-bool FEBlendSoftwareApplier::apply(const Filter&, const FilterEffectVector& inputEffects)
+bool FEBlendSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
-    FilterEffect* in2 = inputEffects[1].get();
+    auto& input = inputs[0].get();
+    auto& input2 = inputs[1].get();
 
-    auto resultImage = m_effect.imageBufferResult();
+    auto resultImage = result.imageBuffer();
     if (!resultImage)
         return false;
 
-    auto imageBuffer = in->imageBufferResult();
-    auto imageBuffer2 = in2->imageBufferResult();
-    if (!imageBuffer || !imageBuffer2)
+    auto inputImage = input.imageBuffer();
+    auto inputImage2 = input2.imageBuffer();
+    if (!inputImage || !inputImage2)
         return false;
 
-    GraphicsContext& filterContext = resultImage->context();
-    filterContext.drawImageBuffer(*imageBuffer2, m_effect.drawingRegionOfInputImage(in2->absolutePaintRect()));
-    filterContext.drawImageBuffer(*imageBuffer, m_effect.drawingRegionOfInputImage(in->absolutePaintRect()), { { }, imageBuffer->logicalSize() }, { CompositeOperator::SourceOver, m_effect.blendMode() });
+    auto& filterContext = resultImage->context();
+    filterContext.drawImageBuffer(*inputImage2, m_effect.drawingRegionOfInputImage(input2.absoluteImageRect()));
+    filterContext.drawImageBuffer(*inputImage, m_effect.drawingRegionOfInputImage(input.absoluteImageRect()), { { }, inputImage->logicalSize() }, { CompositeOperator::SourceOver, m_effect.blendMode() });
     return true;
 }
 #endif
diff --git a/Source/WebCore/platform/graphics/filters/software/FEBlendSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEBlendSoftwareApplier.h
index 9ada841..1502852 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEBlendSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEBlendSoftwareApplier.h
@@ -35,7 +35,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/software/FEColorMatrixSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FEColorMatrixSoftwareApplier.cpp
index 67ec0a1..44a3950 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEColorMatrixSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FEColorMatrixSoftwareApplier.cpp
@@ -259,27 +259,24 @@
     applyPlatformUnaccelerated(pixelBuffer);
 }
 
-bool FEColorMatrixSoftwareApplier::apply(const Filter&, const FilterEffectVector& inputEffects)
+bool FEColorMatrixSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result)
 {
-    auto in = inputEffects[0].get();
+    auto& input = inputs[0].get();
 
-    auto resultImage = m_effect.imageBufferResult();
+    auto resultImage = result.imageBuffer();
     if (!resultImage)
         return false;
 
-    auto inBuffer = in->imageBufferResult();
-    if (inBuffer)
-        resultImage->context().drawImageBuffer(*inBuffer, m_effect.drawingRegionOfInputImage(in->absolutePaintRect()));
+    auto inputImage = input.imageBuffer();
+    if (inputImage)
+        resultImage->context().drawImageBuffer(*inputImage, m_effect.drawingRegionOfInputImage(input.absoluteImageRect()));
 
-    PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, m_effect.resultColorSpace() };
+    PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, result.colorSpace() };
     IntRect imageRect(IntPoint(), resultImage->truncatedLogicalSize());
     auto pixelBuffer = resultImage->getPixelBuffer(format, imageRect);
     if (!pixelBuffer)
         return false;
 
-    if (m_effect.type() == FECOLORMATRIX_TYPE_LUMINANCETOALPHA)
-        m_effect.setIsAlphaImage(true);
-
     applyPlatform(*pixelBuffer);
     resultImage->putPixelBuffer(*pixelBuffer, imageRect);
     return true;
diff --git a/Source/WebCore/platform/graphics/filters/software/FEColorMatrixSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEColorMatrixSoftwareApplier.h
index 1339489..a661945 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEColorMatrixSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEColorMatrixSoftwareApplier.h
@@ -34,7 +34,7 @@
 public:
     FEColorMatrixSoftwareApplier(FEColorMatrix&);
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 
 private:
     inline void matrix(float& red, float& green, float& blue, float& alpha) const;
diff --git a/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.cpp
index de442ad..ca09d89 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.cpp
@@ -131,16 +131,16 @@
     }
 }
 
-bool FEComponentTransferSoftwareApplier::apply(const Filter&, const FilterEffectVector& inputEffects)
+bool FEComponentTransferSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
+    auto& input = inputs[0].get();
     
-    auto destinationPixelBuffer = m_effect.pixelBufferResult(AlphaPremultiplication::Unpremultiplied);
+    auto destinationPixelBuffer = result.pixelBuffer(AlphaPremultiplication::Unpremultiplied);
     if (!destinationPixelBuffer)
         return false;
 
-    auto drawingRect = m_effect.requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
-    in->copyPixelBufferResult(*destinationPixelBuffer, drawingRect);
+    auto drawingRect = m_effect.requestedRegionOfInputPixelBuffer(input.absoluteImageRect());
+    input.copyPixelBuffer(*destinationPixelBuffer, drawingRect);
 
     applyPlatform(*destinationPixelBuffer);
     return true;
diff --git a/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h
index 5e321c71..cc90b8c 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h
@@ -35,7 +35,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 
 private:
     using LookupTable = std::array<uint8_t, 256>;
diff --git a/Source/WebCore/platform/graphics/filters/software/FECompositeSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FECompositeSoftwareApplier.cpp
index 54d5997..2c6bb4a 100644
--- a/Source/WebCore/platform/graphics/filters/software/FECompositeSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FECompositeSoftwareApplier.cpp
@@ -126,19 +126,19 @@
 }
 #endif
 
-bool FECompositeSoftwareApplier::applyArithmetic(FilterEffect* in, FilterEffect* in2)
+bool FECompositeSoftwareApplier::applyArithmetic(FilterImage& input, FilterImage& input2, FilterImage& result)
 {
-    auto destinationPixelBuffer = m_effect.pixelBufferResult(AlphaPremultiplication::Premultiplied);
+    auto destinationPixelBuffer = result.pixelBuffer(AlphaPremultiplication::Premultiplied);
     if (!destinationPixelBuffer)
         return false;
 
-    IntRect effectADrawingRect = m_effect.requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
-    auto sourcePixelBuffer = in->getPixelBufferResult(AlphaPremultiplication::Premultiplied, effectADrawingRect, m_effect.operatingColorSpace());
+    IntRect effectADrawingRect = m_effect.requestedRegionOfInputPixelBuffer(input.absoluteImageRect());
+    auto sourcePixelBuffer = input.getPixelBuffer(AlphaPremultiplication::Premultiplied, effectADrawingRect, m_effect.operatingColorSpace());
     if (!sourcePixelBuffer)
         return false;
 
-    IntRect effectBDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(in2->absolutePaintRect());
-    in2->copyPixelBufferResult(*destinationPixelBuffer, effectBDrawingRect);
+    IntRect effectBDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(input2.absoluteImageRect());
+    input2.copyPixelBuffer(*destinationPixelBuffer, effectBDrawingRect);
 
     auto& sourcePixelArray = sourcePixelBuffer->data();
     auto& destinationPixelArray = destinationPixelBuffer->data();
@@ -149,15 +149,15 @@
     return true;
 }
 
-bool FECompositeSoftwareApplier::applyNonArithmetic(FilterEffect* in, FilterEffect* in2)
+bool FECompositeSoftwareApplier::applyNonArithmetic(FilterImage& input, FilterImage& input2, FilterImage& result)
 {
-    auto resultImage = m_effect.imageBufferResult();
+    auto resultImage = result.imageBuffer();
     if (!resultImage)
         return false;
 
-    auto imageBuffer = in->imageBufferResult();
-    auto imageBuffer2 = in2->imageBufferResult();
-    if (!imageBuffer || !imageBuffer2)
+    auto inputImage = input.imageBuffer();
+    auto inputImage2 = input2.imageBuffer();
+    if (!inputImage || !inputImage2)
         return false;
 
     auto& filterContext = resultImage->context();
@@ -167,38 +167,38 @@
         return false;
 
     case FECOMPOSITE_OPERATOR_OVER:
-        filterContext.drawImageBuffer(*imageBuffer2, m_effect.drawingRegionOfInputImage(in2->absolutePaintRect()));
-        filterContext.drawImageBuffer(*imageBuffer, m_effect.drawingRegionOfInputImage(in->absolutePaintRect()));
+        filterContext.drawImageBuffer(*inputImage2, m_effect.drawingRegionOfInputImage(input2.absoluteImageRect()));
+        filterContext.drawImageBuffer(*inputImage, m_effect.drawingRegionOfInputImage(input.absoluteImageRect()));
         break;
 
     case FECOMPOSITE_OPERATOR_IN: {
         // Applies only to the intersected region.
-        IntRect destinationRect = in->absolutePaintRect();
-        destinationRect.intersect(in2->absolutePaintRect());
-        destinationRect.intersect(m_effect.absolutePaintRect());
+        IntRect destinationRect = input.absoluteImageRect();
+        destinationRect.intersect(input2.absoluteImageRect());
+        destinationRect.intersect(result.absoluteImageRect());
         if (destinationRect.isEmpty())
             break;
-        IntRect adjustedDestinationRect = destinationRect - m_effect.absolutePaintRect().location();
-        IntRect sourceRect = destinationRect - in->absolutePaintRect().location();
-        IntRect source2Rect = destinationRect - in2->absolutePaintRect().location();
-        filterContext.drawImageBuffer(*imageBuffer2, FloatRect(adjustedDestinationRect), FloatRect(source2Rect));
-        filterContext.drawImageBuffer(*imageBuffer, FloatRect(adjustedDestinationRect), FloatRect(sourceRect), { CompositeOperator::SourceIn });
+        IntRect adjustedDestinationRect = destinationRect - result.absoluteImageRect().location();
+        IntRect sourceRect = destinationRect - input.absoluteImageRect().location();
+        IntRect source2Rect = destinationRect - input2.absoluteImageRect().location();
+        filterContext.drawImageBuffer(*inputImage2, FloatRect(adjustedDestinationRect), FloatRect(source2Rect));
+        filterContext.drawImageBuffer(*inputImage, FloatRect(adjustedDestinationRect), FloatRect(sourceRect), { CompositeOperator::SourceIn });
         break;
     }
 
     case FECOMPOSITE_OPERATOR_OUT:
-        filterContext.drawImageBuffer(*imageBuffer, m_effect.drawingRegionOfInputImage(in->absolutePaintRect()));
-        filterContext.drawImageBuffer(*imageBuffer2, m_effect.drawingRegionOfInputImage(in2->absolutePaintRect()), { { }, imageBuffer2->logicalSize() }, CompositeOperator::DestinationOut);
+        filterContext.drawImageBuffer(*inputImage, m_effect.drawingRegionOfInputImage(input.absoluteImageRect()));
+        filterContext.drawImageBuffer(*inputImage2, m_effect.drawingRegionOfInputImage(input2.absoluteImageRect()), { { }, inputImage2->logicalSize() }, CompositeOperator::DestinationOut);
         break;
 
     case FECOMPOSITE_OPERATOR_ATOP:
-        filterContext.drawImageBuffer(*imageBuffer2, m_effect.drawingRegionOfInputImage(in2->absolutePaintRect()));
-        filterContext.drawImageBuffer(*imageBuffer, m_effect.drawingRegionOfInputImage(in->absolutePaintRect()), { { }, imageBuffer->logicalSize() }, CompositeOperator::SourceAtop);
+        filterContext.drawImageBuffer(*inputImage2, m_effect.drawingRegionOfInputImage(input2.absoluteImageRect()));
+        filterContext.drawImageBuffer(*inputImage, m_effect.drawingRegionOfInputImage(input.absoluteImageRect()), { { }, inputImage->logicalSize() }, CompositeOperator::SourceAtop);
         break;
 
     case FECOMPOSITE_OPERATOR_XOR:
-        filterContext.drawImageBuffer(*imageBuffer2, m_effect.drawingRegionOfInputImage(in2->absolutePaintRect()));
-        filterContext.drawImageBuffer(*imageBuffer, m_effect.drawingRegionOfInputImage(in->absolutePaintRect()), { { }, imageBuffer->logicalSize() }, CompositeOperator::XOR);
+        filterContext.drawImageBuffer(*inputImage2, m_effect.drawingRegionOfInputImage(input2.absoluteImageRect()));
+        filterContext.drawImageBuffer(*inputImage, m_effect.drawingRegionOfInputImage(input.absoluteImageRect()), { { }, inputImage->logicalSize() }, CompositeOperator::XOR);
         break;
 
     case FECOMPOSITE_OPERATOR_ARITHMETIC:
@@ -206,22 +206,22 @@
         return false;
 
     case FECOMPOSITE_OPERATOR_LIGHTER:
-        filterContext.drawImageBuffer(*imageBuffer2, m_effect.drawingRegionOfInputImage(in2->absolutePaintRect()));
-        filterContext.drawImageBuffer(*imageBuffer, m_effect.drawingRegionOfInputImage(in->absolutePaintRect()), { { }, imageBuffer->logicalSize() }, CompositeOperator::PlusLighter);
+        filterContext.drawImageBuffer(*inputImage2, m_effect.drawingRegionOfInputImage(input2.absoluteImageRect()));
+        filterContext.drawImageBuffer(*inputImage, m_effect.drawingRegionOfInputImage(input.absoluteImageRect()), { { }, inputImage->logicalSize() }, CompositeOperator::PlusLighter);
         break;
     }
 
     return true;
 }
 
-bool FECompositeSoftwareApplier::apply(const Filter&, const FilterEffectVector& inputEffects)
+bool FECompositeSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
-    FilterEffect* in2 = inputEffects[1].get();
+    auto& input = inputs[0].get();
+    auto& input2 = inputs[1].get();
 
     if (m_effect.operation() == FECOMPOSITE_OPERATOR_ARITHMETIC)
-        return applyArithmetic(in, in2);
-    return applyNonArithmetic(in, in2);
+        return applyArithmetic(input, input2, result);
+    return applyNonArithmetic(input, input2, result);
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/software/FECompositeSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FECompositeSoftwareApplier.h
index 2609f59..86ae02f 100644
--- a/Source/WebCore/platform/graphics/filters/software/FECompositeSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FECompositeSoftwareApplier.h
@@ -34,7 +34,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 
 private:
     static uint8_t clampByte(int);
@@ -47,8 +47,8 @@
 
     static inline void applyPlatformArithmetic(unsigned char* source, unsigned char* destination, int pixelArrayLength, float k1, float k2, float k3, float k4);
 
-    bool applyArithmetic(FilterEffect* in, FilterEffect* in2);
-    bool applyNonArithmetic(FilterEffect* in, FilterEffect* in2);
+    bool applyArithmetic(FilterImage& input, FilterImage& input2, FilterImage& result);
+    bool applyNonArithmetic(FilterImage& input, FilterImage& input2, FilterImage& result);
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.cpp
index ab8aa86..8eb2aac 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.cpp
@@ -286,24 +286,24 @@
         setOuterPixels(paintingData, clipRight, paintingData.targetOffset.y(), paintingData.width, clipBottom);
 }
 
-bool FEConvolveMatrixSoftwareApplier::apply(const Filter&, const FilterEffectVector& inputEffects)
+bool FEConvolveMatrixSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
+    auto& input = inputs[0].get();
 
     auto alphaFormat = m_effect.preserveAlpha() ? AlphaPremultiplication::Unpremultiplied : AlphaPremultiplication::Premultiplied;
-    auto destinationPixelBuffer = m_effect.pixelBufferResult(alphaFormat);
+    auto destinationPixelBuffer = result.pixelBuffer(alphaFormat);
     if (!destinationPixelBuffer)
         return false;
 
-    auto effectDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
-    auto sourcePixelBuffer = in->getPixelBufferResult(alphaFormat, effectDrawingRect, m_effect.operatingColorSpace());
+    auto effectDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(input.absoluteImageRect());
+    auto sourcePixelBuffer = input.getPixelBuffer(alphaFormat, effectDrawingRect, m_effect.operatingColorSpace());
     if (!sourcePixelBuffer)
         return false;
 
     auto& sourcePixelArray = sourcePixelBuffer->data();
     auto& destinationPixelArray = destinationPixelBuffer->data();
     
-    auto paintSize = m_effect.absolutePaintRect().size();
+    auto paintSize = result.absoluteImageRect().size();
 
     PaintingData paintingData = {
         sourcePixelArray,
diff --git a/Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.h
index 24d6c08..d1d19a5 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.h
@@ -37,7 +37,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 
 private:
     struct PaintingData {
diff --git a/Source/WebCore/platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.cpp
index db3c21c..d90cf855 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.cpp
@@ -49,32 +49,32 @@
     return m_effect.yChannelSelector() - 1;
 }
 
-bool FEDisplacementMapSoftwareApplier::apply(const Filter& filter, const FilterEffectVector& inputEffects)
+bool FEDisplacementMapSoftwareApplier::apply(const Filter& filter, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
-    FilterEffect* in2 = inputEffects[1].get();
+    auto& input = inputs[0].get();
+    auto& input2 = inputs[1].get();
 
-    auto destinationPixelBuffer = m_effect.pixelBufferResult(AlphaPremultiplication::Premultiplied);
+    auto destinationPixelBuffer = result.pixelBuffer(AlphaPremultiplication::Premultiplied);
     if (!destinationPixelBuffer)
         return false;
 
     auto& destinationPixelArray = destinationPixelBuffer->data();
 
-    auto effectADrawingRect = m_effect.requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
-    auto inputPixelBuffer = in->getPixelBufferResult(AlphaPremultiplication::Premultiplied, effectADrawingRect);
+    auto effectADrawingRect = m_effect.requestedRegionOfInputPixelBuffer(input.absoluteImageRect());
+    auto inputPixelBuffer = input.getPixelBuffer(AlphaPremultiplication::Premultiplied, effectADrawingRect);
 
-    auto effectBDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(in2->absolutePaintRect());
+    auto effectBDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(input2.absoluteImageRect());
     // The calculations using the pixel values from ‘in2’ are performed using non-premultiplied color values.
-    auto displacementPixelBuffer = in2->getPixelBufferResult(AlphaPremultiplication::Unpremultiplied, effectBDrawingRect);
+    auto displacementPixelBuffer = input2.getPixelBuffer(AlphaPremultiplication::Unpremultiplied, effectBDrawingRect);
     
     if (!inputPixelBuffer || !displacementPixelBuffer)
         return false;
 
-    auto& inputImage = inputPixelBuffer->data();
-    auto& displacementImage = displacementPixelBuffer->data();
-    ASSERT(inputImage.length() == displacementImage.length());
+    auto& inputPixelArray = inputPixelBuffer->data();
+    auto& displacementPixelArray = displacementPixelBuffer->data();
+    ASSERT(inputPixelArray.length() == displacementPixelArray.length());
 
-    IntSize paintSize = m_effect.absolutePaintRect().size();
+    IntSize paintSize = result.absoluteImageRect().size();
 
     FloatSize scale = filter.scaledByFilterScale({ m_effect.scale(), m_effect.scale() });
     float scaleForColorX = scale.width() / 255.0;
@@ -93,8 +93,8 @@
         for (int x = 0; x < paintSize.width(); ++x) {
             int destinationIndex = lineStartOffset + x * 4;
             
-            int srcX = x + static_cast<int>(scaleForColorX * displacementImage.item(destinationIndex + displacementChannelX) + scaledOffsetX);
-            int srcY = y + static_cast<int>(scaleForColorY * displacementImage.item(destinationIndex + displacementChannelY) + scaledOffsetY);
+            int srcX = x + static_cast<int>(scaleForColorX * displacementPixelArray.item(destinationIndex + displacementChannelX) + scaledOffsetX);
+            int srcY = y + static_cast<int>(scaleForColorY * displacementPixelArray.item(destinationIndex + displacementChannelY) + scaledOffsetY);
 
             unsigned* destinationPixelPtr = reinterpret_cast<unsigned*>(destinationPixelArray.data() + destinationIndex);
             if (srcX < 0 || srcX >= paintSize.width() || srcY < 0 || srcY >= paintSize.height()) {
@@ -102,7 +102,7 @@
                 continue;
             }
 
-            *destinationPixelPtr = *reinterpret_cast<unsigned*>(inputImage.data() + byteOffsetOfPixel(srcX, srcY, rowBytes));
+            *destinationPixelPtr = *reinterpret_cast<unsigned*>(inputPixelArray.data() + byteOffsetOfPixel(srcX, srcY, rowBytes));
         }
     }
 
diff --git a/Source/WebCore/platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.h
index 9e6ca6e..b857cf8 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.h
@@ -34,7 +34,7 @@
 public:
     FEDisplacementMapSoftwareApplier(FEDisplacementMap&);
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 
 private:
     static inline unsigned byteOffsetOfPixel(unsigned x, unsigned y, unsigned rowBytes)
diff --git a/Source/WebCore/platform/graphics/filters/software/FEDropShadowSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FEDropShadowSoftwareApplier.cpp
index e17a61b..7641833 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEDropShadowSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FEDropShadowSoftwareApplier.cpp
@@ -30,33 +30,33 @@
 
 namespace WebCore {
 
-bool FEDropShadowSoftwareApplier::apply(const Filter& filter, const FilterEffectVector& inputEffects)
+bool FEDropShadowSoftwareApplier::apply(const Filter& filter, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
+    auto& input = inputs[0].get();
 
-    auto resultImage = m_effect.imageBufferResult();
+    auto resultImage = result.imageBuffer();
     if (!resultImage)
         return false;
 
     FloatSize blurRadius = 2 * filter.scaledByFilterScale({ m_effect.stdDeviationX(), m_effect.stdDeviationY() });
     FloatSize offset = filter.scaledByFilterScale({ m_effect.dx(), m_effect.dy() });
 
-    FloatRect drawingRegion = m_effect.drawingRegionOfInputImage(in->absolutePaintRect());
+    FloatRect drawingRegion = m_effect.drawingRegionOfInputImage(input.absoluteImageRect());
     FloatRect drawingRegionWithOffset(drawingRegion);
     drawingRegionWithOffset.move(offset);
 
-    auto sourceImage = in->imageBufferResult();
-    if (!sourceImage)
+    auto inputImage = input.imageBuffer();
+    if (!inputImage)
         return false;
 
     GraphicsContext& resultContext = resultImage->context();
     resultContext.setAlpha(m_effect.shadowOpacity());
-    resultContext.drawImageBuffer(*sourceImage, drawingRegionWithOffset);
+    resultContext.drawImageBuffer(*inputImage, drawingRegionWithOffset);
     resultContext.setAlpha(1);
 
     ShadowBlur contextShadow(blurRadius, offset, m_effect.shadowColor());
 
-    PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, m_effect.resultColorSpace() };
+    PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, result.colorSpace() };
     IntRect shadowArea(IntPoint(), resultImage->truncatedLogicalSize());
     auto pixelBuffer = resultImage->getPixelBuffer(format, shadowArea);
     if (!pixelBuffer)
@@ -68,10 +68,10 @@
     resultImage->putPixelBuffer(*pixelBuffer, shadowArea);
 
     resultContext.setCompositeOperation(CompositeOperator::SourceIn);
-    resultContext.fillRect(FloatRect(FloatPoint(), m_effect.absolutePaintRect().size()), m_effect.shadowColor());
+    resultContext.fillRect(FloatRect(FloatPoint(), result.absoluteImageRect().size()), m_effect.shadowColor());
     resultContext.setCompositeOperation(CompositeOperator::DestinationOver);
 
-    resultImage->context().drawImageBuffer(*sourceImage, drawingRegion);
+    resultImage->context().drawImageBuffer(*inputImage, drawingRegion);
     return true;
 }
 
diff --git a/Source/WebCore/platform/graphics/filters/software/FEDropShadowSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEDropShadowSoftwareApplier.h
index 45f6c0f..b4a893b 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEDropShadowSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEDropShadowSoftwareApplier.h
@@ -32,7 +32,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/software/FEFloodSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FEFloodSoftwareApplier.cpp
index 803e0e2..31da8b4 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEFloodSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FEFloodSoftwareApplier.cpp
@@ -30,14 +30,14 @@
 
 namespace WebCore {
 
-bool FEFloodSoftwareApplier::apply(const Filter&, const FilterEffectVector&)
+bool FEFloodSoftwareApplier::apply(const Filter&, const FilterImageVector&, FilterImage& result)
 {
-    auto resultImage = m_effect.imageBufferResult();
+    auto resultImage = result.imageBuffer();
     if (!resultImage)
         return false;
 
     auto color = m_effect.floodColor().colorWithAlphaMultipliedBy(m_effect.floodOpacity());
-    resultImage->context().fillRect(FloatRect(FloatPoint(), m_effect.absolutePaintRect().size()), color);
+    resultImage->context().fillRect(FloatRect(FloatPoint(), result.absoluteImageRect().size()), color);
 
     return true;
 }
diff --git a/Source/WebCore/platform/graphics/filters/software/FEFloodSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEFloodSoftwareApplier.h
index 1535712..2cca05d 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEFloodSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEFloodSoftwareApplier.h
@@ -34,7 +34,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.cpp
index 5621eb5..1dfa97e 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.cpp
@@ -425,30 +425,28 @@
     boxBlurGeneric(ioBuffer, tmpPixelArray, kernelSizeX, kernelSizeY, paintSize, isAlphaImage, edgeMode);
 }
 
-bool FEGaussianBlurSoftwareApplier::apply(const Filter& filter, const FilterEffectVector& inputEffects)
+bool FEGaussianBlurSoftwareApplier::apply(const Filter& filter, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
+    auto& input = inputs[0].get();
 
-    auto destinationPixelBuffer = m_effect.pixelBufferResult(AlphaPremultiplication::Premultiplied);
+    auto destinationPixelBuffer = result.pixelBuffer(AlphaPremultiplication::Premultiplied);
     if (!destinationPixelBuffer)
         return false;
 
-    m_effect.setIsAlphaImage(in->isAlphaImage());
-
-    auto effectDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
-    in->copyPixelBufferResult(*destinationPixelBuffer, effectDrawingRect);
+    auto effectDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(input.absoluteImageRect());
+    input.copyPixelBuffer(*destinationPixelBuffer, effectDrawingRect);
     if (!m_effect.stdDeviationX() && !m_effect.stdDeviationY())
         return true;
 
     auto kernelSize = m_effect.calculateKernelSize(filter, { m_effect.stdDeviationX(), m_effect.stdDeviationY() });
 
-    IntSize paintSize = m_effect.absolutePaintRect().size();
+    IntSize paintSize = result.absoluteImageRect().size();
     auto tmpImageData = Uint8ClampedArray::tryCreateUninitialized(paintSize.area() * 4);
     if (!tmpImageData)
         return false;
 
     auto& destinationPixelArray = destinationPixelBuffer->data();
-    applyPlatform(destinationPixelArray, *tmpImageData, kernelSize.width(), kernelSize.height(), paintSize, m_effect.isAlphaImage(), m_effect.edgeMode());
+    applyPlatform(destinationPixelArray, *tmpImageData, kernelSize.width(), kernelSize.height(), paintSize, result.isAlphaImage(), m_effect.edgeMode());
     return true;
 }
 
diff --git a/Source/WebCore/platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.h
index 0227d32..4a87ee4 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.h
@@ -36,7 +36,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 
 private:
     struct ApplyParameters {
diff --git a/Source/WebCore/platform/graphics/filters/software/FELightingSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FELightingSoftwareApplier.cpp
index f18f608..c198f46 100644
--- a/Source/WebCore/platform/graphics/filters/software/FELightingSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FELightingSoftwareApplier.cpp
@@ -391,27 +391,25 @@
     }
 }
 
-bool FELightingSoftwareApplier::apply(const Filter&, const FilterEffectVector& inputEffects)
+bool FELightingSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
+    auto& input = inputs[0].get();
 
-    auto destinationPixelBuffer = m_effect.pixelBufferResult(AlphaPremultiplication::Premultiplied);
+    auto destinationPixelBuffer = result.pixelBuffer(AlphaPremultiplication::Premultiplied);
     if (!destinationPixelBuffer)
         return false;
 
     auto& destinationPixelArray = destinationPixelBuffer->data();
 
-    m_effect.setIsAlphaImage(false);
-
-    auto effectDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
-    in->copyPixelBufferResult(*destinationPixelBuffer, effectDrawingRect);
+    auto effectDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(input.absoluteImageRect());
+    input.copyPixelBuffer(*destinationPixelBuffer, effectDrawingRect);
 
     // FIXME: support kernelUnitLengths other than (1,1). The issue here is that the W3
     // standard has no test case for them, and other browsers (like Firefox) has strange
     // output for various kernelUnitLengths, and I am not sure they are reliable.
     // Anyway, feConvolveMatrix should also use the implementation
 
-    IntSize size = IntSize(m_effect.absolutePaintRect().size());
+    IntSize size = IntSize(result.absoluteImageRect().size());
 
     // FIXME: do something if width or height (or both) is 1 pixel.
     // The W3 spec does not define this case. Now the filter just returns.
diff --git a/Source/WebCore/platform/graphics/filters/software/FELightingSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FELightingSoftwareApplier.h
index 676b8b7..3c3724e 100644
--- a/Source/WebCore/platform/graphics/filters/software/FELightingSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FELightingSoftwareApplier.h
@@ -41,7 +41,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 
 private:
     static constexpr int cPixelSize = 4;
diff --git a/Source/WebCore/platform/graphics/filters/software/FEMergeSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FEMergeSoftwareApplier.cpp
index d5d4aab..0138f5c 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEMergeSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FEMergeSoftwareApplier.cpp
@@ -29,21 +29,21 @@
 
 namespace WebCore {
 
-bool FEMergeSoftwareApplier::apply(const Filter&, const FilterEffectVector& inputEffects)
+bool FEMergeSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result)
 {
-    ASSERT(inputEffects.size() > 0);
+    ASSERT(inputs.size() == m_effect.numberOfEffectInputs());
 
-    auto resultImage = m_effect.imageBufferResult();
+    auto resultImage = result.imageBuffer();
     if (!resultImage)
         return false;
 
     auto& filterContext = resultImage->context();
 
-    for (auto& in : inputEffects) {
-        auto inBuffer = in->imageBufferResult();
-        if (!inBuffer)
+    for (auto& input : inputs) {
+        auto inputImage = input->imageBuffer();
+        if (!inputImage)
             continue;
-        filterContext.drawImageBuffer(*inBuffer, m_effect.drawingRegionOfInputImage(in->absolutePaintRect()));
+        filterContext.drawImageBuffer(*inputImage, m_effect.drawingRegionOfInputImage(input->absoluteImageRect()));
     }
 
     return true;
diff --git a/Source/WebCore/platform/graphics/filters/software/FEMergeSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEMergeSoftwareApplier.h
index 821d844..1b30aba 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEMergeSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEMergeSoftwareApplier.h
@@ -34,7 +34,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/software/FEMorphologySoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FEMorphologySoftwareApplier.cpp
index 94fd892..a0d960a 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEMorphologySoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FEMorphologySoftwareApplier.cpp
@@ -141,25 +141,23 @@
     applyPlatformGeneric(paintingData, 0, paintingData.height);
 }
 
-bool FEMorphologySoftwareApplier::apply(const Filter& filter, const FilterEffectVector& inputEffects)
+bool FEMorphologySoftwareApplier::apply(const Filter& filter, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
+    auto& input = inputs[0].get();
 
-    auto destinationPixelBuffer = m_effect.pixelBufferResult(AlphaPremultiplication::Premultiplied);
+    auto destinationPixelBuffer = result.pixelBuffer(AlphaPremultiplication::Premultiplied);
     if (!destinationPixelBuffer)
         return false;
 
-    m_effect.setIsAlphaImage(in->isAlphaImage());
-
     auto isDegenerate = [](int radiusX, int radiusY) -> bool {
         return radiusX < 0 || radiusY < 0 || (!radiusX && !radiusY);
     };
 
-    IntRect effectDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
+    IntRect effectDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(input.absoluteImageRect());
     IntSize radius = flooredIntSize(FloatSize(m_effect.radiusX(), m_effect.radiusY()));
 
     if (isDegenerate(radius.width(), radius.height())) {
-        in->copyPixelBufferResult(*destinationPixelBuffer, effectDrawingRect);
+        input.copyPixelBuffer(*destinationPixelBuffer, effectDrawingRect);
         return true;
     }
 
@@ -168,11 +166,11 @@
     int radiusY = std::min(effectDrawingRect.height() - 1, radius.height());
 
     if (isDegenerate(radiusX, radiusY)) {
-        in->copyPixelBufferResult(*destinationPixelBuffer, effectDrawingRect);
+        input.copyPixelBuffer(*destinationPixelBuffer, effectDrawingRect);
         return true;
     }
 
-    auto sourcePixelBuffer = in->getPixelBufferResult(AlphaPremultiplication::Premultiplied, effectDrawingRect, m_effect.operatingColorSpace());
+    auto sourcePixelBuffer = input.getPixelBuffer(AlphaPremultiplication::Premultiplied, effectDrawingRect, m_effect.operatingColorSpace());
     if (!sourcePixelBuffer)
         return false;
 
diff --git a/Source/WebCore/platform/graphics/filters/software/FEMorphologySoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEMorphologySoftwareApplier.h
index 8224161..f13bbb1 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEMorphologySoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEMorphologySoftwareApplier.h
@@ -38,7 +38,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 
 private:
     using ColumnExtrema = Vector<ColorComponents<uint8_t, 4>, 16>;
diff --git a/Source/WebCore/platform/graphics/filters/software/FEOffsetSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FEOffsetSoftwareApplier.cpp
index b47f8fe..f0da5d2 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEOffsetSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FEOffsetSoftwareApplier.cpp
@@ -32,21 +32,19 @@
 
 namespace WebCore {
 
-bool FEOffsetSoftwareApplier::apply(const Filter& filter, const FilterEffectVector& inputEffects)
+bool FEOffsetSoftwareApplier::apply(const Filter& filter, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
+    auto& input = inputs[0].get();
 
-    auto resultImage = m_effect.imageBufferResult();
-    auto inBuffer = in->imageBufferResult();
-    if (!resultImage || !inBuffer)
+    auto resultImage = result.imageBuffer();
+    auto inputImage = input.imageBuffer();
+    if (!resultImage || !inputImage)
         return false;
 
-    m_effect.setIsAlphaImage(in->isAlphaImage());
-
-    FloatRect drawingRegion = m_effect.drawingRegionOfInputImage(in->absolutePaintRect());
+    FloatRect drawingRegion = m_effect.drawingRegionOfInputImage(input.absoluteImageRect());
     drawingRegion.move(filter.scaledByFilterScale({ m_effect.dx(), m_effect.dy() }));
-    resultImage->context().drawImageBuffer(*inBuffer, drawingRegion);
 
+    resultImage->context().drawImageBuffer(*inputImage, drawingRegion);
     return true;
 }
 
diff --git a/Source/WebCore/platform/graphics/filters/software/FEOffsetSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEOffsetSoftwareApplier.h
index 1c3fd84..c345b72 100644
--- a/Source/WebCore/platform/graphics/filters/software/FEOffsetSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FEOffsetSoftwareApplier.h
@@ -34,7 +34,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/software/FETileSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FETileSoftwareApplier.cpp
index d3a1cf6..33c7a03 100644
--- a/Source/WebCore/platform/graphics/filters/software/FETileSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FETileSoftwareApplier.cpp
@@ -27,53 +27,47 @@
 #include "Filter.h"
 #include "GraphicsContext.h"
 #include "Pattern.h"
-#include "SVGRenderingContext.h"
 
 namespace WebCore {
 
-bool FETileSoftwareApplier::apply(const Filter& filter, const FilterEffectVector& inputEffects)
+bool FETileSoftwareApplier::apply(const Filter& filter, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
+    auto& input = inputs[0].get();
 
-    auto resultImage = m_effect.imageBufferResult();
-    auto inBuffer = in->imageBufferResult();
-    if (!resultImage || !inBuffer)
+    auto resultImage = result.imageBuffer();
+    auto inputImage = input.imageBuffer();
+    if (!resultImage || !inputImage)
         return false;
 
-    m_effect.setIsAlphaImage(in->isAlphaImage());
+    auto inputImageRect = input.absoluteImageRect();
+    auto resultImageRect = result.absoluteImageRect();
 
-    // Source input needs more attention. It has the size of the filterRegion but gives the
-    // size of the cutted sourceImage back. This is part of the specification and optimization.
-    FloatRect tileRect = in->maxEffectRect();
-    FloatPoint inMaxEffectLocation = tileRect.location();
-    FloatPoint maxEffectLocation = m_effect.maxEffectRect().location();
-    if (in->filterType() == FilterEffect::Type::SourceGraphic || in->filterType() == FilterEffect::Type::SourceAlpha) {
-        tileRect = filter.filterRegion();
-        tileRect.scale(filter.filterScale());
-    }
+    auto tileRect = filter.maxEffectRect(input.primitiveSubregion());
+    tileRect.scale(filter.filterScale());
 
-    // FIXME: remove this non-paltform call.
-    auto tileImage = SVGRenderingContext::createImageBuffer(tileRect, tileRect, DestinationColorSpace::SRGB(), filter.renderingMode());
+    auto maxResultRect = filter.maxEffectRect(result.primitiveSubregion());
+    maxResultRect.scale(filter.filterScale());
+
+    auto tileImage = ImageBuffer::create(tileRect.size(), filter.renderingMode(), 1, DestinationColorSpace::SRGB(), PixelFormat::BGRA8);
     if (!tileImage)
         return false;
 
-    GraphicsContext& tileImageContext = tileImage->context();
-    tileImageContext.translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y());
-    tileImageContext.drawImageBuffer(*inBuffer, in->absolutePaintRect().location());
+    auto& tileImageContext = tileImage->context();
+    tileImageContext.translate(-tileRect.location());
+    tileImageContext.drawImageBuffer(*inputImage, inputImageRect.location());
 
-    auto tileImageCopy = ImageBuffer::sinkIntoNativeImage(WTFMove(tileImage));
-    if (!tileImageCopy)
+    auto patternImage = ImageBuffer::sinkIntoNativeImage(WTFMove(tileImage));
+    if (!patternImage)
         return false;
 
     AffineTransform patternTransform;
-    patternTransform.translate(inMaxEffectLocation - maxEffectLocation);
+    patternTransform.translate(tileRect.location() - maxResultRect.location());
 
-    auto pattern = Pattern::create(tileImageCopy.releaseNonNull(), { true, true, patternTransform });
+    auto pattern = Pattern::create(patternImage.releaseNonNull(), { true, true, patternTransform });
 
-    GraphicsContext& filterContext = resultImage->context();
-    filterContext.setFillPattern(WTFMove(pattern));
-    filterContext.fillRect(FloatRect(FloatPoint(), m_effect.absolutePaintRect().size()));
-
+    auto& resultContext = resultImage->context();
+    resultContext.setFillPattern(WTFMove(pattern));
+    resultContext.fillRect(FloatRect(FloatPoint(), resultImageRect.size()));
     return true;
 }
 
diff --git a/Source/WebCore/platform/graphics/filters/software/FETileSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FETileSoftwareApplier.h
index 8605d8b..4a5cc21 100644
--- a/Source/WebCore/platform/graphics/filters/software/FETileSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FETileSoftwareApplier.h
@@ -34,7 +34,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/software/FETurbulenceSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/FETurbulenceSoftwareApplier.cpp
index 119623f..e27bd3d 100644
--- a/Source/WebCore/platform/graphics/filters/software/FETurbulenceSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/FETurbulenceSoftwareApplier.cpp
@@ -339,13 +339,13 @@
     applyPlatformGeneric(filterRegion, filterScale, pixelArray, paintingData, stitchData, 0, height);
 }
 
-bool FETurbulenceSoftwareApplier::apply(const Filter& filter, const FilterEffectVector&)
+bool FETurbulenceSoftwareApplier::apply(const Filter& filter, const FilterImageVector&, FilterImage& result)
 {
-    auto destinationPixelBuffer = m_effect.pixelBufferResult(AlphaPremultiplication::Unpremultiplied);
+    auto destinationPixelBuffer = result.pixelBuffer(AlphaPremultiplication::Unpremultiplied);
     if (!destinationPixelBuffer)
         return false;
 
-    IntSize resultSize(m_effect.absolutePaintRect().size());
+    IntSize resultSize(result.absoluteImageRect().size());
     if (resultSize.area().hasOverflowed())
         return false;
 
@@ -356,7 +356,7 @@
         return true;
     }
 
-    auto tileSize = roundedIntSize(m_effect.filterPrimitiveSubregion().size());
+    auto tileSize = roundedIntSize(result.primitiveSubregion().size());
 
     float baseFrequencyX = m_effect.baseFrequencyX();
     float baseFrequencyY = m_effect.baseFrequencyY();
@@ -364,7 +364,7 @@
 
     auto paintingData = initPaintingData(m_effect.type(), baseFrequencyX, baseFrequencyY, m_effect.numOctaves(), m_effect.seed(), m_effect.stitchTiles(), tileSize);
 
-    applyPlatform(m_effect.absolutePaintRect(), filter.filterScale(), destinationPixelArray, paintingData, stitchData);
+    applyPlatform(result.absoluteImageRect(), filter.filterScale(), destinationPixelArray, paintingData, stitchData);
     return true;
 }
 
diff --git a/Source/WebCore/platform/graphics/filters/software/FETurbulenceSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FETurbulenceSoftwareApplier.h
index 3ce68e3..a52e7c5 100644
--- a/Source/WebCore/platform/graphics/filters/software/FETurbulenceSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/FETurbulenceSoftwareApplier.h
@@ -41,7 +41,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 
 private:
     // Produces results in the range [1, 2**31 - 2]. Algorithm is:
diff --git a/Source/WebCore/platform/graphics/filters/software/SourceAlphaSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/SourceAlphaSoftwareApplier.cpp
index 62358df..5025195 100644
--- a/Source/WebCore/platform/graphics/filters/software/SourceAlphaSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/SourceAlphaSoftwareApplier.cpp
@@ -27,24 +27,23 @@
 
 namespace WebCore {
 
-bool SourceAlphaSoftwareApplier::apply(const Filter&, const FilterEffectVector& inputEffects)
+bool SourceAlphaSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result)
 {
-    FilterEffect* in = inputEffects[0].get();
+    auto& input = inputs[0].get();
 
-    auto resultImage = m_effect.imageBufferResult();
+    auto resultImage = result.imageBuffer();
     if (!resultImage)
         return false;
     
-    auto imageBuffer = in->imageBufferResult();
-    if (!imageBuffer)
+    auto inputImage = input.imageBuffer();
+    if (!inputImage)
         return false;
 
-    FloatRect imageRect(FloatPoint(), m_effect.absolutePaintRect().size());
-    GraphicsContext& filterContext = resultImage->context();
+    FloatRect imageRect(FloatPoint(), result.absoluteImageRect().size());
+    auto& filterContext = resultImage->context();
 
     filterContext.fillRect(imageRect, Color::black);
-    filterContext.drawImageBuffer(*imageBuffer, IntPoint(), CompositeOperator::DestinationIn);
-
+    filterContext.drawImageBuffer(*inputImage, IntPoint(), CompositeOperator::DestinationIn);
     return true;
 }
 
diff --git a/Source/WebCore/platform/graphics/filters/software/SourceAlphaSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/SourceAlphaSoftwareApplier.h
index df86035..748ff7e 100644
--- a/Source/WebCore/platform/graphics/filters/software/SourceAlphaSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/SourceAlphaSoftwareApplier.h
@@ -32,7 +32,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp b/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp
index 5451dc3..7b5d804 100644
--- a/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp
+++ b/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp
@@ -27,9 +27,9 @@
 
 namespace WebCore {
 
-bool SourceGraphicSoftwareApplier::apply(const Filter& filter, const FilterEffectVector&)
+bool SourceGraphicSoftwareApplier::apply(const Filter& filter, const FilterImageVector&, FilterImage& result)
 {
-    auto resultImage = m_effect.imageBufferResult();
+    auto resultImage = result.imageBuffer();
     auto sourceImage = filter.sourceImage();
     if (!resultImage || !sourceImage)
         return false;
diff --git a/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.h
index 6199ab7..07169cc 100644
--- a/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.h
+++ b/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.h
@@ -33,7 +33,7 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/rendering/CSSFilter.cpp b/Source/WebCore/rendering/CSSFilter.cpp
index 3c3f5c1..e28b88f 100644
--- a/Source/WebCore/rendering/CSSFilter.cpp
+++ b/Source/WebCore/rendering/CSSFilter.cpp
@@ -442,8 +442,11 @@
 {
     if (m_filterRenderer && m_filterRenderer->hasResult())
         return m_filterRenderer->output();
-    
-    return lastEffect()->imageBufferResult();
+
+    if (auto result = lastEffect()->filterImage())
+        return result->imageBuffer();
+
+    return nullptr;
 }
 
 void CSSFilter::setSourceImageRect(const FloatRect& sourceImageRect)
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
index f0a265b..934fc83 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
@@ -246,10 +246,10 @@
         }
         filterData.state = FilterData::Built;
 
-        ImageBuffer* resultImage = lastEffect->imageBufferResult();
-        if (resultImage) {
+        if (auto result = lastEffect->filterImage()) {
+            auto resultImage = result->imageBuffer();
             context->scale(FloatSize(1 / filterData.filter->filterScale().width(), 1 / filterData.filter->filterScale().height()));
-            context->drawImageBuffer(*resultImage, lastEffect->absolutePaintRect());
+            context->drawImageBuffer(*resultImage, result->absoluteImageRect());
             context->scale(filterData.filter->filterScale());
         }
     }
diff --git a/Source/WebCore/svg/graphics/filters/SVGFEImage.cpp b/Source/WebCore/svg/graphics/filters/SVGFEImage.cpp
index c759c9a..074df19 100644
--- a/Source/WebCore/svg/graphics/filters/SVGFEImage.cpp
+++ b/Source/WebCore/svg/graphics/filters/SVGFEImage.cpp
@@ -82,16 +82,16 @@
 public:
     using Base::Base;
 
-    bool apply(const Filter&, const FilterEffectVector& inputEffects) override;
+    bool apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) override;
 };
 
-bool FEImageSoftwareApplier::apply(const Filter& filter, const FilterEffectVector&)
+bool FEImageSoftwareApplier::apply(const Filter& filter, const FilterImageVector&, FilterImage& result)
 {
-    auto resultImage = m_effect.imageBufferResult();
+    auto resultImage = result.imageBuffer();
     if (!resultImage)
         return false;
 
-    auto primitiveSubregion = m_effect.filterPrimitiveSubregion();
+    auto primitiveSubregion = result.primitiveSubregion();
     auto& context = resultImage->context();
 
     WTF::switchOn(m_effect.sourceImage(),
@@ -117,7 +117,7 @@
 
 bool FEImage::platformApplySoftware(const Filter& filter)
 {
-    return FEImageSoftwareApplier(*this).apply(filter, inputEffects());
+    return FEImageSoftwareApplier(*this).apply(filter, { }, *filterImage());
 }
 
 TextStream& FEImage::externalRepresentation(TextStream& ts, RepresentationType representation) const