Skip to content
Permalink
Browse files
[GPU Process] [Filters] Don't use Uint8ClampedArray in software filte…
…r appliers

https://bugs.webkit.org/show_bug.cgi?id=240777
rdar://93916935

Reviewed by Simon Fraser.

The plan is to allocate the FilterImage buffers differently for GPUProcess. The
first step is to hide the underlying memory of PixelBuffer from the software
filter appliers. Helpers functions will provide access to Uint8ClampedArray. In
future patches different memory allocation will be used by new sub-classes of
PixelBuffer.

* Source/WebCore/platform/graphics/PixelBuffer.cpp:
(WebCore::PixelBuffer::bytes const):
(WebCore::PixelBuffer::byteLength const):
(WebCore::PixelBuffer::setRange):
(WebCore::PixelBuffer::zeroRange):
(WebCore::PixelBuffer::item const):
(WebCore::PixelBuffer::set):
(WebCore::PixelBuffer::createScratchPixelBuffer const):
* Source/WebCore/platform/graphics/PixelBuffer.h:
(WebCore::PixelBuffer::zeroFill):
* Source/WebCore/platform/graphics/filters/FEComposite.h:
* Source/WebCore/platform/graphics/filters/FilterImage.cpp:
(WebCore::FilterImage::correctPremultipliedPixelBuffer):
* Source/WebCore/platform/graphics/filters/software/FEColorMatrixSoftwareApplier.cpp:
(WebCore::FEColorMatrixSoftwareApplier::applyPlatformAccelerated const):
(WebCore::FEColorMatrixSoftwareApplier::applyPlatformUnaccelerated const):
* Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.cpp:
(WebCore::FEComponentTransferSoftwareApplier::applyPlatform const):
* Source/WebCore/platform/graphics/filters/software/FECompositeSoftwareApplier.cpp:
(WebCore::FECompositeSoftwareApplier::applyArithmetic const):
* Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.cpp:
(WebCore::FEConvolveMatrixSoftwareApplier::setDestinationPixels):
(WebCore::FEConvolveMatrixSoftwareApplier::setInteriorPixels):
(WebCore::FEConvolveMatrixSoftwareApplier::setOuterPixels):
(WebCore::FEConvolveMatrixSoftwareApplier::apply const):
* Source/WebCore/platform/graphics/filters/software/FEConvolveMatrixSoftwareApplier.h:
* Source/WebCore/platform/graphics/filters/software/FEDisplacementMapSoftwareApplier.cpp:
(WebCore::FEDisplacementMapSoftwareApplier::apply const):
* Source/WebCore/platform/graphics/filters/software/FEDropShadowSoftwareApplier.cpp:
(WebCore::FEDropShadowSoftwareApplier::apply const):
* Source/WebCore/platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.cpp:
(WebCore::FEGaussianBlurSoftwareApplier::boxBlurAlphaOnly):
(WebCore::FEGaussianBlurSoftwareApplier::boxBlur):
(WebCore::FEGaussianBlurSoftwareApplier::boxBlurAccelerated):
(WebCore::FEGaussianBlurSoftwareApplier::boxBlurUnaccelerated):
(WebCore::FEGaussianBlurSoftwareApplier::boxBlurGeneric):
(WebCore::FEGaussianBlurSoftwareApplier::boxBlurWorker):
(WebCore::FEGaussianBlurSoftwareApplier::applyPlatform):
(WebCore::FEGaussianBlurSoftwareApplier::apply const):
* Source/WebCore/platform/graphics/filters/software/FEGaussianBlurSoftwareApplier.h:
* Source/WebCore/platform/graphics/filters/software/FELightingSoftwareApplier.cpp:
(WebCore::FELightingSoftwareApplier::apply const):
* Source/WebCore/platform/graphics/filters/software/FELightingSoftwareApplier.h:
* Source/WebCore/platform/graphics/filters/software/FEMorphologySoftwareApplier.cpp:
(WebCore::FEMorphologySoftwareApplier::columnExtremum):
(WebCore::FEMorphologySoftwareApplier::applyPlatformGeneric):
(WebCore::FEMorphologySoftwareApplier::apply const):
* Source/WebCore/platform/graphics/filters/software/FEMorphologySoftwareApplier.h:
* Source/WebCore/platform/graphics/filters/software/FETurbulenceSoftwareApplier.cpp:
(WebCore::FETurbulenceSoftwareApplier::applyPlatformGeneric):
(WebCore::FETurbulenceSoftwareApplier::applyPlatformWorker):
(WebCore::FETurbulenceSoftwareApplier::applyPlatform):
(WebCore::FETurbulenceSoftwareApplier::apply const):
* Source/WebCore/platform/graphics/filters/software/FETurbulenceSoftwareApplier.h:

Canonical link: https://commits.webkit.org/250982@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@294832 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
shallawa committed May 25, 2022
1 parent f3f187a commit 5fa57abfe3f4b1dbf2fe1f8032bdcb3d72bbed07
Showing 19 changed files with 226 additions and 190 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 Apple Inc. All rights reserved.
* Copyright (C) 2021-2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -120,9 +120,56 @@ PixelBuffer PixelBuffer::deepClone() const
return { m_format, m_size, Uint8ClampedArray::create(m_data->data(), m_data->length()) };
}

uint8_t* PixelBuffer::bytes() const
{
return m_data->data();
}

size_t PixelBuffer::sizeInBytes() const
{
ASSERT(m_data->byteLength() == m_size.area() * 4);
return m_data->byteLength();
}

bool PixelBuffer::setRange(const uint8_t* data, size_t dataByteLength, size_t byteOffset)
{
if (!isSumSmallerThanOrEqual(byteOffset, dataByteLength, sizeInBytes()))
return false;

memmove(bytes() + byteOffset, data, dataByteLength);
return true;
}

bool PixelBuffer::zeroRange(size_t byteOffset, size_t rangeByteLength)
{
if (!isSumSmallerThanOrEqual(byteOffset, rangeByteLength, sizeInBytes()))
return false;

memset(bytes() + byteOffset, 0, rangeByteLength);
return true;
}

uint8_t PixelBuffer::item(size_t index) const
{
RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(index < sizeInBytes());
return bytes()[index];
}

void PixelBuffer::set(size_t index, double value)
{
RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(index < sizeInBytes());
bytes()[index] = JSC::Uint8ClampedAdaptor::toNativeFromDouble(value);
}

std::optional<PixelBuffer> PixelBuffer::createScratchPixelBuffer(const IntSize& size) const
{
return PixelBuffer::tryCreate(m_format, size);
}

TextStream& operator<<(TextStream& ts, const PixelBuffer& pixelBuffer)
{
return ts << &pixelBuffer.data() << "format ( " << pixelBuffer.format() << ")";
}

}
} // namespace WebCore

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 Apple Inc. All rights reserved.
* Copyright (C) 2021-2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -61,6 +61,18 @@ class PixelBuffer {

PixelBuffer deepClone() const;

uint8_t* bytes() const;
size_t sizeInBytes() const;

bool setRange(const uint8_t* data, size_t dataByteLength, size_t byteOffset);
bool zeroRange(size_t byteOffset, size_t rangeByteLength);
void zeroFill() { zeroRange(0, sizeInBytes()); }

uint8_t item(size_t index) const;
void set(size_t index, double value);

std::optional<PixelBuffer> createScratchPixelBuffer(const IntSize&) const;

template<class Encoder> void encode(Encoder&) const;
template<class Decoder> static std::optional<PixelBuffer> decode(Decoder&);

@@ -119,4 +131,4 @@ template<class Decoder> std::optional<PixelBuffer> PixelBuffer::decode(Decoder&
return result;
}

}
} // namespace WebCore
@@ -73,8 +73,6 @@ class FEComposite : public FilterEffect {

WTF::TextStream& externalRepresentation(WTF::TextStream&, FilterRepresentation) const override;

inline void platformArithmeticSoftware(const Uint8ClampedArray& source, Uint8ClampedArray& destination, float k1, float k2, float k3, float k4);

#if HAVE(ARM_NEON_INTRINSICS)
template <int b1, int b4>
static inline void computeArithmeticPixelsNeon(const uint8_t* source, uint8_t* destination, unsigned pixelArrayLength, float k1, float k2, float k3, float k4);
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 Apple Inc. All rights reserved.
* Copyright (C) 2021-2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -300,46 +300,45 @@ void FilterImage::correctPremultipliedPixelBuffer()
if (!m_premultipliedPixelBuffer || m_isValidPremultiplied)
return;

Uint8ClampedArray& imageArray = m_premultipliedPixelBuffer->data();
uint8_t* pixelData = imageArray.data();
int pixelArrayLength = imageArray.length();
uint8_t* pixelBytes = m_premultipliedPixelBuffer->bytes();
int pixelByteLength = m_premultipliedPixelBuffer->sizeInBytes();

// We must have four bytes per pixel, and complete pixels
ASSERT(!(pixelArrayLength % 4));
ASSERT(!(pixelByteLength % 4));

#if HAVE(ARM_NEON_INTRINSICS)
if (pixelArrayLength >= 64) {
uint8_t* lastPixel = pixelData + (pixelArrayLength & ~0x3f);
if (pixelByteLength >= 64) {
uint8_t* lastPixel = pixelBytes + (pixelByteLength & ~0x3f);
do {
// Increments pixelData by 64.
uint8x16x4_t sixteenPixels = vld4q_u8(pixelData);
// Increments pixelBytes by 64.
uint8x16x4_t sixteenPixels = vld4q_u8(pixelBytes);
sixteenPixels.val[0] = vminq_u8(sixteenPixels.val[0], sixteenPixels.val[3]);
sixteenPixels.val[1] = vminq_u8(sixteenPixels.val[1], sixteenPixels.val[3]);
sixteenPixels.val[2] = vminq_u8(sixteenPixels.val[2], sixteenPixels.val[3]);
vst4q_u8(pixelData, sixteenPixels);
pixelData += 64;
} while (pixelData < lastPixel);
vst4q_u8(pixelBytes, sixteenPixels);
pixelBytes += 64;
} while (pixelBytes < lastPixel);

pixelArrayLength &= 0x3f;
if (!pixelArrayLength)
pixelByteLength &= 0x3f;
if (!pixelByteLength)
return;
}
#endif

int numPixels = pixelArrayLength / 4;
int numPixels = pixelByteLength / 4;

// Iterate over each pixel, checking alpha and adjusting color components if necessary
while (--numPixels >= 0) {
// Alpha is the 4th byte in a pixel
uint8_t a = *(pixelData + 3);
uint8_t a = *(pixelBytes + 3);
// Clamp each component to alpha, and increment the pixel location
for (int i = 0; i < 3; ++i) {
if (*pixelData > a)
*pixelData = a;
++pixelData;
if (*pixelBytes > a)
*pixelBytes = a;
++pixelBytes;
}
// Increment for alpha
++pixelData;
++pixelBytes;
}
}

@@ -3,7 +3,7 @@
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2021 Apple Inc. All rights reserved.
* Copyright (C) 2021-2022 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -83,25 +83,21 @@ inline void FEColorMatrixSoftwareApplier::luminance(float& red, float& green, fl
#if USE(ACCELERATE)
void FEColorMatrixSoftwareApplier::applyPlatformAccelerated(PixelBuffer& pixelBuffer) const
{
auto& pixelArray = pixelBuffer.data();
auto* pixelBytes = pixelBuffer.bytes();
auto bufferSize = pixelBuffer.size();

ASSERT(pixelArray.length() == bufferSize.area() * 4);

const int32_t divisor = 256;
uint8_t* data = pixelArray.data();

vImage_Buffer src;
src.width = bufferSize.width();
src.height = bufferSize.height();
src.rowBytes = bufferSize.width() * 4;
src.data = data;
src.data = pixelBytes;

vImage_Buffer dest;
dest.width = bufferSize.width();
dest.height = bufferSize.height();
dest.rowBytes = bufferSize.width() * 4;
dest.data = data;
dest.data = pixelBytes;

switch (m_effect.type()) {
case FECOLORMATRIX_TYPE_UNKNOWN:
@@ -192,53 +188,52 @@ void FEColorMatrixSoftwareApplier::applyPlatformAccelerated(PixelBuffer& pixelBu

void FEColorMatrixSoftwareApplier::applyPlatformUnaccelerated(PixelBuffer& pixelBuffer) const
{
auto& pixelArray = pixelBuffer.data();
unsigned pixelArrayLength = pixelArray.length();
auto pixelByteLength = pixelBuffer.sizeInBytes();

switch (m_effect.type()) {
case FECOLORMATRIX_TYPE_UNKNOWN:
break;

case FECOLORMATRIX_TYPE_MATRIX:
for (unsigned pixelByteOffset = 0; pixelByteOffset < pixelArrayLength; pixelByteOffset += 4) {
float red = pixelArray.item(pixelByteOffset);
float green = pixelArray.item(pixelByteOffset + 1);
float blue = pixelArray.item(pixelByteOffset + 2);
float alpha = pixelArray.item(pixelByteOffset + 3);
for (unsigned pixelByteOffset = 0; pixelByteOffset < pixelByteLength; pixelByteOffset += 4) {
float red = pixelBuffer.item(pixelByteOffset);
float green = pixelBuffer.item(pixelByteOffset + 1);
float blue = pixelBuffer.item(pixelByteOffset + 2);
float alpha = pixelBuffer.item(pixelByteOffset + 3);
matrix(red, green, blue, alpha);
pixelArray.set(pixelByteOffset, red);
pixelArray.set(pixelByteOffset + 1, green);
pixelArray.set(pixelByteOffset + 2, blue);
pixelArray.set(pixelByteOffset + 3, alpha);
pixelBuffer.set(pixelByteOffset, red);
pixelBuffer.set(pixelByteOffset + 1, green);
pixelBuffer.set(pixelByteOffset + 2, blue);
pixelBuffer.set(pixelByteOffset + 3, alpha);
}
break;

case FECOLORMATRIX_TYPE_SATURATE:
case FECOLORMATRIX_TYPE_HUEROTATE:
for (unsigned pixelByteOffset = 0; pixelByteOffset < pixelArrayLength; pixelByteOffset += 4) {
float red = pixelArray.item(pixelByteOffset);
float green = pixelArray.item(pixelByteOffset + 1);
float blue = pixelArray.item(pixelByteOffset + 2);
float alpha = pixelArray.item(pixelByteOffset + 3);
for (unsigned pixelByteOffset = 0; pixelByteOffset < pixelByteLength; pixelByteOffset += 4) {
float red = pixelBuffer.item(pixelByteOffset);
float green = pixelBuffer.item(pixelByteOffset + 1);
float blue = pixelBuffer.item(pixelByteOffset + 2);
float alpha = pixelBuffer.item(pixelByteOffset + 3);
saturateAndHueRotate(red, green, blue);
pixelArray.set(pixelByteOffset, red);
pixelArray.set(pixelByteOffset + 1, green);
pixelArray.set(pixelByteOffset + 2, blue);
pixelArray.set(pixelByteOffset + 3, alpha);
pixelBuffer.set(pixelByteOffset, red);
pixelBuffer.set(pixelByteOffset + 1, green);
pixelBuffer.set(pixelByteOffset + 2, blue);
pixelBuffer.set(pixelByteOffset + 3, alpha);
}
break;

case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
for (unsigned pixelByteOffset = 0; pixelByteOffset < pixelArrayLength; pixelByteOffset += 4) {
float red = pixelArray.item(pixelByteOffset);
float green = pixelArray.item(pixelByteOffset + 1);
float blue = pixelArray.item(pixelByteOffset + 2);
float alpha = pixelArray.item(pixelByteOffset + 3);
for (unsigned pixelByteOffset = 0; pixelByteOffset < pixelByteLength; pixelByteOffset += 4) {
float red = pixelBuffer.item(pixelByteOffset);
float green = pixelBuffer.item(pixelByteOffset + 1);
float blue = pixelBuffer.item(pixelByteOffset + 2);
float alpha = pixelBuffer.item(pixelByteOffset + 3);
luminance(red, green, blue, alpha);
pixelArray.set(pixelByteOffset, red);
pixelArray.set(pixelByteOffset + 1, green);
pixelArray.set(pixelByteOffset + 2, blue);
pixelArray.set(pixelByteOffset + 3, alpha);
pixelBuffer.set(pixelByteOffset, red);
pixelBuffer.set(pixelByteOffset + 1, green);
pixelBuffer.set(pixelByteOffset + 2, blue);
pixelBuffer.set(pixelByteOffset + 3, alpha);
}
break;
}
@@ -4,7 +4,7 @@
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
* Copyright (C) 2021 Apple Inc. All rights reserved.
* Copyright (C) 2021-2022 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -114,16 +114,15 @@ FEComponentTransferSoftwareApplier::LookupTable FEComponentTransferSoftwareAppli

void FEComponentTransferSoftwareApplier::applyPlatform(PixelBuffer& pixelBuffer) const
{
auto& pixelArray = pixelBuffer.data();
unsigned pixelArrayLength = pixelArray.length();
uint8_t* data = pixelArray.data();
auto* data = pixelBuffer.bytes();
auto pixelByteLength = pixelBuffer.sizeInBytes();

auto redTable = computeLookupTable(m_effect.redFunction());
auto greenTable = computeLookupTable(m_effect.greenFunction());
auto blueTable = computeLookupTable(m_effect.blueFunction());
auto alphaTable = computeLookupTable(m_effect.alphaFunction());

for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
for (unsigned pixelOffset = 0; pixelOffset < pixelByteLength; pixelOffset += 4) {
data[pixelOffset] = redTable[data[pixelOffset]];
data[pixelOffset + 1] = greenTable[data[pixelOffset + 1]];
data[pixelOffset + 2] = blueTable[data[pixelOffset + 2]];
@@ -4,7 +4,7 @@
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
* Copyright (C) 2021 Apple Inc. All rights reserved.
* Copyright (C) 2021-2022 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -140,13 +140,13 @@ bool FECompositeSoftwareApplier::applyArithmetic(FilterImage& input, FilterImage
IntRect effectBDrawingRect = result.absoluteImageRectRelativeTo(input2);
input2.copyPixelBuffer(*destinationPixelBuffer, effectBDrawingRect);

auto& sourcePixelArray = sourcePixelBuffer->data();
auto& destinationPixelArray = destinationPixelBuffer->data();
auto* sourcePixelBytes = sourcePixelBuffer->bytes();
auto* destinationPixelBytes = destinationPixelBuffer->bytes();

int length = sourcePixelArray.length();
ASSERT(length == static_cast<int>(destinationPixelArray.length()));
auto length = sourcePixelBuffer->sizeInBytes();
ASSERT(length == destinationPixelBuffer->sizeInBytes());
#if !HAVE(ARM_NEON_INTRINSICS)
applyPlatformArithmetic(sourcePixelArray.data(), destinationPixelArray.data(), length, m_effect.k1(), m_effect.k2(), m_effect.k3(), m_effect.k4());
applyPlatformArithmetic(sourcePixelBytes, destinationPixelBytes, length, m_effect.k1(), m_effect.k2(), m_effect.k3(), m_effect.k4());
#endif
return true;
}

0 comments on commit 5fa57ab

Please sign in to comment.