Diff
Modified: trunk/Source/WebCore/ChangeLog (286764 => 286765)
--- trunk/Source/WebCore/ChangeLog 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/ChangeLog 2021-12-09 06:39:26 UTC (rev 286765)
@@ -1,3 +1,113 @@
+2021-12-08 Said Abou-Hallawa <s...@apple.com>
+
+ [GPU Process] [Filters] Make Filter::apply() and FilterEffect:apply() take FilterImageVector for the inputs
+ https://bugs.webkit.org/show_bug.cgi?id=233973
+ rdar://86248999
+
+ Reviewed by Cameron McCormack.
+
+ This is a step towards removing the dependency on the input effects. This
+ step is required to make encoding/decoding the FilterEffect just be
+ sending or receiving its primitive data.
+
+ In this patch:
+
+ -- The sourceImage and sourceImageRect arguments to Filter::apply() are
+ used to create a FilterImage. This will be the input to the SourceGraphic.
+
+ -- The members m_sourceImage and m_sourceImageRect of Filter are removed.
+
+ -- CSSFilter::apply() loops through its functions and uses the result
+ of every function as the input to the next one. The initial input is
+ the sourceImage. And the result of the last function is the returned
+ FilterImage.
+
+ -- SVGFilter::apply() loops through its _expression_. It uses a stack of
+ FilterImageVector to keep track of the inputs while applying each
+ FilterEffect. Every FilterEffect is asked to takeInputs() from this
+ stack. The result of applying the FilterEffect is pushed on this stack.
+ The stack should have a single FilterImage when finishing the loop.
+ This item is the result of applying the Filter.
+
+ -- FilterEffect::transformInputsColorSpace() was added to transform the
+ input FilterImageVector to the operating color space of FilterEffect.
+ It is overridden by FEDisplacementMap which does not transform the
+ color space of the first input FilterImage.
+
+ -- FilterEffect::correctPremultipliedInputs() was added to correct the
+ premultiplied pixels of the inputs FilterImageVector. We do not need
+ to do this correction if the FilterEffect we apply is arithmetic
+ composite filter. Otherwise we need to correct the FilterImage of any
+ arithmetic composite filter in the FilterImageVector.
+
+ -- No need for totalNumberFilterEffects(). This count is the size of the
+ SVGFilter _expression_.
+
+ * platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm:
+ (WebCore::SourceGraphicCoreImageApplier::apply const):
+ * platform/graphics/filters/FEBlend.h:
+ * platform/graphics/filters/FEComposite.h:
+ * platform/graphics/filters/FEDisplacementMap.cpp:
+ (WebCore::FEDisplacementMap::calculateImageRect const):
+ (WebCore::FEDisplacementMap::transformInputsColorSpace const):
+ (WebCore::FEDisplacementMap::transformResultColorSpace): Deleted.
+ * platform/graphics/filters/FEDisplacementMap.h:
+ * platform/graphics/filters/FEFlood.h:
+ * platform/graphics/filters/FEMerge.h:
+ * platform/graphics/filters/FETurbulence.h:
+ * platform/graphics/filters/Filter.cpp:
+ (WebCore::Filter::apply):
+ * platform/graphics/filters/Filter.h:
+ (WebCore::Filter::sourceImageRect const): Deleted.
+ (WebCore::Filter::setSourceImageRect): Deleted.
+ (WebCore::Filter::sourceImage const): Deleted.
+ (WebCore::Filter::setSourceImage): Deleted.
+ * platform/graphics/filters/FilterEffect.cpp:
+ (WebCore::FilterEffect::takeImageInputs const):
+ (WebCore::FilterEffect::calculateImageRect const):
+ (WebCore::FilterEffect::transformInputsColorSpace const):
+ (WebCore::FilterEffect::correctPremultipliedInputs const):
+ (WebCore::FilterEffect::apply):
+ (WebCore::FilterEffect::inputEffect const):
+ (WebCore::FilterEffect::inputFilterImages const): Deleted.
+ (WebCore::FilterEffect::correctPremultipliedResultIfNeeded): Deleted.
+ (WebCore::FilterEffect::transformResultColorSpace): Deleted.
+ * platform/graphics/filters/FilterEffect.h:
+ (WebCore::FilterEffect::filterImage const):
+ (WebCore::FilterEffect::numberOfEffectInputs const):
+ (WebCore::FilterEffect::numberOfImageInputs const):
+ (WebCore::FilterEffect::resultIsValidPremultiplied const):
+ (WebCore::FilterEffect::mayProduceInvalidPremultipliedPixels const): Deleted.
+ (WebCore::FilterEffect::correctFilterResultIfNeeded): Deleted.
+ (WebCore::FilterEffect::transformResultColorSpace): Deleted.
+ * platform/graphics/filters/FilterFunction.h:
+ (WebCore::FilterFunction::apply):
+ * platform/graphics/filters/FilterImage.cpp:
+ (WebCore::FilterImage::create):
+ (WebCore::FilterImage::FilterImage):
+ (WebCore::FilterImage::correctPremultipliedPixelBuffer):
+ * platform/graphics/filters/FilterImage.h:
+ * platform/graphics/filters/SourceAlpha.cpp:
+ (WebCore::SourceAlpha::calculateImageRect const): Deleted.
+ * platform/graphics/filters/SourceAlpha.h:
+ * platform/graphics/filters/SourceGraphic.cpp:
+ (WebCore::SourceGraphic::calculateImageRect const): Deleted.
+ * platform/graphics/filters/SourceGraphic.h:
+ * platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp:
+ (WebCore::SourceGraphicSoftwareApplier::apply const):
+ * rendering/CSSFilter.cpp:
+ (WebCore::CSSFilter::apply):
+ * rendering/CSSFilter.h:
+ * svg/graphics/filters/SVGFEImage.h:
+ * svg/graphics/filters/SVGFilter.cpp:
+ (WebCore::SVGFilter::apply):
+ * svg/graphics/filters/SVGFilter.h:
+ * svg/graphics/filters/SVGFilterBuilder.cpp:
+ (WebCore::SVGFilterBuilder::buildFilterEffects):
+ (WebCore::SVGFilterBuilder::buildExpression const):
+ (WebCore::collectEffects): Deleted.
+ (WebCore::totalNumberFilterEffects): Deleted.
+
2021-12-08 Patrick Griffis <pgrif...@igalia.com>
CSP: Skip whitespace at beginning of policy header
Modified: trunk/Source/WebCore/platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm 2021-12-09 06:39:26 UTC (rev 286765)
@@ -28,15 +28,16 @@
#if USE(CORE_IMAGE)
-#import "Filter.h"
#import "FilterImage.h"
#import "PlatformImageBuffer.h"
namespace WebCore {
-bool SourceGraphicCoreImageApplier::apply(const Filter& filter, const FilterImageVector&, FilterImage& result) const
+bool SourceGraphicCoreImageApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) const
{
- auto sourceImage = filter.sourceImage();
+ auto& input = inputs[0].get();
+
+ auto sourceImage = input.imageBuffer();
if (!sourceImage)
return false;
Modified: trunk/Source/WebCore/platform/graphics/filters/FEBlend.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FEBlend.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEBlend.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -41,6 +41,8 @@
private:
FEBlend(BlendMode);
+ unsigned numberOfEffectInputs() const override { return 2; }
+
std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
void platformApplyNEON(unsigned char* srcPixelArrayA, unsigned char* srcPixelArrayB, unsigned char* dstPixelArray,
Modified: trunk/Source/WebCore/platform/graphics/filters/FEComposite.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FEComposite.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEComposite.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -63,9 +63,11 @@
private:
FEComposite(const CompositeOperationType&, float k1, float k2, float k3, float k4);
+ unsigned numberOfEffectInputs() const override { return 2; }
+
FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
- bool mayProduceInvalidPremultipliedPixels() const override { return m_type == FECOMPOSITE_OPERATOR_ARITHMETIC; }
+ bool resultIsValidPremultiplied() const override { return m_type != FECOMPOSITE_OPERATOR_ARITHMETIC; }
std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
Modified: trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp 2021-12-09 06:39:26 UTC (rev 286765)
@@ -68,6 +68,11 @@
return true;
}
+FloatRect FEDisplacementMap::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect& primitiveSubregion) const
+{
+ return filter.maxEffectRect(primitiveSubregion);
+}
+
const DestinationColorSpace& FEDisplacementMap::resultColorSpace(const FilterImageVector& inputs) const
{
// Spec: The 'color-interpolation-filters' property only applies to the 'in2' source image
@@ -77,18 +82,13 @@
return inputs[0]->colorSpace();
}
-void FEDisplacementMap::transformResultColorSpace(FilterEffect* in, const int index)
+void FEDisplacementMap::transformInputsColorSpace(const FilterImageVector& inputs) const
{
// Do not transform the first primitive input, as per the spec.
- if (index)
- in->transformResultColorSpace(operatingColorSpace());
+ ASSERT(inputs.size() == 2);
+ inputs[1]->transformToColorSpace(operatingColorSpace());
}
-FloatRect FEDisplacementMap::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect& primitiveSubregion) const
-{
- return filter.maxEffectRect(primitiveSubregion);
-}
-
std::unique_ptr<FilterEffectApplier> FEDisplacementMap::createApplier(const Filter&) const
{
return FilterEffectApplier::create<FEDisplacementMapSoftwareApplier>(*this);
Modified: trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -54,11 +54,13 @@
private:
FEDisplacementMap(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float);
- const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const override;
- void transformResultColorSpace(FilterEffect*, const int) override;
+ unsigned numberOfEffectInputs() const override { return 2; }
FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
+ const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const override;
+ void transformInputsColorSpace(const FilterImageVector& inputs) const override;
+
std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
WTF::TextStream& externalRepresentation(WTF::TextStream&, FilterRepresentation) const override;
Modified: trunk/Source/WebCore/platform/graphics/filters/FEFlood.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FEFlood.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEFlood.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -49,6 +49,8 @@
private:
FEFlood(const Color& floodColor, float floodOpacity);
+ unsigned numberOfEffectInputs() const override { return 0; }
+
FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
Modified: trunk/Source/WebCore/platform/graphics/filters/FEMerge.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FEMerge.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEMerge.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -30,6 +30,8 @@
public:
WEBCORE_EXPORT static Ref<FEMerge> create(unsigned numberOfEffectInputs);
+ unsigned numberOfEffectInputs() const override { return m_numberOfEffectInputs; }
+
template<class Encoder> void encode(Encoder&) const;
template<class Decoder> static std::optional<Ref<FEMerge>> decode(Decoder&);
Modified: trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -63,6 +63,8 @@
private:
FETurbulence(TurbulenceType, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles);
+ unsigned numberOfEffectInputs() const override { return 0; }
+
FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
Modified: trunk/Source/WebCore/platform/graphics/filters/Filter.cpp (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/Filter.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/Filter.cpp 2021-12-09 06:39:26 UTC (rev 286765)
@@ -83,13 +83,20 @@
RefPtr<FilterImage> Filter::apply(ImageBuffer* sourceImage, const FloatRect& sourceImageRect)
{
- setSourceImage(sourceImage);
- setSourceImageRect(sourceImageRect);
+ RefPtr<FilterImage> input;
- auto result = apply();
+ if (sourceImage) {
+ auto absoluteSourceImageRect = enclosingIntRect(scaledByFilterScale(sourceImageRect));
+ input = FilterImage::create(m_filterRegion, sourceImageRect, absoluteSourceImageRect, Ref { *sourceImage });
+ if (!input)
+ return nullptr;
+ }
+
+ auto result = apply(input.get());
if (!result)
- return { };
+ return nullptr;
+ result->correctPremultipliedPixelBuffer();
result->transformToColorSpace(DestinationColorSpace::SRGB());
return result;
}
Modified: trunk/Source/WebCore/platform/graphics/filters/Filter.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/Filter.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/Filter.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -44,15 +44,9 @@
FloatSize filterScale() const { return m_filterScale; }
void setFilterScale(const FloatSize& filterScale) { m_filterScale = filterScale; }
- FloatRect sourceImageRect() const { return m_sourceImageRect; }
- void setSourceImageRect(const FloatRect& sourceImageRect) { m_sourceImageRect = sourceImageRect; }
-
FloatRect filterRegion() const { return m_filterRegion; }
void setFilterRegion(const FloatRect& filterRegion) { m_filterRegion = filterRegion; }
- ImageBuffer* sourceImage() const { return m_sourceImage.get(); }
- void setSourceImage(RefPtr<ImageBuffer>&& sourceImage) { m_sourceImage = WTFMove(sourceImage); }
-
ClipOperation clipOperation() const { return m_clipOperation; }
void setClipOperation(ClipOperation clipOperation) { m_clipOperation = clipOperation; }
@@ -68,8 +62,8 @@
virtual RefPtr<FilterEffect> lastEffect() const = 0;
bool clampFilterRegionIfNeeded();
-
- virtual RefPtr<FilterImage> apply() = 0;
+
+ virtual RefPtr<FilterImage> apply(FilterImage* sourceImage) = 0;
WEBCORE_EXPORT RefPtr<FilterImage> apply(ImageBuffer* sourceImage, const FloatRect& sourceImageRect);
protected:
@@ -81,10 +75,6 @@
FloatSize m_filterScale;
ClipOperation m_clipOperation;
FloatRect m_filterRegion;
-
- // FIXME: these should not be members of Filter. They should be passed to Filter::apply().
- FloatRect m_sourceImageRect;
- RefPtr<ImageBuffer> m_sourceImage;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp 2021-12-09 06:39:26 UTC (rev 286765)
@@ -33,12 +33,20 @@
namespace WebCore {
-FloatRect FilterEffect::calculateImageRect(const Filter& filter, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const
+FilterImageVector FilterEffect::takeImageInputs(FilterImageVector& stack) const
{
- FloatRect imageRect;
- for (auto& input : inputs)
- imageRect.unite(input->imageRect());
- return filter.clipToMaxEffectRect(imageRect, primitiveSubregion);
+ unsigned inputsSize = numberOfImageInputs();
+ ASSERT(stack.size() >= inputsSize);
+ if (!inputsSize)
+ return { };
+
+ Vector<Ref<FilterImage>> inputs;
+ inputs.reserveInitialCapacity(inputsSize);
+
+ for (; inputsSize; --inputsSize)
+ inputs.uncheckedAppend(stack.takeLast());
+
+ return inputs;
}
FloatRect FilterEffect::calculatePrimitiveSubregion(const Filter& filter, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& geometry) const
@@ -68,51 +76,60 @@
return primitiveSubregion;
}
-FilterEffect* FilterEffect::inputEffect(unsigned number) const
+FloatRect FilterEffect::calculateImageRect(const Filter& filter, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const
{
- ASSERT_WITH_SECURITY_IMPLICATION(number < m_inputEffects.size());
- return m_inputEffects.at(number).get();
+ FloatRect imageRect;
+ for (auto& input : inputs)
+ imageRect.unite(input->imageRect());
+ return filter.clipToMaxEffectRect(imageRect, primitiveSubregion);
}
-bool FilterEffect::apply(const Filter& filter, const std::optional<FilterEffectGeometry>& geometry)
+void FilterEffect::transformInputsColorSpace(const FilterImageVector& inputs) const
{
- if (hasResult())
- return true;
+ for (auto& input : inputs)
+ input->transformToColorSpace(operatingColorSpace());
+}
- unsigned size = m_inputEffects.size();
- for (unsigned i = 0; i < size; ++i) {
- FilterEffect* in = m_inputEffects.at(i).get();
+void FilterEffect::correctPremultipliedInputs(const FilterImageVector& inputs) const
+{
+ // Correct any invalid pixels, if necessary, in the result of a filter operation.
+ // This method is used to ensure valid pixel values on filter inputs and the final result.
+ // Only the arithmetic composite filter ever needs to perform correction.
+ for (auto& input : inputs)
+ input->correctPremultipliedPixelBuffer();
+}
- // Convert input results to the current effect's color space.
- ASSERT(in->hasResult());
- transformResultColorSpace(in, i);
- }
+RefPtr<FilterImage> FilterEffect::apply(const Filter& filter, FilterImage& input)
+{
+ return apply(filter, FilterImageVector { Ref { input } });
+}
- if (!mayProduceInvalidPremultipliedPixels()) {
- for (auto& in : m_inputEffects)
- in->correctPremultipliedResultIfNeeded();
- }
+RefPtr<FilterImage> FilterEffect::apply(const Filter& filter, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& geometry)
+{
+ ASSERT(inputs.size() == numberOfImageInputs());
- auto inputFilterImages = this->inputFilterImages();
+ if (m_filterImage)
+ return m_filterImage;
- auto primitiveSubregion = calculatePrimitiveSubregion(filter, inputFilterImages, geometry);
- auto imageRect = calculateImageRect(filter, inputFilterImages, primitiveSubregion);
+ auto primitiveSubregion = calculatePrimitiveSubregion(filter, inputs, geometry);
+ auto imageRect = calculateImageRect(filter, inputs, primitiveSubregion);
auto absoluteImageRect = enclosingIntRect(filter.scaledByFilterScale(imageRect));
if (absoluteImageRect.isEmpty() || ImageBuffer::sizeNeedsClamping(absoluteImageRect.size()))
- return false;
+ return nullptr;
- auto isAlphaImage = resultIsAlphaImage(inputFilterImages);
- auto imageColorSpace = resultColorSpace(inputFilterImages);
+ auto isAlphaImage = resultIsAlphaImage(inputs);
+ auto isValidPremultiplied = resultIsValidPremultiplied();
+ auto imageColorSpace = resultColorSpace(inputs);
- m_filterImage = FilterImage::create(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, filter.renderingMode(), imageColorSpace);
- if (!m_filterImage)
- return false;
-
auto applier = createApplier(filter);
if (!applier)
- return false;
+ return nullptr;
+ m_filterImage = FilterImage::create(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, isValidPremultiplied, filter.renderingMode(), imageColorSpace);
+ if (!m_filterImage)
+ return nullptr;
+
LOG_WITH_STREAM(Filters, stream
<< "FilterEffect " << filterName() << " " << this << " apply():"
<< "\n filterPrimitiveSubregion " << primitiveSubregion
@@ -120,9 +137,22 @@
<< "\n maxEffectRect " << filter.maxEffectRect(primitiveSubregion)
<< "\n filter scale " << filter.filterScale());
- return applier->apply(filter, inputFilterImages, *m_filterImage);
+ transformInputsColorSpace(inputs);
+ if (isValidPremultiplied)
+ correctPremultipliedInputs(inputs);
+
+ if (!applier->apply(filter, inputs, *m_filterImage))
+ m_filterImage = nullptr;
+
+ return m_filterImage;
}
+FilterEffect* FilterEffect::inputEffect(unsigned number) const
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(number < m_inputEffects.size());
+ return m_inputEffects.at(number).get();
+}
+
void FilterEffect::clearResult()
{
m_filterImage = nullptr;
@@ -137,30 +167,6 @@
effect->clearResultsRecursive();
}
-FilterImageVector FilterEffect::inputFilterImages() const
-{
- FilterImageVector filterImages;
-
- for (auto& inputEffect : m_inputEffects)
- filterImages.append(*inputEffect->filterImage());
-
- return filterImages;
-}
-
-void FilterEffect::correctPremultipliedResultIfNeeded()
-{
- if (!hasResult() || !mayProduceInvalidPremultipliedPixels())
- return;
- m_filterImage->correctPremultipliedPixelBuffer();
-}
-
-void FilterEffect::transformResultColorSpace(const DestinationColorSpace& destinationColorSpace)
-{
- if (!hasResult())
- return;
- m_filterImage->transformToColorSpace(destinationColorSpace);
-}
-
TextStream& FilterEffect::externalRepresentation(TextStream& ts, FilterRepresentation representation) const
{
// FIXME: We should dump the subRegions of the filter primitives here later. This isn't
Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -40,21 +40,21 @@
class FilterEffectGeometry;
class FilterEffect : public FilterFunction {
+ using FilterFunction::apply;
+
public:
void clearResult() override;
void clearResultsRecursive();
bool hasResult() const { return m_filterImage; }
- FilterImage* filterImage() const { return m_filterImage.get(); }
+ RefPtr<FilterImage> filterImage() const { return m_filterImage; }
+ FilterImageVector takeImageInputs(FilterImageVector& stack) const;
FilterEffectVector& inputEffects() { return m_inputEffects; }
FilterEffect* inputEffect(unsigned) const;
- unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
- void transformResultColorSpace(const DestinationColorSpace&);
+ RefPtr<FilterImage> apply(const Filter&, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& = std::nullopt);
- bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) override;
-
const DestinationColorSpace& operatingColorSpace() const { return m_operatingColorSpace; }
virtual void setOperatingColorSpace(const DestinationColorSpace& colorSpace) { m_operatingColorSpace = colorSpace; }
@@ -63,29 +63,28 @@
protected:
using FilterFunction::FilterFunction;
- virtual bool mayProduceInvalidPremultipliedPixels() const { return false; }
+ virtual unsigned numberOfEffectInputs() const { return 1; }
+ unsigned numberOfImageInputs() const { return filterType() == FilterEffect::Type::SourceGraphic ? 1 : numberOfEffectInputs(); }
- void correctPremultipliedResultIfNeeded();
+ FloatRect calculatePrimitiveSubregion(const Filter&, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>&) const;
- // Correct any invalid pixels, if necessary, in the result of a filter operation.
- // This method is used to ensure valid pixel values on filter inputs and the final result.
- // Only the arithmetic composite filter ever needs to perform correction.
- virtual void correctFilterResultIfNeeded() { }
-
- virtual void transformResultColorSpace(FilterEffect* in, const int) { in->transformResultColorSpace(m_operatingColorSpace); }
-
- FilterImageVector inputFilterImages() const;
-
- FloatRect calculatePrimitiveSubregion(const Filter&, const FilterImageVector&, const std::optional<FilterEffectGeometry>&) const;
-
virtual FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const;
// Solid black image with different alpha values.
virtual bool resultIsAlphaImage(const FilterImageVector&) const { return false; }
+
+ virtual bool resultIsValidPremultiplied() const { return true; }
+
virtual const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const { return m_operatingColorSpace; }
+ virtual void transformInputsColorSpace(const FilterImageVector& inputs) const;
+
+ void correctPremultipliedInputs(const FilterImageVector& inputs) const;
+
virtual std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const = 0;
+ RefPtr<FilterImage> apply(const Filter&, FilterImage& input) override;
+
FilterEffectVector m_inputEffects;
RefPtr<FilterImage> m_filterImage;
Modified: trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -26,6 +26,8 @@
#pragma once
#include "FilterEffectGeometry.h"
+#include "FilterImage.h"
+#include "FilterImageVector.h"
#include "FloatRect.h"
#include "IntRectExtent.h"
#include <wtf/RefCounted.h>
@@ -94,7 +96,7 @@
virtual bool supportsCoreImageRendering() const { return false; }
#endif
- virtual bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) { return false; }
+ virtual RefPtr<FilterImage> apply(const Filter&, FilterImage&) { return nullptr; }
virtual IntOutsets outsets() const { return { }; }
virtual void clearResult() { }
Modified: trunk/Source/WebCore/platform/graphics/filters/FilterImage.cpp (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FilterImage.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterImage.cpp 2021-12-09 06:39:26 UTC (rev 286765)
@@ -38,22 +38,38 @@
namespace WebCore {
-RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
+RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
{
ASSERT(!ImageBuffer::sizeNeedsClamping(absoluteImageRect.size()));
- return adoptRef(new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, renderingMode, colorSpace));
+ return adoptRef(new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, isValidPremultiplied, renderingMode, colorSpace));
}
-FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
+RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&& imageBuffer)
+{
+ return adoptRef(*new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, WTFMove(imageBuffer)));
+}
+
+FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
: m_primitiveSubregion(primitiveSubregion)
, m_imageRect(imageRect)
, m_absoluteImageRect(absoluteImageRect)
, m_isAlphaImage(isAlphaImage)
+ , m_isValidPremultiplied(isValidPremultiplied)
, m_renderingMode(renderingMode)
, m_colorSpace(colorSpace)
{
}
+FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&& imageBuffer)
+ : m_primitiveSubregion(primitiveSubregion)
+ , m_imageRect(imageRect)
+ , m_absoluteImageRect(absoluteImageRect)
+ , m_renderingMode(imageBuffer->renderingMode())
+ , m_colorSpace(imageBuffer->colorSpace())
+ , m_imageBuffer(WTFMove(imageBuffer))
+{
+}
+
FloatRect FilterImage::maxEffectRect(const Filter& filter) const
{
return filter.maxEffectRect(m_primitiveSubregion);
@@ -281,7 +297,7 @@
void FilterImage::correctPremultipliedPixelBuffer()
{
// Must operate on pre-multiplied results; other formats cannot have invalid pixels.
- if (!m_premultipliedPixelBuffer)
+ if (!m_premultipliedPixelBuffer || m_isValidPremultiplied)
return;
Uint8ClampedArray& imageArray = m_premultipliedPixelBuffer->data();
Modified: trunk/Source/WebCore/platform/graphics/filters/FilterImage.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/FilterImage.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterImage.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -45,7 +45,8 @@
class FilterImage : public RefCounted<FilterImage> {
public:
- static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode, const DestinationColorSpace&);
+ static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode, const DestinationColorSpace&);
+ static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&&);
// The return values are in filter coordinates.
FloatRect primitiveSubregion() const { return m_primitiveSubregion; }
@@ -76,7 +77,8 @@
#endif
private:
- FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode, const DestinationColorSpace&);
+ FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode, const DestinationColorSpace&);
+ FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&&);
std::optional<PixelBuffer>& pixelBufferSlot(AlphaPremultiplication);
@@ -93,6 +95,7 @@
IntRect m_absoluteImageRect;
bool m_isAlphaImage { false };
+ bool m_isValidPremultiplied { true };
RenderingMode m_renderingMode;
DestinationColorSpace m_colorSpace;
Modified: trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp 2021-12-09 06:39:26 UTC (rev 286765)
@@ -48,11 +48,6 @@
inputEffects().append(&sourceEffect);
}
-FloatRect SourceAlpha::calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect&) const
-{
- return inputs[0]->imageRect();
-}
-
std::unique_ptr<FilterEffectApplier> SourceAlpha::createApplier(const Filter&) const
{
return FilterEffectApplier::create<SourceAlphaSoftwareApplier>(*this);
Modified: trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -35,8 +35,6 @@
SourceAlpha();
explicit SourceAlpha(FilterEffect&);
- FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
-
std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
WTF::TextStream& externalRepresentation(WTF::TextStream&, FilterRepresentation) const override;
Modified: trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp 2021-12-09 06:39:26 UTC (rev 286765)
@@ -41,11 +41,6 @@
{
}
-FloatRect SourceGraphic::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect&) const
-{
- return filter.sourceImageRect();
-}
-
std::unique_ptr<FilterEffectApplier> SourceGraphic::createApplier(const Filter& filter) const
{
#if USE(CORE_IMAGE)
Modified: trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.h (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -38,7 +38,7 @@
bool supportsCoreImageRendering() const override { return true; }
#endif
- FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
+ unsigned numberOfEffectInputs() const override { return 0; }
std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
Modified: trunk/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp (286764 => 286765)
--- trunk/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp 2021-12-09 06:39:26 UTC (rev 286765)
@@ -21,17 +21,17 @@
#include "config.h"
#include "SourceGraphicSoftwareApplier.h"
-#include "Filter.h"
#include "GraphicsContext.h"
#include "ImageBuffer.h"
-#include "SourceGraphic.h"
namespace WebCore {
-bool SourceGraphicSoftwareApplier::apply(const Filter& filter, const FilterImageVector&, FilterImage& result) const
+bool SourceGraphicSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) const
{
+ auto& input = inputs[0].get();
+
auto resultImage = result.imageBuffer();
- auto sourceImage = filter.sourceImage();
+ auto sourceImage = input.imageBuffer();
if (!resultImage || !sourceImage)
return false;
Modified: trunk/Source/WebCore/rendering/CSSFilter.cpp (286764 => 286765)
--- trunk/Source/WebCore/rendering/CSSFilter.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/rendering/CSSFilter.cpp 2021-12-09 06:39:26 UTC (rev 286765)
@@ -368,15 +368,20 @@
function->clearResult();
}
-RefPtr<FilterImage> CSSFilter::apply()
+RefPtr<FilterImage> CSSFilter::apply(FilterImage* sourceImage)
{
+ if (!sourceImage)
+ return nullptr;
+
+ RefPtr<FilterImage> result = sourceImage;
+
for (auto& function : m_functions) {
- if (function->isSVGFilter())
- downcast<SVGFilter>(function.ptr())->setSourceImageRect(sourceImageRect());
- if (!function->apply(*this))
+ result = function->apply(*this, *result);
+ if (!result)
return nullptr;
}
- return lastEffect()->filterImage();
+
+ return result;
}
void CSSFilter::setFilterRegion(const FloatRect& filterRegion)
Modified: trunk/Source/WebCore/rendering/CSSFilter.h (286764 => 286765)
--- trunk/Source/WebCore/rendering/CSSFilter.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/rendering/CSSFilter.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -56,7 +56,7 @@
IntOutsets outsets() const final;
void clearIntermediateResults();
- RefPtr<FilterImage> apply() final;
+ RefPtr<FilterImage> apply(FilterImage* sourceImage) final;
private:
CSSFilter(RenderingMode, const FloatSize& filterScale, ClipOperation, bool hasFilterThatMovesPixels, bool hasFilterThatShouldBeRestrictedBySecurityOrigin);
Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h (286764 => 286765)
--- trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -47,6 +47,8 @@
private:
FEImage(SourceImage&&, const FloatRect& sourceImageRect, const SVGPreserveAspectRatioValue&);
+ unsigned numberOfEffectInputs() const override { return 0; }
+
// FEImage results are always in DestinationColorSpace::SRGB()
void setOperatingColorSpace(const DestinationColorSpace&) override { }
Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp (286764 => 286765)
--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp 2021-12-09 06:39:26 UTC (rev 286765)
@@ -117,20 +117,51 @@
return m_expression.last().effect.ptr();
}
-bool SVGFilter::apply(const Filter& filter, const std::optional<FilterEffectGeometry>&)
+RefPtr<FilterImage> SVGFilter::apply(const Filter&, FilterImage& sourceImage)
{
- setSourceImage({ filter.sourceImage() });
- return apply();
+ return apply(&sourceImage);
}
-RefPtr<FilterImage> SVGFilter::apply()
+RefPtr<FilterImage> SVGFilter::apply(FilterImage* sourceImage)
{
ASSERT(!m_expression.isEmpty());
+
+ FilterImageVector stack;
+
for (auto& term : m_expression) {
- if (!term.effect->apply(*this, term.geometry))
+ auto& effect = term.effect;
+ auto geometry = term.geometry;
+
+ if (effect->filterType() == FilterEffect::Type::SourceGraphic) {
+ if (auto result = effect->filterImage()) {
+ stack.append(result.releaseNonNull());
+ continue;
+ }
+
+ if (!sourceImage)
+ return nullptr;
+
+ // Add sourceImage as an input to the SourceGraphic.
+ stack.append(Ref { *sourceImage });
+ }
+
+ // Need to remove the inputs here in case the effect already has a result.
+ auto inputs = effect->takeImageInputs(stack);
+
+ if (auto result = effect->filterImage()) {
+ stack.append(result.releaseNonNull());
+ continue;
+ }
+
+ auto result = term.effect->apply(*this, inputs, geometry);
+ if (!result)
return nullptr;
+
+ stack.append(result.releaseNonNull());
}
- return lastEffect()->filterImage();
+
+ ASSERT(stack.size() == 1);
+ return stack.takeLast();
}
IntOutsets SVGFilter::outsets() const
Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h (286764 => 286765)
--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h 2021-12-09 06:39:26 UTC (rev 286765)
@@ -48,7 +48,7 @@
RefPtr<FilterEffect> lastEffect() const final;
- RefPtr<FilterImage> apply() final;
+ RefPtr<FilterImage> apply(FilterImage* sourceImage) final;
WTF::TextStream& externalRepresentation(WTF::TextStream&, FilterRepresentation) const final;
@@ -63,7 +63,7 @@
#endif
FloatSize resolvedSize(const FloatSize&) const final;
- bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) final;
+ RefPtr<FilterImage> apply(const Filter&, FilterImage& sourceImage) final;
IntOutsets outsets() const final;
void clearResult() final;
Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp (286764 => 286765)
--- trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp 2021-12-09 06:39:26 UTC (rev 286765)
@@ -34,6 +34,9 @@
namespace WebCore {
+static constexpr unsigned maxTotalNumberFilterEffects = 100;
+static constexpr unsigned maxCountChildNodes = 200;
+
void SVGFilterBuilder::setupBuiltinEffects(Ref<FilterEffect> sourceGraphic)
{
m_builtinEffects.add(SourceGraphic::effectName(), sourceGraphic.ptr());
@@ -76,28 +79,8 @@
}
#endif
-static unsigned collectEffects(const FilterEffect* effect, HashSet<const FilterEffect*>& allEffects)
-{
- allEffects.add(effect);
- unsigned size = effect->numberOfEffectInputs();
- for (unsigned i = 0; i < size; ++i) {
- FilterEffect* in = effect->inputEffect(i);
- collectEffects(in, allEffects);
- }
- return allEffects.size();
-}
-
-static unsigned totalNumberFilterEffects(const FilterEffect& lastEffect)
-{
- HashSet<const FilterEffect*> allEffects;
- return collectEffects(&lastEffect, allEffects);
-}
-
RefPtr<FilterEffect> SVGFilterBuilder::buildFilterEffects(SVGFilterElement& filterElement)
{
- static constexpr unsigned maxCountChildNodes = 200;
- static constexpr unsigned maxTotalNumberFilterEffects = 100;
-
if (filterElement.countChildNodes() > maxCountChildNodes)
return nullptr;
@@ -124,10 +107,8 @@
add(effectElement.result(), effect);
}
- if (!effect || totalNumberFilterEffects(*effect) > maxTotalNumberFilterEffects) {
+ if (!effect)
clearEffects();
- return nullptr;
- }
return effect;
}
@@ -240,6 +221,9 @@
if (!buildEffectExpression(m_lastEffect, stack, 0, _expression_))
return false;
+ if (_expression_.size() > maxTotalNumberFilterEffects)
+ return false;
+
_expression_.reverse();
_expression_.shrinkToFit();
return true;