250 lines
11 KiB
Diff
250 lines
11 KiB
Diff
Original source: Jacek Piszczek <jacek.piszczek@runbox.com>
|
|
|
|
diff --git a/Source/WebCore/platform/graphics/PixelBufferConversion.cpp b/Source/WebCore/platform/graphics/PixelBufferConversion.cpp
|
|
index 9acf304d..618b7b26 100644
|
|
--- a/Source/WebCore/platform/graphics/PixelBufferConversion.cpp
|
|
+++ b/Source/WebCore/platform/graphics/PixelBufferConversion.cpp
|
|
@@ -140,9 +140,17 @@ static void convertImagePixelsAccelerated(const ConstPixelBufferConversionView&
|
|
enum class PixelFormatConversion { None, Permute };
|
|
|
|
template<PixelFormatConversion pixelFormatConversion>
|
|
+#if CPU(BIG_ENDIAN)
|
|
+static void convertSinglePixelPremultipliedToPremultiplied(PixelFormat sourcePixelFormat, const uint8_t* sourcePixel, PixelFormat destinationPixelFormat, uint8_t* destinationPixel)
|
|
+#else
|
|
static void convertSinglePixelPremultipliedToPremultiplied(const uint8_t* sourcePixel, uint8_t* destinationPixel)
|
|
+#endif
|
|
{
|
|
+#if CPU(BIG_ENDIAN)
|
|
+ uint8_t alpha = sourcePixel[sourcePixelFormat == PixelFormat::ARGB8 ? 0 : 3];
|
|
+#else
|
|
uint8_t alpha = sourcePixel[3];
|
|
+#endif
|
|
if (!alpha) {
|
|
reinterpret_cast<uint32_t*>(destinationPixel)[0] = 0;
|
|
return;
|
|
@@ -151,23 +158,81 @@ static void convertSinglePixelPremultipliedToPremultiplied(const uint8_t* source
|
|
if constexpr (pixelFormatConversion == PixelFormatConversion::None)
|
|
reinterpret_cast<uint32_t*>(destinationPixel)[0] = reinterpret_cast<const uint32_t*>(sourcePixel)[0];
|
|
else {
|
|
+#if CPU(BIG_ENDIAN)
|
|
+ // Swap pixel channels ARGB <-> RGBA.
|
|
+ if (destinationPixelFormat == PixelFormat::ARGB8)
|
|
+ {
|
|
+ destinationPixel[0] = sourcePixel[3];
|
|
+ destinationPixel[1] = sourcePixel[0];
|
|
+ destinationPixel[2] = sourcePixel[1];
|
|
+ destinationPixel[3] = sourcePixel[2];
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ destinationPixel[0] = sourcePixel[1];
|
|
+ destinationPixel[1] = sourcePixel[2];
|
|
+ destinationPixel[2] = sourcePixel[3];
|
|
+ destinationPixel[3] = sourcePixel[0];
|
|
+ }
|
|
+#else
|
|
// Swap pixel channels BGRA <-> RGBA.
|
|
destinationPixel[0] = sourcePixel[2];
|
|
destinationPixel[1] = sourcePixel[1];
|
|
destinationPixel[2] = sourcePixel[0];
|
|
destinationPixel[3] = sourcePixel[3];
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
template<PixelFormatConversion pixelFormatConversion>
|
|
+#if CPU(BIG_ENDIAN)
|
|
+static void convertSinglePixelPremultipliedToUnpremultiplied(PixelFormat sourcePixelFormat, const uint8_t* sourcePixel, PixelFormat destinationPixelFormat, uint8_t* destinationPixel)
|
|
+#else
|
|
static void convertSinglePixelPremultipliedToUnpremultiplied(const uint8_t* sourcePixel, uint8_t* destinationPixel)
|
|
+#endif
|
|
{
|
|
+#if CPU(BIG_ENDIAN)
|
|
+ uint8_t alpha = sourcePixel[sourcePixelFormat == PixelFormat::ARGB8 ? 0 : 3];
|
|
+#else
|
|
uint8_t alpha = sourcePixel[3];
|
|
+#endif
|
|
if (!alpha || alpha == 255) {
|
|
+#if CPU(BIG_ENDIAN)
|
|
+ convertSinglePixelPremultipliedToPremultiplied<pixelFormatConversion>(sourcePixelFormat, sourcePixel, destinationPixelFormat, destinationPixel);
|
|
+#else
|
|
convertSinglePixelPremultipliedToPremultiplied<pixelFormatConversion>(sourcePixel, destinationPixel);
|
|
+#endif
|
|
return;
|
|
}
|
|
|
|
+#if CPU(BIG_ENDIAN)
|
|
+ UNUSED_PARAM(destinationPixelFormat);
|
|
+ if constexpr (pixelFormatConversion == PixelFormatConversion::None) {
|
|
+ if (sourcePixelFormat == PixelFormat::ARGB8) {
|
|
+ destinationPixel[0] = alpha;
|
|
+ destinationPixel[1] = (sourcePixel[1] * 255) / alpha;
|
|
+ destinationPixel[2] = (sourcePixel[2] * 255) / alpha;
|
|
+ destinationPixel[3] = (sourcePixel[3] * 255) / alpha;
|
|
+ } else {
|
|
+ destinationPixel[0] = (sourcePixel[0] * 255) / alpha;
|
|
+ destinationPixel[1] = (sourcePixel[1] * 255) / alpha;
|
|
+ destinationPixel[2] = (sourcePixel[2] * 255) / alpha;
|
|
+ destinationPixel[3] = alpha;
|
|
+ }
|
|
+ } else {
|
|
+ if (sourcePixelFormat == PixelFormat::ARGB8) {
|
|
+ destinationPixel[0] = (sourcePixel[1] * 255) / alpha;
|
|
+ destinationPixel[1] = (sourcePixel[2] * 255) / alpha;
|
|
+ destinationPixel[2] = (sourcePixel[3] * 255) / alpha;
|
|
+ destinationPixel[3] = alpha;
|
|
+ } else {
|
|
+ destinationPixel[0] = alpha;
|
|
+ destinationPixel[1] = (sourcePixel[0] * 255) / alpha;
|
|
+ destinationPixel[2] = (sourcePixel[1] * 255) / alpha;
|
|
+ destinationPixel[3] = (sourcePixel[2] * 255) / alpha;
|
|
+ }
|
|
+ }
|
|
+#else
|
|
if constexpr (pixelFormatConversion == PixelFormatConversion::None) {
|
|
destinationPixel[0] = (sourcePixel[0] * 255) / alpha;
|
|
destinationPixel[1] = (sourcePixel[1] * 255) / alpha;
|
|
@@ -180,17 +245,58 @@ static void convertSinglePixelPremultipliedToUnpremultiplied(const uint8_t* sour
|
|
destinationPixel[2] = (sourcePixel[0] * 255) / alpha;
|
|
destinationPixel[3] = alpha;
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
template<PixelFormatConversion pixelFormatConversion>
|
|
+#if CPU(BIG_ENDIAN)
|
|
+static void convertSinglePixelUnpremultipliedToPremultiplied(PixelFormat sourcePixelFormat, const uint8_t* sourcePixel, PixelFormat destinationPixelFormat, uint8_t* destinationPixel)
|
|
+#else
|
|
static void convertSinglePixelUnpremultipliedToPremultiplied(const uint8_t* sourcePixel, uint8_t* destinationPixel)
|
|
+#endif
|
|
{
|
|
+#if CPU(BIG_ENDIAN)
|
|
+ uint8_t alpha = sourcePixel[sourcePixelFormat == PixelFormat::ARGB8 ? 0 : 3];
|
|
+#else
|
|
uint8_t alpha = sourcePixel[3];
|
|
+#endif
|
|
if (!alpha || alpha == 255) {
|
|
+#if CPU(BIG_ENDIAN)
|
|
+ convertSinglePixelPremultipliedToPremultiplied<pixelFormatConversion>(sourcePixelFormat, sourcePixel, destinationPixelFormat, destinationPixel);
|
|
+#else
|
|
convertSinglePixelPremultipliedToPremultiplied<pixelFormatConversion>(sourcePixel, destinationPixel);
|
|
+#endif
|
|
return;
|
|
}
|
|
|
|
+#if CPU(BIG_ENDIAN)
|
|
+ UNUSED_PARAM(destinationPixelFormat);
|
|
+ if constexpr (pixelFormatConversion == PixelFormatConversion::None) {
|
|
+ if (sourcePixelFormat == PixelFormat::ARGB8) {
|
|
+ destinationPixel[0] = alpha;
|
|
+ destinationPixel[1] = (sourcePixel[1] * alpha + 254) / 255;
|
|
+ destinationPixel[2] = (sourcePixel[2] * alpha + 254) / 255;
|
|
+ destinationPixel[3] = (sourcePixel[3] * alpha + 254) / 255;
|
|
+ } else {
|
|
+ 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 {
|
|
+ if (sourcePixelFormat == PixelFormat::ARGB8) {
|
|
+ destinationPixel[0] = (sourcePixel[1] * alpha + 254) / 255;
|
|
+ destinationPixel[1] = (sourcePixel[2] * alpha + 254) / 255;
|
|
+ destinationPixel[2] = (sourcePixel[3] * alpha + 254) / 255;
|
|
+ destinationPixel[3] = alpha;
|
|
+ } else {
|
|
+ destinationPixel[0] = alpha;
|
|
+ destinationPixel[1] = (sourcePixel[0] * alpha + 254) / 255;
|
|
+ destinationPixel[2] = (sourcePixel[1] * alpha + 254) / 255;
|
|
+ destinationPixel[3] = (sourcePixel[2] * alpha + 254) / 255;
|
|
+ }
|
|
+ }
|
|
+#else
|
|
if constexpr (pixelFormatConversion == PixelFormatConversion::None) {
|
|
destinationPixel[0] = (sourcePixel[0] * alpha + 254) / 255;
|
|
destinationPixel[1] = (sourcePixel[1] * alpha + 254) / 255;
|
|
@@ -203,23 +309,49 @@ static void convertSinglePixelUnpremultipliedToPremultiplied(const uint8_t* sour
|
|
destinationPixel[2] = (sourcePixel[0] * alpha + 254) / 255;
|
|
destinationPixel[3] = alpha;
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
template<PixelFormatConversion pixelFormatConversion>
|
|
+#if CPU(BIG_ENDIAN)
|
|
+static void convertSinglePixelUnpremultipliedToUnpremultiplied(PixelFormat sourcePixelFormat, const uint8_t* sourcePixel, PixelFormat destinationPixelFormat, uint8_t* destinationPixel)
|
|
+#else
|
|
static void convertSinglePixelUnpremultipliedToUnpremultiplied(const uint8_t* sourcePixel, uint8_t* destinationPixel)
|
|
+#endif
|
|
{
|
|
if constexpr (pixelFormatConversion == PixelFormatConversion::None)
|
|
reinterpret_cast<uint32_t*>(destinationPixel)[0] = reinterpret_cast<const uint32_t*>(sourcePixel)[0];
|
|
else {
|
|
+#if CPU(BIG_ENDIAN)
|
|
+ UNUSED_PARAM(sourcePixelFormat);
|
|
+ // Swap pixel channels ARGB <-> RGBA.
|
|
+ if (destinationPixelFormat == PixelFormat::ARGB8) {
|
|
+ destinationPixel[0] = sourcePixel[3];
|
|
+ destinationPixel[1] = sourcePixel[0];
|
|
+ destinationPixel[2] = sourcePixel[1];
|
|
+ destinationPixel[3] = sourcePixel[2];
|
|
+ }
|
|
+ else {
|
|
+ destinationPixel[0] = sourcePixel[1];
|
|
+ destinationPixel[1] = sourcePixel[2];
|
|
+ destinationPixel[2] = sourcePixel[3];
|
|
+ destinationPixel[3] = sourcePixel[0];
|
|
+ }
|
|
+#else
|
|
// Swap pixel channels BGRA <-> RGBA.
|
|
destinationPixel[0] = sourcePixel[2];
|
|
destinationPixel[1] = sourcePixel[1];
|
|
destinationPixel[2] = sourcePixel[0];
|
|
destinationPixel[3] = sourcePixel[3];
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
+#if CPU(BIG_ENDIAN)
|
|
+template<void (*convertFunctor)(PixelFormat, const uint8_t*, PixelFormat, uint8_t*)>
|
|
+#else
|
|
template<void (*convertFunctor)(const uint8_t*, uint8_t*)>
|
|
+#endif
|
|
static void convertImagePixelsUnaccelerated(const ConstPixelBufferConversionView& source, const PixelBufferConversionView& destination, const IntSize& destinationSize)
|
|
{
|
|
const uint8_t* sourceRows = source.rows;
|
|
@@ -228,7 +360,11 @@ static void convertImagePixelsUnaccelerated(const ConstPixelBufferConversionView
|
|
size_t bytesPerRow = destinationSize.width() * 4;
|
|
for (int y = 0; y < destinationSize.height(); ++y) {
|
|
for (size_t x = 0; x < bytesPerRow; x += 4)
|
|
+#if CPU(BIG_ENDIAN)
|
|
+ convertFunctor(source.format.pixelFormat, &sourceRows[x], destination.format.pixelFormat, &destinationRows[x]);
|
|
+#else
|
|
convertFunctor(&sourceRows[x], &destinationRows[x]);
|
|
+#endif
|
|
sourceRows += source.bytesPerRow;
|
|
destinationRows += destination.bytesPerRow;
|
|
}
|
|
@@ -237,6 +373,7 @@ static void convertImagePixelsUnaccelerated(const ConstPixelBufferConversionView
|
|
void convertImagePixels(const ConstPixelBufferConversionView& source, const PixelBufferConversionView& destination, const IntSize& destinationSize)
|
|
{
|
|
// We don't currently support converting pixel data with non-8-bit buffers.
|
|
+ // BGRA8 is actually ARGB8 on BIG_ENDIAN.
|
|
ASSERT(source.format.pixelFormat == PixelFormat::RGBA8 || source.format.pixelFormat == PixelFormat::BGRA8);
|
|
ASSERT(destination.format.pixelFormat == PixelFormat::RGBA8 || destination.format.pixelFormat == PixelFormat::BGRA8);
|
|
|
|
diff --git a/Source/WebCore/platform/graphics/PixelFormat.h b/Source/WebCore/platform/graphics/PixelFormat.h
|
|
index 1ca711b8..4a7168f8 100644
|
|
--- a/Source/WebCore/platform/graphics/PixelFormat.h
|
|
+++ b/Source/WebCore/platform/graphics/PixelFormat.h
|
|
@@ -33,6 +33,9 @@ namespace WebCore {
|
|
enum class PixelFormat : uint8_t {
|
|
RGBA8,
|
|
BGRA8,
|
|
+#if CPU(BIG_ENDIAN)
|
|
+ ARGB8 = BGRA8, // BGRA will actually be ARGB on BIG_ENDIAN
|
|
+#endif
|
|
RGB10,
|
|
RGB10A8,
|
|
};
|