Title: [286578] trunk/Source/WebCore
Revision
286578
Author
s...@apple.com
Date
2021-12-06 16:36:58 -0800 (Mon, 06 Dec 2021)

Log Message

[GPU Process] Make FilterEffect calculate the primitive subregion only when needed
https://bugs.webkit.org/show_bug.cgi?id=232705
rdar://85290142

Reviewed by Cameron McCormack.

In this patch:

1. resultColorSpace() will return colorSpace() from a FilterImageVector
   instead of returning the resultColorSpace() of the FilterEffect.

2. Filter::clampFilterRegionIfNeeded() will clamp the filterRegion()
   instead of clamping the maxEffectRect of the lastEffect() since all
   the primitiveSubregions and the imageRects have to clipped to the
   filterRegion().

3. determineFilterPrimitiveSubregion() is replaced by calculatePrimitiveSubregion()
   which will calculate the primitiveSubregion from a FilterImageVector
   and an optional FilterEffectGeometry.

4. Many of FilterEffects are made protected instead of having them public.

5. SVGFilterExpression will be defined as a Vector of SVGFilterExpressionTerm
   which is a struct of FilterEffect and optional FilterEffectGeometry.

6. SVGFilter will replace the members whose types are FilterEffectVector
   and FilterEffectGeometryMap with a single member of type SVGFilterExpression.

* Headers.cmake:
* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/filters/FEDisplacementMap.cpp:
(WebCore::FEDisplacementMap::resultColorSpace const):
* platform/graphics/filters/FEDisplacementMap.h:
* platform/graphics/filters/Filter.cpp:
(WebCore::Filter::clampFilterRegionIfNeeded):
* platform/graphics/filters/Filter.h:
(WebCore::Filter::effectGeometry const): Deleted.
* platform/graphics/filters/FilterEffect.cpp:
(WebCore::FilterEffect::calculatePrimitiveSubregion const):
(WebCore::FilterEffect::apply):
(WebCore::FilterEffect::externalRepresentation const):
(WebCore::FilterEffect::determineFilterPrimitiveSubregion): Deleted.
* platform/graphics/filters/FilterEffect.h:
(WebCore::FilterEffect::resultColorSpace const):
(WebCore::FilterEffect::filterPrimitiveSubregion const): Deleted.
(WebCore::FilterEffect::setFilterPrimitiveSubregion): Deleted.
* platform/graphics/filters/FilterFunction.h:
(WebCore::FilterFunction::apply):
* svg/graphics/filters/SVGFilter.cpp:
(WebCore::SVGFilter::create):
(WebCore::SVGFilter::supportsCoreImageRendering const):
(WebCore::SVGFilter::lastEffect const):
(WebCore::SVGFilter::apply):
(WebCore::SVGFilter::clearResult):
(WebCore::SVGFilter::effectGeometry const): Deleted.
* svg/graphics/filters/SVGFilter.h:
* svg/graphics/filters/SVGFilterBuilder.cpp:
(WebCore::SVGFilterBuilder::effectGeometry const):
(WebCore::SVGFilterBuilder::buildEffectExpression const):
(WebCore::SVGFilterBuilder::buildExpression const):
(WebCore::buildEffectExpression): Deleted.
* svg/graphics/filters/SVGFilterBuilder.h:
(WebCore::SVGFilterBuilder::takeEffectGeometryMap): Deleted.
* svg/graphics/filters/SVGFilterExpression.h: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (286577 => 286578)


--- trunk/Source/WebCore/ChangeLog	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/ChangeLog	2021-12-07 00:36:58 UTC (rev 286578)
@@ -1,3 +1,70 @@
+2021-12-06  Said Abou-Hallawa  <s...@apple.com>
+
+        [GPU Process] Make FilterEffect calculate the primitive subregion only when needed
+        https://bugs.webkit.org/show_bug.cgi?id=232705
+        rdar://85290142
+
+        Reviewed by Cameron McCormack.
+
+        In this patch:
+
+        1. resultColorSpace() will return colorSpace() from a FilterImageVector
+           instead of returning the resultColorSpace() of the FilterEffect.
+
+        2. Filter::clampFilterRegionIfNeeded() will clamp the filterRegion() 
+           instead of clamping the maxEffectRect of the lastEffect() since all
+           the primitiveSubregions and the imageRects have to clipped to the
+           filterRegion().
+
+        3. determineFilterPrimitiveSubregion() is replaced by calculatePrimitiveSubregion()
+           which will calculate the primitiveSubregion from a FilterImageVector
+           and an optional FilterEffectGeometry.
+
+        4. Many of FilterEffects are made protected instead of having them public.
+
+        5. SVGFilterExpression will be defined as a Vector of SVGFilterExpressionTerm
+           which is a struct of FilterEffect and optional FilterEffectGeometry.
+
+        6. SVGFilter will replace the members whose types are FilterEffectVector
+           and FilterEffectGeometryMap with a single member of type SVGFilterExpression.
+
+        * Headers.cmake:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/graphics/filters/FEDisplacementMap.cpp:
+        (WebCore::FEDisplacementMap::resultColorSpace const):
+        * platform/graphics/filters/FEDisplacementMap.h:
+        * platform/graphics/filters/Filter.cpp:
+        (WebCore::Filter::clampFilterRegionIfNeeded):
+        * platform/graphics/filters/Filter.h:
+        (WebCore::Filter::effectGeometry const): Deleted.
+        * platform/graphics/filters/FilterEffect.cpp:
+        (WebCore::FilterEffect::calculatePrimitiveSubregion const):
+        (WebCore::FilterEffect::apply):
+        (WebCore::FilterEffect::externalRepresentation const):
+        (WebCore::FilterEffect::determineFilterPrimitiveSubregion): Deleted.
+        * platform/graphics/filters/FilterEffect.h:
+        (WebCore::FilterEffect::resultColorSpace const):
+        (WebCore::FilterEffect::filterPrimitiveSubregion const): Deleted.
+        (WebCore::FilterEffect::setFilterPrimitiveSubregion): Deleted.
+        * platform/graphics/filters/FilterFunction.h:
+        (WebCore::FilterFunction::apply):
+        * svg/graphics/filters/SVGFilter.cpp:
+        (WebCore::SVGFilter::create):
+        (WebCore::SVGFilter::supportsCoreImageRendering const):
+        (WebCore::SVGFilter::lastEffect const):
+        (WebCore::SVGFilter::apply):
+        (WebCore::SVGFilter::clearResult):
+        (WebCore::SVGFilter::effectGeometry const): Deleted.
+        * svg/graphics/filters/SVGFilter.h:
+        * svg/graphics/filters/SVGFilterBuilder.cpp:
+        (WebCore::SVGFilterBuilder::effectGeometry const):
+        (WebCore::SVGFilterBuilder::buildEffectExpression const):
+        (WebCore::SVGFilterBuilder::buildExpression const):
+        (WebCore::buildEffectExpression): Deleted.
+        * svg/graphics/filters/SVGFilterBuilder.h:
+        (WebCore::SVGFilterBuilder::takeEffectGeometryMap): Deleted.
+        * svg/graphics/filters/SVGFilterExpression.h: Added.
+
 2021-12-06  Ryan Haddad  <ryanhad...@apple.com>
 
         REGRESSION (r286507): [macOS] Many file system access layout tests became flaky failures

Modified: trunk/Source/WebCore/Headers.cmake (286577 => 286578)


--- trunk/Source/WebCore/Headers.cmake	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/Headers.cmake	2021-12-07 00:36:58 UTC (rev 286578)
@@ -1910,6 +1910,7 @@
     svg/graphics/SVGImageCache.h
 
     svg/graphics/filters/SVGFilter.h
+    svg/graphics/filters/SVGFilterExpression.h
 
     svg/properties/SVGList.h
     svg/properties/SVGPrimitiveList.h

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (286577 => 286578)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-12-07 00:36:58 UTC (rev 286578)
@@ -2318,6 +2318,7 @@
 		7299BC6723D6A53200CC6883 /* AlphaPremultiplication.h in Headers */ = {isa = PBXBuildFile; fileRef = 7299BC6423D686A600CC6883 /* AlphaPremultiplication.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		7299BC6823D6A53E00CC6883 /* RenderingMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 7299BC6623D686C600CC6883 /* RenderingMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		729D05302531424300422098 /* RenderingResourceIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 729D052E25313E2600422098 /* RenderingResourceIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		72A5D192275E8FFE0065833E /* SVGFilterExpression.h in Headers */ = {isa = PBXBuildFile; fileRef = 726CDE25275B489700A445B2 /* SVGFilterExpression.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		72A73BEF245A3F90001C9D03 /* AnimationFrameRate.h in Headers */ = {isa = PBXBuildFile; fileRef = 722A815C238FD50500C00583 /* AnimationFrameRate.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		72B8B0352753438600F752AA /* FilterFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 7262D756272A174100C56A09 /* FilterFunction.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		72B8B0362753441400F752AA /* FilterImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 72435EF4273D07670005E7EE /* FilterImage.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -11200,6 +11201,7 @@
 		7266F0282243120300833975 /* SVGAnimationAdditiveListFunctionImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGAnimationAdditiveListFunctionImpl.h; sourceTree = "<group>"; };
 		7266F029224312B100833975 /* SVGAnimationAdditiveListFunction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGAnimationAdditiveListFunction.h; sourceTree = "<group>"; };
 		7266F02A2243149B00833975 /* SVGAnimatedPropertyList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedPropertyList.h; sourceTree = "<group>"; };
+		726CDE25275B489700A445B2 /* SVGFilterExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGFilterExpression.h; sourceTree = "<group>"; };
 		726D56E1253AE0430002EF90 /* PlatformImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformImage.h; sourceTree = "<group>"; };
 		727AFED11A2EA6A0000442E8 /* EXTsRGB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EXTsRGB.cpp; sourceTree = "<group>"; };
 		727AFED21A2EA6A0000442E8 /* EXTsRGB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTsRGB.h; sourceTree = "<group>"; };
@@ -28447,6 +28449,7 @@
 				845E72FA0FD2623900A87D79 /* SVGFilter.h */,
 				081EBF380FD34F4100DA7559 /* SVGFilterBuilder.cpp */,
 				081EBF390FD34F4100DA7559 /* SVGFilterBuilder.h */,
+				726CDE25275B489700A445B2 /* SVGFilterExpression.h */,
 			);
 			path = filters;
 			sourceTree = "<group>";
@@ -37149,6 +37152,7 @@
 				845E72FC0FD2623900A87D79 /* SVGFilter.h in Headers */,
 				081EBF3B0FD34F4100DA7559 /* SVGFilterBuilder.h in Headers */,
 				B2227A0C0D00BF220071B782 /* SVGFilterElement.h in Headers */,
+				72A5D192275E8FFE0065833E /* SVGFilterExpression.h in Headers */,
 				B2227A0F0D00BF220071B782 /* SVGFilterPrimitiveStandardAttributes.h in Headers */,
 				B2227A120D00BF220071B782 /* SVGFitToViewBox.h in Headers */,
 				B2A1F2AB0CEF0ABF00442F6A /* SVGFontElement.h in Headers */,

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


--- trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp	2021-12-07 00:36:58 UTC (rev 286578)
@@ -68,13 +68,13 @@
     return true;
 }
 
-const DestinationColorSpace& FEDisplacementMap::resultColorSpace() const
+const DestinationColorSpace& FEDisplacementMap::resultColorSpace(const FilterImageVector& inputs) const
 {
     // Spec: The 'color-interpolation-filters' property only applies to the 'in2' source image
     // and does not apply to the 'in' source image. The 'in' source image must remain in its
     // current color space.
     // The result is in that same color space because it is a displacement of the 'in' image.
-    return inputEffect(0)->resultColorSpace();
+    return inputs[0]->colorSpace();
 }
 
 void FEDisplacementMap::transformResultColorSpace(FilterEffect* in, const int index)

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


--- trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h	2021-12-07 00:36:58 UTC (rev 286578)
@@ -54,7 +54,7 @@
 private:
     FEDisplacementMap(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float);
 
-    const DestinationColorSpace& resultColorSpace() const override;
+    const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const override;
     void transformResultColorSpace(FilterEffect*, const int) override;
 
     FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;

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


--- trunk/Source/WebCore/platform/graphics/filters/Filter.cpp	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/platform/graphics/filters/Filter.cpp	2021-12-07 00:36:58 UTC (rev 286578)
@@ -71,21 +71,13 @@
 
 bool Filter::clampFilterRegionIfNeeded()
 {
-    auto lastEffect = this->lastEffect();
-    lastEffect->determineFilterPrimitiveSubregion(*this);
-    
-    auto maxEffectRect = this->maxEffectRect(lastEffect->filterPrimitiveSubregion());
-    auto scaledMaxEffectRect = scaledByFilterScale(maxEffectRect);
+    auto scaledFilterRegion = scaledByFilterScale(m_filterRegion);
 
     FloatSize clampingScale(1, 1);
-    if (!ImageBuffer::sizeNeedsClamping(scaledMaxEffectRect.size(), clampingScale))
+    if (!ImageBuffer::sizeNeedsClamping(scaledFilterRegion.size(), clampingScale))
         return false;
 
     m_filterScale = m_filterScale * clampingScale;
-
-    // At least one FilterEffect has a too big image size,
-    // recalculate the effect sizes with new scale factors.
-    lastEffect->determineFilterPrimitiveSubregion(*this);
     return true;
 }
 

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


--- trunk/Source/WebCore/platform/graphics/filters/Filter.h	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/platform/graphics/filters/Filter.h	2021-12-07 00:36:58 UTC (rev 286578)
@@ -63,8 +63,6 @@
     FloatSize scaledByFilterScale(const FloatSize&) const;
     FloatRect scaledByFilterScale(const FloatRect&) const;
 
-    virtual std::optional<FilterEffectGeometry> effectGeometry(FilterEffect&) const { return std::nullopt; }
-
     FloatRect maxEffectRect(const FloatRect& primitiveSubregion) const;
     FloatRect clipToMaxEffectRect(const FloatRect& imageRect, const FloatRect& primitiveSubregion) const;
 

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


--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp	2021-12-07 00:36:58 UTC (rev 286578)
@@ -26,6 +26,7 @@
 
 #include "Filter.h"
 #include "FilterEffectApplier.h"
+#include "FilterEffectGeometry.h"
 #include "ImageBuffer.h"
 #include "Logging.h"
 #include <wtf/text/TextStream.h>
@@ -40,26 +41,20 @@
     return filter.clipToMaxEffectRect(imageRect, primitiveSubregion);
 }
 
-FloatRect FilterEffect::determineFilterPrimitiveSubregion(const Filter& filter)
+FloatRect FilterEffect::calculatePrimitiveSubregion(const Filter& filter, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& geometry) const
 {
     // This function implements https://www.w3.org/TR/filter-effects-1/#FilterPrimitiveSubRegion.
     FloatRect primitiveSubregion;
 
-    // If there is no input effects, take the effect boundaries as unite rect.
-    if (!m_inputEffects.isEmpty()) {
-        for (auto& effect : m_inputEffects) {
-            auto inputPrimitiveSubregion = effect->determineFilterPrimitiveSubregion(filter);
-            primitiveSubregion.unite(inputPrimitiveSubregion);
-        }
+    // If there is no input effects, take the effect boundaries as unite rect. Don't use the input's subregion for FETile.
+    if (!inputs.isEmpty() && filterType() != FilterEffect::Type::FETile) {
+        for (auto& input : inputs)
+            primitiveSubregion.unite(input->primitiveSubregion());
     } else
         primitiveSubregion = filter.filterRegion();
 
-    // Don't use the input's subregion for FETile.
-    if (filterType() == FilterEffect::Type::FETile)
-        primitiveSubregion = filter.filterRegion();
-    
     // Clip the primitive subregion to the effect geometry.
-    if (auto geometry = filter.effectGeometry(*this)) {
+    if (geometry) {
         if (auto x = geometry->x())
             primitiveSubregion.setX(*x);
         if (auto y = geometry->y())
@@ -70,7 +65,6 @@
             primitiveSubregion.setHeight(*height);
     }
 
-    setFilterPrimitiveSubregion(primitiveSubregion);
     return primitiveSubregion;
 }
 
@@ -80,7 +74,7 @@
     return m_inputEffects.at(number).get();
 }
 
-bool FilterEffect::apply(const Filter& filter)
+bool FilterEffect::apply(const Filter& filter, const std::optional<FilterEffectGeometry>& geometry)
 {
     if (hasResult())
         return true;
@@ -100,7 +94,9 @@
     }
 
     auto inputFilterImages = this->inputFilterImages();
-    auto imageRect = calculateImageRect(filter, inputFilterImages, m_filterPrimitiveSubregion);
+
+    auto primitiveSubregion = calculatePrimitiveSubregion(filter, inputFilterImages, geometry);
+    auto imageRect = calculateImageRect(filter, inputFilterImages, primitiveSubregion);
     auto absoluteImageRect = enclosingIntRect(filter.scaledByFilterScale(imageRect));
 
     if (absoluteImageRect.isEmpty() || ImageBuffer::sizeNeedsClamping(absoluteImageRect.size()))
@@ -107,9 +103,9 @@
         return false;
     
     auto isAlphaImage = resultIsAlphaImage(inputFilterImages);
-    auto imageColorSpace = resultColorSpace();
+    auto imageColorSpace = resultColorSpace(inputFilterImages);
 
-    m_filterImage = FilterImage::create(m_filterPrimitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, filter.renderingMode(), imageColorSpace);
+    m_filterImage = FilterImage::create(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, filter.renderingMode(), imageColorSpace);
     if (!m_filterImage)
         return false;
 
@@ -119,9 +115,9 @@
 
     LOG_WITH_STREAM(Filters, stream
         << "FilterEffect " << filterName() << " " << this << " apply():"
-        << "\n  filterPrimitiveSubregion " << m_filterPrimitiveSubregion
+        << "\n  filterPrimitiveSubregion " << primitiveSubregion
         << "\n  absolutePaintRect " << absoluteImageRect
-        << "\n  maxEffectRect " << filter.scaledByFilterScale(filter.maxEffectRect(m_filterPrimitiveSubregion))
+        << "\n  maxEffectRect " << filter.maxEffectRect(primitiveSubregion)
         << "\n  filter scale " << filter.filterScale());
 
     return applier->apply(filter, inputFilterImages, *m_filterImage);
@@ -173,7 +169,6 @@
     if (representationType == RepresentationType::Debugging) {
         TextStream::IndentScope indentScope(ts);
         ts.dumpProperty("operating colorspace", operatingColorSpace());
-        ts.dumpProperty("result colorspace", resultColorSpace());
         ts << "\n" << indent;
     }
     return ts;

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


--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h	2021-12-07 00:36:58 UTC (rev 286578)
@@ -37,6 +37,7 @@
 
 class Filter;
 class FilterEffectApplier;
+class FilterEffectGeometry;
 
 class FilterEffect : public FilterFunction {
 public:
@@ -45,58 +46,51 @@
     bool hasResult() const { return m_filterImage; }
 
     FilterImage* filterImage() const { return m_filterImage.get(); }
-    FilterImageVector inputFilterImages() const;
 
-    void correctPremultipliedResultIfNeeded();
-
     FilterEffectVector& inputEffects() { return m_inputEffects; }
     FilterEffect* inputEffect(unsigned) const;
     unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
 
-    // Recurses on inputs.
-    FloatRect determineFilterPrimitiveSubregion(const Filter&);
+    void transformResultColorSpace(const DestinationColorSpace&);
 
-    bool apply(const Filter&) override;
+    bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) override;
 
+    const DestinationColorSpace& operatingColorSpace() const { return m_operatingColorSpace; }
+    virtual void setOperatingColorSpace(const DestinationColorSpace& colorSpace) { m_operatingColorSpace = colorSpace; }
+
+    enum class RepresentationType { TestOutput, Debugging };
+    virtual WTF::TextStream& externalRepresentation(WTF::TextStream&, RepresentationType = RepresentationType::TestOutput) const;
+
+protected:
+    using FilterFunction::FilterFunction;
+
+    virtual bool mayProduceInvalidPremultipliedPixels() const { return false; }
+
+    void correctPremultipliedResultIfNeeded();
+
     // Correct any invalid pixels, if necessary, in the result of a filter operation.
     // This method is used to ensure valid pixel values on filter inputs and the final result.
     // Only the arithmetic composite filter ever needs to perform correction.
     virtual void correctFilterResultIfNeeded() { }
 
-    enum class RepresentationType { TestOutput, Debugging };
-    virtual WTF::TextStream& externalRepresentation(WTF::TextStream&, RepresentationType = RepresentationType::TestOutput) const;
+    virtual void transformResultColorSpace(FilterEffect* in, const int) { in->transformResultColorSpace(m_operatingColorSpace); }
 
-    FloatRect filterPrimitiveSubregion() const { return m_filterPrimitiveSubregion; }
-    void setFilterPrimitiveSubregion(const FloatRect& filterPrimitiveSubregion) { m_filterPrimitiveSubregion = filterPrimitiveSubregion; }
+    FilterImageVector inputFilterImages() const;
+    
+    FloatRect calculatePrimitiveSubregion(const Filter&, const FilterImageVector&, const std::optional<FilterEffectGeometry>&) const;
 
     virtual FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const;
 
-    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 FilterImageVector&) const { return false; }
-    virtual const DestinationColorSpace& resultColorSpace() const { return m_operatingColorSpace; }
+    virtual const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const { return m_operatingColorSpace; }
 
-    virtual void transformResultColorSpace(FilterEffect* in, const int) { in->transformResultColorSpace(m_operatingColorSpace); }
-    void transformResultColorSpace(const DestinationColorSpace&);
-
-protected:
-    using FilterFunction::FilterFunction;
-
-    virtual bool mayProduceInvalidPremultipliedPixels() const { return false; }
-    
     virtual std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const = 0;
 
-private:
     FilterEffectVector m_inputEffects;
 
     RefPtr<FilterImage> m_filterImage;
 
-    // The subregion of a filter primitive according to the SVG Filter specification in local coordinates.
-    // This is SVG specific and needs to move to RenderSVGResourceFilterPrimitive.
-    FloatRect m_filterPrimitiveSubregion;
-
     DestinationColorSpace m_operatingColorSpace { DestinationColorSpace::SRGB() };
 };
 

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


--- trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h	2021-12-07 00:36:58 UTC (rev 286578)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "FilterEffectGeometry.h"
 #include "FloatRect.h"
 #include "IntRectExtent.h"
 #include <wtf/RefCounted.h>
@@ -88,7 +89,7 @@
     virtual bool supportsCoreImageRendering() const { return false; }
 #endif
 
-    virtual bool apply(const Filter&) { return false; }
+    virtual bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) { return false; }
     virtual IntOutsets outsets() const { return { }; }
     virtual void clearResult() { }
 

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


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp	2021-12-07 00:36:58 UTC (rev 286578)
@@ -54,7 +54,7 @@
     if (!builder.buildFilterEffects(filterElement))
         return nullptr;
 
-    FilterEffectVector _expression_;
+    SVGFilterExpression _expression_;
     if (!builder.buildExpression(_expression_))
         return nullptr;
 
@@ -61,8 +61,6 @@
     ASSERT(!_expression_.isEmpty());
     filter->setExpression(WTFMove(_expression_));
 
-    filter->setEffectGeometryMap(builder.takeEffectGeometryMap());
-
 #if USE(CORE_IMAGE)
     if (!filter->supportsCoreImageRendering())
         filter->setRenderingMode(RenderingMode::Unaccelerated);
@@ -90,8 +88,8 @@
         return false;
 
     ASSERT(!m_expression.isEmpty());
-    for (auto& effect : m_expression) {
-        if (!effect->supportsCoreImageRendering())
+    for (auto& term : m_expression) {
+        if (!term.effect->supportsCoreImageRendering())
             return false;
     }
 
@@ -99,15 +97,14 @@
 }
 #endif
 
-std::optional<FilterEffectGeometry> SVGFilter::effectGeometry(FilterEffect& effect) const
+RefPtr<FilterEffect> SVGFilter::lastEffect() const
 {
-    auto it = m_effectGeometryMap.find(effect);
-    if (it != m_effectGeometryMap.end())
-        return it->value;
-    return std::nullopt;
+    if (m_expression.isEmpty())
+        return nullptr;
+    return m_expression.last().effect.ptr();
 }
 
-bool SVGFilter::apply(const Filter& filter)
+bool SVGFilter::apply(const Filter& filter, const std::optional<FilterEffectGeometry>&)
 {
     setSourceImage({ filter.sourceImage() });
     return apply();
@@ -116,8 +113,8 @@
 RefPtr<FilterImage> SVGFilter::apply()
 {
     ASSERT(!m_expression.isEmpty());
-    for (auto& effect : m_expression) {
-        if (!effect->apply(*this))
+    for (auto& term : m_expression) {
+        if (!term.effect->apply(*this, term.geometry))
             return nullptr;
     }
     return lastEffect()->filterImage();
@@ -132,8 +129,8 @@
 void SVGFilter::clearResult()
 {
     ASSERT(!m_expression.isEmpty());
-    for (auto& effect : m_expression)
-        effect->clearResult();
+    for (auto& term : m_expression)
+        term.effect->clearResult();
 }
 
 } // namespace WebCore

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


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h	2021-12-07 00:36:58 UTC (rev 286578)
@@ -22,8 +22,8 @@
 #pragma once
 
 #include "Filter.h"
-#include "FilterEffectVector.h"
 #include "FloatRect.h"
+#include "SVGFilterExpression.h"
 #include "SVGUnitTypes.h"
 #include <wtf/Ref.h>
 #include <wtf/TypeCasts.h>
@@ -42,7 +42,7 @@
 
     FloatRect targetBoundingBox() const { return m_targetBoundingBox; }
 
-    RefPtr<FilterEffect> lastEffect() const final { return !m_expression.isEmpty() ? m_expression.last() : nullptr; }
+    RefPtr<FilterEffect> lastEffect() const final;
 
     RefPtr<FilterImage> apply() final;
 
@@ -49,17 +49,14 @@
 private:
     SVGFilter(RenderingMode, const FloatSize& filterScale, ClipOperation, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, SVGUnitTypes::SVGUnitType primitiveUnits);
 
-    // FIXME: Merge the effectBoundaries in the _expression_ node.
-    void setExpression(FilterEffectVector&& _expression_) { m_expression = WTFMove(_expression_); }
-    void setEffectGeometryMap(FilterEffectGeometryMap&& effectGeometryMap) { m_effectGeometryMap = WTFMove(effectGeometryMap); }
+    void setExpression(SVGFilterExpression&& _expression_) { m_expression = WTFMove(_expression_); }
 
 #if USE(CORE_IMAGE)
     bool supportsCoreImageRendering() const final;
 #endif
-    std::optional<FilterEffectGeometry> effectGeometry(FilterEffect&) const final;
     FloatSize resolvedSize(const FloatSize&) const final;
 
-    bool apply(const Filter&) final;
+    bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) final;
     IntOutsets outsets() const final;
     void clearResult() final;
 
@@ -66,9 +63,7 @@
     FloatRect m_targetBoundingBox;
     SVGUnitTypes::SVGUnitType m_primitiveUnits;
 
-    // FIXME: Make m_expression a Vector of the FilterEffect and the effectBoundaries.
-    FilterEffectVector m_expression;
-    FilterEffectGeometryMap m_effectGeometryMap;
+    SVGFilterExpression m_expression;
 };
 
 } // namespace WebCore

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


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp	2021-12-07 00:36:58 UTC (rev 286578)
@@ -201,8 +201,16 @@
         clearResultsRecursive(reference);
 }
 
-static bool buildEffectExpression(const RefPtr<FilterEffect>& effect, FilterEffectVector& stack, FilterEffectVector& _expression_)
+std::optional<FilterEffectGeometry> SVGFilterBuilder::effectGeometry(FilterEffect& effect) const
 {
+    auto it = m_effectGeometryMap.find(effect);
+    if (it != m_effectGeometryMap.end())
+        return it->value;
+    return std::nullopt;
+}
+
+bool SVGFilterBuilder::buildEffectExpression(const RefPtr<FilterEffect>& effect, FilterEffectVector& stack, SVGFilterExpression& _expression_) const
+{
     // A cycle is detected.
     if (stack.contains(effect))
         return false;
@@ -209,7 +217,7 @@
 
     stack.append(effect);
     
-    _expression_.append(effect);
+    _expression_.append({ *effect, effectGeometry(*effect) });
 
     for (auto& inputEffect : effect->inputEffects()) {
         if (!buildEffectExpression(inputEffect, stack, _expression_))
@@ -223,7 +231,7 @@
     return true;
 }
 
-bool SVGFilterBuilder::buildExpression(FilterEffectVector& _expression_) const
+bool SVGFilterBuilder::buildExpression(SVGFilterExpression& _expression_) const
 {
     if (!m_lastEffect)
         return false;

Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h (286577 => 286578)


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h	2021-12-07 00:36:31 UTC (rev 286577)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h	2021-12-07 00:36:58 UTC (rev 286578)
@@ -22,6 +22,7 @@
 #pragma once
 
 #include "FilterEffect.h"
+#include "SVGFilterExpression.h"
 #include "SVGUnitTypes.h"
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
@@ -68,10 +69,8 @@
 
     void setupBuiltinEffects(Ref<FilterEffect> sourceGraphic);
     RefPtr<FilterEffect> buildFilterEffects(SVGFilterElement&);
-    bool buildExpression(FilterEffectVector& _expression_) const;
+    bool buildExpression(SVGFilterExpression&) const;
 
-    FilterEffectGeometryMap takeEffectGeometryMap() { return WTFMove(m_effectGeometryMap); }
-
 private:
     inline void addBuiltinEffects()
     {
@@ -79,6 +78,9 @@
             m_effectReferences.add(effect, FilterEffectSet());
     }
 
+    std::optional<FilterEffectGeometry> effectGeometry(FilterEffect&) const;
+    bool buildEffectExpression(const RefPtr<FilterEffect>&, FilterEffectVector& stack, SVGFilterExpression&) const;
+
     HashMap<AtomString, RefPtr<FilterEffect>> m_builtinEffects;
     HashMap<AtomString, RefPtr<FilterEffect>> m_namedEffects;
     // The value is a list, which contains those filter effects,

Added: trunk/Source/WebCore/svg/graphics/filters/SVGFilterExpression.h (0 => 286578)


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilterExpression.h	                        (rev 0)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilterExpression.h	2021-12-07 00:36:58 UTC (rev 286578)
@@ -0,0 +1,42 @@
+/*
+ * 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 "FloatRect.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FilterEffect;
+
+struct SVGFilterExpressionTerm {
+    Ref<FilterEffect> effect;
+    std::optional<FilterEffectGeometry> geometry;
+};
+
+using SVGFilterExpression = Vector<SVGFilterExpressionTerm>;
+
+} // namespace WebCore
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to