⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 286765 in webkit


Ignore:
Timestamp:
Dec 8, 2021, 10:39:26 PM (5 years ago)
Author:
Said Abou-Hallawa
Message:

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

Reviewed by Cameron McCormack.

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

In this patch:

-- The sourceImage and sourceImageRect arguments to Filter::apply() are

used to create a FilterImage. This will be the input to the SourceGraphic.

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

-- CSSFilter::apply() loops through its functions and uses the result

of every function as the input to the next one. The initial input is
the sourceImage. And the result of the last function is the returned
FilterImage.

-- SVGFilter::apply() loops through its expression. It uses a stack of

FilterImageVector to keep track of the inputs while applying each
FilterEffect. Every FilterEffect is asked to takeInputs() from this
stack. The result of applying the FilterEffect is pushed on this stack.
The stack should have a single FilterImage when finishing the loop.
This item is the result of applying the Filter.

-- FilterEffect::transformInputsColorSpace() was added to transform the

input FilterImageVector to the operating color space of FilterEffect.
It is overridden by FEDisplacementMap which does not transform the
color space of the first input FilterImage.

-- FilterEffect::correctPremultipliedInputs() was added to correct the

premultiplied pixels of the inputs FilterImageVector. We do not need
to do this correction if the FilterEffect we apply is arithmetic
composite filter. Otherwise we need to correct the FilterImage of any
arithmetic composite filter in the FilterImageVector.

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

SVGFilter expression.

  • platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm:

(WebCore::SourceGraphicCoreImageApplier::apply const):

  • platform/graphics/filters/FEBlend.h:
  • platform/graphics/filters/FEComposite.h:
  • platform/graphics/filters/FEDisplacementMap.cpp:

(WebCore::FEDisplacementMap::calculateImageRect const):
(WebCore::FEDisplacementMap::transformInputsColorSpace const):
(WebCore::FEDisplacementMap::transformResultColorSpace): Deleted.

  • platform/graphics/filters/FEDisplacementMap.h:
  • platform/graphics/filters/FEFlood.h:
  • platform/graphics/filters/FEMerge.h:
  • platform/graphics/filters/FETurbulence.h:
  • platform/graphics/filters/Filter.cpp:

(WebCore::Filter::apply):

  • platform/graphics/filters/Filter.h:

(WebCore::Filter::sourceImageRect const): Deleted.
(WebCore::Filter::setSourceImageRect): Deleted.
(WebCore::Filter::sourceImage const): Deleted.
(WebCore::Filter::setSourceImage): Deleted.

  • platform/graphics/filters/FilterEffect.cpp:

(WebCore::FilterEffect::takeImageInputs const):
(WebCore::FilterEffect::calculateImageRect const):
(WebCore::FilterEffect::transformInputsColorSpace const):
(WebCore::FilterEffect::correctPremultipliedInputs const):
(WebCore::FilterEffect::apply):
(WebCore::FilterEffect::inputEffect const):
(WebCore::FilterEffect::inputFilterImages const): Deleted.
(WebCore::FilterEffect::correctPremultipliedResultIfNeeded): Deleted.
(WebCore::FilterEffect::transformResultColorSpace): Deleted.

  • platform/graphics/filters/FilterEffect.h:

(WebCore::FilterEffect::filterImage const):
(WebCore::FilterEffect::numberOfEffectInputs const):
(WebCore::FilterEffect::numberOfImageInputs const):
(WebCore::FilterEffect::resultIsValidPremultiplied const):
(WebCore::FilterEffect::mayProduceInvalidPremultipliedPixels const): Deleted.
(WebCore::FilterEffect::correctFilterResultIfNeeded): Deleted.
(WebCore::FilterEffect::transformResultColorSpace): Deleted.

  • platform/graphics/filters/FilterFunction.h:

(WebCore::FilterFunction::apply):

  • platform/graphics/filters/FilterImage.cpp:

(WebCore::FilterImage::create):
(WebCore::FilterImage::FilterImage):
(WebCore::FilterImage::correctPremultipliedPixelBuffer):

  • platform/graphics/filters/FilterImage.h:
  • platform/graphics/filters/SourceAlpha.cpp:

(WebCore::SourceAlpha::calculateImageRect const): Deleted.

  • platform/graphics/filters/SourceAlpha.h:
  • platform/graphics/filters/SourceGraphic.cpp:

(WebCore::SourceGraphic::calculateImageRect const): Deleted.

  • platform/graphics/filters/SourceGraphic.h:
  • platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp:

(WebCore::SourceGraphicSoftwareApplier::apply const):

  • rendering/CSSFilter.cpp:

(WebCore::CSSFilter::apply):

  • rendering/CSSFilter.h:
  • svg/graphics/filters/SVGFEImage.h:
  • svg/graphics/filters/SVGFilter.cpp:

(WebCore::SVGFilter::apply):

  • svg/graphics/filters/SVGFilter.h:
  • svg/graphics/filters/SVGFilterBuilder.cpp:

(WebCore::SVGFilterBuilder::buildFilterEffects):
(WebCore::SVGFilterBuilder::buildExpression const):
(WebCore::collectEffects): Deleted.
(WebCore::totalNumberFilterEffects): Deleted.

Location:
trunk/Source/WebCore
Files:
27 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286763 r286765  
     12021-12-08  Said Abou-Hallawa  <said@apple.com>
     2
     3        [GPU Process] [Filters] Make Filter::apply() and FilterEffect:apply() take FilterImageVector for the inputs
     4        https://bugs.webkit.org/show_bug.cgi?id=233973
     5        rdar://86248999
     6
     7        Reviewed by Cameron McCormack.
     8
     9        This is a step towards removing the dependency on the input effects. This
     10        step is required to make encoding/decoding the FilterEffect just be
     11        sending or receiving its primitive data.
     12
     13        In this patch:
     14
     15        -- The sourceImage and sourceImageRect arguments to Filter::apply() are
     16           used to create a FilterImage. This will be the input to the SourceGraphic.
     17
     18        -- The members m_sourceImage and m_sourceImageRect of Filter are removed.
     19
     20        -- CSSFilter::apply() loops through its functions and uses the result
     21           of every function as the input to the next one. The initial input is
     22           the sourceImage. And the result of the last function is the returned
     23           FilterImage.
     24
     25        -- SVGFilter::apply() loops through its expression. It uses a stack of
     26           FilterImageVector to keep track of the inputs while applying each
     27           FilterEffect. Every FilterEffect is asked to takeInputs() from this
     28           stack. The result of applying the FilterEffect is pushed on this stack.
     29           The stack should have a single FilterImage when finishing the loop.
     30           This item is the result of applying the Filter.
     31
     32        -- FilterEffect::transformInputsColorSpace() was added to transform the
     33           input FilterImageVector to the operating color space of FilterEffect.
     34           It is overridden by FEDisplacementMap which does not transform the
     35           color space of the first input FilterImage.
     36
     37        -- FilterEffect::correctPremultipliedInputs() was added to correct the
     38           premultiplied pixels of the inputs FilterImageVector. We do not need
     39           to do this correction if the FilterEffect we apply is arithmetic
     40           composite filter. Otherwise we need to correct the FilterImage of any
     41           arithmetic composite filter in the FilterImageVector.
     42
     43        -- No need for totalNumberFilterEffects(). This count is the size of the
     44           SVGFilter expression.
     45
     46        * platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm:
     47        (WebCore::SourceGraphicCoreImageApplier::apply const):
     48        * platform/graphics/filters/FEBlend.h:
     49        * platform/graphics/filters/FEComposite.h:
     50        * platform/graphics/filters/FEDisplacementMap.cpp:
     51        (WebCore::FEDisplacementMap::calculateImageRect const):
     52        (WebCore::FEDisplacementMap::transformInputsColorSpace const):
     53        (WebCore::FEDisplacementMap::transformResultColorSpace): Deleted.
     54        * platform/graphics/filters/FEDisplacementMap.h:
     55        * platform/graphics/filters/FEFlood.h:
     56        * platform/graphics/filters/FEMerge.h:
     57        * platform/graphics/filters/FETurbulence.h:
     58        * platform/graphics/filters/Filter.cpp:
     59        (WebCore::Filter::apply):
     60        * platform/graphics/filters/Filter.h:
     61        (WebCore::Filter::sourceImageRect const): Deleted.
     62        (WebCore::Filter::setSourceImageRect): Deleted.
     63        (WebCore::Filter::sourceImage const): Deleted.
     64        (WebCore::Filter::setSourceImage): Deleted.
     65        * platform/graphics/filters/FilterEffect.cpp:
     66        (WebCore::FilterEffect::takeImageInputs const):
     67        (WebCore::FilterEffect::calculateImageRect const):
     68        (WebCore::FilterEffect::transformInputsColorSpace const):
     69        (WebCore::FilterEffect::correctPremultipliedInputs const):
     70        (WebCore::FilterEffect::apply):
     71        (WebCore::FilterEffect::inputEffect const):
     72        (WebCore::FilterEffect::inputFilterImages const): Deleted.
     73        (WebCore::FilterEffect::correctPremultipliedResultIfNeeded): Deleted.
     74        (WebCore::FilterEffect::transformResultColorSpace): Deleted.
     75        * platform/graphics/filters/FilterEffect.h:
     76        (WebCore::FilterEffect::filterImage const):
     77        (WebCore::FilterEffect::numberOfEffectInputs const):
     78        (WebCore::FilterEffect::numberOfImageInputs const):
     79        (WebCore::FilterEffect::resultIsValidPremultiplied const):
     80        (WebCore::FilterEffect::mayProduceInvalidPremultipliedPixels const): Deleted.
     81        (WebCore::FilterEffect::correctFilterResultIfNeeded): Deleted.
     82        (WebCore::FilterEffect::transformResultColorSpace): Deleted.
     83        * platform/graphics/filters/FilterFunction.h:
     84        (WebCore::FilterFunction::apply):
     85        * platform/graphics/filters/FilterImage.cpp:
     86        (WebCore::FilterImage::create):
     87        (WebCore::FilterImage::FilterImage):
     88        (WebCore::FilterImage::correctPremultipliedPixelBuffer):
     89        * platform/graphics/filters/FilterImage.h:
     90        * platform/graphics/filters/SourceAlpha.cpp:
     91        (WebCore::SourceAlpha::calculateImageRect const): Deleted.
     92        * platform/graphics/filters/SourceAlpha.h:
     93        * platform/graphics/filters/SourceGraphic.cpp:
     94        (WebCore::SourceGraphic::calculateImageRect const): Deleted.
     95        * platform/graphics/filters/SourceGraphic.h:
     96        * platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp:
     97        (WebCore::SourceGraphicSoftwareApplier::apply const):
     98        * rendering/CSSFilter.cpp:
     99        (WebCore::CSSFilter::apply):
     100        * rendering/CSSFilter.h:
     101        * svg/graphics/filters/SVGFEImage.h:
     102        * svg/graphics/filters/SVGFilter.cpp:
     103        (WebCore::SVGFilter::apply):
     104        * svg/graphics/filters/SVGFilter.h:
     105        * svg/graphics/filters/SVGFilterBuilder.cpp:
     106        (WebCore::SVGFilterBuilder::buildFilterEffects):
     107        (WebCore::SVGFilterBuilder::buildExpression const):
     108        (WebCore::collectEffects): Deleted.
     109        (WebCore::totalNumberFilterEffects): Deleted.
     110
    11112021-12-08  Patrick Griffis  <pgriffis@igalia.com>
    2112
  • trunk/Source/WebCore/platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm

    r286193 r286765  
    2929#if USE(CORE_IMAGE)
    3030
    31 #import "Filter.h"
    3231#import "FilterImage.h"
    3332#import "PlatformImageBuffer.h"
     
    3534namespace WebCore {
    3635
    37 bool SourceGraphicCoreImageApplier::apply(const Filter& filter, const FilterImageVector&, FilterImage& result) const
     36bool SourceGraphicCoreImageApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) const
    3837{
    39     auto sourceImage = filter.sourceImage();
     38    auto& input = inputs[0].get();
     39
     40    auto sourceImage = input.imageBuffer();
    4041    if (!sourceImage)
    4142        return false;
  • trunk/Source/WebCore/platform/graphics/filters/FEBlend.h

    r286589 r286765  
    4242    FEBlend(BlendMode);
    4343
     44    unsigned numberOfEffectInputs() const override { return 2; }
     45   
    4446    std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
    4547
  • trunk/Source/WebCore/platform/graphics/filters/FEComposite.h

    r286589 r286765  
    6464    FEComposite(const CompositeOperationType&, float k1, float k2, float k3, float k4);
    6565
     66    unsigned numberOfEffectInputs() const override { return 2; }
     67
    6668    FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
    6769
    68     bool mayProduceInvalidPremultipliedPixels() const override { return m_type == FECOMPOSITE_OPERATOR_ARITHMETIC; }
     70    bool resultIsValidPremultiplied() const override { return m_type != FECOMPOSITE_OPERATOR_ARITHMETIC; }
    6971
    7072    std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
  • trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp

    r286589 r286765  
    6969}
    7070
     71FloatRect FEDisplacementMap::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect& primitiveSubregion) const
     72{
     73    return filter.maxEffectRect(primitiveSubregion);
     74}
     75
    7176const DestinationColorSpace& FEDisplacementMap::resultColorSpace(const FilterImageVector& inputs) const
    7277{
     
    7883}
    7984
    80 void FEDisplacementMap::transformResultColorSpace(FilterEffect* in, const int index)
     85void FEDisplacementMap::transformInputsColorSpace(const FilterImageVector& inputs) const
    8186{
    8287    // Do not transform the first primitive input, as per the spec.
    83     if (index)
    84         in->transformResultColorSpace(operatingColorSpace());
    85 }
    86 
    87 FloatRect FEDisplacementMap::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect& primitiveSubregion) const
    88 {
    89     return filter.maxEffectRect(primitiveSubregion);
     88    ASSERT(inputs.size() == 2);
     89    inputs[1]->transformToColorSpace(operatingColorSpace());
    9090}
    9191
  • trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h

    r286589 r286765  
    5555    FEDisplacementMap(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float);
    5656
    57     const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const override;
    58     void transformResultColorSpace(FilterEffect*, const int) override;
     57    unsigned numberOfEffectInputs() const override { return 2; }
    5958
    6059    FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
     60
     61    const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const override;
     62    void transformInputsColorSpace(const FilterImageVector& inputs) const override;
    6163
    6264    std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
  • trunk/Source/WebCore/platform/graphics/filters/FEFlood.h

    r286589 r286765  
    5050    FEFlood(const Color& floodColor, float floodOpacity);
    5151
     52    unsigned numberOfEffectInputs() const override { return 0; }
     53
    5254    FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
    5355
  • trunk/Source/WebCore/platform/graphics/filters/FEMerge.h

    r286589 r286765  
    3030public:
    3131    WEBCORE_EXPORT static Ref<FEMerge> create(unsigned numberOfEffectInputs);
     32
     33    unsigned numberOfEffectInputs() const override { return m_numberOfEffectInputs; }
    3234
    3335    template<class Encoder> void encode(Encoder&) const;
  • trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h

    r286589 r286765  
    6363private:
    6464    FETurbulence(TurbulenceType, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles);
     65
     66    unsigned numberOfEffectInputs() const override { return 0; }
    6567
    6668    FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
  • trunk/Source/WebCore/platform/graphics/filters/Filter.cpp

    r286578 r286765  
    8484RefPtr<FilterImage> Filter::apply(ImageBuffer* sourceImage, const FloatRect& sourceImageRect)
    8585{
    86     setSourceImage(sourceImage);
    87     setSourceImageRect(sourceImageRect);
     86    RefPtr<FilterImage> input;
    8887
    89     auto result = apply();
     88    if (sourceImage) {
     89        auto absoluteSourceImageRect = enclosingIntRect(scaledByFilterScale(sourceImageRect));
     90        input = FilterImage::create(m_filterRegion, sourceImageRect, absoluteSourceImageRect, Ref { *sourceImage });
     91        if (!input)
     92            return nullptr;
     93    }
     94
     95    auto result = apply(input.get());
    9096    if (!result)
    91         return { };
     97        return nullptr;
    9298
     99    result->correctPremultipliedPixelBuffer();
    93100    result->transformToColorSpace(DestinationColorSpace::SRGB());
    94101    return result;
  • trunk/Source/WebCore/platform/graphics/filters/Filter.h

    r286589 r286765  
    4545    void setFilterScale(const FloatSize& filterScale) { m_filterScale = filterScale; }
    4646
    47     FloatRect sourceImageRect() const { return m_sourceImageRect; }
    48     void setSourceImageRect(const FloatRect& sourceImageRect) { m_sourceImageRect = sourceImageRect; }
    49 
    5047    FloatRect filterRegion() const { return m_filterRegion; }
    5148    void setFilterRegion(const FloatRect& filterRegion) { m_filterRegion = filterRegion; }
    52 
    53     ImageBuffer* sourceImage() const { return m_sourceImage.get(); }
    54     void setSourceImage(RefPtr<ImageBuffer>&& sourceImage) { m_sourceImage = WTFMove(sourceImage); }
    5549
    5650    ClipOperation clipOperation() const { return m_clipOperation; }
     
    6963
    7064    bool clampFilterRegionIfNeeded();
    71    
    72     virtual RefPtr<FilterImage> apply() = 0;
     65
     66    virtual RefPtr<FilterImage> apply(FilterImage* sourceImage) = 0;
    7367    WEBCORE_EXPORT RefPtr<FilterImage> apply(ImageBuffer* sourceImage, const FloatRect& sourceImageRect);
    7468
     
    8276    ClipOperation m_clipOperation;
    8377    FloatRect m_filterRegion;
    84 
    85     // FIXME: these should not be members of Filter. They should be passed to Filter::apply().
    86     FloatRect m_sourceImageRect;
    87     RefPtr<ImageBuffer> m_sourceImage;
    8878};
    8979
  • trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp

    r286589 r286765  
    3434namespace WebCore {
    3535
    36 FloatRect FilterEffect::calculateImageRect(const Filter& filter, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const
     36FilterImageVector FilterEffect::takeImageInputs(FilterImageVector& stack) const
    3737{
    38     FloatRect imageRect;
    39     for (auto& input : inputs)
    40         imageRect.unite(input->imageRect());
    41     return filter.clipToMaxEffectRect(imageRect, primitiveSubregion);
     38    unsigned inputsSize = numberOfImageInputs();
     39    ASSERT(stack.size() >= inputsSize);
     40    if (!inputsSize)
     41        return { };
     42
     43    Vector<Ref<FilterImage>> inputs;
     44    inputs.reserveInitialCapacity(inputsSize);
     45
     46    for (; inputsSize; --inputsSize)
     47        inputs.uncheckedAppend(stack.takeLast());
     48
     49    return inputs;
    4250}
    4351
     
    6977}
    7078
    71 FilterEffect* FilterEffect::inputEffect(unsigned number) const
     79FloatRect FilterEffect::calculateImageRect(const Filter& filter, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const
    7280{
    73     ASSERT_WITH_SECURITY_IMPLICATION(number < m_inputEffects.size());
    74     return m_inputEffects.at(number).get();
     81    FloatRect imageRect;
     82    for (auto& input : inputs)
     83        imageRect.unite(input->imageRect());
     84    return filter.clipToMaxEffectRect(imageRect, primitiveSubregion);
    7585}
    7686
    77 bool FilterEffect::apply(const Filter& filter, const std::optional<FilterEffectGeometry>& geometry)
     87void FilterEffect::transformInputsColorSpace(const FilterImageVector& inputs) const
    7888{
    79     if (hasResult())
    80         return true;
     89    for (auto& input : inputs)
     90        input->transformToColorSpace(operatingColorSpace());
     91}
    8192
    82     unsigned size = m_inputEffects.size();
    83     for (unsigned i = 0; i < size; ++i) {
    84         FilterEffect* in = m_inputEffects.at(i).get();
     93void FilterEffect::correctPremultipliedInputs(const FilterImageVector& inputs) const
     94{
     95    // Correct any invalid pixels, if necessary, in the result of a filter operation.
     96    // This method is used to ensure valid pixel values on filter inputs and the final result.
     97    // Only the arithmetic composite filter ever needs to perform correction.
     98    for (auto& input : inputs)
     99        input->correctPremultipliedPixelBuffer();
     100}
    85101
    86         // Convert input results to the current effect's color space.
    87         ASSERT(in->hasResult());
    88         transformResultColorSpace(in, i);
    89     }
     102RefPtr<FilterImage> FilterEffect::apply(const Filter& filter, FilterImage& input)
     103{
     104    return apply(filter, FilterImageVector { Ref { input } });
     105}
    90106
    91     if (!mayProduceInvalidPremultipliedPixels()) {
    92         for (auto& in : m_inputEffects)
    93             in->correctPremultipliedResultIfNeeded();
    94     }
     107RefPtr<FilterImage> FilterEffect::apply(const Filter& filter, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& geometry)
     108{
     109    ASSERT(inputs.size() == numberOfImageInputs());
    95110
    96     auto inputFilterImages = this->inputFilterImages();
     111    if (m_filterImage)
     112        return m_filterImage;
    97113
    98     auto primitiveSubregion = calculatePrimitiveSubregion(filter, inputFilterImages, geometry);
    99     auto imageRect = calculateImageRect(filter, inputFilterImages, primitiveSubregion);
     114    auto primitiveSubregion = calculatePrimitiveSubregion(filter, inputs, geometry);
     115    auto imageRect = calculateImageRect(filter, inputs, primitiveSubregion);
    100116    auto absoluteImageRect = enclosingIntRect(filter.scaledByFilterScale(imageRect));
    101117
    102118    if (absoluteImageRect.isEmpty() || ImageBuffer::sizeNeedsClamping(absoluteImageRect.size()))
    103         return false;
     119        return nullptr;
    104120   
    105     auto isAlphaImage = resultIsAlphaImage(inputFilterImages);
    106     auto imageColorSpace = resultColorSpace(inputFilterImages);
    107 
    108     m_filterImage = FilterImage::create(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, filter.renderingMode(), imageColorSpace);
    109     if (!m_filterImage)
    110         return false;
     121    auto isAlphaImage = resultIsAlphaImage(inputs);
     122    auto isValidPremultiplied = resultIsValidPremultiplied();
     123    auto imageColorSpace = resultColorSpace(inputs);
    111124
    112125    auto applier = createApplier(filter);
    113126    if (!applier)
    114         return false;
     127        return nullptr;
     128
     129    m_filterImage = FilterImage::create(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, isValidPremultiplied, filter.renderingMode(), imageColorSpace);
     130    if (!m_filterImage)
     131        return nullptr;
    115132
    116133    LOG_WITH_STREAM(Filters, stream
     
    121138        << "\n  filter scale " << filter.filterScale());
    122139
    123     return applier->apply(filter, inputFilterImages, *m_filterImage);
     140    transformInputsColorSpace(inputs);
     141    if (isValidPremultiplied)
     142        correctPremultipliedInputs(inputs);
     143
     144    if (!applier->apply(filter, inputs, *m_filterImage))
     145        m_filterImage = nullptr;
     146
     147    return m_filterImage;
     148}
     149
     150FilterEffect* FilterEffect::inputEffect(unsigned number) const
     151{
     152    ASSERT_WITH_SECURITY_IMPLICATION(number < m_inputEffects.size());
     153    return m_inputEffects.at(number).get();
    124154}
    125155
     
    136166    for (auto& effect : m_inputEffects)
    137167        effect->clearResultsRecursive();
    138 }
    139 
    140 FilterImageVector FilterEffect::inputFilterImages() const
    141 {
    142     FilterImageVector filterImages;
    143 
    144     for (auto& inputEffect : m_inputEffects)
    145         filterImages.append(*inputEffect->filterImage());
    146 
    147     return filterImages;
    148 }
    149 
    150 void FilterEffect::correctPremultipliedResultIfNeeded()
    151 {
    152     if (!hasResult() || !mayProduceInvalidPremultipliedPixels())
    153         return;
    154     m_filterImage->correctPremultipliedPixelBuffer();
    155 }
    156 
    157 void FilterEffect::transformResultColorSpace(const DestinationColorSpace& destinationColorSpace)
    158 {
    159     if (!hasResult())
    160         return;
    161     m_filterImage->transformToColorSpace(destinationColorSpace);
    162168}
    163169
  • trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h

    r286589 r286765  
    4141
    4242class FilterEffect : public FilterFunction {
     43    using FilterFunction::apply;
     44
    4345public:
    4446    void clearResult() override;
     
    4648    bool hasResult() const { return m_filterImage; }
    4749
    48     FilterImage* filterImage() const { return m_filterImage.get(); }
     50    RefPtr<FilterImage> filterImage() const { return m_filterImage; }
     51    FilterImageVector takeImageInputs(FilterImageVector& stack) const;
    4952
    5053    FilterEffectVector& inputEffects() { return m_inputEffects; }
    5154    FilterEffect* inputEffect(unsigned) const;
    52     unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
    5355
    54     void transformResultColorSpace(const DestinationColorSpace&);
    55 
    56     bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) override;
     56    RefPtr<FilterImage> apply(const Filter&, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& = std::nullopt);
    5757
    5858    const DestinationColorSpace& operatingColorSpace() const { return m_operatingColorSpace; }
     
    6464    using FilterFunction::FilterFunction;
    6565
    66     virtual bool mayProduceInvalidPremultipliedPixels() const { return false; }
     66    virtual unsigned numberOfEffectInputs() const { return 1; }
     67    unsigned numberOfImageInputs() const { return filterType() == FilterEffect::Type::SourceGraphic ? 1 : numberOfEffectInputs(); }
    6768
    68     void correctPremultipliedResultIfNeeded();
    69 
    70     // Correct any invalid pixels, if necessary, in the result of a filter operation.
    71     // This method is used to ensure valid pixel values on filter inputs and the final result.
    72     // Only the arithmetic composite filter ever needs to perform correction.
    73     virtual void correctFilterResultIfNeeded() { }
    74 
    75     virtual void transformResultColorSpace(FilterEffect* in, const int) { in->transformResultColorSpace(m_operatingColorSpace); }
    76 
    77     FilterImageVector inputFilterImages() const;
    78    
    79     FloatRect calculatePrimitiveSubregion(const Filter&, const FilterImageVector&, const std::optional<FilterEffectGeometry>&) const;
     69    FloatRect calculatePrimitiveSubregion(const Filter&, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>&) const;
    8070
    8171    virtual FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const;
     
    8373    // Solid black image with different alpha values.
    8474    virtual bool resultIsAlphaImage(const FilterImageVector&) const { return false; }
     75
     76    virtual bool resultIsValidPremultiplied() const { return true; }
     77
    8578    virtual const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const { return m_operatingColorSpace; }
    8679
     80    virtual void transformInputsColorSpace(const FilterImageVector& inputs) const;
     81   
     82    void correctPremultipliedInputs(const FilterImageVector& inputs) const;
     83
    8784    virtual std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const = 0;
     85
     86    RefPtr<FilterImage> apply(const Filter&, FilterImage& input) override;
    8887
    8988    FilterEffectVector m_inputEffects;
  • trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h

    r286589 r286765  
    2727
    2828#include "FilterEffectGeometry.h"
     29#include "FilterImage.h"
     30#include "FilterImageVector.h"
    2931#include "FloatRect.h"
    3032#include "IntRectExtent.h"
     
    9597#endif
    9698
    97     virtual bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) { return false; }
     99    virtual RefPtr<FilterImage> apply(const Filter&, FilterImage&) { return nullptr; }
    98100    virtual IntOutsets outsets() const { return { }; }
    99101    virtual void clearResult() { }
  • trunk/Source/WebCore/platform/graphics/filters/FilterImage.cpp

    r286287 r286765  
    3939namespace WebCore {
    4040
    41 RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
     41RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
    4242{
    4343    ASSERT(!ImageBuffer::sizeNeedsClamping(absoluteImageRect.size()));
    44     return adoptRef(new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, renderingMode, colorSpace));
    45 }
    46 
    47 FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
     44    return adoptRef(new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, isValidPremultiplied, renderingMode, colorSpace));
     45}
     46
     47RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&& imageBuffer)
     48{
     49    return adoptRef(*new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, WTFMove(imageBuffer)));
     50}
     51
     52FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
    4853    : m_primitiveSubregion(primitiveSubregion)
    4954    , m_imageRect(imageRect)
    5055    , m_absoluteImageRect(absoluteImageRect)
    5156    , m_isAlphaImage(isAlphaImage)
     57    , m_isValidPremultiplied(isValidPremultiplied)
    5258    , m_renderingMode(renderingMode)
    5359    , m_colorSpace(colorSpace)
     60{
     61}
     62
     63FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&& imageBuffer)
     64    : m_primitiveSubregion(primitiveSubregion)
     65    , m_imageRect(imageRect)
     66    , m_absoluteImageRect(absoluteImageRect)
     67    , m_renderingMode(imageBuffer->renderingMode())
     68    , m_colorSpace(imageBuffer->colorSpace())
     69    , m_imageBuffer(WTFMove(imageBuffer))
    5470{
    5571}
     
    282298{
    283299    // Must operate on pre-multiplied results; other formats cannot have invalid pixels.
    284     if (!m_premultipliedPixelBuffer)
     300    if (!m_premultipliedPixelBuffer || m_isValidPremultiplied)
    285301        return;
    286302
  • trunk/Source/WebCore/platform/graphics/filters/FilterImage.h

    r286391 r286765  
    4646class FilterImage : public RefCounted<FilterImage> {
    4747public:
    48     static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode, const DestinationColorSpace&);
     48    static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode, const DestinationColorSpace&);
     49    static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&&);
    4950
    5051    // The return values are in filter coordinates.
     
    7778
    7879private:
    79     FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode, const DestinationColorSpace&);
     80    FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode, const DestinationColorSpace&);
     81    FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&&);
    8082
    8183    std::optional<PixelBuffer>& pixelBufferSlot(AlphaPremultiplication);
     
    9496
    9597    bool m_isAlphaImage { false };
     98    bool m_isValidPremultiplied { true };
    9699    RenderingMode m_renderingMode;
    97100    DestinationColorSpace m_colorSpace;
  • trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp

    r286753 r286765  
    4949}
    5050
    51 FloatRect SourceAlpha::calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect&) const
    52 {
    53     return inputs[0]->imageRect();
    54 }
    55 
    5651std::unique_ptr<FilterEffectApplier> SourceAlpha::createApplier(const Filter&) const
    5752{
  • trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.h

    r286753 r286765  
    3636    explicit SourceAlpha(FilterEffect&);
    3737
    38     FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
    39 
    4038    std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
    4139
  • trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp

    r286589 r286765  
    4242}
    4343
    44 FloatRect SourceGraphic::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect&) const
    45 {
    46     return filter.sourceImageRect();
    47 }
    48 
    4944std::unique_ptr<FilterEffectApplier> SourceGraphic::createApplier(const Filter& filter) const
    5045{
  • trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.h

    r286589 r286765  
    3939#endif
    4040
    41     FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
     41    unsigned numberOfEffectInputs() const override { return 0; }
    4242
    4343    std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
  • trunk/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp

    r286203 r286765  
    2222#include "SourceGraphicSoftwareApplier.h"
    2323
    24 #include "Filter.h"
    2524#include "GraphicsContext.h"
    2625#include "ImageBuffer.h"
    27 #include "SourceGraphic.h"
    2826
    2927namespace WebCore {
    3028
    31 bool SourceGraphicSoftwareApplier::apply(const Filter& filter, const FilterImageVector&, FilterImage& result) const
     29bool SourceGraphicSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) const
    3230{
     31    auto& input = inputs[0].get();
     32
    3333    auto resultImage = result.imageBuffer();
    34     auto sourceImage = filter.sourceImage();
     34    auto sourceImage = input.imageBuffer();
    3535    if (!resultImage || !sourceImage)
    3636        return false;
  • trunk/Source/WebCore/rendering/CSSFilter.cpp

    r286589 r286765  
    369369}
    370370
    371 RefPtr<FilterImage> CSSFilter::apply()
    372 {
     371RefPtr<FilterImage> CSSFilter::apply(FilterImage* sourceImage)
     372{
     373    if (!sourceImage)
     374        return nullptr;
     375   
     376    RefPtr<FilterImage> result = sourceImage;
     377
    373378    for (auto& function : m_functions) {
    374         if (function->isSVGFilter())
    375             downcast<SVGFilter>(function.ptr())->setSourceImageRect(sourceImageRect());
    376         if (!function->apply(*this))
     379        result = function->apply(*this, *result);
     380        if (!result)
    377381            return nullptr;
    378382    }
    379     return lastEffect()->filterImage();
     383
     384    return result;
    380385}
    381386
  • trunk/Source/WebCore/rendering/CSSFilter.h

    r286589 r286765  
    5757
    5858    void clearIntermediateResults();
    59     RefPtr<FilterImage> apply() final;
     59    RefPtr<FilterImage> apply(FilterImage* sourceImage) final;
    6060
    6161private:
  • trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h

    r286589 r286765  
    4848    FEImage(SourceImage&&, const FloatRect& sourceImageRect, const SVGPreserveAspectRatioValue&);
    4949
     50    unsigned numberOfEffectInputs() const override { return 0; }
     51
    5052    // FEImage results are always in DestinationColorSpace::SRGB()
    5153    void setOperatingColorSpace(const DestinationColorSpace&) override { }
  • trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp

    r286753 r286765  
    118118}
    119119
    120 bool SVGFilter::apply(const Filter& filter, const std::optional<FilterEffectGeometry>&)
     120RefPtr<FilterImage> SVGFilter::apply(const Filter&, FilterImage& sourceImage)
    121121{
    122     setSourceImage({ filter.sourceImage() });
    123     return apply();
     122    return apply(&sourceImage);
    124123}
    125124
    126 RefPtr<FilterImage> SVGFilter::apply()
     125RefPtr<FilterImage> SVGFilter::apply(FilterImage* sourceImage)
    127126{
    128127    ASSERT(!m_expression.isEmpty());
     128
     129    FilterImageVector stack;
     130
    129131    for (auto& term : m_expression) {
    130         if (!term.effect->apply(*this, term.geometry))
     132        auto& effect = term.effect;
     133        auto geometry = term.geometry;
     134
     135        if (effect->filterType() == FilterEffect::Type::SourceGraphic) {
     136            if (auto result = effect->filterImage()) {
     137                stack.append(result.releaseNonNull());
     138                continue;
     139            }
     140
     141            if (!sourceImage)
     142                return nullptr;
     143
     144            // Add sourceImage as an input to the SourceGraphic.
     145            stack.append(Ref { *sourceImage });
     146        }
     147
     148        // Need to remove the inputs here in case the effect already has a result.
     149        auto inputs = effect->takeImageInputs(stack);
     150
     151        if (auto result = effect->filterImage()) {
     152            stack.append(result.releaseNonNull());
     153            continue;
     154        }
     155
     156        auto result = term.effect->apply(*this, inputs, geometry);
     157        if (!result)
    131158            return nullptr;
     159
     160        stack.append(result.releaseNonNull());
    132161    }
    133     return lastEffect()->filterImage();
     162   
     163    ASSERT(stack.size() == 1);
     164    return stack.takeLast();
    134165}
    135166
  • trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h

    r286753 r286765  
    4949    RefPtr<FilterEffect> lastEffect() const final;
    5050
    51     RefPtr<FilterImage> apply() final;
     51    RefPtr<FilterImage> apply(FilterImage* sourceImage) final;
    5252
    5353    WTF::TextStream& externalRepresentation(WTF::TextStream&, FilterRepresentation) const final;
     
    6464    FloatSize resolvedSize(const FloatSize&) const final;
    6565
    66     bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) final;
     66    RefPtr<FilterImage> apply(const Filter&, FilterImage& sourceImage) final;
    6767    IntOutsets outsets() const final;
    6868    void clearResult() final;
  • trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp

    r286589 r286765  
    3535namespace WebCore {
    3636
     37static constexpr unsigned maxTotalNumberFilterEffects = 100;
     38static constexpr unsigned maxCountChildNodes = 200;
     39
    3740void SVGFilterBuilder::setupBuiltinEffects(Ref<FilterEffect> sourceGraphic)
    3841{
     
    7780#endif
    7881
    79 static unsigned collectEffects(const FilterEffect* effect, HashSet<const FilterEffect*>& allEffects)
    80 {
    81     allEffects.add(effect);
    82     unsigned size = effect->numberOfEffectInputs();
    83     for (unsigned i = 0; i < size; ++i) {
    84         FilterEffect* in = effect->inputEffect(i);
    85         collectEffects(in, allEffects);
    86     }
    87     return allEffects.size();
    88 }
    89 
    90 static unsigned totalNumberFilterEffects(const FilterEffect& lastEffect)
    91 {
    92     HashSet<const FilterEffect*> allEffects;
    93     return collectEffects(&lastEffect, allEffects);
    94 }
    95 
    9682RefPtr<FilterEffect> SVGFilterBuilder::buildFilterEffects(SVGFilterElement& filterElement)
    9783{
    98     static constexpr unsigned maxCountChildNodes = 200;
    99     static constexpr unsigned maxTotalNumberFilterEffects = 100;
    100 
    10184    if (filterElement.countChildNodes() > maxCountChildNodes)
    10285        return nullptr;
     
    125108    }
    126109
    127     if (!effect || totalNumberFilterEffects(*effect) > maxTotalNumberFilterEffects) {
     110    if (!effect)
    128111        clearEffects();
    129         return nullptr;
    130     }
    131112
    132113    return effect;
     
    241222        return false;
    242223
     224    if (expression.size() > maxTotalNumberFilterEffects)
     225        return false;
     226
    243227    expression.reverse();
    244228    expression.shrinkToFit();
Note: See TracChangeset for help on using the changeset viewer.