Diff
Modified: trunk/Source/WebCore/ChangeLog (277368 => 277369)
--- trunk/Source/WebCore/ChangeLog 2021-05-12 14:33:51 UTC (rev 277368)
+++ trunk/Source/WebCore/ChangeLog 2021-05-12 14:51:31 UTC (rev 277369)
@@ -1,3 +1,69 @@
+2021-05-12 Sam Weinig <wei...@apple.com>
+
+ Factor copyImagePixels pixel conversion code into its own file
+ https://bugs.webkit.org/show_bug.cgi?id=225673
+
+ Reviewed by Darin Adler.
+
+ Removes virtual ImageBufferBackend::copyImagePixels() function and
+ moves functionality to new PixelBufferConversion.h/cpp.
+
+ Merge USE(ACCELERATE) code from ImageBufferCGBackend into the same
+ file and do some light cleanup.
+
+ - Function renamed to covert convertImagePixels to convey that it is
+ doing more than copying.
+ - Add PixelBufferConversionView/ConstPixelBufferConversionView structs
+ to hold parameters for the conversions, including a ColorSpace member
+ that is not yet used but will be shortly.
+ - Uses constexpr conditionals in unaccelerated cases to hoist branch
+ checking for pixel format conversion requirements outside the main
+ loop.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ Add new files.
+
+ * platform/graphics/PixelBufferConversion.cpp: Added.
+ (WebCore::makeVImageBuffer):
+ (WebCore::convertImagePixelsAccelerated):
+ (WebCore::convertSinglePixelPremultipliedToPremultiplied):
+ (WebCore::convertSinglePixelPremultipliedToUnpremultiplied):
+ (WebCore::convertSinglePixelUnpremultipliedToPremultiplied):
+ (WebCore::convertSinglePixelUnpremultipliedToUnpremultiplied):
+ (WebCore::convertFunctor):
+ (WebCore::convertImagePixels):
+ * platform/graphics/PixelBufferConversion.h: Added.
+ Move existing copyImagePixels implementations here.
+
+ * platform/graphics/ImageBufferBackend.cpp:
+ (WebCore::ImageBufferBackend::toBGRAData const):
+ (WebCore::ImageBufferBackend::getPixelBuffer const):
+ (WebCore::ImageBufferBackend::putPixelBuffer):
+ (WebCore::copyPremultipliedToPremultiplied): Deleted.
+ (WebCore::copyPremultipliedToUnpremultiplied): Deleted.
+ (WebCore::copyUnpremultipliedToPremultiplied): Deleted.
+ (WebCore::copyUnpremultipliedToUnpremultiplied): Deleted.
+ (WebCore::copyFunctor): Deleted.
+ (WebCore::ImageBufferBackend::copyImagePixels const): Deleted.
+ * platform/graphics/ImageBufferBackend.h:
+ * platform/graphics/cg/ImageBufferCGBackend.cpp:
+ (WebCore::makeVImageBuffer): Deleted.
+ (WebCore::copyImagePixelsAccelerated): Deleted.
+ (WebCore::ImageBufferCGBackend::copyImagePixels const): Deleted.
+ * platform/graphics/cg/ImageBufferCGBackend.h:
+ Remove existing copyImagePixels() implementation and call new
+ convertImagePixels() instead.
+
+ * platform/graphics/filters/FilterEffect.cpp:
+ (WebCore::FilterEffect::copyUnmultipliedResult):
+ (WebCore::FilterEffect::copyPremultipliedResult):
+ (WebCore::FilterEffect::createUnmultipliedImageResult):
+ (WebCore::FilterEffect::createPremultipliedImageResult):
+ Fix pixel format for the PixelBuffers to match existing behaviors.
+ These are not being used at the moment but will in the future
+ and new assert in putPixelBuffer caught these being incorrect.
+
2021-05-12 Commit Queue <commit-qu...@webkit.org>
Unreviewed, reverting r277320 and r277329.
Modified: trunk/Source/WebCore/Sources.txt (277368 => 277369)
--- trunk/Source/WebCore/Sources.txt 2021-05-12 14:33:51 UTC (rev 277368)
+++ trunk/Source/WebCore/Sources.txt 2021-05-12 14:51:31 UTC (rev 277369)
@@ -2013,6 +2013,7 @@
platform/graphics/PathUtilities.cpp
platform/graphics/Pattern.cpp
platform/graphics/PixelBuffer.cpp
+platform/graphics/PixelBufferConversion.cpp
platform/graphics/PlatformTimeRanges.cpp
platform/graphics/Region.cpp
platform/graphics/RemoteGraphicsContextGLProxyBase.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (277368 => 277369)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-05-12 14:33:51 UTC (rev 277368)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-05-12 14:51:31 UTC (rev 277369)
@@ -14092,6 +14092,8 @@
BC06F24C06D18A7E004A6FA3 /* XSLTProcessor.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = XSLTProcessor.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
BC06F24D06D18A7E004A6FA3 /* XSLTProcessorLibxslt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XSLTProcessorLibxslt.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
BC073BA90C399B1F000F5979 /* FloatConversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FloatConversion.h; sourceTree = "<group>"; };
+ BC0CA74C264AED0A004FDC62 /* PixelBufferConversion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PixelBufferConversion.h; sourceTree = "<group>"; };
+ BC0CA74D264AED0A004FDC62 /* PixelBufferConversion.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PixelBufferConversion.cpp; sourceTree = "<group>"; };
BC10137B25C3624B00DC773C /* ColorModels.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorModels.h; sourceTree = "<group>"; };
BC10137E25C3631600DC773C /* ColorTransferFunctions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorTransferFunctions.h; sourceTree = "<group>"; };
BC124EE40C2641CD009E2349 /* BarProp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BarProp.cpp; sourceTree = "<group>"; };
@@ -27053,6 +27055,8 @@
A8FA6E5B0E4CFDED00D5CF49 /* Pattern.h */,
BC4839BB2646181A00A28B62 /* PixelBuffer.cpp */,
BC4839BA2646181A00A28B62 /* PixelBuffer.h */,
+ BC0CA74D264AED0A004FDC62 /* PixelBufferConversion.cpp */,
+ BC0CA74C264AED0A004FDC62 /* PixelBufferConversion.h */,
BCA55912263DBD79007F19B3 /* PixelFormat.h */,
726D56E1253AE0430002EF90 /* PlatformImage.h */,
72BAC3A623E17328008D741C /* PlatformImageBuffer.h */,
Modified: trunk/Source/WebCore/platform/graphics/ImageBufferBackend.cpp (277368 => 277369)
--- trunk/Source/WebCore/platform/graphics/ImageBufferBackend.cpp 2021-05-12 14:33:51 UTC (rev 277368)
+++ trunk/Source/WebCore/platform/graphics/ImageBufferBackend.cpp 2021-05-12 14:51:31 UTC (rev 277369)
@@ -28,6 +28,7 @@
#include "Image.h"
#include "PixelBuffer.h"
+#include "PixelBufferConversion.h"
namespace WebCore {
@@ -93,141 +94,33 @@
Vector<uint8_t> ImageBufferBackend::toBGRAData(void* data) const
{
Vector<uint8_t> result(4 * logicalSize().area().unsafeGet());
- size_t destinationBytesPerRow = logicalSize().width() * 4;
- size_t sourceBytesPerRow = bytesPerRow();
- uint8_t* sourceRows = reinterpret_cast<uint8_t*>(data);
+ ConstPixelBufferConversionView source;
+ source.alphaFormat = AlphaPremultiplication::Premultiplied;
+ source.colorSpace = DestinationColorSpace::SRGB;
+ source.pixelFormat = pixelFormat();
+ source.bytesPerRow = bytesPerRow();
+ source.rows = reinterpret_cast<const uint8_t*>(data);
+
+ PixelBufferConversionView destination;
+ destination.alphaFormat = AlphaPremultiplication::Unpremultiplied;
+ destination.colorSpace = DestinationColorSpace::SRGB;
+ destination.pixelFormat = PixelFormat::BGRA8;
+ destination.bytesPerRow = logicalSize().width() * 4;
+ destination.rows = result.data();
- copyImagePixels(
- AlphaPremultiplication::Premultiplied, pixelFormat(), sourceBytesPerRow, sourceRows,
- AlphaPremultiplication::Unpremultiplied, PixelFormat::BGRA8, destinationBytesPerRow, result.data(), logicalSize());
+ convertImagePixels(source, destination, logicalSize());
return result;
}
-static inline void copyPremultipliedToPremultiplied(PixelFormat sourcePixelFormat, const uint8_t* sourcePixel, PixelFormat destinationPixelFormat, uint8_t* destinationPixel)
-{
- uint8_t alpha = sourcePixel[3];
- if (!alpha) {
- reinterpret_cast<uint32_t*>(destinationPixel)[0] = 0;
- return;
- }
-
- if (sourcePixelFormat == destinationPixelFormat) {
- reinterpret_cast<uint32_t*>(destinationPixel)[0] = reinterpret_cast<const uint32_t*>(sourcePixel)[0];
- return;
- }
-
- // Swap pixel channels BGRA <-> RGBA.
- destinationPixel[0] = sourcePixel[2];
- destinationPixel[1] = sourcePixel[1];
- destinationPixel[2] = sourcePixel[0];
- destinationPixel[3] = sourcePixel[3];
-}
-
-static inline void copyPremultipliedToUnpremultiplied(PixelFormat sourcePixelFormat, const uint8_t* sourcePixel, PixelFormat destinationPixelFormat, uint8_t* destinationPixel)
-{
- uint8_t alpha = sourcePixel[3];
- if (!alpha || alpha == 255) {
- copyPremultipliedToPremultiplied(sourcePixelFormat, sourcePixel, destinationPixelFormat, destinationPixel);
- return;
- }
-
- if (sourcePixelFormat == destinationPixelFormat) {
- destinationPixel[0] = (sourcePixel[0] * 255) / alpha;
- destinationPixel[1] = (sourcePixel[1] * 255) / alpha;
- destinationPixel[2] = (sourcePixel[2] * 255) / alpha;
- destinationPixel[3] = alpha;
- return;
- }
-
- // Swap pixel channels BGRA <-> RGBA.
- destinationPixel[0] = (sourcePixel[2] * 255) / alpha;
- destinationPixel[1] = (sourcePixel[1] * 255) / alpha;
- destinationPixel[2] = (sourcePixel[0] * 255) / alpha;
- destinationPixel[3] = alpha;
-}
-
-static inline void copyUnpremultipliedToPremultiplied(PixelFormat sourcePixelFormat, const uint8_t* sourcePixel, PixelFormat destinationPixelFormat, uint8_t* destinationPixel)
-{
- uint8_t alpha = sourcePixel[3];
- if (!alpha || alpha == 255) {
- copyPremultipliedToPremultiplied(sourcePixelFormat, sourcePixel, destinationPixelFormat, destinationPixel);
- return;
- }
-
- if (sourcePixelFormat == destinationPixelFormat) {
- destinationPixel[0] = (sourcePixel[0] * alpha + 254) / 255;
- destinationPixel[1] = (sourcePixel[1] * alpha + 254) / 255;
- destinationPixel[2] = (sourcePixel[2] * alpha + 254) / 255;
- destinationPixel[3] = alpha;
- return;
- }
-
- // Swap pixel channels BGRA <-> RGBA.
- destinationPixel[0] = (sourcePixel[2] * alpha + 254) / 255;
- destinationPixel[1] = (sourcePixel[1] * alpha + 254) / 255;
- destinationPixel[2] = (sourcePixel[0] * alpha + 254) / 255;
- destinationPixel[3] = alpha;
-}
-
-static inline void copyUnpremultipliedToUnpremultiplied(PixelFormat sourcePixelFormat, const uint8_t* sourcePixel, PixelFormat destinationPixelFormat, uint8_t* destinationPixel)
-{
- if (sourcePixelFormat == destinationPixelFormat) {
- reinterpret_cast<uint32_t*>(destinationPixel)[0] = reinterpret_cast<const uint32_t*>(sourcePixel)[0];
- return;
- }
-
- // Swap pixel channels BGRA <-> RGBA.
- destinationPixel[0] = sourcePixel[2];
- destinationPixel[1] = sourcePixel[1];
- destinationPixel[2] = sourcePixel[0];
- destinationPixel[3] = sourcePixel[3];
-}
-
-template<void (*copyFunctor)(PixelFormat, const uint8_t*, PixelFormat, uint8_t*)>
-static inline void copyImagePixelsUnaccelerated(
- PixelFormat sourcePixelFormat, unsigned sourceBytesPerRow, uint8_t* sourceRows,
- PixelFormat destinationPixelFormat, unsigned destinationBytesPerRow, uint8_t* destinationRows, const IntSize& size)
-{
- size_t bytesPerRow = size.width() * 4;
- for (int y = 0; y < size.height(); ++y) {
- for (size_t x = 0; x < bytesPerRow; x += 4)
- copyFunctor(sourcePixelFormat, &sourceRows[x], destinationPixelFormat, &destinationRows[x]);
- sourceRows += sourceBytesPerRow;
- destinationRows += destinationBytesPerRow;
- }
-}
-
-void ImageBufferBackend::copyImagePixels(
- AlphaPremultiplication sourceAlphaFormat, PixelFormat sourcePixelFormat, unsigned sourceBytesPerRow, uint8_t* sourceRows,
- AlphaPremultiplication destinationAlphaFormat, PixelFormat destinationPixelFormat, unsigned destinationBytesPerRow, uint8_t* destinationRows, const IntSize& size) const
-{
- // We don't currently support getting or putting pixel data with deep color buffers.
- ASSERT(sourcePixelFormat == PixelFormat::RGBA8 || sourcePixelFormat == PixelFormat::BGRA8);
- ASSERT(destinationPixelFormat == PixelFormat::RGBA8 || destinationPixelFormat == PixelFormat::BGRA8);
-
- if (sourceAlphaFormat == destinationAlphaFormat) {
- if (sourceAlphaFormat == AlphaPremultiplication::Premultiplied)
- copyImagePixelsUnaccelerated<copyPremultipliedToPremultiplied>(sourcePixelFormat, sourceBytesPerRow, sourceRows, destinationPixelFormat, destinationBytesPerRow, destinationRows, size);
- else
- copyImagePixelsUnaccelerated<copyUnpremultipliedToUnpremultiplied>(sourcePixelFormat, sourceBytesPerRow, sourceRows, destinationPixelFormat, destinationBytesPerRow, destinationRows, size);
- return;
- }
-
- if (destinationAlphaFormat == AlphaPremultiplication::Unpremultiplied) {
- copyImagePixelsUnaccelerated<copyPremultipliedToUnpremultiplied>(sourcePixelFormat, sourceBytesPerRow, sourceRows, destinationPixelFormat, destinationBytesPerRow, destinationRows, size);
- return;
- }
-
- copyImagePixelsUnaccelerated<copyUnpremultipliedToPremultiplied>(sourcePixelFormat, sourceBytesPerRow, sourceRows, destinationPixelFormat, destinationBytesPerRow, destinationRows, size);
-}
-
Optional<PixelBuffer> ImageBufferBackend::getPixelBuffer(AlphaPremultiplication destinationAlphaFormat, const IntRect& sourceRect, void* data) const
{
auto sourceRectScaled = toBackendCoordinates(sourceRect);
- auto pixelBuffer = PixelBuffer::tryCreate(DestinationColorSpace::SRGB, PixelFormat::RGBA8, sourceRectScaled.size());
+ auto destinationPixelFormat = PixelFormat::RGBA8;
+
+ auto pixelBuffer = PixelBuffer::tryCreate(DestinationColorSpace::SRGB, destinationPixelFormat, sourceRectScaled.size());
if (!pixelBuffer)
return WTF::nullopt;
@@ -243,15 +136,27 @@
if (destinationRect.size() != sourceRectScaled.size())
pixelBuffer->data().zeroFill();
+ unsigned sourceBytesPerRow = bytesPerRow();
+ const uint8_t* sourceRows = reinterpret_cast<uint8_t*>(data) + sourceRectClipped.y() * sourceBytesPerRow + sourceRectClipped.x() * 4;
+
unsigned destinationBytesPerRow = 4 * sourceRectScaled.width();
uint8_t* destinationRows = pixelBuffer->data().data() + destinationRect.y() * destinationBytesPerRow + destinationRect.x() * 4;
- unsigned sourceBytesPerRow = bytesPerRow();
- uint8_t* sourceRows = reinterpret_cast<uint8_t*>(data) + sourceRectClipped.y() * sourceBytesPerRow + sourceRectClipped.x() * 4;
+ ConstPixelBufferConversionView source;
+ source.alphaFormat = AlphaPremultiplication::Premultiplied;
+ source.colorSpace = DestinationColorSpace::SRGB;
+ source.pixelFormat = pixelFormat();
+ source.bytesPerRow = sourceBytesPerRow;
+ source.rows = sourceRows;
+
+ PixelBufferConversionView destination;
+ destination.alphaFormat = destinationAlphaFormat;
+ destination.colorSpace = DestinationColorSpace::SRGB;
+ destination.pixelFormat = destinationPixelFormat;
+ destination.bytesPerRow = destinationBytesPerRow;
+ destination.rows = destinationRows;
- copyImagePixels(
- AlphaPremultiplication::Premultiplied, pixelFormat(), sourceBytesPerRow, sourceRows,
- destinationAlphaFormat, PixelFormat::RGBA8, destinationBytesPerRow, destinationRows, destinationRect.size());
+ convertImagePixels(source, destination, destinationRect.size());
return pixelBuffer;
}
@@ -258,6 +163,9 @@
void ImageBufferBackend::putPixelBuffer(AlphaPremultiplication sourceAlphaFormat, const PixelBuffer& pixelBuffer, const IntRect& sourceRect, const IntPoint& destinationPoint, AlphaPremultiplication destinationAlphaFormat, void* data)
{
+ // FIXME: Add support for non-RGBA8 pixel formats.
+ ASSERT(pixelBuffer.format() == PixelFormat::RGBA8);
+
auto sourceRectScaled = toBackendCoordinates(sourceRect);
auto destinationPointScaled = toBackendCoordinates(destinationPoint);
@@ -274,15 +182,27 @@
destinationRect.intersect(backendRect());
sourceRectClipped.setSize(destinationRect.size());
+ unsigned sourceBytesPerRow = 4 * pixelBuffer.size().width();
+ const uint8_t* sourceRows = pixelBuffer.data().data() + sourceRectClipped.y() * sourceBytesPerRow + sourceRectClipped.x() * 4;
+
unsigned destinationBytesPerRow = bytesPerRow();
uint8_t* destinationRows = reinterpret_cast<uint8_t*>(data) + destinationRect.y() * destinationBytesPerRow + destinationRect.x() * 4;
- unsigned sourceBytesPerRow = 4 * pixelBuffer.size().width();
- uint8_t* sourceRows = pixelBuffer.data().data() + sourceRectClipped.y() * sourceBytesPerRow + sourceRectClipped.x() * 4;
+ ConstPixelBufferConversionView source;
+ source.alphaFormat = sourceAlphaFormat;
+ source.colorSpace = DestinationColorSpace::SRGB;
+ source.pixelFormat = PixelFormat::RGBA8;
+ source.bytesPerRow = sourceBytesPerRow;
+ source.rows = sourceRows;
+
+ PixelBufferConversionView destination;
+ destination.alphaFormat = destinationAlphaFormat;
+ destination.colorSpace = DestinationColorSpace::SRGB;
+ destination.pixelFormat = pixelFormat();
+ destination.bytesPerRow = destinationBytesPerRow;
+ destination.rows = destinationRows;
- copyImagePixels(
- sourceAlphaFormat, PixelFormat::RGBA8, sourceBytesPerRow, sourceRows,
- destinationAlphaFormat, pixelFormat(), destinationBytesPerRow, destinationRows, destinationRect.size());
+ convertImagePixels(source, destination, destinationRect.size());
}
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/graphics/ImageBufferBackend.h (277368 => 277369)
--- trunk/Source/WebCore/platform/graphics/ImageBufferBackend.h 2021-05-12 14:33:51 UTC (rev 277368)
+++ trunk/Source/WebCore/platform/graphics/ImageBufferBackend.h 2021-05-12 14:51:31 UTC (rev 277369)
@@ -148,10 +148,6 @@
IntRect logicalRect() const { return IntRect(IntPoint::zero(), logicalSize()); };
IntRect backendRect() const { return IntRect(IntPoint::zero(), backendSize()); };
- WEBCORE_EXPORT virtual void copyImagePixels(
- AlphaPremultiplication srcAlphaFormat, PixelFormat srcPixelFormat, unsigned srcBytesPerRow, uint8_t* srcRows,
- AlphaPremultiplication destAlphaFormat, PixelFormat destPixelFormat, unsigned destBytesPerRow, uint8_t* destRows, const IntSize&) const;
-
WEBCORE_EXPORT Vector<uint8_t> toBGRAData(void* data) const;
WEBCORE_EXPORT Optional<PixelBuffer> getPixelBuffer(AlphaPremultiplication outputFormat, const IntRect& srcRect, void* data) const;
Added: trunk/Source/WebCore/platform/graphics/PixelBufferConversion.cpp (0 => 277369)
--- trunk/Source/WebCore/platform/graphics/PixelBufferConversion.cpp (rev 0)
+++ trunk/Source/WebCore/platform/graphics/PixelBufferConversion.cpp 2021-05-12 14:51:31 UTC (rev 277369)
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PixelBufferConversion.h"
+
+#include "AlphaPremultiplication.h"
+#include "ColorSpace.h"
+#include "IntSize.h"
+#include "PixelFormat.h"
+
+#if USE(ACCELERATE)
+#include <Accelerate/Accelerate.h>
+#endif
+
+namespace WebCore {
+
+#if USE(ACCELERATE)
+
+template<typename View> static inline vImage_Buffer makeVImageBuffer(const View& view, const IntSize& size)
+{
+ vImage_Buffer vImageBuffer;
+
+ vImageBuffer.height = static_cast<vImagePixelCount>(size.height());
+ vImageBuffer.width = static_cast<vImagePixelCount>(size.width());
+ vImageBuffer.rowBytes = view.bytesPerRow;
+ vImageBuffer.data = ""
+
+ return vImageBuffer;
+}
+
+static inline void convertImagePixelsAccelerated(const ConstPixelBufferConversionView& source, const PixelBufferConversionView& destination, const IntSize& destinationSize)
+{
+ auto sourceVImageBuffer = makeVImageBuffer(source, destinationSize);
+ auto destinationVImageBuffer = makeVImageBuffer(destination, destinationSize);
+
+ if (source.alphaFormat != destination.alphaFormat) {
+ if (destination.alphaFormat == AlphaPremultiplication::Unpremultiplied) {
+ if (source.pixelFormat == PixelFormat::RGBA8)
+ vImageUnpremultiplyData_RGBA8888(&sourceVImageBuffer, &destinationVImageBuffer, kvImageNoFlags);
+ else
+ vImageUnpremultiplyData_BGRA8888(&sourceVImageBuffer, &destinationVImageBuffer, kvImageNoFlags);
+ } else {
+ if (source.pixelFormat == PixelFormat::RGBA8)
+ vImagePremultiplyData_RGBA8888(&sourceVImageBuffer, &destinationVImageBuffer, kvImageNoFlags);
+ else
+ vImagePremultiplyData_BGRA8888(&sourceVImageBuffer, &destinationVImageBuffer, kvImageNoFlags);
+ }
+
+ sourceVImageBuffer = destinationVImageBuffer;
+ }
+
+ if (source.pixelFormat != destination.pixelFormat) {
+ // Swap pixel channels BGRA <-> RGBA.
+ const uint8_t map[4] = { 2, 1, 0, 3 };
+ vImagePermuteChannels_ARGB8888(&sourceVImageBuffer, &destinationVImageBuffer, map, kvImageNoFlags);
+ }
+}
+#endif
+
+enum class PixelFormatConversion { None, Permute };
+
+template<PixelFormatConversion pixelFormatConversion>
+static inline void convertSinglePixelPremultipliedToPremultiplied(const uint8_t* sourcePixel, uint8_t* destinationPixel)
+{
+ uint8_t alpha = sourcePixel[3];
+ if (!alpha) {
+ reinterpret_cast<uint32_t*>(destinationPixel)[0] = 0;
+ return;
+ }
+
+ if constexpr (pixelFormatConversion == PixelFormatConversion::None)
+ reinterpret_cast<uint32_t*>(destinationPixel)[0] = reinterpret_cast<const uint32_t*>(sourcePixel)[0];
+ else {
+ // Swap pixel channels BGRA <-> RGBA.
+ destinationPixel[0] = sourcePixel[2];
+ destinationPixel[1] = sourcePixel[1];
+ destinationPixel[2] = sourcePixel[0];
+ destinationPixel[3] = sourcePixel[3];
+ }
+}
+
+template<PixelFormatConversion pixelFormatConversion>
+static inline void convertSinglePixelPremultipliedToUnpremultiplied(const uint8_t* sourcePixel, uint8_t* destinationPixel)
+{
+ uint8_t alpha = sourcePixel[3];
+ if (!alpha || alpha == 255) {
+ convertSinglePixelPremultipliedToPremultiplied<pixelFormatConversion>(sourcePixel, destinationPixel);
+ return;
+ }
+
+ if constexpr (pixelFormatConversion == PixelFormatConversion::None) {
+ destinationPixel[0] = (sourcePixel[0] * 255) / alpha;
+ destinationPixel[1] = (sourcePixel[1] * 255) / alpha;
+ destinationPixel[2] = (sourcePixel[2] * 255) / alpha;
+ destinationPixel[3] = alpha;
+ } else {
+ // Swap pixel channels BGRA <-> RGBA.
+ destinationPixel[0] = (sourcePixel[2] * 255) / alpha;
+ destinationPixel[1] = (sourcePixel[1] * 255) / alpha;
+ destinationPixel[2] = (sourcePixel[0] * 255) / alpha;
+ destinationPixel[3] = alpha;
+ }
+}
+
+template<PixelFormatConversion pixelFormatConversion>
+static inline void convertSinglePixelUnpremultipliedToPremultiplied(const uint8_t* sourcePixel, uint8_t* destinationPixel)
+{
+ uint8_t alpha = sourcePixel[3];
+ if (!alpha || alpha == 255) {
+ convertSinglePixelPremultipliedToPremultiplied<pixelFormatConversion>(sourcePixel, destinationPixel);
+ return;
+ }
+
+ if constexpr (pixelFormatConversion == PixelFormatConversion::None) {
+ destinationPixel[0] = (sourcePixel[0] * alpha + 254) / 255;
+ destinationPixel[1] = (sourcePixel[1] * alpha + 254) / 255;
+ destinationPixel[2] = (sourcePixel[2] * alpha + 254) / 255;
+ destinationPixel[3] = alpha;
+ } else {
+ // Swap pixel channels BGRA <-> RGBA.
+ destinationPixel[0] = (sourcePixel[2] * alpha + 254) / 255;
+ destinationPixel[1] = (sourcePixel[1] * alpha + 254) / 255;
+ destinationPixel[2] = (sourcePixel[0] * alpha + 254) / 255;
+ destinationPixel[3] = alpha;
+ }
+}
+
+template<PixelFormatConversion pixelFormatConversion>
+static inline void convertSinglePixelUnpremultipliedToUnpremultiplied(const uint8_t* sourcePixel, uint8_t* destinationPixel)
+{
+ if constexpr (pixelFormatConversion == PixelFormatConversion::None)
+ reinterpret_cast<uint32_t*>(destinationPixel)[0] = reinterpret_cast<const uint32_t*>(sourcePixel)[0];
+ else {
+ // Swap pixel channels BGRA <-> RGBA.
+ destinationPixel[0] = sourcePixel[2];
+ destinationPixel[1] = sourcePixel[1];
+ destinationPixel[2] = sourcePixel[0];
+ destinationPixel[3] = sourcePixel[3];
+ }
+}
+
+template<void (*convertFunctor)(const uint8_t*, uint8_t*)>
+static inline void convertImagePixelsUnaccelerated(const ConstPixelBufferConversionView& source, const PixelBufferConversionView& destination, const IntSize& destinationSize)
+{
+ const uint8_t* sourceRows = source.rows;
+ uint8_t* destinationRows = destination.rows;
+
+ size_t bytesPerRow = destinationSize.width() * 4;
+ for (int y = 0; y < destinationSize.height(); ++y) {
+ for (size_t x = 0; x < bytesPerRow; x += 4)
+ convertFunctor(&sourceRows[x], &destinationRows[x]);
+ sourceRows += source.bytesPerRow;
+ destinationRows += destination.bytesPerRow;
+ }
+}
+
+void convertImagePixels(const ConstPixelBufferConversionView& source, const PixelBufferConversionView& destination, const IntSize& destinationSize)
+{
+ // We don't currently support converting pixel data with non-8-bit buffers.
+ ASSERT(source.pixelFormat == PixelFormat::RGBA8 || source.pixelFormat == PixelFormat::BGRA8);
+ ASSERT(destination.pixelFormat == PixelFormat::RGBA8 || destination.pixelFormat == PixelFormat::BGRA8);
+
+ // We don't currently support converting pixel data between different color spaces.
+ ASSERT(source.colorSpace == destination.colorSpace);
+
+#if USE(ACCELERATE)
+ if (source.alphaFormat == destination.alphaFormat && source.pixelFormat == destination.pixelFormat) {
+ // FIXME: Can thes both just use per-row memcpy?
+ if (source.alphaFormat == AlphaPremultiplication::Premultiplied)
+ convertImagePixelsUnaccelerated<convertSinglePixelPremultipliedToPremultiplied<PixelFormatConversion::None>>(source, destination, destinationSize);
+ else
+ convertImagePixelsUnaccelerated<convertSinglePixelUnpremultipliedToUnpremultiplied<PixelFormatConversion::None>>(source, destination, destinationSize);
+ } else
+ convertImagePixelsAccelerated(source, destination, destinationSize);
+#else
+ if (source.alphaFormat == destination.alphaFormat) {
+ if (source.pixelFormat == destination.pixelFormat) {
+ if (source.alphaFormat == AlphaPremultiplication::Premultiplied)
+ convertImagePixelsUnaccelerated<convertSinglePixelPremultipliedToPremultiplied<PixelFormatConversion::None>>(source, destination, destinationSize);
+ else
+ convertImagePixelsUnaccelerated<convertSinglePixelUnpremultipliedToUnpremultiplied<PixelFormatConversion::None>>(source, destination, destinationSize);
+ } else {
+ if (destination.alphaFormat == AlphaPremultiplication::Unpremultiplied)
+ convertImagePixelsUnaccelerated<convertSinglePixelPremultipliedToPremultiplied<PixelFormatConversion::Permute>>(source, destination, destinationSize);
+ else
+ convertImagePixelsUnaccelerated<convertSinglePixelUnpremultipliedToUnpremultiplied<PixelFormatConversion::Permute>>(source, destination, destinationSize);
+ }
+ } else {
+ if (source.pixelFormat == destination.pixelFormat) {
+ if (source.alphaFormat == AlphaPremultiplication::Premultiplied)
+ convertImagePixelsUnaccelerated<convertSinglePixelPremultipliedToUnpremultiplied<PixelFormatConversion::None>>(source, destination, destinationSize);
+ else
+ convertImagePixelsUnaccelerated<convertSinglePixelUnpremultipliedToPremultiplied<PixelFormatConversion::None>>(source, destination, destinationSize);
+ } else {
+ if (destination.alphaFormat == AlphaPremultiplication::Unpremultiplied)
+ convertImagePixelsUnaccelerated<convertSinglePixelPremultipliedToUnpremultiplied<PixelFormatConversion::Permute>>(source, destination, destinationSize);
+ else
+ convertImagePixelsUnaccelerated<convertSinglePixelUnpremultipliedToPremultiplied<PixelFormatConversion::Permute>>(source, destination, destinationSize);
+ }
+ }
+#endif
+}
+
+}
Added: trunk/Source/WebCore/platform/graphics/PixelBufferConversion.h (0 => 277369)
--- trunk/Source/WebCore/platform/graphics/PixelBufferConversion.h (rev 0)
+++ trunk/Source/WebCore/platform/graphics/PixelBufferConversion.h 2021-05-12 14:51:31 UTC (rev 277369)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+namespace WebCore {
+
+class IntSize;
+
+enum class AlphaPremultiplication : uint8_t;
+enum class DestinationColorSpace : uint8_t;
+enum class PixelFormat : uint8_t;
+
+struct PixelBufferConversionView {
+ AlphaPremultiplication alphaFormat;
+ DestinationColorSpace colorSpace;
+ PixelFormat pixelFormat;
+ unsigned bytesPerRow;
+ uint8_t* rows;
+};
+
+struct ConstPixelBufferConversionView {
+ AlphaPremultiplication alphaFormat;
+ DestinationColorSpace colorSpace;
+ PixelFormat pixelFormat;
+ unsigned bytesPerRow;
+ const uint8_t* rows;
+};
+
+void convertImagePixels(const ConstPixelBufferConversionView& source, const PixelBufferConversionView& destination, const IntSize&);
+
+}
Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.cpp (277368 => 277369)
--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.cpp 2021-05-12 14:33:51 UTC (rev 277368)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.cpp 2021-05-12 14:51:31 UTC (rev 277369)
@@ -35,10 +35,6 @@
#include "MIMETypeRegistry.h"
#include "PixelBuffer.h"
#include "RuntimeApplicationChecks.h"
-
-#if USE(ACCELERATE)
-#include <Accelerate/Accelerate.h>
-#endif
#include <CoreGraphics/CoreGraphics.h>
#include <pal/spi/cg/CoreGraphicsSPI.h>
@@ -250,73 +246,6 @@
return WTF::makeUnique<ThreadSafeImageBufferFlusherCG>(context().platformContext());
}
-#if USE(ACCELERATE)
-static inline vImage_Buffer makeVImageBuffer(unsigned bytesPerRow, uint8_t* rows, const IntSize& size)
-{
- vImage_Buffer vImageBuffer;
-
- vImageBuffer.height = static_cast<vImagePixelCount>(size.height());
- vImageBuffer.width = static_cast<vImagePixelCount>(size.width());
- vImageBuffer.rowBytes = bytesPerRow;
- vImageBuffer.data = ""
- return vImageBuffer;
-}
-
-static inline void copyImagePixelsAccelerated(
- AlphaPremultiplication srcAlphaFormat, PixelFormat srcPixelFormat, vImage_Buffer& src,
- AlphaPremultiplication destAlphaFormat, PixelFormat destPixelFormat, vImage_Buffer& dest)
-{
- if (srcAlphaFormat == destAlphaFormat) {
- ASSERT(srcPixelFormat != destPixelFormat);
- // The destination alpha format can be unpremultiplied in the
- // case of an ImageBitmap created from an ImageData with
- // premultiplyAlpha=="none".
-
- // Swap pixel channels BGRA <-> RGBA.
- const uint8_t map[4] = { 2, 1, 0, 3 };
- vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags);
- return;
- }
-
- if (destAlphaFormat == AlphaPremultiplication::Unpremultiplied) {
- if (srcPixelFormat == PixelFormat::RGBA8)
- vImageUnpremultiplyData_RGBA8888(&src, &dest, kvImageNoFlags);
- else
- vImageUnpremultiplyData_BGRA8888(&src, &dest, kvImageNoFlags);
- } else {
- if (srcPixelFormat == PixelFormat::RGBA8)
- vImagePremultiplyData_RGBA8888(&src, &dest, kvImageNoFlags);
- else
- vImagePremultiplyData_BGRA8888(&src, &dest, kvImageNoFlags);
- }
-
- if (srcPixelFormat != destPixelFormat) {
- // Swap pixel channels BGRA <-> RGBA.
- const uint8_t map[4] = { 2, 1, 0, 3 };
- vImagePermuteChannels_ARGB8888(&dest, &dest, map, kvImageNoFlags);
- }
-}
-
-void ImageBufferCGBackend::copyImagePixels(
- AlphaPremultiplication srcAlphaFormat, PixelFormat srcPixelFormat, unsigned srcBytesPerRow, uint8_t* srcRows,
- AlphaPremultiplication destAlphaFormat, PixelFormat destPixelFormat, unsigned destBytesPerRow, uint8_t* destRows, const IntSize& size) const
-{
- // We don't currently support getting or putting pixel data with deep color buffers.
- ASSERT(srcPixelFormat == PixelFormat::RGBA8 || srcPixelFormat == PixelFormat::BGRA8);
- ASSERT(destPixelFormat == PixelFormat::RGBA8 || destPixelFormat == PixelFormat::BGRA8);
-
- if (srcAlphaFormat == destAlphaFormat && srcPixelFormat == destPixelFormat) {
- ImageBufferBackend::copyImagePixels(srcAlphaFormat, srcPixelFormat, srcBytesPerRow, srcRows, destAlphaFormat, destPixelFormat, destBytesPerRow, destRows, size);
- return;
- }
-
- vImage_Buffer src = "" srcRows, size);
- vImage_Buffer dest = makeVImageBuffer(destBytesPerRow, destRows, size);
-
- copyImagePixelsAccelerated(srcAlphaFormat, srcPixelFormat, src, destAlphaFormat, destPixelFormat, dest);
-}
-#endif
-
} // namespace WebCore
#endif // USE(CG)
Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.h (277368 => 277369)
--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.h 2021-05-12 14:33:51 UTC (rev 277368)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.h 2021-05-12 14:51:31 UTC (rev 277369)
@@ -54,12 +54,6 @@
static RetainPtr<CGColorSpaceRef> contextColorSpace(const GraphicsContext&);
void setupContext() const;
virtual RetainPtr<CFDataRef> toCFData(const String& mimeType, Optional<double> quality, PreserveResolution) const;
-
-#if USE(ACCELERATE)
- void copyImagePixels(
- AlphaPremultiplication srcAlphaFormat, PixelFormat srcPixelFormat, unsigned srcBytesPerRow, uint8_t* srcRows,
- AlphaPremultiplication destAlphaFormat, PixelFormat destPixelFormat, unsigned destBytesPerRow, uint8_t* destRows, const IntSize&) const override;
-#endif
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp (277368 => 277369)
--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp 2021-05-12 14:33:51 UTC (rev 277368)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp 2021-05-12 14:51:31 UTC (rev 277369)
@@ -505,7 +505,7 @@
IntSize inputSize(m_absolutePaintRect.size());
ASSERT(!ImageBuffer::sizeNeedsClamping(inputSize));
inputSize.scale(m_filter.filterScale());
- m_unmultipliedImageResult = PixelBuffer::tryCreate(DestinationColorSpace::SRGB, PixelFormat::BGRA8, inputSize);
+ m_unmultipliedImageResult = PixelBuffer::tryCreate(DestinationColorSpace::SRGB, PixelFormat::RGBA8, inputSize);
if (!m_unmultipliedImageResult)
return;
copyUnpremultiplyingAlpha(m_premultipliedImageResult->data(), m_unmultipliedImageResult->data(), inputSize);
@@ -538,7 +538,7 @@
IntSize inputSize(m_absolutePaintRect.size());
ASSERT(!ImageBuffer::sizeNeedsClamping(inputSize));
inputSize.scale(m_filter.filterScale());
- m_premultipliedImageResult = PixelBuffer::tryCreate(DestinationColorSpace::SRGB, PixelFormat::BGRA8, inputSize);
+ m_premultipliedImageResult = PixelBuffer::tryCreate(DestinationColorSpace::SRGB, PixelFormat::RGBA8, inputSize);
if (!m_premultipliedImageResult)
return;
copyPremultiplyingAlpha(m_unmultipliedImageResult->data(), m_premultipliedImageResult->data(), inputSize);
@@ -580,7 +580,7 @@
IntSize resultSize(m_absolutePaintRect.size());
ASSERT(!ImageBuffer::sizeNeedsClamping(resultSize));
resultSize.scale(m_filter.filterScale());
- m_unmultipliedImageResult = PixelBuffer::tryCreate(DestinationColorSpace::SRGB, PixelFormat::BGRA8, resultSize);
+ m_unmultipliedImageResult = PixelBuffer::tryCreate(DestinationColorSpace::SRGB, PixelFormat::RGBA8, resultSize);
return m_unmultipliedImageResult;
}
@@ -598,7 +598,7 @@
IntSize resultSize(m_absolutePaintRect.size());
ASSERT(!ImageBuffer::sizeNeedsClamping(resultSize));
resultSize.scale(m_filter.filterScale());
- m_premultipliedImageResult = PixelBuffer::tryCreate(DestinationColorSpace::SRGB, PixelFormat::BGRA8, resultSize);
+ m_premultipliedImageResult = PixelBuffer::tryCreate(DestinationColorSpace::SRGB, PixelFormat::RGBA8, resultSize);
return m_premultipliedImageResult;
}