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

Changeset 286129 in webkit


Ignore:
Timestamp:
Nov 23, 2021, 1:22:16 AM (5 years ago)
Author:
Said Abou-Hallawa
Message:

[GPU Process] Refactor the FilterEffect result buffers into a new class named 'FilterImage'
https://bugs.webkit.org/show_bug.cgi?id=225088
rdar://77487760

Reviewed by Cameron McCormack.

Move the storage and the logic for managing the result of applying the
FilterEffect to its inputs to a new class named 'FilterImage'. This will
simplify the implementation of FilterEffect. It will also allow integrating
the CoreImage seamlessly and simplifying the geometry calculation.

Instead of having three ways to create the result of a FilterEffect, there
will be one way which is by calling FilterImage::create(). This call will
not create a concrete result. But requesting the ImageBuffer or a PixelBuffer
from FilterImage will make this creation happen

The default of the operating ColorSpace is sRGB. But it will be set to
linearRGB if the color interpolation of the filter effect element is
linearRGB. The only exception is the FEImage whose result has to be in
sRGB always.

The default value of the result ColorSpace is the operating ColorSpace.
The only exception is FEDisplacementMap whose result has to be in the
ColorSpace of its first input FilterEffect.

  • Sources.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:

(WebCore::FilterEffectRendererCoreImage::connectCIFilters):

  • platform/graphics/cpu/arm/filters/FEBlendNEON.h:

(WebCore::FEBlend::platformApplySoftware):

  • platform/graphics/filters/FEBlend.cpp:

(WebCore::FEBlend::platformApplySoftware):

  • platform/graphics/filters/FEColorMatrix.cpp:

(WebCore::FEColorMatrix::platformApplySoftware):

  • platform/graphics/filters/FEComponentTransfer.cpp:

(WebCore::FEComponentTransfer::platformApplySoftware):

  • platform/graphics/filters/FEComposite.cpp:

(WebCore::FEComposite::platformApplySoftware):
(WebCore::FEComposite::correctFilterResultIfNeeded): Deleted.

  • platform/graphics/filters/FEComposite.h:

requiresValidPreMultipliedPixels() is replaced by the opposite
mayProduceInvalidPremultipliedPixels(). Correcting the premultiplied
result will be done by FilterEffect.

  • platform/graphics/filters/FEConvolveMatrix.cpp:

(WebCore::FEConvolveMatrix::platformApplySoftware):

  • platform/graphics/filters/FEDisplacementMap.cpp:

(WebCore::FEDisplacementMap::resultColorSpace const):
(WebCore::FEDisplacementMap::platformApplySoftware):
(WebCore::FEDisplacementMap::setResultColorSpace): Deleted.

  • platform/graphics/filters/FEDisplacementMap.h:

(WebCore::FEDisplacementMap::xChannelIndex const):
(WebCore::FEDisplacementMap::yChannelIndex const):

  • platform/graphics/filters/FEDropShadow.cpp:

(WebCore::FEDropShadow::platformApplySoftware):

  • platform/graphics/filters/FEFlood.cpp:

(WebCore::FEFlood::platformApplySoftware):

  • platform/graphics/filters/FEFlood.h:
  • platform/graphics/filters/FEGaussianBlur.cpp:

(WebCore::FEGaussianBlur::platformApplySoftware):

  • platform/graphics/filters/FELighting.cpp:

(WebCore::FELighting::platformApplySoftware):

  • platform/graphics/filters/FEMerge.cpp:

(WebCore::FEMerge::platformApplySoftware):

  • platform/graphics/filters/FEMorphology.cpp:

(WebCore::FEMorphology::platformApplySoftware):

  • platform/graphics/filters/FEOffset.cpp:

(WebCore::FEOffset::platformApplySoftware):

  • platform/graphics/filters/FETile.cpp:

(WebCore::FETile::platformApplySoftware):

  • platform/graphics/filters/FETurbulence.cpp:

(WebCore::FETurbulence::platformApplySoftware):

  • platform/graphics/filters/FilterEffect.cpp:

(WebCore::FilterEffect::apply):
(WebCore::FilterEffect::createResult):

(WebCore::FilterEffect::clearResult):
(WebCore::FilterEffect::clearResultsRecursive):
Clearing the result can be done by nullifying a single pointer.

(WebCore::FilterEffect::imageBufferResult):
(WebCore::FilterEffect::unpremultipliedResult):
(WebCore::FilterEffect::premultipliedResult):
(WebCore::FilterEffect::getUnpremultipliedResult):
(WebCore::FilterEffect::getPremultipliedResult):
(WebCore::FilterEffect::copyUnpremultipliedResult const):
(WebCore::FilterEffect::copyPremultipliedResult const):
(WebCore::FilterEffect::correctPremultipliedResultIfNeeded):
(WebCore::FilterEffect::transformResultColorSpace):
(WebCore::FilterEffect::externalRepresentation const):
(WebCore::FilterEffect::forceValidPreMultipliedPixels): Deleted.
(WebCore::FilterEffect::unmultipliedResult): Deleted.
(WebCore::FilterEffect::copyImageBytes const): Deleted.
(WebCore::copyPremultiplyingAlpha): Deleted.
(WebCore::copyUnpremultiplyingAlpha): Deleted.
(WebCore::FilterEffect::convertPixelBufferToColorSpace): Deleted.
(WebCore::FilterEffect::convertImageBufferToColorSpace): Deleted.
(WebCore::FilterEffect::copyConvertedImageBufferToDestination): Deleted.
(WebCore::FilterEffect::copyConvertedPixelBufferToDestination): Deleted.
(WebCore::FilterEffect::copyUnmultipliedResult): Deleted.
(WebCore::FilterEffect::copyPremultipliedResult): Deleted.
(WebCore::FilterEffect::createImageBufferResult): Deleted.
(WebCore::FilterEffect::createUnmultipliedImageResult): Deleted.
(WebCore::FilterEffect::createPremultipliedImageResult): Deleted.
(WebCore::FilterEffect::requiresPixelBufferColorSpaceConversion): Deleted.
All the logic of these functions was moved to FilterImage.cpp.

  • platform/graphics/filters/FilterEffect.h:

(WebCore::FilterEffect::hasResult const):
(WebCore::FilterEffect::resultColorSpace const):
(WebCore::FilterEffect::mayProduceInvalidPremultipliedPixels const):
(WebCore::FilterEffect::correctFilterResultIfNeeded): Deleted.
(WebCore::FilterEffect::setResultColorSpace): Deleted.
(WebCore::FilterEffect::requiresValidPreMultipliedPixels): Deleted.

  • platform/graphics/filters/FilterImage.cpp: Added.

(WebCore::FilterImage::create):
(WebCore::FilterImage::FilterImage):
(WebCore::FilterImage::imageBuffer):
(WebCore::copyPremultiplyingAlpha):
(WebCore::copyUnpremultiplyingAlpha):
(WebCore::FilterImage::pixelBufferIfExists):
(WebCore::FilterImage::pixelBuffer):
(WebCore::FilterImage::getPixelBuffer):
(WebCore::FilterImage::requiresPixelBufferColorSpaceConversion const):
(WebCore::FilterImage::copyImageBytes const):
(WebCore::FilterImage::getConvertedPixelBuffer const):
(WebCore::FilterImage::copyPixelBuffer):
(WebCore::FilterImage::correctPremultipliedPixelBuffer):
(WebCore::FilterImage::transformToColorSpace):

  • platform/graphics/filters/FilterImage.h: Added.

(WebCore::FilterImage::absoluteImageRect const):
(WebCore::FilterImage::renderingMode const):
(WebCore::FilterImage::colorSpace const):
(WebCore::FilterImage::imageBufferIfExists):

  • platform/graphics/filters/SourceAlpha.cpp:

(WebCore::SourceAlpha::platformApplySoftware):

  • platform/graphics/filters/SourceGraphic.cpp:

(WebCore::SourceGraphic::platformApplySoftware):

  • platform/graphics/filters/SourceGraphic.h:

(WebCore::SourceGraphic::SourceGraphic):

  • rendering/svg/RenderSVGResourceFilter.cpp:

(WebCore::RenderSVGResourceFilter::postApplyResource):

  • svg/graphics/filters/SVGFEImage.cpp:

(WebCore::FEImage::platformApplySoftware):

  • svg/graphics/filters/SVGFEImage.h:
Location:
trunk/Source/WebCore
Files:
2 added
31 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286126 r286129  
     12021-11-23  Said Abou-Hallawa  <said@apple.com>
     2
     3        [GPU Process] Refactor the FilterEffect result buffers into a new class named 'FilterImage'
     4        https://bugs.webkit.org/show_bug.cgi?id=225088
     5        rdar://77487760
     6
     7        Reviewed by Cameron McCormack.
     8
     9        Move the storage and the logic for managing the result of applying the
     10        FilterEffect to its inputs to a new class named 'FilterImage'. This will
     11        simplify the implementation of FilterEffect. It will also allow integrating
     12        the CoreImage seamlessly and simplifying the geometry calculation.
     13
     14        Instead of having three ways to create the result of a FilterEffect, there
     15        will be one way which is by calling FilterImage::create(). This call will
     16        not create a concrete result. But requesting the ImageBuffer or a PixelBuffer
     17        from FilterImage will make this creation happen
     18
     19        The default of the operating ColorSpace is sRGB. But it will be set to
     20        linearRGB if the color interpolation of the filter effect element is
     21        linearRGB. The only exception is the FEImage whose result has to be in
     22        sRGB always.
     23
     24        The default value of the result ColorSpace is the operating ColorSpace.
     25        The only exception is FEDisplacementMap whose result has to be in the
     26        ColorSpace of its first input FilterEffect.
     27
     28        * Sources.txt:
     29        * WebCore.xcodeproj/project.pbxproj:
     30        * platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:
     31        (WebCore::FilterEffectRendererCoreImage::connectCIFilters):
     32        * platform/graphics/cpu/arm/filters/FEBlendNEON.h:
     33        (WebCore::FEBlend::platformApplySoftware):
     34        * platform/graphics/filters/FEBlend.cpp:
     35        (WebCore::FEBlend::platformApplySoftware):
     36        * platform/graphics/filters/FEColorMatrix.cpp:
     37        (WebCore::FEColorMatrix::platformApplySoftware):
     38        * platform/graphics/filters/FEComponentTransfer.cpp:
     39        (WebCore::FEComponentTransfer::platformApplySoftware):
     40        * platform/graphics/filters/FEComposite.cpp:
     41        (WebCore::FEComposite::platformApplySoftware):
     42        (WebCore::FEComposite::correctFilterResultIfNeeded): Deleted.
     43        * platform/graphics/filters/FEComposite.h:
     44        requiresValidPreMultipliedPixels() is replaced by the opposite
     45        mayProduceInvalidPremultipliedPixels(). Correcting the premultiplied
     46        result will be done by FilterEffect.
     47
     48        * platform/graphics/filters/FEConvolveMatrix.cpp:
     49        (WebCore::FEConvolveMatrix::platformApplySoftware):
     50        * platform/graphics/filters/FEDisplacementMap.cpp:
     51        (WebCore::FEDisplacementMap::resultColorSpace const):
     52        (WebCore::FEDisplacementMap::platformApplySoftware):
     53        (WebCore::FEDisplacementMap::setResultColorSpace): Deleted.
     54        * platform/graphics/filters/FEDisplacementMap.h:
     55        (WebCore::FEDisplacementMap::xChannelIndex const):
     56        (WebCore::FEDisplacementMap::yChannelIndex const):
     57        * platform/graphics/filters/FEDropShadow.cpp:
     58        (WebCore::FEDropShadow::platformApplySoftware):
     59        * platform/graphics/filters/FEFlood.cpp:
     60        (WebCore::FEFlood::platformApplySoftware):
     61        * platform/graphics/filters/FEFlood.h:
     62        * platform/graphics/filters/FEGaussianBlur.cpp:
     63        (WebCore::FEGaussianBlur::platformApplySoftware):
     64        * platform/graphics/filters/FELighting.cpp:
     65        (WebCore::FELighting::platformApplySoftware):
     66        * platform/graphics/filters/FEMerge.cpp:
     67        (WebCore::FEMerge::platformApplySoftware):
     68        * platform/graphics/filters/FEMorphology.cpp:
     69        (WebCore::FEMorphology::platformApplySoftware):
     70        * platform/graphics/filters/FEOffset.cpp:
     71        (WebCore::FEOffset::platformApplySoftware):
     72        * platform/graphics/filters/FETile.cpp:
     73        (WebCore::FETile::platformApplySoftware):
     74        * platform/graphics/filters/FETurbulence.cpp:
     75        (WebCore::FETurbulence::platformApplySoftware):
     76        * platform/graphics/filters/FilterEffect.cpp:
     77        (WebCore::FilterEffect::apply):
     78        (WebCore::FilterEffect::createResult):
     79
     80        (WebCore::FilterEffect::clearResult):
     81        (WebCore::FilterEffect::clearResultsRecursive):
     82        Clearing the result can be done by nullifying a single pointer.
     83
     84        (WebCore::FilterEffect::imageBufferResult):
     85        (WebCore::FilterEffect::unpremultipliedResult):
     86        (WebCore::FilterEffect::premultipliedResult):
     87        (WebCore::FilterEffect::getUnpremultipliedResult):
     88        (WebCore::FilterEffect::getPremultipliedResult):
     89        (WebCore::FilterEffect::copyUnpremultipliedResult const):
     90        (WebCore::FilterEffect::copyPremultipliedResult const):
     91        (WebCore::FilterEffect::correctPremultipliedResultIfNeeded):
     92        (WebCore::FilterEffect::transformResultColorSpace):
     93        (WebCore::FilterEffect::externalRepresentation const):
     94        (WebCore::FilterEffect::forceValidPreMultipliedPixels): Deleted.
     95        (WebCore::FilterEffect::unmultipliedResult): Deleted.
     96        (WebCore::FilterEffect::copyImageBytes const): Deleted.
     97        (WebCore::copyPremultiplyingAlpha): Deleted.
     98        (WebCore::copyUnpremultiplyingAlpha): Deleted.
     99        (WebCore::FilterEffect::convertPixelBufferToColorSpace): Deleted.
     100        (WebCore::FilterEffect::convertImageBufferToColorSpace): Deleted.
     101        (WebCore::FilterEffect::copyConvertedImageBufferToDestination): Deleted.
     102        (WebCore::FilterEffect::copyConvertedPixelBufferToDestination): Deleted.
     103        (WebCore::FilterEffect::copyUnmultipliedResult): Deleted.
     104        (WebCore::FilterEffect::copyPremultipliedResult): Deleted.
     105        (WebCore::FilterEffect::createImageBufferResult): Deleted.
     106        (WebCore::FilterEffect::createUnmultipliedImageResult): Deleted.
     107        (WebCore::FilterEffect::createPremultipliedImageResult): Deleted.
     108        (WebCore::FilterEffect::requiresPixelBufferColorSpaceConversion): Deleted.
     109        All the logic of these functions was moved to FilterImage.cpp.
     110
     111        * platform/graphics/filters/FilterEffect.h:
     112        (WebCore::FilterEffect::hasResult const):
     113        (WebCore::FilterEffect::resultColorSpace const):
     114        (WebCore::FilterEffect::mayProduceInvalidPremultipliedPixels const):
     115        (WebCore::FilterEffect::correctFilterResultIfNeeded): Deleted.
     116        (WebCore::FilterEffect::setResultColorSpace): Deleted.
     117        (WebCore::FilterEffect::requiresValidPreMultipliedPixels): Deleted.
     118        * platform/graphics/filters/FilterImage.cpp: Added.
     119        (WebCore::FilterImage::create):
     120        (WebCore::FilterImage::FilterImage):
     121        (WebCore::FilterImage::imageBuffer):
     122        (WebCore::copyPremultiplyingAlpha):
     123        (WebCore::copyUnpremultiplyingAlpha):
     124        (WebCore::FilterImage::pixelBufferIfExists):
     125        (WebCore::FilterImage::pixelBuffer):
     126        (WebCore::FilterImage::getPixelBuffer):
     127        (WebCore::FilterImage::requiresPixelBufferColorSpaceConversion const):
     128        (WebCore::FilterImage::copyImageBytes const):
     129        (WebCore::FilterImage::getConvertedPixelBuffer const):
     130        (WebCore::FilterImage::copyPixelBuffer):
     131        (WebCore::FilterImage::correctPremultipliedPixelBuffer):
     132        (WebCore::FilterImage::transformToColorSpace):
     133        * platform/graphics/filters/FilterImage.h: Added.
     134        (WebCore::FilterImage::absoluteImageRect const):
     135        (WebCore::FilterImage::renderingMode const):
     136        (WebCore::FilterImage::colorSpace const):
     137        (WebCore::FilterImage::imageBufferIfExists):
     138        * platform/graphics/filters/SourceAlpha.cpp:
     139        (WebCore::SourceAlpha::platformApplySoftware):
     140        * platform/graphics/filters/SourceGraphic.cpp:
     141        (WebCore::SourceGraphic::platformApplySoftware):
     142        * platform/graphics/filters/SourceGraphic.h:
     143        (WebCore::SourceGraphic::SourceGraphic):
     144        * rendering/svg/RenderSVGResourceFilter.cpp:
     145        (WebCore::RenderSVGResourceFilter::postApplyResource):
     146        * svg/graphics/filters/SVGFEImage.cpp:
     147        (WebCore::FEImage::platformApplySoftware):
     148        * svg/graphics/filters/SVGFEImage.h:
     149
    11502021-11-22  Simon Fraser  <simon.fraser@apple.com>
    2151
  • trunk/Source/WebCore/Sources.txt

    r286112 r286129  
    21042104platform/graphics/filters/FilterEffectRenderer.cpp
    21052105platform/graphics/filters/FilterFunction.cpp
     2106platform/graphics/filters/FilterImage.cpp
    21062107platform/graphics/filters/FilterOperation.cpp
    21072108platform/graphics/filters/FilterOperations.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r286112 r286129  
    1086810868                721B49702512AC0400FE9D3B /* ImageBitmapBacking.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImageBitmapBacking.h; sourceTree = "<group>"; };
    1086910869                722A815C238FD50500C00583 /* AnimationFrameRate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AnimationFrameRate.h; sourceTree = "<group>"; };
     10870                72435EF4273D07670005E7EE /* FilterImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FilterImage.h; sourceTree = "<group>"; };
     10871                72435EF5273D07670005E7EE /* FilterImage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FilterImage.cpp; sourceTree = "<group>"; };
    1087010872                724ED3291A3A7E5400F5F13C /* EXTBlendMinMax.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EXTBlendMinMax.cpp; sourceTree = "<group>"; };
    1087110873                724ED32A1A3A7E5400F5F13C /* EXTBlendMinMax.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTBlendMinMax.h; sourceTree = "<group>"; };
     
    2594625948                                7262D757272A174100C56A09 /* FilterFunction.cpp */,
    2594725949                                7262D756272A174100C56A09 /* FilterFunction.h */,
     25950                                72435EF5273D07670005E7EE /* FilterImage.cpp */,
     25951                                72435EF4273D07670005E7EE /* FilterImage.h */,
    2594825952                                49ECEB631499790D00CDD3A4 /* FilterOperation.cpp */,
    2594925953                                49ECEB641499790D00CDD3A4 /* FilterOperation.h */,
  • trunk/Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm

    r285796 r286129  
    117117    }
    118118    effect.determineAbsolutePaintRect(filter);
    119     effect.setResultColorSpace(effect.operatingColorSpace());
    120119   
    121120    if (effect.absolutePaintRect().isEmpty() || ImageBuffer::sizeNeedsClamping(effect.absolutePaintRect().size()))
  • trunk/Source/WebCore/platform/graphics/cpu/arm/filters/FEBlendNEON.h

    r285916 r286129  
    112112    FilterEffect* in2 = inputEffect(1);
    113113
    114     auto& destinationPixelBuffer = createPremultipliedImageResult();
     114    auto& destinationPixelBuffer = pixelBufferResult(AlphaPremultiplication::Premultiplied);
    115115    if (!destinationPixelBuffer)
    116116        return false;
     
    119119
    120120    IntRect effectADrawingRect = requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
    121     auto sourcePixelArrayA = in->premultipliedResult(effectADrawingRect);
     121    auto sourcePixelArrayA = in->getPixelBufferResult(AlphaPremultiplication::Premultiplied, effectADrawingRect);
    122122
    123123    IntRect effectBDrawingRect = requestedRegionOfInputPixelBuffer(in2->absolutePaintRect());
    124     auto sourcePixelArrayB = in2->premultipliedResult(effectBDrawingRect);
     124    auto sourcePixelArrayB = in2->getPixelBufferResult(AlphaPremultiplication::Premultiplied, effectBDrawingRect);
    125125
    126126    unsigned sourcePixelArrayLength = sourcePixelArrayA->length();
  • trunk/Source/WebCore/platform/graphics/filters/FEBlend.cpp

    r285916 r286129  
    6060    FilterEffect* in2 = inputEffect(1);
    6161
    62     ImageBuffer* resultImage = createImageBufferResult();
     62    auto resultImage = imageBufferResult();
    6363    if (!resultImage)
    6464        return false;
    65     GraphicsContext& filterContext = resultImage->context();
    6665
    67     ImageBuffer* imageBuffer = in->imageBufferResult();
    68     ImageBuffer* imageBuffer2 = in2->imageBufferResult();
     66    auto imageBuffer = in->imageBufferResult();
     67    auto imageBuffer2 = in2->imageBufferResult();
    6968    if (!imageBuffer || !imageBuffer2)
    7069        return false;
    7170
     71    GraphicsContext& filterContext = resultImage->context();
    7272    filterContext.drawImageBuffer(*imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect()));
    7373    filterContext.drawImageBuffer(*imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()), { { }, imageBuffer->logicalSize() }, { CompositeOperator::SourceOver, m_mode });
  • trunk/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp

    r285916 r286129  
    278278    FilterEffect* in = inputEffect(0);
    279279
    280     ImageBuffer* resultImage = createImageBufferResult();
     280    auto resultImage = imageBufferResult();
    281281    if (!resultImage)
    282282        return false;
    283283
    284     ImageBuffer* inBuffer = in->imageBufferResult();
     284    auto inBuffer = in->imageBufferResult();
    285285    if (inBuffer)
    286286        resultImage->context().drawImageBuffer(*inBuffer, drawingRegionOfInputImage(in->absolutePaintRect()));
  • trunk/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp

    r285916 r286129  
    106106    FilterEffect* in = inputEffect(0);
    107107
    108     auto& destinationPixelBuffer = createUnmultipliedImageResult();
     108    auto destinationPixelBuffer = pixelBufferResult(AlphaPremultiplication::Unpremultiplied);
    109109    if (!destinationPixelBuffer)
    110110        return false;
    111 
    112     auto& destinationPixelArray = destinationPixelBuffer->data();
    113111
    114112    LookupTable redTable;
     
    119117
    120118    IntRect drawingRect = requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
    121     in->copyUnmultipliedResult(destinationPixelArray, drawingRect, operatingColorSpace());
     119    in->copyPixelBufferResult(*destinationPixelBuffer, drawingRect);
     120   
     121    auto& destinationPixelArray = destinationPixelBuffer->data();
     122    uint8_t* data = destinationPixelArray.data();
    122123    unsigned destinationPixelArrayLength = destinationPixelArray.length();
    123     uint8_t* data = destinationPixelArray.data();
     124
    124125    for (unsigned pixelOffset = 0; pixelOffset < destinationPixelArrayLength; pixelOffset += 4) {
    125126        data[pixelOffset] = redTable[data[pixelOffset]];
  • trunk/Source/WebCore/platform/graphics/filters/FEComposite.cpp

    r285916 r286129  
    8888}
    8989
    90 void FEComposite::correctFilterResultIfNeeded()
    91 {
    92     if (m_type != FECOMPOSITE_OPERATOR_ARITHMETIC)
    93         return;
    94 
    95     forceValidPreMultipliedPixels();
    96 }
    97    
    9890static unsigned char clampByte(int c)
    9991{
     
    230222
    231223    if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC) {
    232         auto& destinationPixelBuffer = createPremultipliedImageResult();
     224        auto destinationPixelBuffer = pixelBufferResult(AlphaPremultiplication::Premultiplied);
    233225        if (!destinationPixelBuffer)
    234226            return false;
    235227       
     228        IntRect effectADrawingRect = requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
     229        auto sourcePixelBuffer = in->getPixelBufferResult(AlphaPremultiplication::Premultiplied, effectADrawingRect, operatingColorSpace());
     230        if (!sourcePixelBuffer)
     231            return false;
     232
     233        IntRect effectBDrawingRect = requestedRegionOfInputPixelBuffer(in2->absolutePaintRect());
     234        in2->copyPixelBufferResult(*destinationPixelBuffer, effectBDrawingRect);
     235
     236        auto& sourcePixelArray = sourcePixelBuffer->data();
    236237        auto& destinationPixelArray = destinationPixelBuffer->data();
    237 
    238         IntRect effectADrawingRect = requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
    239         auto sourcePixelArray = in->premultipliedResult(effectADrawingRect, operatingColorSpace());
    240         if (!sourcePixelArray)
    241             return false;
    242 
    243         IntRect effectBDrawingRect = requestedRegionOfInputPixelBuffer(in2->absolutePaintRect());
    244         in2->copyPremultipliedResult(destinationPixelArray, effectBDrawingRect, operatingColorSpace());
    245 
    246         platformArithmeticSoftware(*sourcePixelArray, destinationPixelArray, m_k1, m_k2, m_k3, m_k4);
     238        platformArithmeticSoftware(sourcePixelArray, destinationPixelArray, m_k1, m_k2, m_k3, m_k4);
    247239        return true;
    248240    }
    249241
    250     ImageBuffer* resultImage = createImageBufferResult();
     242    auto resultImage = imageBufferResult();
    251243    if (!resultImage)
    252244        return false;
     245
     246    auto imageBuffer = in->imageBufferResult();
     247    auto imageBuffer2 = in2->imageBufferResult();
     248    if (!imageBuffer || !imageBuffer2)
     249        return false;
     250
    253251    GraphicsContext& filterContext = resultImage->context();
    254 
    255     ImageBuffer* imageBuffer = in->imageBufferResult();
    256     ImageBuffer* imageBuffer2 = in2->imageBufferResult();
    257     if (!imageBuffer || !imageBuffer2)
    258         return false;
    259252
    260253    switch (m_type) {
  • trunk/Source/WebCore/platform/graphics/filters/FEComposite.h

    r285916 r286129  
    6060    FEComposite(const CompositeOperationType&, float k1, float k2, float k3, float k4);
    6161
    62     void correctFilterResultIfNeeded() override;
     62    void determineAbsolutePaintRect(const Filter&) override;
    6363
    64     bool requiresValidPreMultipliedPixels() override { return m_type != FECOMPOSITE_OPERATOR_ARITHMETIC; }
    65 
    66     void determineAbsolutePaintRect(const Filter&) override;
     64    bool mayProduceInvalidPremultipliedPixels() const override { return m_type == FECOMPOSITE_OPERATOR_ARITHMETIC; }
    6765
    6866    bool platformApplySoftware(const Filter&) override;
  • trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp

    r285916 r286129  
    366366    FilterEffect* in = inputEffect(0);
    367367
    368     auto& destinationPixelBuffer = m_preserveAlpha ? createUnmultipliedImageResult() : createPremultipliedImageResult();
     368    auto alphaFormat = m_preserveAlpha ? AlphaPremultiplication::Unpremultiplied : AlphaPremultiplication::Premultiplied;
     369    auto destinationPixelBuffer = pixelBufferResult(alphaFormat);
    369370    if (!destinationPixelBuffer)
    370371        return false;
    371372
     373    IntRect effectDrawingRect = requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
     374    auto sourcePixelBuffer = in->getPixelBufferResult(alphaFormat, effectDrawingRect, operatingColorSpace());
     375    if (!sourcePixelBuffer)
     376        return false;
     377
     378    auto& sourcePixelArray = sourcePixelBuffer->data();
    372379    auto& destinationPixelArray = destinationPixelBuffer->data();
    373 
    374     IntRect effectDrawingRect = requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
    375 
    376     RefPtr<Uint8ClampedArray> sourcePixelArray;
    377     if (m_preserveAlpha)
    378         sourcePixelArray = in->unmultipliedResult(effectDrawingRect, operatingColorSpace());
    379     else
    380         sourcePixelArray = in->premultipliedResult(effectDrawingRect, operatingColorSpace());
    381     if (!sourcePixelArray)
    382         return false;
    383380
    384381    IntSize paintSize = absolutePaintRect().size();
    385382   
    386383    PaintingData paintingData = {
    387         *sourcePixelArray,
     384        sourcePixelArray,
    388385        destinationPixelArray,
    389386        paintSize.width(),
  • trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp

    r285916 r286129  
    6969}
    7070
    71 void FEDisplacementMap::setResultColorSpace(const DestinationColorSpace&)
     71const DestinationColorSpace& FEDisplacementMap::resultColorSpace() const
    7272{
    7373    // Spec: The 'color-interpolation-filters' property only applies to the 'in2' source image
    7474    // and does not apply to the 'in' source image. The 'in' source image must remain in its
    7575    // current color space.
    76     // The result is in that smae color space because it is a displacement of the 'in' image.
    77     FilterEffect::setResultColorSpace(inputEffect(0)->resultColorSpace());
     76    // The result is in that same color space because it is a displacement of the 'in' image.
     77    return inputEffect(0)->resultColorSpace();
    7878}
    7979
     
    9999    ASSERT(m_yChannelSelector != CHANNEL_UNKNOWN);
    100100
    101     auto& destinationPixelBuffer = createPremultipliedImageResult();
     101    auto destinationPixelBuffer = pixelBufferResult(AlphaPremultiplication::Premultiplied);
    102102    if (!destinationPixelBuffer)
    103103        return false;
     
    106106
    107107    IntRect effectADrawingRect = requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
    108     auto inputImage = in->premultipliedResult(effectADrawingRect);
     108    auto inputPixelBuffer = in->getPixelBufferResult(AlphaPremultiplication::Premultiplied, effectADrawingRect);
    109109
    110110    IntRect effectBDrawingRect = requestedRegionOfInputPixelBuffer(in2->absolutePaintRect());
    111111    // The calculations using the pixel values from ‘in2’ are performed using non-premultiplied color values.
    112     auto displacementImage = in2->unmultipliedResult(effectBDrawingRect);
     112    auto displacementPixelBuffer = in2->getPixelBufferResult(AlphaPremultiplication::Unpremultiplied, effectBDrawingRect);
    113113   
    114     if (!inputImage || !displacementImage)
     114    if (!inputPixelBuffer || !displacementPixelBuffer)
    115115        return false;
    116116
    117     ASSERT(inputImage->length() == displacementImage->length());
     117    auto& inputImage = inputPixelBuffer->data();
     118    auto& displacementImage = displacementPixelBuffer->data();
     119    ASSERT(inputImage.length() == displacementImage.length());
    118120
    119121    IntSize paintSize = absolutePaintRect().size();
     
    136138            int destinationIndex = lineStartOffset + x * 4;
    137139           
    138             int srcX = x + static_cast<int>(scaleForColorX * displacementImage->item(destinationIndex + displacementChannelX) + scaledOffsetX);
    139             int srcY = y + static_cast<int>(scaleForColorY * displacementImage->item(destinationIndex + displacementChannelY) + scaledOffsetY);
     140            int srcX = x + static_cast<int>(scaleForColorX * displacementImage.item(destinationIndex + displacementChannelX) + scaledOffsetX);
     141            int srcY = y + static_cast<int>(scaleForColorY * displacementImage.item(destinationIndex + displacementChannelY) + scaledOffsetY);
    140142
    141143            unsigned* destinationPixelPtr = reinterpret_cast<unsigned*>(destinationPixelArray.data() + destinationIndex);
     
    145147            }
    146148
    147             *destinationPixelPtr = *reinterpret_cast<unsigned*>(inputImage->data() + byteOffsetOfPixel(srcX, srcY, rowBytes));
     149            *destinationPixelPtr = *reinterpret_cast<unsigned*>(inputImage.data() + byteOffsetOfPixel(srcX, srcY, rowBytes));
    148150        }
    149151    }
  • trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h

    r285916 r286129  
    4848    bool setScale(float);
    4949
    50     void setResultColorSpace(const DestinationColorSpace&) override;
    51     void transformResultColorSpace(FilterEffect*, const int) override;
    52 
    5350private:
    5451    FEDisplacementMap(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float);
    5552
    56     bool platformApplySoftware(const Filter&) override;
     53    int xChannelIndex() const { return m_xChannelSelector - 1; }
     54    int yChannelIndex() const { return m_yChannelSelector - 1; }
    5755
    5856    void determineAbsolutePaintRect(const Filter&) override { setAbsolutePaintRect(enclosingIntRect(maxEffectRect())); }
    5957
    60     int xChannelIndex() const { return m_xChannelSelector - 1; }
    61     int yChannelIndex() const { return m_yChannelSelector - 1; }
     58    const DestinationColorSpace& resultColorSpace() const override;
     59    void transformResultColorSpace(FilterEffect*, const int) override;
     60
     61    bool platformApplySoftware(const Filter&) override;
    6262
    6363    WTF::TextStream& externalRepresentation(WTF::TextStream&, RepresentationType) const override;
  • trunk/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp

    r285916 r286129  
    7474    FilterEffect* in = inputEffect(0);
    7575
    76     ImageBuffer* resultImage = createImageBufferResult();
     76    auto resultImage = imageBufferResult();
    7777    if (!resultImage)
    7878        return false;
     
    8585    drawingRegionWithOffset.move(offset);
    8686
    87     ImageBuffer* sourceImage = in->imageBufferResult();
     87    auto sourceImage = in->imageBufferResult();
    8888    if (!sourceImage)
    8989        return false;
  • trunk/Source/WebCore/platform/graphics/filters/FEFlood.cpp

    r285916 r286129  
    6161bool FEFlood::platformApplySoftware(const Filter&)
    6262{
    63     ImageBuffer* resultImage = createImageBufferResult();
     63    auto resultImage = imageBufferResult();
    6464    if (!resultImage)
    6565        return false;
  • trunk/Source/WebCore/platform/graphics/filters/FEFlood.h

    r285916 r286129  
    4040    // feFlood does not perform color interpolation of any kind, so the result is always in the current
    4141    // color space regardless of the value of color-interpolation-filters.
    42     void setOperatingColorSpace(const DestinationColorSpace&) override { FilterEffect::setResultColorSpace(DestinationColorSpace::SRGB()); }
    43     void setResultColorSpace(const DestinationColorSpace&) override { FilterEffect::setResultColorSpace(DestinationColorSpace::SRGB()); }
     42    void setOperatingColorSpace(const DestinationColorSpace&) override { }
    4443#endif
    4544
  • trunk/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp

    r285916 r286129  
    524524    FilterEffect* in = inputEffect(0);
    525525
    526     auto& destinationPixelBuffer = createPremultipliedImageResult();
     526    auto destinationPixelBuffer = pixelBufferResult(AlphaPremultiplication::Premultiplied);
    527527    if (!destinationPixelBuffer)
    528528        return false;
    529529
    530     auto& destinationPixelArray = destinationPixelBuffer->data();
    531 
    532530    setIsAlphaImage(in->isAlphaImage());
    533531
    534532    IntRect effectDrawingRect = requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
    535     in->copyPremultipliedResult(destinationPixelArray, effectDrawingRect, operatingColorSpace());
     533    in->copyPixelBufferResult(*destinationPixelBuffer, effectDrawingRect);
    536534    if (!m_stdX && !m_stdY)
    537535        return true;
     
    544542        return false;
    545543
     544    auto& destinationPixelArray = destinationPixelBuffer->data();
    546545    platformApply(destinationPixelArray, *tmpImageData, kernelSize.width(), kernelSize.height(), paintSize);
    547546    return true;
  • trunk/Source/WebCore/platform/graphics/filters/FELighting.cpp

    r285916 r286129  
    476476    FilterEffect* in = inputEffect(0);
    477477
    478     auto& destinationPixelBuffer = createPremultipliedImageResult();
     478    auto destinationPixelBuffer = pixelBufferResult(AlphaPremultiplication::Premultiplied);
    479479    if (!destinationPixelBuffer)
    480480        return false;
    481481
    482     auto& destinationPixelArray = destinationPixelBuffer->data();
    483 
    484482    setIsAlphaImage(false);
    485483
    486484    IntRect effectDrawingRect = requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
    487     in->copyPremultipliedResult(destinationPixelArray, effectDrawingRect, operatingColorSpace());
     485    in->copyPixelBufferResult(*destinationPixelBuffer, effectDrawingRect);
     486
    488487    // FIXME: support kernelUnitLengths other than (1,1). The issue here is that the W3
    489488    // standard has no test case for them, and other browsers (like Firefox) has strange
     
    492491
    493492    IntSize absolutePaintSize = absolutePaintRect().size();
     493    auto& destinationPixelArray = destinationPixelBuffer->data();
     494
    494495    drawLighting(destinationPixelArray, absolutePaintSize.width(), absolutePaintSize.height());
    495496    return true;
  • trunk/Source/WebCore/platform/graphics/filters/FEMerge.cpp

    r285916 r286129  
    4444    ASSERT(size > 0);
    4545
    46     ImageBuffer* resultImage = createImageBufferResult();
     46    auto resultImage = imageBufferResult();
    4747    if (!resultImage)
    4848        return false;
     
    5151    for (unsigned i = 0; i < size; ++i) {
    5252        FilterEffect* in = inputEffect(i);
    53         if (ImageBuffer* inBuffer = in->imageBufferResult())
     53        if (auto inBuffer = in->imageBufferResult())
    5454            filterContext.drawImageBuffer(*inBuffer, drawingRegionOfInputImage(in->absolutePaintRect()));
    5555    }
  • trunk/Source/WebCore/platform/graphics/filters/FEMorphology.cpp

    r285916 r286129  
    230230}
    231231
    232 bool FEMorphology::platformApplyDegenerate(Uint8ClampedArray& dstPixelArray, const IntRect& imageRect, int radiusX, int radiusY)
    233 {
    234     if (radiusX < 0 || radiusY < 0 || (!radiusX && !radiusY)) {
    235         FilterEffect* in = inputEffect(0);
    236         in->copyPremultipliedResult(dstPixelArray, imageRect, operatingColorSpace());
     232bool FEMorphology::isDegenerate(int radiusX, int radiusY) const
     233{
     234    return radiusX < 0 || radiusY < 0 || (!radiusX && !radiusY);
     235}
     236
     237bool FEMorphology::platformApplySoftware(const Filter& filter)
     238{
     239    FilterEffect* in = inputEffect(0);
     240
     241    auto destinationPixelBuffer = pixelBufferResult(AlphaPremultiplication::Premultiplied);
     242    if (!destinationPixelBuffer)
     243        return false;
     244
     245    setIsAlphaImage(in->isAlphaImage());
     246
     247    IntRect effectDrawingRect = requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
     248
     249    IntSize radius = flooredIntSize(FloatSize(m_radiusX, m_radiusY));
     250    if (isDegenerate(radius.width(), radius.height())) {
     251        in->copyPixelBufferResult(*destinationPixelBuffer, effectDrawingRect);
    237252        return true;
    238253    }
    239     return false;
    240 }
    241 
    242 bool FEMorphology::platformApplySoftware(const Filter& filter)
    243 {
    244     FilterEffect* in = inputEffect(0);
    245 
    246     auto& destinationPixelBuffer = createPremultipliedImageResult();
    247     if (!destinationPixelBuffer)
    248         return false;
    249 
    250     auto& destinationPixelArray = destinationPixelBuffer->data();
    251 
    252     setIsAlphaImage(in->isAlphaImage());
    253 
    254     IntRect effectDrawingRect = requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
    255 
    256     IntSize radius = flooredIntSize(FloatSize(m_radiusX, m_radiusY));
    257     if (platformApplyDegenerate(destinationPixelArray, effectDrawingRect, radius.width(), radius.height()))
    258         return true;
    259 
    260     auto sourcePixelArray = in->premultipliedResult(effectDrawingRect, operatingColorSpace());
    261     if (!sourcePixelArray)
    262         return false;
    263254
    264255    radius = flooredIntSize(filter.scaledByFilterScale({ m_radiusX, m_radiusY }));
     
    266257    int radiusY = std::min(effectDrawingRect.height() - 1, radius.height());
    267258
    268     if (platformApplyDegenerate(destinationPixelArray, effectDrawingRect, radiusX, radiusY))
     259    if (isDegenerate(radiusX, radiusY)) {
     260        in->copyPixelBufferResult(*destinationPixelBuffer, effectDrawingRect);
    269261        return true;
    270    
     262    }
     263
     264    auto sourcePixelBuffer = in->getPixelBufferResult(AlphaPremultiplication::Premultiplied, effectDrawingRect, operatingColorSpace());
     265    if (!sourcePixelBuffer)
     266        return false;
     267
     268    auto& sourcePixelArray = sourcePixelBuffer->data();
     269    auto& destinationPixelArray = destinationPixelBuffer->data();
     270
    271271    PaintingData paintingData;
    272     paintingData.srcPixelArray = sourcePixelArray.get();
     272    paintingData.srcPixelArray = &sourcePixelArray;
    273273    paintingData.dstPixelArray = &destinationPixelArray;
    274274    paintingData.width = ceilf(effectDrawingRect.width());
  • trunk/Source/WebCore/platform/graphics/filters/FEMorphology.h

    r285916 r286129  
    5454    WTF::TextStream& externalRepresentation(WTF::TextStream&, RepresentationType) const override;
    5555
    56     bool platformApplyDegenerate(Uint8ClampedArray& dstPixelArray, const IntRect& imageRect, int radiusX, int radiusY);
     56    bool isDegenerate(int radiusX, int radiusY) const;
    5757
    5858    struct PaintingData {
  • trunk/Source/WebCore/platform/graphics/filters/FEOffset.cpp

    r285916 r286129  
    6969    FilterEffect* in = inputEffect(0);
    7070
    71     ImageBuffer* resultImage = createImageBufferResult();
    72     ImageBuffer* inBuffer = in->imageBufferResult();
     71    auto resultImage = imageBufferResult();
     72    auto inBuffer = in->imageBufferResult();
    7373    if (!resultImage || !inBuffer)
    7474        return false;
  • trunk/Source/WebCore/platform/graphics/filters/FETile.cpp

    r285916 r286129  
    4545bool FETile::platformApplySoftware(const Filter& filter)
    4646{
    47 // FIXME: See bug 47315. This is a hack to work around a compile failure, but is incorrect behavior otherwise.
    4847    FilterEffect* in = inputEffect(0);
    4948
    50     ImageBuffer* resultImage = createImageBufferResult();
    51     ImageBuffer* inBuffer = in->imageBufferResult();
     49    auto resultImage = imageBufferResult();
     50    auto inBuffer = in->imageBufferResult();
    5251    if (!resultImage || !inBuffer)
    5352        return false;
  • trunk/Source/WebCore/platform/graphics/filters/FETurbulence.cpp

    r285916 r286129  
    396396bool FETurbulence::platformApplySoftware(const Filter& filter)
    397397{
    398     auto& destinationPixelBuffer = createUnmultipliedImageResult();
     398    auto destinationPixelBuffer = pixelBufferResult(AlphaPremultiplication::Unpremultiplied);
    399399    if (!destinationPixelBuffer)
    400400        return false;
  • trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp

    r285916 r286129  
    2828#include "Filter.h"
    2929#include "GeometryUtilities.h"
    30 #include "GraphicsContext.h"
    3130#include "ImageBuffer.h"
    3231#include "Logging.h"
    3332#include "PixelBuffer.h"
    34 #include <JavaScriptCore/JSCInlines.h>
    35 #include <JavaScriptCore/TypedArrayInlines.h>
    3633#include <wtf/text/TextStream.h>
    3734
    38 #if HAVE(ARM_NEON_INTRINSICS)
    39 #include <arm_neon.h>
    40 #endif
    41 
    42 #if USE(ACCELERATE)
    43 #include <Accelerate/Accelerate.h>
    44 #endif
    45 
    4635namespace WebCore {
    47 
    48 FilterEffect::FilterEffect(FilterEffect::Type type)
    49     : FilterFunction(type)
    50 {
    51 }
    5236
    5337void FilterEffect::determineAbsolutePaintRect(const Filter&)
     
    158142
    159143    determineAbsolutePaintRect(filter);
    160     setResultColorSpace(m_operatingColorSpace);
    161144
    162145    LOG_WITH_STREAM(Filters, stream
     
    172155        return false;
    173156
    174     if (requiresValidPreMultipliedPixels()) {
    175         for (unsigned i = 0; i < size; ++i)
    176             inputEffect(i)->correctFilterResultIfNeeded();
     157    if (!mayProduceInvalidPremultipliedPixels()) {
     158        for (auto& in : m_inputEffects)
     159            in->correctPremultipliedResultIfNeeded();
    177160    }
     161   
     162    if (!createResult())
     163        return false;
    178164
    179165    // Add platform specific apply functions here and return earlier.
     
    181167}
    182168
    183 void FilterEffect::forceValidPreMultipliedPixels()
    184 {
    185     // Must operate on pre-multiplied results; other formats cannot have invalid pixels.
    186     if (!m_premultipliedImageResult)
    187         return;
    188 
    189     auto& imageArray = m_premultipliedImageResult->data();
    190     uint8_t* pixelData = imageArray.data();
    191     int pixelArrayLength = imageArray.length();
    192 
    193     // We must have four bytes per pixel, and complete pixels
    194     ASSERT(!(pixelArrayLength % 4));
    195 
    196 #if HAVE(ARM_NEON_INTRINSICS)
    197     if (pixelArrayLength >= 64) {
    198         uint8_t* lastPixel = pixelData + (pixelArrayLength & ~0x3f);
    199         do {
    200             // Increments pixelData by 64.
    201             uint8x16x4_t sixteenPixels = vld4q_u8(pixelData);
    202             sixteenPixels.val[0] = vminq_u8(sixteenPixels.val[0], sixteenPixels.val[3]);
    203             sixteenPixels.val[1] = vminq_u8(sixteenPixels.val[1], sixteenPixels.val[3]);
    204             sixteenPixels.val[2] = vminq_u8(sixteenPixels.val[2], sixteenPixels.val[3]);
    205             vst4q_u8(pixelData, sixteenPixels);
    206             pixelData += 64;
    207         } while (pixelData < lastPixel);
    208 
    209         pixelArrayLength &= 0x3f;
    210         if (!pixelArrayLength)
    211             return;
    212     }
    213 #endif
    214 
    215     int numPixels = pixelArrayLength / 4;
    216 
    217     // Iterate over each pixel, checking alpha and adjusting color components if necessary
    218     while (--numPixels >= 0) {
    219         // Alpha is the 4th byte in a pixel
    220         uint8_t a = *(pixelData + 3);
    221         // Clamp each component to alpha, and increment the pixel location
    222         for (int i = 0; i < 3; ++i) {
    223             if (*pixelData > a)
    224                 *pixelData = a;
    225             ++pixelData;
    226         }
    227         // Increment for alpha
    228         ++pixelData;
    229     }
     169bool FilterEffect::createResult()
     170{
     171    m_filterImage = FilterImage::create(m_absolutePaintRect, RenderingMode::Unaccelerated, resultColorSpace());
     172    return m_filterImage;
    230173}
    231174
    232175void FilterEffect::clearResult()
    233176{
    234     m_imageBufferResult = nullptr;
    235     m_unmultipliedImageResult = std::nullopt;
    236     m_premultipliedImageResult = std::nullopt;
     177    m_filterImage = nullptr;
    237178}
    238179
     
    241182    // Clear all results, regardless that the current effect has
    242183    // a result. Can be used if an effect is in an erroneous state.
    243     if (hasResult())
    244         clearResult();
    245 
    246     unsigned size = m_inputEffects.size();
    247     for (unsigned i = 0; i < size; ++i)
    248         m_inputEffects.at(i).get()->clearResultsRecursive();
     184    clearResult();
     185    for (auto& effect : m_inputEffects)
     186        effect->clearResultsRecursive();
    249187}
    250188
    251189ImageBuffer* FilterEffect::imageBufferResult()
    252190{
    253     LOG_WITH_STREAM(Filters, stream << "FilterEffect " << filterName() << " " << this << " imageBufferResult(). Existing image buffer " << m_imageBufferResult.get() <<  " m_premultipliedImageResult " << m_premultipliedImageResult << " m_unmultipliedImageResult " << m_unmultipliedImageResult);
    254 
    255191    if (!hasResult())
    256192        return nullptr;
    257 
    258     if (m_imageBufferResult)
    259         return m_imageBufferResult.get();
    260 
    261     // FIXME: Respect the Filter::renderingMode() when creating the filter ImageBuffer result.
    262     // For now just pass RenderingMode::Unaccelerated. This will not be a behavior change since
    263     // this is what we do for the software filter code path anyway.
    264     m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), RenderingMode::Unaccelerated, 1, m_resultColorSpace, PixelFormat::BGRA8);
    265     if (!m_imageBufferResult)
     193    return m_filterImage->imageBuffer();
     194}
     195
     196PixelBuffer* FilterEffect::pixelBufferResult(AlphaPremultiplication alphaFormat)
     197{
     198    if (!hasResult())
    266199        return nullptr;
    267 
    268     IntRect destinationRect(IntPoint(), m_absolutePaintRect.size());
    269     if (m_premultipliedImageResult)
    270         m_imageBufferResult->putPixelBuffer(*m_premultipliedImageResult, destinationRect);
    271     else
    272         m_imageBufferResult->putPixelBuffer(*m_unmultipliedImageResult, destinationRect);
    273     return m_imageBufferResult.get();
    274 }
    275 
    276 RefPtr<Uint8ClampedArray> FilterEffect::unmultipliedResult(const IntRect& rect, std::optional<DestinationColorSpace> colorSpace)
    277 {
    278     IntSize scaledSize(rect.size());
    279     ASSERT(!ImageBuffer::sizeNeedsClamping(scaledSize));
    280     auto checkedArea = scaledSize.area<RecordOverflow>() * 4;
    281     if (checkedArea.hasOverflowed())
    282         return nullptr;
    283     auto pixelArray = Uint8ClampedArray::tryCreateUninitialized(checkedArea);
    284     if (!pixelArray)
    285         return nullptr;
    286     copyUnmultipliedResult(*pixelArray, rect, colorSpace);
    287     return pixelArray;
    288 }
    289 
    290 RefPtr<Uint8ClampedArray> FilterEffect::premultipliedResult(const IntRect& rect, std::optional<DestinationColorSpace> colorSpace)
    291 {
    292     IntSize scaledSize(rect.size());
    293     ASSERT(!ImageBuffer::sizeNeedsClamping(scaledSize));
    294     auto checkedArea = scaledSize.area<RecordOverflow>() * 4;
    295     if (checkedArea.hasOverflowed())
    296         return nullptr;
    297     auto pixelArray = Uint8ClampedArray::tryCreateUninitialized(checkedArea);
    298     if (!pixelArray)
    299         return nullptr;
    300     copyPremultipliedResult(*pixelArray, rect, colorSpace);
    301     return pixelArray;
    302 }
    303 
    304 void FilterEffect::copyImageBytes(const Uint8ClampedArray& source, Uint8ClampedArray& destination, const IntRect& rect) const
    305 {
    306     IntRect scaledRect(rect);
    307     IntSize scaledPaintSize(m_absolutePaintRect.size());
    308 
    309     // Initialize the destination to transparent black, if not entirely covered by the source.
    310     if (scaledRect.x() < 0 || scaledRect.y() < 0 || scaledRect.maxX() > scaledPaintSize.width() || scaledRect.maxY() > scaledPaintSize.height())
    311         memset(destination.data(), 0, destination.length());
    312 
    313     // Early return if the rect does not intersect with the source.
    314     if (scaledRect.maxX() <= 0 || scaledRect.maxY() <= 0 || scaledRect.x() >= scaledPaintSize.width() || scaledRect.y() >= scaledPaintSize.height())
     200    return m_filterImage->pixelBuffer(alphaFormat);
     201}
     202
     203std::optional<PixelBuffer> FilterEffect::getPixelBufferResult(AlphaPremultiplication alphaFormat, const IntRect& sourceRect, std::optional<DestinationColorSpace> colorSpace)
     204{
     205    ASSERT(hasResult());
     206    return m_filterImage->getPixelBuffer(alphaFormat, sourceRect, colorSpace);
     207}
     208
     209void FilterEffect::copyPixelBufferResult(PixelBuffer& destinationPixelBuffer, const IntRect& sourceRect) const
     210{
     211    ASSERT(hasResult());
     212    m_filterImage->copyPixelBuffer(destinationPixelBuffer, sourceRect);
     213}
     214
     215void FilterEffect::correctPremultipliedResultIfNeeded()
     216{
     217    if (!hasResult() || !mayProduceInvalidPremultipliedPixels())
    315218        return;
    316 
    317     int xOrigin = scaledRect.x();
    318     int xDest = 0;
    319     if (xOrigin < 0) {
    320         xDest = -xOrigin;
    321         xOrigin = 0;
    322     }
    323     int xEnd = scaledRect.maxX();
    324     if (xEnd > scaledPaintSize.width())
    325         xEnd = scaledPaintSize.width();
    326 
    327     int yOrigin = scaledRect.y();
    328     int yDest = 0;
    329     if (yOrigin < 0) {
    330         yDest = -yOrigin;
    331         yOrigin = 0;
    332     }
    333     int yEnd = scaledRect.maxY();
    334     if (yEnd > scaledPaintSize.height())
    335         yEnd = scaledPaintSize.height();
    336 
    337     int size = (xEnd - xOrigin) * 4;
    338     int destinationScanline = scaledRect.width() * 4;
    339     int sourceScanline = scaledPaintSize.width() * 4;
    340     uint8_t* destinationPixel = destination.data() + ((yDest * scaledRect.width()) + xDest) * 4;
    341     const uint8_t* sourcePixel = source.data() + ((yOrigin * scaledPaintSize.width()) + xOrigin) * 4;
    342 
    343     while (yOrigin < yEnd) {
    344         memcpy(destinationPixel, sourcePixel, size);
    345         destinationPixel += destinationScanline;
    346         sourcePixel += sourceScanline;
    347         ++yOrigin;
    348     }
    349 }
    350 
    351 static void copyPremultiplyingAlpha(const Uint8ClampedArray& source, Uint8ClampedArray& destination, const IntSize& inputSize)
    352 {
    353 #if USE(ACCELERATE)
    354     size_t rowBytes = inputSize.width() * 4;
    355 
    356     vImage_Buffer src;
    357     src.width = inputSize.width();
    358     src.height = inputSize.height();
    359     src.rowBytes = rowBytes;
    360     src.data = reinterpret_cast<void*>(source.data());
    361 
    362     vImage_Buffer dest;
    363     dest.width = inputSize.width();
    364     dest.height = inputSize.height();
    365     dest.rowBytes = rowBytes;
    366     dest.data = reinterpret_cast<void*>(destination.data());
    367 
    368     vImagePremultiplyData_RGBA8888(&src, &dest, kvImageNoFlags);
    369 #else
    370     const uint8_t* sourceComponent = source.data();
    371     const uint8_t* end = sourceComponent + (inputSize.area() * 4).value();
    372     uint8_t* destinationComponent = destination.data();
    373 
    374     while (sourceComponent < end) {
    375         int alpha = sourceComponent[3];
    376         destinationComponent[0] = static_cast<int>(sourceComponent[0]) * alpha / 255;
    377         destinationComponent[1] = static_cast<int>(sourceComponent[1]) * alpha / 255;
    378         destinationComponent[2] = static_cast<int>(sourceComponent[2]) * alpha / 255;
    379         destinationComponent[3] = alpha;
    380         sourceComponent += 4;
    381         destinationComponent += 4;
    382     }
    383 #endif
    384 }
    385 
    386 static void copyUnpremultiplyingAlpha(const Uint8ClampedArray& source, Uint8ClampedArray& destination, const IntSize& inputSize)
    387 {
    388 #if USE(ACCELERATE)
    389     size_t rowBytes = inputSize.width() * 4;
    390 
    391     vImage_Buffer src;
    392     src.width = inputSize.width();
    393     src.height = inputSize.height();
    394     src.rowBytes = rowBytes;
    395     src.data = reinterpret_cast<void*>(source.data());
    396 
    397     vImage_Buffer dest;
    398     dest.width = inputSize.width();
    399     dest.height = inputSize.height();
    400     dest.rowBytes = rowBytes;
    401     dest.data = reinterpret_cast<void*>(destination.data());
    402 
    403     vImageUnpremultiplyData_RGBA8888(&src, &dest, kvImageNoFlags);
    404 #else
    405     const uint8_t* sourceComponent = source.data();
    406     const uint8_t* end = sourceComponent + (inputSize.area() * 4).value();
    407     uint8_t* destinationComponent = destination.data();
    408     while (sourceComponent < end) {
    409         int alpha = sourceComponent[3];
    410         if (alpha) {
    411             destinationComponent[0] = static_cast<int>(sourceComponent[0]) * 255 / alpha;
    412             destinationComponent[1] = static_cast<int>(sourceComponent[1]) * 255 / alpha;
    413             destinationComponent[2] = static_cast<int>(sourceComponent[2]) * 255 / alpha;
    414         } else {
    415             destinationComponent[0] = 0;
    416             destinationComponent[1] = 0;
    417             destinationComponent[2] = 0;
    418         }
    419         destinationComponent[3] = alpha;
    420         sourceComponent += 4;
    421         destinationComponent += 4;
    422     }
    423 #endif
    424 }
    425 
    426 std::optional<PixelBuffer> FilterEffect::convertPixelBufferToColorSpace(const DestinationColorSpace& targetColorSpace, PixelBuffer& pixelBuffer)
    427 {
    428     // FIXME: Using an ImageBuffer to perform the color space conversion is unnecessary. We can do it directly.
    429 
    430     IntRect destinationRect(IntPoint(), pixelBuffer.size());
    431     FloatSize clampedSize = ImageBuffer::clampedSize(destinationRect.size());
    432     // Create an ImageBuffer to store incoming PixelBuffer
    433     auto buffer = ImageBuffer::create(clampedSize, RenderingMode::Unaccelerated, 1, operatingColorSpace(), PixelFormat::BGRA8);
    434     if (!buffer)
    435         return std::nullopt;
    436     buffer->putPixelBuffer(pixelBuffer, destinationRect);
    437     return convertImageBufferToColorSpace(targetColorSpace, *buffer, destinationRect, pixelBuffer.format().alphaFormat);
    438 }
    439 
    440 std::optional<PixelBuffer> FilterEffect::convertImageBufferToColorSpace(const DestinationColorSpace& targetColorSpace, ImageBuffer& inputBuffer, const IntRect& rect, AlphaPremultiplication outputAlphaFormat)
    441 {
    442     // FIXME: This can be done more directly using PixelBufferConversion.
    443 
    444     FloatSize clampedSize = ImageBuffer::clampedSize(rect.size());
    445 
    446     // Create an ImageBuffer with the correct color space and utilize CG to handle color space conversion
    447     auto convertedBuffer = ImageBuffer::create(clampedSize, RenderingMode::Unaccelerated, 1, targetColorSpace, PixelFormat::BGRA8);
    448     if (!convertedBuffer)
    449         return std::nullopt;
    450 
    451     // Color space conversion happens internally when drawing from one image buffer to another
    452     convertedBuffer->context().drawImageBuffer(inputBuffer, rect);
    453    
    454     PixelBufferFormat format { outputAlphaFormat, PixelFormat::RGBA8, targetColorSpace };
    455     return convertedBuffer->getPixelBuffer(format, rect);
    456 }
    457 
    458 void FilterEffect::copyConvertedImageBufferToDestination(Uint8ClampedArray& destination, const DestinationColorSpace& colorSpace, AlphaPremultiplication outputFormat, const IntRect& destRect)
    459 {
    460     // Converts the data stored in m_imageBufferResult, and save to destination
    461     auto convertedPixelBuffer = convertImageBufferToColorSpace(colorSpace, *m_imageBufferResult, { IntPoint(), m_absolutePaintRect.size() }, outputFormat);
    462     if (!convertedPixelBuffer)
     219    m_filterImage->correctPremultipliedPixelBuffer();
     220}
     221
     222void FilterEffect::transformResultColorSpace(const DestinationColorSpace& destinationColorSpace)
     223{
     224    if (!hasResult())
    463225        return;
    464     copyImageBytes(convertedPixelBuffer->data(), destination, destRect);
    465 }
    466 
    467 void FilterEffect::copyConvertedPixelBufferToDestination(Uint8ClampedArray& destination, PixelBuffer& pixelBuffer, const DestinationColorSpace& colorSpace, const IntRect& destRect)
    468 {
    469     // Converts the data stored in m_unmultipliedImageResult/m_premultipliedImageResult,
    470     // whichever isn't null, and save to destination
    471     auto convertedPixelBuffer = convertPixelBufferToColorSpace(colorSpace, pixelBuffer);
    472     if (!convertedPixelBuffer)
    473         return;
    474     copyImageBytes(convertedPixelBuffer->data(), destination, destRect);
    475 }
    476 
    477 void FilterEffect::copyUnmultipliedResult(Uint8ClampedArray& destination, const IntRect& rect, std::optional<DestinationColorSpace> colorSpace)
    478 {
    479     ASSERT(hasResult());
    480    
    481     LOG_WITH_STREAM(Filters, stream << "FilterEffect " << filterName() << " " << this << " copyUnmultipliedResult(). Existing image buffer " << m_imageBufferResult.get() <<  " m_premultipliedImageResult " << m_premultipliedImageResult << " m_unmultipliedImageResult " << m_unmultipliedImageResult);
    482 
    483     if (!m_unmultipliedImageResult) {
    484         // We prefer a conversion from the image buffer.
    485         if (m_imageBufferResult) {
    486             if (requiresPixelBufferColorSpaceConversion(colorSpace)) {
    487                 copyConvertedImageBufferToDestination(destination, *colorSpace, AlphaPremultiplication::Unpremultiplied, rect);
    488                 return;
    489             }
    490 
    491             ASSERT(m_imageBufferResult->colorSpace() == m_resultColorSpace);
    492             PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    493             m_unmultipliedImageResult = m_imageBufferResult->getPixelBuffer(format, { IntPoint(), m_absolutePaintRect.size() });
    494             if (!m_unmultipliedImageResult)
    495                 return;
    496         } else {
    497             IntSize inputSize(m_absolutePaintRect.size());
    498             ASSERT(!ImageBuffer::sizeNeedsClamping(inputSize));
    499            
    500             ASSERT(m_premultipliedImageResult->format().colorSpace == m_resultColorSpace);
    501             PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    502             m_unmultipliedImageResult = PixelBuffer::tryCreate(format, inputSize);
    503             if (!m_unmultipliedImageResult)
    504                 return;
    505             copyUnpremultiplyingAlpha(m_premultipliedImageResult->data(), m_unmultipliedImageResult->data(), inputSize);
    506         }
    507     }
    508     if (requiresPixelBufferColorSpaceConversion(colorSpace)) {
    509         copyConvertedPixelBufferToDestination(destination, *m_unmultipliedImageResult, *colorSpace, rect);
    510         return;
    511     }
    512     copyImageBytes(m_unmultipliedImageResult->data(), destination, rect);
    513 }
    514 
    515 void FilterEffect::copyPremultipliedResult(Uint8ClampedArray& destination, const IntRect& rect, std::optional<DestinationColorSpace> colorSpace)
    516 {
    517     ASSERT(hasResult());
    518 
    519     LOG_WITH_STREAM(Filters, stream << "FilterEffect " << filterName() << " " << this << " copyPremultipliedResult(). Existing image buffer " << m_imageBufferResult.get() <<  " m_premultipliedImageResult " << m_premultipliedImageResult << " m_unmultipliedImageResult " << m_unmultipliedImageResult);
    520 
    521     if (!m_premultipliedImageResult) {
    522         // We prefer a conversion from the image buffer.
    523         if (m_imageBufferResult) {
    524             if (requiresPixelBufferColorSpaceConversion(colorSpace)) {
    525                 copyConvertedImageBufferToDestination(destination, *colorSpace, AlphaPremultiplication::Premultiplied, rect);
    526                 return;
    527             }
    528 
    529             ASSERT(m_imageBufferResult->colorSpace() == m_resultColorSpace);
    530             PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    531             m_premultipliedImageResult = m_imageBufferResult->getPixelBuffer(format, { IntPoint(), m_absolutePaintRect.size() });
    532             if (!m_premultipliedImageResult)
    533                 return;
    534         } else {
    535             IntSize inputSize(m_absolutePaintRect.size());
    536             ASSERT(!ImageBuffer::sizeNeedsClamping(inputSize));
    537 
    538             ASSERT(m_unmultipliedImageResult->format().colorSpace == m_resultColorSpace);
    539             PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    540             m_premultipliedImageResult = PixelBuffer::tryCreate(format, inputSize);
    541             if (!m_premultipliedImageResult)
    542                 return;
    543             copyPremultiplyingAlpha(m_unmultipliedImageResult->data(), m_premultipliedImageResult->data(), inputSize);
    544         }
    545     }
    546 
    547     if (requiresPixelBufferColorSpaceConversion(colorSpace)) {
    548         copyConvertedPixelBufferToDestination(destination, *m_premultipliedImageResult, *colorSpace, rect);
    549         return;
    550     }
    551     copyImageBytes(m_premultipliedImageResult->data(), destination, rect);
    552 }
    553 
    554 ImageBuffer* FilterEffect::createImageBufferResult()
    555 {
    556     LOG(Filters, "FilterEffect %s %p createImageBufferResult %dx%d", filterName().characters8(), this, m_absolutePaintRect.size().width(), m_absolutePaintRect.size().height());
    557 
    558     // Only one result type is allowed.
    559     ASSERT(!hasResult());
    560     if (m_absolutePaintRect.isEmpty())
    561         return nullptr;
    562 
    563     FloatSize clampedSize = ImageBuffer::clampedSize(m_absolutePaintRect.size());
    564     m_imageBufferResult = ImageBuffer::create(clampedSize, RenderingMode::Unaccelerated, 1, m_resultColorSpace, PixelFormat::BGRA8);
    565     return m_imageBufferResult.get();
    566 }
    567 
    568 std::optional<PixelBuffer>& FilterEffect::createUnmultipliedImageResult()
    569 {
    570     LOG(Filters, "FilterEffect %s %p createUnmultipliedImageResult", filterName().characters8(), this);
    571 
    572     // Only one result type is allowed.
    573     ASSERT(!hasResult());
    574     ASSERT(!m_unmultipliedImageResult);
    575 
    576     if (m_absolutePaintRect.isEmpty())
    577         return m_unmultipliedImageResult;
    578 
    579     IntSize resultSize(m_absolutePaintRect.size());
    580     ASSERT(!ImageBuffer::sizeNeedsClamping(resultSize));
    581     PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    582     m_unmultipliedImageResult = PixelBuffer::tryCreate(format, resultSize);
    583     return m_unmultipliedImageResult;
    584 }
    585 
    586 std::optional<PixelBuffer>& FilterEffect::createPremultipliedImageResult()
    587 {
    588     LOG(Filters, "FilterEffect %s %p createPremultipliedImageResult", filterName().characters8(), this);
    589 
    590     // Only one result type is allowed.
    591     ASSERT(!hasResult());
    592     ASSERT(!m_premultipliedImageResult);
    593 
    594     if (m_absolutePaintRect.isEmpty())
    595         return m_premultipliedImageResult;
    596 
    597     IntSize resultSize(m_absolutePaintRect.size());
    598     ASSERT(!ImageBuffer::sizeNeedsClamping(resultSize));
    599     PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    600     m_premultipliedImageResult = PixelBuffer::tryCreate(format, resultSize);
    601     return m_premultipliedImageResult;
    602 }
    603 
    604 bool FilterEffect::requiresPixelBufferColorSpaceConversion(std::optional<DestinationColorSpace> destinationColorSpace)
    605 {
    606 #if USE(CG)
    607     // This function determines whether we need the step of an extra color space conversion
    608     // We only need extra color conversion when 1) color space is different in the input
    609     // AND 2) the filter is manipulating raw pixels
    610     return destinationColorSpace && resultColorSpace() != *destinationColorSpace;
    611 #else
    612     // Additional color space conversion is not needed on non-CG
    613     UNUSED_PARAM(destinationColorSpace);
    614     return false;
    615 #endif
    616 }
    617 
    618 void FilterEffect::transformResultColorSpace(const DestinationColorSpace& destinationColorSpace)
    619 {
    620 #if USE(CG)
    621     // CG handles color space adjustments internally.
    622     UNUSED_PARAM(destinationColorSpace);
    623 #else
    624     if (!hasResult() || destinationColorSpace == m_resultColorSpace)
    625         return;
    626 
    627     // FIXME: We can avoid this potentially unnecessary ImageBuffer conversion by adding
    628     // color space transform support for the {pre,un}multiplied arrays.
    629     imageBufferResult()->transformToColorSpace(destinationColorSpace);
    630 
    631     m_resultColorSpace = destinationColorSpace;
    632 
    633     m_unmultipliedImageResult = std::nullopt;
    634     m_premultipliedImageResult = std::nullopt;
    635 #endif
     226    m_filterImage->transformToColorSpace(destinationColorSpace);
    636227}
    637228
     
    644235        TextStream::IndentScope indentScope(ts);
    645236        ts.dumpProperty("alpha image", m_alphaImage);
    646         ts.dumpProperty("operating colorspace", m_operatingColorSpace);
    647         ts.dumpProperty("result colorspace", m_resultColorSpace);
     237        ts.dumpProperty("operating colorspace", operatingColorSpace());
     238        ts.dumpProperty("result colorspace", resultColorSpace());
    648239        ts << "\n" << indent;
    649240    }
  • trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h

    r285916 r286129  
    2323#pragma once
    2424
    25 #include "AlphaPremultiplication.h"
    2625#include "DestinationColorSpace.h"
    2726#include "FilterEffectVector.h"
    2827#include "FilterFunction.h"
    29 #include "FloatRect.h"
     28#include "FilterImage.h"
    3029#include "IntRect.h"
    31 #include "IntRectExtent.h"
    32 #include "PixelBuffer.h"
    33 #include <JavaScriptCore/Forward.h>
    34 #include <wtf/MathExtras.h>
    35 #include <wtf/RefPtr.h>
    3630#include <wtf/Vector.h>
    3731
     
    4741class FilterEffect : public FilterFunction {
    4842public:
     43    bool createResult();
    4944    void clearResult() override;
    5045    void clearResultsRecursive();
    5146
     47    bool hasResult() const { return m_filterImage; }
     48
    5249    ImageBuffer* imageBufferResult();
    53     RefPtr<Uint8ClampedArray> unmultipliedResult(const IntRect&, std::optional<DestinationColorSpace> = std::nullopt);
    54     RefPtr<Uint8ClampedArray> premultipliedResult(const IntRect&, std::optional<DestinationColorSpace> = std::nullopt);
    55     void copyUnmultipliedResult(Uint8ClampedArray& destination, const IntRect&, std::optional<DestinationColorSpace> = std::nullopt);
    56     void copyPremultipliedResult(Uint8ClampedArray& destination, const IntRect&, std::optional<DestinationColorSpace> = std::nullopt);
     50    PixelBuffer* pixelBufferResult(AlphaPremultiplication);
     51    std::optional<PixelBuffer> getPixelBufferResult(AlphaPremultiplication, const IntRect& sourceRect, std::optional<DestinationColorSpace> = std::nullopt);
     52    void copyPixelBufferResult(PixelBuffer& destinationPixelBuffer, const IntRect& sourceRect) const;
     53    void correctPremultipliedResultIfNeeded();
     54
    5755    FilterEffectVector& inputEffects() { return m_inputEffects; }
    5856    FilterEffect* inputEffect(unsigned) const;
    5957    unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
    6058   
    61     inline bool hasResult() const
    62     {
    63         // This function needs platform specific checks, if the memory managment is not done by FilterEffect.
    64         return m_imageBufferResult
    65             || m_unmultipliedImageResult
    66             || m_premultipliedImageResult;
    67     }
    68 
    6959    FloatRect drawingRegionOfInputImage(const IntRect&) const;
    7060    IntRect requestedRegionOfInputPixelBuffer(const IntRect&) const;
     
    124114    const DestinationColorSpace& operatingColorSpace() const { return m_operatingColorSpace; }
    125115    virtual void setOperatingColorSpace(const DestinationColorSpace& colorSpace) { m_operatingColorSpace = colorSpace; }
    126     const DestinationColorSpace& resultColorSpace() const { return m_resultColorSpace; }
    127     virtual void setResultColorSpace(const DestinationColorSpace& colorSpace) { m_resultColorSpace = colorSpace; }
     116
     117    virtual const DestinationColorSpace& resultColorSpace() const { return m_operatingColorSpace; }
    128118
    129119    virtual void transformResultColorSpace(FilterEffect* in, const int) { in->transformResultColorSpace(m_operatingColorSpace); }
     
    139129
    140130protected:
    141     FilterEffect(Type);
    142    
    143     ImageBuffer* createImageBufferResult();
    144     std::optional<PixelBuffer>& createUnmultipliedImageResult();
    145     std::optional<PixelBuffer>& createPremultipliedImageResult();
     131    using FilterFunction::FilterFunction;
    146132
    147     // Return true if the filter will only operate correctly on valid RGBA values, with
    148     // alpha in [0,255] and each color component in [0, alpha].
    149     virtual bool requiresValidPreMultipliedPixels() { return true; }
    150 
    151     // If a pre-multiplied image, check every pixel for validity and correct if necessary.
    152     void forceValidPreMultipliedPixels();
     133    virtual bool mayProduceInvalidPremultipliedPixels() const { return false; }
    153134
    154135    void clipAbsolutePaintRect();
     
    157138    virtual bool platformApplySoftware(const Filter&) = 0;
    158139
    159     void copyImageBytes(const Uint8ClampedArray& source, Uint8ClampedArray& destination, const IntRect&) const;
    160     void copyConvertedImageBufferToDestination(Uint8ClampedArray&, const DestinationColorSpace&, AlphaPremultiplication, const IntRect&);
    161     void copyConvertedPixelBufferToDestination(Uint8ClampedArray&, PixelBuffer&, const DestinationColorSpace&, const IntRect&);
    162     bool requiresPixelBufferColorSpaceConversion(std::optional<DestinationColorSpace>);
    163     std::optional<PixelBuffer> convertImageBufferToColorSpace(const DestinationColorSpace&, ImageBuffer&, const IntRect&, AlphaPremultiplication);
    164     std::optional<PixelBuffer> convertPixelBufferToColorSpace(const DestinationColorSpace&, PixelBuffer&);
    165    
    166140    FilterEffectVector m_inputEffects;
    167141
    168     RefPtr<ImageBuffer> m_imageBufferResult;
    169     std::optional<PixelBuffer> m_unmultipliedImageResult;
    170     std::optional<PixelBuffer> m_premultipliedImageResult;
     142    RefPtr<FilterImage> m_filterImage;
    171143
    172144    IntRect m_absolutePaintRect;
     
    196168    bool m_clipsToBounds { true };
    197169
    198 #if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
    199     DestinationColorSpace m_operatingColorSpace { DestinationColorSpace::LinearSRGB() };
    200 #else
    201170    DestinationColorSpace m_operatingColorSpace { DestinationColorSpace::SRGB() };
    202 #endif
    203     DestinationColorSpace m_resultColorSpace { DestinationColorSpace::SRGB() };
    204171};
    205172
  • trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp

    r285916 r286129  
    4848bool SourceAlpha::platformApplySoftware(const Filter&)
    4949{
    50     ImageBuffer* resultImage = createImageBufferResult();
     50    ImageBuffer* resultImage = imageBufferResult();
    5151    if (!resultImage)
    5252        return false;
  • trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp

    r285916 r286129  
    3535    : FilterEffect(FilterEffect::Type::SourceGraphic)
    3636{
    37     setOperatingColorSpace(DestinationColorSpace::SRGB());
    3837}
    3938
     
    4645bool SourceGraphic::platformApplySoftware(const Filter& filter)
    4746{
    48     ImageBuffer* resultImage = createImageBufferResult();
     47    ImageBuffer* resultImage = imageBufferResult();
    4948    ImageBuffer* sourceImage = filter.sourceImage();
    5049    if (!resultImage || !sourceImage)
  • trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp

    r285796 r286129  
    242242            filterData.state = FilterData::Applying;
    243243            filterData.filter->apply();
    244             lastEffect->correctFilterResultIfNeeded();
     244            lastEffect->correctPremultipliedResultIfNeeded();
    245245            lastEffect->transformResultColorSpace(DestinationColorSpace::SRGB());
    246246        }
  • trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.cpp

    r285916 r286129  
    7777bool FEImage::platformApplySoftware(const Filter& filter)
    7878{
    79     // FEImage results are always in DestinationColorSpace::SRGB()
    80     setResultColorSpace(DestinationColorSpace::SRGB());
    81 
    82     ImageBuffer* resultImage = createImageBufferResult();
     79    auto resultImage = imageBufferResult();
    8380    if (!resultImage)
    8481        return false;
  • trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h

    r285916 r286129  
    4545    FEImage(SourceImage&&, const FloatRect& sourceImageRect, const SVGPreserveAspectRatioValue&);
    4646
     47    // FEImage results are always in DestinationColorSpace::SRGB()
     48    void setOperatingColorSpace(const DestinationColorSpace&) override { }
     49
    4750    void determineAbsolutePaintRect(const Filter&) final;
    4851
Note: See TracChangeset for help on using the changeset viewer.