summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qdrawhelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting/qdrawhelper.cpp')
-rw-r--r--src/gui/painting/qdrawhelper.cpp1093
1 files changed, 739 insertions, 354 deletions
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index bbeb9fd9ea..ac15d8f4f4 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -43,7 +43,7 @@
#include <qstylehints.h>
#include <qguiapplication.h>
#include <qatomic.h>
-#include <private/qcolorprofile_p.h>
+#include <private/qcolortrclut_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qpainter_p.h>
@@ -55,6 +55,7 @@
#endif
#include <private/qguiapplication_p.h>
#include <private/qrgba64_p.h>
+#include <qendian.h>
#include <qloggingcategory.h>
#include <qmath.h>
@@ -856,6 +857,44 @@ static const QRgba64 *QT_FASTCALL fetchGrayscale8ToRGB64(QRgba64 *buffer, const
return buffer;
}
+static void QT_FASTCALL convertGrayscale16ToRGB32(uint *buffer, int count, const QVector<QRgb> *)
+{
+ for (int i = 0; i < count; ++i) {
+ const uint x = qt_div_257(buffer[i]);
+ buffer[i] = qRgb(x, x, x);
+ }
+}
+
+static const uint *QT_FASTCALL fetchGrayscale16ToRGB32(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ const unsigned short *s = reinterpret_cast<const unsigned short *>(src) + index;
+ for (int i = 0; i < count; ++i) {
+ const uint x = qt_div_257(s[i]);
+ buffer[i] = qRgb(x, x, x);
+ }
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL convertGrayscale16ToRGBA64(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ const unsigned short *s = reinterpret_cast<const unsigned short *>(src);
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromRgba64(s[i], s[i], s[i], 65535);
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL fetchGrayscale16ToRGBA64(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ const unsigned short *s = reinterpret_cast<const unsigned short *>(src) + index;
+ for (int i = 0; i < count; ++i) {
+ buffer[i] = QRgba64::fromRgba64(s[i], s[i], s[i], 65535);
+ }
+ return buffer;
+}
+
static void QT_FASTCALL storeARGB32FromARGB32PM(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
{
@@ -1047,18 +1086,8 @@ static const QRgba64 *QT_FASTCALL fetchRGB32ToRGB64(QRgba64 *buffer, const uchar
static const QRgba64 *QT_FASTCALL convertARGB32ToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
-#ifdef __SSE2__
- qConvertARGB32PMToRGBA64PM_sse2<false, false>(buffer, src, count);
- for (int i = 0; i < count; ++i)
- buffer[i] = buffer[i].premultiplied();
-#elif defined(__ARM_NEON__)
- qConvertARGB32PMToRGBA64PM_neon<false, false>(buffer, src, count);
- for (int i = 0; i < count; ++i)
- buffer[i] = buffer[i].premultiplied();
-#else
for (int i = 0; i < count; ++i)
buffer[i] = QRgba64::fromArgb32(src[i]).premultiplied();
-#endif
return buffer;
}
@@ -1088,6 +1117,7 @@ static const QRgba64 *QT_FASTCALL fetchARGB32PMToRGBA64PM(QRgba64 *buffer, const
return convertARGB32PMToRGBA64PM(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr);
}
+#if QT_CONFIG(raster_64bit)
static void convertRGBA64ToRGBA64PM(QRgba64 *buffer, int count)
{
for (int i = 0; i < count; ++i)
@@ -1097,6 +1127,7 @@ static void convertRGBA64ToRGBA64PM(QRgba64 *buffer, int count)
static void convertRGBA64PMToRGBA64PM(QRgba64 *, int)
{
}
+#endif
static const QRgba64 *QT_FASTCALL fetchRGBA64ToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
@@ -1110,18 +1141,8 @@ static const QRgba64 *QT_FASTCALL fetchRGBA64ToRGBA64PM(QRgba64 *buffer, const u
static const QRgba64 *QT_FASTCALL convertRGBA8888ToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
-#ifdef __SSE2__
- qConvertARGB32PMToRGBA64PM_sse2<true, false>(buffer, src, count);
- for (int i = 0; i < count; ++i)
- buffer[i] = buffer[i].premultiplied();
-#elif defined(__ARM_NEON__)
- qConvertARGB32PMToRGBA64PM_neon<true, false>(buffer, src, count);
- for (int i = 0; i < count; ++i)
- buffer[i] = buffer[i].premultiplied();
-#else
for (int i = 0; i < count; ++i)
buffer[i] = QRgba64::fromArgb32(RGBA2ARGB(src[i])).premultiplied();
-#endif
return buffer;
}
@@ -1361,6 +1382,22 @@ static void QT_FASTCALL storeGrayscale8FromARGB32PM(uchar *dest, const uint *src
dest[index + i] = qGray(qUnpremultiply(src[i]));
}
+static void QT_FASTCALL storeGrayscale16FromRGB32(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ unsigned short *d = reinterpret_cast<unsigned short *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = qGray(src[i]) * 257;
+}
+
+static void QT_FASTCALL storeGrayscale16FromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ unsigned short *d = reinterpret_cast<unsigned short *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = qGray(qUnpremultiply(src[i])) * 257;
+}
+
static const uint *QT_FASTCALL fetchRGB64ToRGB32(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
{
@@ -1487,7 +1524,11 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
{ true, true, QPixelLayout::BPP64, nullptr,
convertPassThrough, nullptr,
fetchRGB64ToRGB32, fetchPassThrough64,
- storeRGB64FromRGB32, storeRGB64FromRGB32 } // Format_RGBA64_Premultiplied
+ storeRGB64FromRGB32, storeRGB64FromRGB32 }, // Format_RGBA64_Premultiplied
+ { false, false, QPixelLayout::BPP16, nullptr,
+ convertGrayscale16ToRGB32, convertGrayscale16ToRGBA64,
+ fetchGrayscale16ToRGB32, fetchGrayscale16ToRGBA64,
+ storeGrayscale16FromARGB32PM, storeGrayscale16FromRGB32 } // Format_Grayscale16
};
Q_STATIC_ASSERT(sizeof(qPixelLayouts) / sizeof(*qPixelLayouts) == QImage::NImageFormats);
@@ -1563,6 +1604,16 @@ static void QT_FASTCALL storeRGBA64PMFromRGBA64PM(uchar *dest, const QRgba64 *sr
memcpy(d, src, count * sizeof(QRgba64));
}
+static void QT_FASTCALL storeGray16FromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ quint16 *d = reinterpret_cast<quint16*>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ QRgba64 s = src[i].unpremultiplied();
+ d[i] = qGray(s.red(), s.green(), s.blue());
+ }
+}
+
ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = {
nullptr,
nullptr,
@@ -1591,7 +1642,8 @@ ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = {
storeGenericFromRGBA64PM<QImage::Format_Grayscale8>,
storeRGBX64FromRGBA64PM,
storeRGBA64FromRGBA64PM,
- storeRGBA64PMFromRGBA64PM
+ storeRGBA64PMFromRGBA64PM,
+ storeGray16FromRGBA64PM
};
/*
@@ -1649,22 +1701,6 @@ static uint *QT_FASTCALL destFetchUndefined(uint *buffer, QRasterBuffer *, int,
return buffer;
}
-static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
-{
- const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
- return const_cast<QRgba64 *>(layout->fetchToRGBA64PM(buffer, rasterBuffer->scanLine(y), x, length, nullptr, nullptr));
-}
-
-static QRgba64 * QT_FASTCALL destFetchRGB64(QRgba64 *, QRasterBuffer *rasterBuffer, int x, int y, int)
-{
- return (QRgba64 *)rasterBuffer->scanLine(y) + x;
-}
-
-static QRgba64 * QT_FASTCALL destFetch64Undefined(QRgba64 *buffer, QRasterBuffer *, int, int, int)
-{
- return buffer;
-}
-
static DestFetchProc destFetchProc[QImage::NImageFormats] =
{
0, // Format_Invalid
@@ -1695,8 +1731,26 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] =
destFetch, // Format_RGBX64
destFetch, // Format_RGBA64
destFetch, // Format_RGBA64_Premultiplied
+ destFetch, // Format_Grayscale16
};
+#if QT_CONFIG(raster_64bit)
+static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
+{
+ const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
+ return const_cast<QRgba64 *>(layout->fetchToRGBA64PM(buffer, rasterBuffer->scanLine(y), x, length, nullptr, nullptr));
+}
+
+static QRgba64 * QT_FASTCALL destFetchRGB64(QRgba64 *, QRasterBuffer *rasterBuffer, int x, int y, int)
+{
+ return (QRgba64 *)rasterBuffer->scanLine(y) + x;
+}
+
+static QRgba64 * QT_FASTCALL destFetch64Undefined(QRgba64 *buffer, QRasterBuffer *, int, int, int)
+{
+ return buffer;
+}
+
static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
{
0, // Format_Invalid
@@ -1727,7 +1781,9 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
destFetchRGB64, // Format_RGBX64
destFetch64, // Format_RGBA64
destFetchRGB64, // Format_RGBA64_Premultiplied
+ destFetch64, // Format_Grayscale16
};
+#endif
/*
Returns the color in the mono destination color table
@@ -1835,21 +1891,6 @@ static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, con
store(dest, buffer, x, length, nullptr, nullptr);
}
-static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
-{
- auto store = qStoreFromRGBA64PM[rasterBuffer->format];
- uchar *dest = rasterBuffer->scanLine(y);
- store(dest, buffer, x, length, nullptr, nullptr);
-}
-
-static void QT_FASTCALL destStore64RGBA64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
-{
- QRgba64 *dest = reinterpret_cast<QRgba64*>(rasterBuffer->scanLine(y)) + x;
- for (int i = 0; i < length; ++i) {
- dest[i] = buffer[i].unpremultiplied();
- }
-}
-
static DestStoreProc destStoreProc[QImage::NImageFormats] =
{
0, // Format_Invalid
@@ -1880,8 +1921,25 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] =
destStore, // Format_RGBX64
destStore, // Format_RGBA64
destStore, // Format_RGBA64_Premultiplied
+ destStore, // Format_Grayscale16
};
+#if QT_CONFIG(raster_64bit)
+static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+ auto store = qStoreFromRGBA64PM[rasterBuffer->format];
+ uchar *dest = rasterBuffer->scanLine(y);
+ store(dest, buffer, x, length, nullptr, nullptr);
+}
+
+static void QT_FASTCALL destStore64RGBA64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+ QRgba64 *dest = reinterpret_cast<QRgba64*>(rasterBuffer->scanLine(y)) + x;
+ for (int i = 0; i < length; ++i) {
+ dest[i] = buffer[i].unpremultiplied();
+ }
+}
+
static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
{
0, // Format_Invalid
@@ -1911,8 +1969,10 @@ static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
destStore64, // Format_Grayscale8
0, // Format_RGBX64
destStore64RGBA64, // Format_RGBA64
- 0 // Format_RGBA64_Premultiplied
+ 0, // Format_RGBA64_Premultiplied
+ destStore64, // Format_Grayscale16
};
+#endif
/*
Source fetches
@@ -1963,6 +2023,7 @@ static const uint *QT_FASTCALL fetchUntransformedRGB16(uint *buffer, const Opera
return buffer;
}
+#if QT_CONFIG(raster_64bit)
static const QRgba64 *QT_FASTCALL fetchUntransformed64(QRgba64 *buffer, const Operator *,
const QSpanData *data, int y, int x, int length)
{
@@ -1976,6 +2037,7 @@ static const QRgba64 *QT_FASTCALL fetchUntransformedRGBA64PM(QRgba64 *, const Op
const uchar *scanLine = data->texture.scanLine(y);
return reinterpret_cast<const QRgba64 *>(scanLine) + x;
}
+#endif
template<TextureBlendType blendType>
inline void fetchTransformed_pixelBounds(int max, int l1, int l2, int &v)
@@ -2166,6 +2228,7 @@ static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *,
return buffer;
}
+#if QT_CONFIG(raster_64bit)
template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */
static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Operator *, const QSpanData *data,
int y, int x, int length)
@@ -2186,6 +2249,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper
convertRGBA64ToRGBA64PM(buffer, length);
return buffer;
}
+#endif
/** \internal
interpolate 4 argb pixels with the distx and disty factor.
@@ -3487,6 +3551,7 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
return buffer;
}
+#if QT_CONFIG(raster_64bit)
template<TextureBlendType blendType>
static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint32(QRgba64 *buffer, const QSpanData *data,
int y, int x, int length)
@@ -3500,8 +3565,8 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint32(QRgba64 *buf
uint sbuf1[BufferSize];
uint sbuf2[BufferSize];
- QRgba64 buf1[BufferSize];
- QRgba64 buf2[BufferSize];
+ alignas(8) QRgba64 buf1[BufferSize];
+ alignas(8) QRgba64 buf2[BufferSize];
QRgba64 *end = buffer + length;
QRgba64 *b = buffer;
@@ -3658,8 +3723,8 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint64(QRgba64 *buf
const qreal cx = x + qreal(0.5);
const qreal cy = y + qreal(0.5);
- QRgba64 buf1[BufferSize];
- QRgba64 buf2[BufferSize];
+ alignas(8) QRgba64 buf1[BufferSize];
+ alignas(8) QRgba64 buf2[BufferSize];
QRgba64 *end = buffer + length;
QRgba64 *b = buffer;
@@ -3807,6 +3872,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
return fetchTransformedBilinear64_uint64<blendType>(buffer, data, y, x, length);
return fetchTransformedBilinear64_uint32<blendType>(buffer, data, y, x, length);
}
+#endif
// FetchUntransformed can have more specialized methods added depending on SIMD features.
static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = {
@@ -3838,6 +3904,7 @@ static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = {
fetchUntransformed, // RGBX64
fetchUntransformed, // RGBA64
fetchUntransformed, // RGBA64_Premultiplied
+ fetchUntransformed, // Grayscale16
};
static const SourceFetchProc sourceFetchGeneric[NBlendTypes] = {
@@ -3876,6 +3943,20 @@ static SourceFetchProc sourceFetchAny32[NBlendTypes] = {
fetchTransformedBilinear<BlendTransformedBilinearTiled, QPixelLayout::BPP32> // TransformedBilinearTiled
};
+static inline SourceFetchProc getSourceFetch(TextureBlendType blendType, QImage::Format format)
+{
+ if (format == QImage::Format_RGB32 || format == QImage::Format_ARGB32_Premultiplied)
+ return sourceFetchARGB32PM[blendType];
+ if (blendType == BlendUntransformed || blendType == BlendTiled)
+ return sourceFetchUntransformed[format];
+ if (qPixelLayouts[format].bpp == QPixelLayout::BPP16)
+ return sourceFetchAny16[blendType];
+ if (qPixelLayouts[format].bpp == QPixelLayout::BPP32)
+ return sourceFetchAny32[blendType];
+ return sourceFetchGeneric[blendType];
+}
+
+#if QT_CONFIG(raster_64bit)
static const SourceFetchProc64 sourceFetchGeneric64[NBlendTypes] = {
fetchUntransformed64, // Untransformed
fetchUntransformed64, // Tiled
@@ -3894,25 +3975,13 @@ static const SourceFetchProc64 sourceFetchRGBA64PM[NBlendTypes] = {
fetchTransformedBilinear64<BlendTransformedBilinearTiled> // BilinearTiled
};
-static inline SourceFetchProc getSourceFetch(TextureBlendType blendType, QImage::Format format)
-{
- if (format == QImage::Format_RGB32 || format == QImage::Format_ARGB32_Premultiplied)
- return sourceFetchARGB32PM[blendType];
- if (blendType == BlendUntransformed || blendType == BlendTiled)
- return sourceFetchUntransformed[format];
- if (qPixelLayouts[format].bpp == QPixelLayout::BPP16)
- return sourceFetchAny16[blendType];
- if (qPixelLayouts[format].bpp == QPixelLayout::BPP32)
- return sourceFetchAny32[blendType];
- return sourceFetchGeneric[blendType];
-}
-
static inline SourceFetchProc64 getSourceFetch64(TextureBlendType blendType, QImage::Format format)
{
if (format == QImage::Format_RGBX64 || format == QImage::Format_RGBA64_Premultiplied)
return sourceFetchRGBA64PM[blendType];
return sourceFetchGeneric64[blendType];
}
+#endif
#define FIXPT_BITS 8
@@ -3924,11 +3993,13 @@ static uint qt_gradient_pixel_fixed(const QGradientData *data, int fixed_pos)
return data->colorTable32[qt_gradient_clamp(data, ipos)];
}
+#if QT_CONFIG(raster_64bit)
static const QRgba64& qt_gradient_pixel64_fixed(const QGradientData *data, int fixed_pos)
{
int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS;
return data->colorTable64[qt_gradient_clamp(data, ipos)];
}
+#endif
static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const QSpanData *data)
{
@@ -3962,6 +4033,7 @@ public:
}
};
+#if QT_CONFIG(raster_64bit)
class GradientBase64
{
public:
@@ -3980,6 +4052,7 @@ public:
qt_memfill64((quint64*)buffer, fill, length);
}
};
+#endif
template<class GradientBase, typename BlendType>
static inline const BlendType * QT_FASTCALL qt_fetch_linear_gradient_template(
@@ -4057,11 +4130,13 @@ static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Ope
return qt_fetch_linear_gradient_template<GradientBase32, uint>(buffer, op, data, y, x, length);
}
+#if QT_CONFIG(raster_64bit)
static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data,
int y, int x, int length)
{
return qt_fetch_linear_gradient_template<GradientBase64, QRgba64>(buffer, op, data, y, x, length);
}
+#endif
static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data)
{
@@ -4123,11 +4198,13 @@ const uint * QT_FASTCALL qt_fetch_radial_gradient_plain(uint *buffer, const Oper
static SourceFetchProc qt_fetch_radial_gradient = qt_fetch_radial_gradient_plain;
+#if QT_CONFIG(raster_64bit)
const QRgba64 * QT_FASTCALL qt_fetch_radial_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data,
int y, int x, int length)
{
return qt_fetch_radial_gradient_template<RadialFetchPlain<GradientBase64>, QRgba64>(buffer, op, data, y, x, length);
}
+#endif
template <class GradientBase, typename BlendType>
static inline const BlendType * QT_FASTCALL qt_fetch_conical_gradient_template(
@@ -4186,23 +4263,29 @@ static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Op
return qt_fetch_conical_gradient_template<GradientBase32, uint>(buffer, data, y, x, length);
}
+#if QT_CONFIG(raster_64bit)
static const QRgba64 * QT_FASTCALL qt_fetch_conical_gradient_rgb64(QRgba64 *buffer, const Operator *, const QSpanData *data,
int y, int x, int length)
{
return qt_fetch_conical_gradient_template<GradientBase64, QRgba64>(buffer, data, y, x, length);
}
+#endif
extern CompositionFunctionSolid qt_functionForModeSolid_C[];
extern CompositionFunctionSolid64 qt_functionForModeSolid64_C[];
static const CompositionFunctionSolid *functionForModeSolid = qt_functionForModeSolid_C;
+#if QT_CONFIG(raster_64bit)
static const CompositionFunctionSolid64 *functionForModeSolid64 = qt_functionForModeSolid64_C;
+#endif
extern CompositionFunction qt_functionForMode_C[];
extern CompositionFunction64 qt_functionForMode64_C[];
static const CompositionFunction *functionForMode = qt_functionForMode_C;
+#if QT_CONFIG(raster_64bit)
static const CompositionFunction64 *functionForMode64 = qt_functionForMode64_C;
+#endif
static TextureBlendType getBlendType(const QSpanData *data)
{
@@ -4232,43 +4315,60 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
switch(data->type) {
case QSpanData::Solid:
- solidSource = data->solid.color.isOpaque();
+ solidSource = data->solidColor.isOpaque();
op.srcFetch = 0;
+#if QT_CONFIG(raster_64bit)
op.srcFetch64 = 0;
+#endif
break;
case QSpanData::LinearGradient:
solidSource = !data->gradient.alphaColor;
getLinearGradientValues(&op.linear, data);
op.srcFetch = qt_fetch_linear_gradient;
+#if QT_CONFIG(raster_64bit)
op.srcFetch64 = qt_fetch_linear_gradient_rgb64;
+#endif
break;
case QSpanData::RadialGradient:
solidSource = !data->gradient.alphaColor;
getRadialGradientValues(&op.radial, data);
op.srcFetch = qt_fetch_radial_gradient;
+#if QT_CONFIG(raster_64bit)
op.srcFetch64 = qt_fetch_radial_gradient_rgb64;
+#endif
break;
case QSpanData::ConicalGradient:
solidSource = !data->gradient.alphaColor;
op.srcFetch = qt_fetch_conical_gradient;
+#if QT_CONFIG(raster_64bit)
op.srcFetch64 = qt_fetch_conical_gradient_rgb64;
+#endif
break;
case QSpanData::Texture:
solidSource = !data->texture.hasAlpha;
op.srcFetch = getSourceFetch(getBlendType(data), data->texture.format);
+#if QT_CONFIG(raster_64bit)
op.srcFetch64 = getSourceFetch64(getBlendType(data), data->texture.format);;
+#endif
break;
default:
Q_UNREACHABLE();
break;
}
+#if !QT_CONFIG(raster_64bit)
+ op.srcFetch64 = 0;
+#endif
op.mode = data->rasterBuffer->compositionMode;
if (op.mode == QPainter::CompositionMode_SourceOver && solidSource)
op.mode = QPainter::CompositionMode_Source;
op.destFetch = destFetchProc[data->rasterBuffer->format];
+#if QT_CONFIG(raster_64bit)
op.destFetch64 = destFetchProc64[data->rasterBuffer->format];
+#else
+ op.destFetch64 = 0;
+#endif
if (op.mode == QPainter::CompositionMode_Source &&
(data->type != QSpanData::Texture || data->texture.const_alpha == 256)) {
const QSpan *lastSpan = spans + spanCount;
@@ -4280,44 +4380,90 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
}
++spans;
}
- if (!alphaSpans) {
+ if (!alphaSpans && spanCount > 0) {
// If all spans are opaque we do not need to fetch dest.
// But don't clear passthrough destFetch as they are just as fast and save destStore.
if (op.destFetch != destFetchARGB32P)
op.destFetch = destFetchUndefined;
+#if QT_CONFIG(raster_64bit)
if (op.destFetch64 != destFetchRGB64)
op.destFetch64 = destFetch64Undefined;
+#endif
}
}
op.destStore = destStoreProc[data->rasterBuffer->format];
- op.destStore64 = destStoreProc64[data->rasterBuffer->format];
-
op.funcSolid = functionForModeSolid[op.mode];
- op.funcSolid64 = functionForModeSolid64[op.mode];
op.func = functionForMode[op.mode];
+#if QT_CONFIG(raster_64bit)
+ op.destStore64 = destStoreProc64[data->rasterBuffer->format];
+ op.funcSolid64 = functionForModeSolid64[op.mode];
op.func64 = functionForMode64[op.mode];
+#else
+ op.destStore64 = 0;
+ op.funcSolid64 = 0;
+ op.func64 = 0;
+#endif
return op;
}
+static void spanfill_from_first(QRasterBuffer *rasterBuffer, QPixelLayout::BPP bpp, int x, int y, int length)
+{
+ switch (bpp) {
+ case QPixelLayout::BPP64: {
+ quint64 *dest = reinterpret_cast<quint64 *>(rasterBuffer->scanLine(y)) + x;
+ qt_memfill_template(dest + 1, dest[0], length - 1);
+ break;
+ }
+ case QPixelLayout::BPP32: {
+ quint32 *dest = reinterpret_cast<quint32 *>(rasterBuffer->scanLine(y)) + x;
+ qt_memfill_template(dest + 1, dest[0], length - 1);
+ break;
+ }
+ case QPixelLayout::BPP24: {
+ quint24 *dest = reinterpret_cast<quint24 *>(rasterBuffer->scanLine(y)) + x;
+ qt_memfill_template(dest + 1, dest[0], length - 1);
+ break;
+ }
+ case QPixelLayout::BPP16: {
+ quint16 *dest = reinterpret_cast<quint16 *>(rasterBuffer->scanLine(y)) + x;
+ qt_memfill_template(dest + 1, dest[0], length - 1);
+ break;
+ }
+ case QPixelLayout::BPP8: {
+ uchar *dest = rasterBuffer->scanLine(y) + x;
+ memset(dest + 1, dest[0], length - 1);
+ break;
+ }
+ default:
+ Q_UNREACHABLE();
+ }
+}
// -------------------- blend methods ---------------------
-#if !defined(Q_CC_SUN)
-static
-#endif
-void blend_color_generic(int count, const QSpan *spans, void *userData)
+static void blend_color_generic(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
uint buffer[BufferSize];
- Operator op = getOperator(data, spans, count);
- const uint color = data->solid.color.toArgb32();
+ Operator op = getOperator(data, nullptr, 0);
+ const uint color = data->solidColor.toArgb32();
+ bool solidFill = data->rasterBuffer->compositionMode == QPainter::CompositionMode_Source
+ || (data->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver && qAlpha(color) == 255);
+ QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp;
while (count--) {
int x = spans->x;
int length = spans->len;
+ if (solidFill && bpp >= QPixelLayout::BPP8 && spans->coverage == 255 && length) {
+ // If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
+ op.destStore(data->rasterBuffer, x, spans->y, &color, 1);
+ spanfill_from_first(data->rasterBuffer, bpp, x, spans->y, length);
+ length = 0;
+ }
+
while (length) {
int l = qMin(BufferSize, length);
uint *dest = op.destFetch(buffer, data->rasterBuffer, x, spans->y, l);
@@ -4335,15 +4481,15 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- const Operator op = getOperator(data, spans, count);
- const uint color = data->solid.color.toArgb32();
+ const Operator op = getOperator(data, nullptr, 0);
+ const uint color = data->solidColor.toArgb32();
if (op.mode == QPainter::CompositionMode_Source) {
// inline for performance
while (count--) {
uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x;
if (spans->coverage == 255) {
- QT_MEMFILL_UINT(target, spans->len, color);
+ qt_memfill(target, color, spans->len);
} else {
uint c = BYTE_MUL(color, spans->coverage);
int ialpha = 255 - spans->coverage;
@@ -4364,35 +4510,33 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
{
+#if QT_CONFIG(raster_64bit)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- Operator op = getOperator(data, spans, count);
+ Operator op = getOperator(data, nullptr, 0);
if (!op.funcSolid64) {
qCDebug(lcQtGuiDrawHelper, "blend_color_generic_rgb64: unsupported 64bit blend attempted, falling back to 32-bit");
return blend_color_generic(count, spans, userData);
}
- quint64 buffer[BufferSize];
- const QRgba64 color = data->solid.color;
+ alignas(8) QRgba64 buffer[BufferSize];
+ const QRgba64 color = data->solidColor;
bool solidFill = data->rasterBuffer->compositionMode == QPainter::CompositionMode_Source
|| (data->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver && color.isOpaque());
- bool isBpp32 = qPixelLayouts[data->rasterBuffer->format].bpp == QPixelLayout::BPP32;
+ QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp;
while (count--) {
int x = spans->x;
int length = spans->len;
- if (solidFill && isBpp32 && spans->coverage == 255) {
+ if (solidFill && bpp >= QPixelLayout::BPP8 && spans->coverage == 255 && length) {
// If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
- if (length > 0) {
- op.destStore64(data->rasterBuffer, x, spans->y, &color, 1);
- uint *dest = (uint*)data->rasterBuffer->scanLine(spans->y) + x;
- qt_memfill32(dest + 1, dest[0], length - 1);
- length = 0;
- }
+ op.destStore64(data->rasterBuffer, x, spans->y, &color, 1);
+ spanfill_from_first(data->rasterBuffer, bpp, x, spans->y, length);
+ length = 0;
}
while (length) {
int l = qMin(BufferSize, length);
- QRgba64 *dest = op.destFetch64((QRgba64 *)buffer, data->rasterBuffer, x, spans->y, l);
+ QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
op.funcSolid64(dest, l, color, spans->coverage);
if (op.destStore64)
op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
@@ -4401,6 +4545,9 @@ void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
}
++spans;
}
+#else
+ blend_color_generic(count, spans, userData);
+#endif
}
static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
@@ -4413,16 +4560,16 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
from qt_gradient_quint16 with minimal overhead.
*/
QPainter::CompositionMode mode = data->rasterBuffer->compositionMode;
- if (mode == QPainter::CompositionMode_SourceOver && data->solid.color.isOpaque())
+ if (mode == QPainter::CompositionMode_SourceOver && data->solidColor.isOpaque())
mode = QPainter::CompositionMode_Source;
if (mode == QPainter::CompositionMode_Source) {
// inline for performance
- ushort c = data->solid.color.toRgb16();
+ ushort c = data->solidColor.toRgb16();
while (count--) {
ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x;
if (spans->coverage == 255) {
- QT_MEMFILL_USHORT(target, spans->len, c);
+ qt_memfill(target, c, spans->len);
} else {
ushort color = BYTE_MUL_RGB16(c, spans->coverage);
int ialpha = 255 - spans->coverage;
@@ -4439,7 +4586,7 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
if (mode == QPainter::CompositionMode_SourceOver) {
while (count--) {
- uint color = BYTE_MUL(data->solid.color.toArgb32(), spans->coverage);
+ uint color = BYTE_MUL(data->solidColor.toArgb32(), spans->coverage);
int ialpha = qAlpha(~color);
ushort c = qConvertRgb32To16(color);
ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x;
@@ -4544,8 +4691,8 @@ struct QBlendBase
BlendType *dest;
- BlendType buffer[BufferSize];
- BlendType src_buffer[BufferSize];
+ alignas(8) BlendType buffer[BufferSize];
+ alignas(8) BlendType src_buffer[BufferSize];
};
class BlendSrcGeneric : public QBlendBase<uint>
@@ -4574,11 +4721,12 @@ public:
}
};
-class BlendSrcGenericRGB64 : public QBlendBase<quint64>
+#if QT_CONFIG(raster_64bit)
+class BlendSrcGenericRGB64 : public QBlendBase<QRgba64>
{
public:
BlendSrcGenericRGB64(QSpanData *d, const Operator &o)
- : QBlendBase<quint64>(d, o)
+ : QBlendBase<QRgba64>(d, o)
{
}
@@ -4587,23 +4735,24 @@ public:
return op.func64 && op.destFetch64;
}
- const quint64 *fetch(int x, int y, int len)
+ const QRgba64 *fetch(int x, int y, int len)
{
- dest = (quint64 *)op.destFetch64((QRgba64 *)buffer, data->rasterBuffer, x, y, len);
- return (const quint64 *)op.srcFetch64((QRgba64 *)src_buffer, &op, data, y, x, len);
+ dest = op.destFetch64(buffer, data->rasterBuffer, x, y, len);
+ return op.srcFetch64(src_buffer, &op, data, y, x, len);
}
- void process(int, int, int len, int coverage, const quint64 *src, int offset)
+ void process(int, int, int len, int coverage, const QRgba64 *src, int offset)
{
- op.func64((QRgba64 *)dest + offset, (const QRgba64 *)src + offset, len, coverage);
+ op.func64(dest + offset, src + offset, len, coverage);
}
void store(int x, int y, int len)
{
if (op.destStore64)
- op.destStore64(data->rasterBuffer, x, y, (QRgba64 *)dest, len);
+ op.destStore64(data->rasterBuffer, x, y, dest, len);
}
};
+#endif
static void blend_src_generic(int count, const QSpan *spans, void *userData)
{
@@ -4612,6 +4761,7 @@ static void blend_src_generic(int count, const QSpan *spans, void *userData)
handleSpans(count, spans, data, blend);
}
+#if QT_CONFIG(raster_64bit)
static void blend_src_generic_rgb64(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -4625,6 +4775,7 @@ static void blend_src_generic_rgb64(int count, const QSpan *spans, void *userDat
handleSpans(count, spans, data, blend32);
}
}
+#endif
static void blend_untransformed_generic(int count, const QSpan *spans, void *userData)
{
@@ -4671,6 +4822,7 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use
}
}
+#if QT_CONFIG(raster_64bit)
static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -4680,8 +4832,8 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
qCDebug(lcQtGuiDrawHelper, "blend_untransformed_generic_rgb64: unsupported 64-bit blend attempted, falling back to 32-bit");
return blend_untransformed_generic(count, spans, userData);
}
- quint64 buffer[BufferSize];
- quint64 src_buffer[BufferSize];
+ alignas(8) QRgba64 buffer[BufferSize];
+ alignas(8) QRgba64 src_buffer[BufferSize];
const int image_width = data->texture.width;
const int image_height = data->texture.height;
@@ -4705,8 +4857,8 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
while (length) {
int l = qMin(BufferSize, length);
- const QRgba64 *src = op.srcFetch64((QRgba64 *)src_buffer, &op, data, sy, sx, l);
- QRgba64 *dest = op.destFetch64((QRgba64 *)buffer, data->rasterBuffer, x, spans->y, l);
+ const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l);
+ QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
op.func64(dest, src, l, coverage);
if (op.destStore64)
op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
@@ -4719,6 +4871,7 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
++spans;
}
}
+#endif
static void blend_untransformed_argb(int count, const QSpan *spans, void *userData)
{
@@ -4913,6 +5066,7 @@ static void blend_tiled_generic(int count, const QSpan *spans, void *userData)
}
}
+#if QT_CONFIG(raster_64bit)
static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -4922,8 +5076,8 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
qCDebug(lcQtGuiDrawHelper, "blend_tiled_generic_rgb64: unsupported 64-bit blend attempted, falling back to 32-bit");
return blend_tiled_generic(count, spans, userData);
}
- quint64 buffer[BufferSize];
- quint64 src_buffer[BufferSize];
+ alignas(8) QRgba64 buffer[BufferSize];
+ alignas(8) QRgba64 src_buffer[BufferSize];
const int image_width = data->texture.width;
const int image_height = data->texture.height;
@@ -4952,7 +5106,7 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
int sl = qMin(image_width, length);
if (sx > 0 && sl > 0) {
int l = qMin(image_width - sx, sl);
- const QRgba64 *src = op.srcFetch64((QRgba64 *)src_buffer, &op, data, sy, sx, l);
+ const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l);
op.destStore64(data->rasterBuffer, x, y, src, l);
x += l;
sx += l;
@@ -4962,7 +5116,7 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
}
if (sl > 0) {
Q_ASSERT(sx == 0);
- const QRgba64 *src = op.srcFetch64((QRgba64 *)src_buffer, &op, data, sy, sx, sl);
+ const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, sl);
op.destStore64(data->rasterBuffer, x, y, src, sl);
x += sl;
sx += sl;
@@ -4994,8 +5148,8 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
int l = qMin(image_width - sx, length);
if (BufferSize < l)
l = BufferSize;
- const QRgba64 *src = op.srcFetch64((QRgba64 *)src_buffer, &op, data, sy, sx, l);
- QRgba64 *dest = op.destFetch64((QRgba64 *)buffer, data->rasterBuffer, x, spans->y, l);
+ const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l);
+ QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
op.func64(dest, src, l, coverage);
if (op.destStore64)
op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
@@ -5008,6 +5162,7 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
++spans;
}
}
+#endif
static void blend_tiled_argb(int count, const QSpan *spans, void *userData)
{
@@ -5184,6 +5339,7 @@ static const ProcessSpans processTextureSpansGeneric[NBlendTypes] = {
blend_src_generic // TransformedBilinearTiled
};
+#if QT_CONFIG(raster_64bit)
static const ProcessSpans processTextureSpansGeneric64[NBlendTypes] = {
blend_untransformed_generic_rgb64, // Untransformed
blend_tiled_generic_rgb64, // Tiled
@@ -5192,6 +5348,7 @@ static const ProcessSpans processTextureSpansGeneric64[NBlendTypes] = {
blend_src_generic_rgb64, // TransformedBilinear
blend_src_generic_rgb64 // TransformedBilinearTiled
};
+#endif
void qBlendTexture(int count, const QSpan *spans, void *userData)
{
@@ -5205,6 +5362,7 @@ void qBlendTexture(int count, const QSpan *spans, void *userData)
case QImage::Format_RGB16:
proc = processTextureSpansRGB16[blendType];
break;
+#if QT_CONFIG(raster_64bit)
#if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8)
case QImage::Format_ARGB32:
case QImage::Format_RGBA8888:
@@ -5216,8 +5374,10 @@ void qBlendTexture(int count, const QSpan *spans, void *userData)
case QImage::Format_RGBX64:
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_Grayscale16:
proc = processTextureSpansGeneric64[blendType];
break;
+#endif // QT_CONFIG(raster_64bit)
case QImage::Format_Invalid:
Q_UNREACHABLE();
return;
@@ -5228,7 +5388,117 @@ void qBlendTexture(int count, const QSpan *spans, void *userData)
proc(count, spans, userData);
}
-template <class DST> Q_STATIC_TEMPLATE_FUNCTION
+static void blend_vertical_gradient_argb(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+
+ LinearGradientValues linear;
+ getLinearGradientValues(&linear, data);
+
+ CompositionFunctionSolid funcSolid =
+ functionForModeSolid[data->rasterBuffer->compositionMode];
+
+ /*
+ The logic for vertical gradient calculations is a mathematically
+ reduced copy of that in fetchLinearGradient() - which is basically:
+
+ qreal ry = data->m22 * (y + 0.5) + data->dy;
+ qreal t = linear.dy*ry + linear.off;
+ t *= (GRADIENT_STOPTABLE_SIZE - 1);
+ quint32 color =
+ qt_gradient_pixel_fixed(&data->gradient,
+ int(t * FIXPT_SIZE));
+
+ This has then been converted to fixed point to improve performance.
+ */
+ const int gss = GRADIENT_STOPTABLE_SIZE - 1;
+ int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
+ int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
+
+ while (count--) {
+ int y = spans->y;
+ int x = spans->x;
+
+ quint32 *dst = (quint32 *)(data->rasterBuffer->scanLine(y)) + x;
+ quint32 color =
+ qt_gradient_pixel_fixed(&data->gradient, yinc * y + off);
+
+ funcSolid(dst, spans->len, color, spans->coverage);
+ ++spans;
+ }
+}
+
+template<ProcessSpans blend_color>
+static void blend_vertical_gradient(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+
+ LinearGradientValues linear;
+ getLinearGradientValues(&linear, data);
+
+ // Based on the same logic as blend_vertical_gradient_argb.
+
+ const int gss = GRADIENT_STOPTABLE_SIZE - 1;
+ int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
+ int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
+
+ while (count--) {
+ int y = spans->y;
+
+#if QT_CONFIG(raster_64bit)
+ data->solidColor = qt_gradient_pixel64_fixed(&data->gradient, yinc * y + off);
+#else
+ data->solidColor = QRgba64::fromArgb32(qt_gradient_pixel_fixed(&data->gradient, yinc * y + off));
+#endif
+ blend_color(1, spans, userData);
+ ++spans;
+ }
+}
+
+void qBlendGradient(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+ bool isVerticalGradient =
+ data->txop <= QTransform::TxScale &&
+ data->type == QSpanData::LinearGradient &&
+ data->gradient.linear.end.x == data->gradient.linear.origin.x;
+ switch (data->rasterBuffer->format) {
+ case QImage::Format_RGB16:
+ if (isVerticalGradient)
+ return blend_vertical_gradient<blend_color_rgb16>(count, spans, userData);
+ return blend_src_generic(count, spans, userData);
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ if (isVerticalGradient)
+ return blend_vertical_gradient_argb(count, spans, userData);
+ return blend_src_generic(count, spans, userData);
+#if QT_CONFIG(raster_64bit)
+#if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8)
+ case QImage::Format_ARGB32:
+ case QImage::Format_RGBA8888:
+#endif
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ if (isVerticalGradient)
+ return blend_vertical_gradient<blend_color_generic_rgb64>(count, spans, userData);
+ return blend_src_generic_rgb64(count, spans, userData);
+#endif // QT_CONFIG(raster_64bit)
+ case QImage::Format_Invalid:
+ break;
+ default:
+ if (isVerticalGradient)
+ return blend_vertical_gradient<blend_color_generic>(count, spans, userData);
+ return blend_src_generic(count, spans, userData);
+ }
+ Q_UNREACHABLE();
+}
+
+template <class DST> static
inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer,
int x, int y, DST color,
const uchar *map,
@@ -5290,103 +5560,6 @@ inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer,
}
}
-static void qt_gradient_argb32(int count, const QSpan *spans, void *userData)
-{
- QSpanData *data = reinterpret_cast<QSpanData *>(userData);
-
- bool isVerticalGradient =
- data->txop <= QTransform::TxScale &&
- data->type == QSpanData::LinearGradient &&
- data->gradient.linear.end.x == data->gradient.linear.origin.x;
-
- if (isVerticalGradient) {
- LinearGradientValues linear;
- getLinearGradientValues(&linear, data);
-
- CompositionFunctionSolid funcSolid =
- functionForModeSolid[data->rasterBuffer->compositionMode];
-
- /*
- The logic for vertical gradient calculations is a mathematically
- reduced copy of that in fetchLinearGradient() - which is basically:
-
- qreal ry = data->m22 * (y + 0.5) + data->dy;
- qreal t = linear.dy*ry + linear.off;
- t *= (GRADIENT_STOPTABLE_SIZE - 1);
- quint32 color =
- qt_gradient_pixel_fixed(&data->gradient,
- int(t * FIXPT_SIZE));
-
- This has then been converted to fixed point to improve performance.
- */
- const int gss = GRADIENT_STOPTABLE_SIZE - 1;
- int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
- int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
-
- while (count--) {
- int y = spans->y;
- int x = spans->x;
-
- quint32 *dst = (quint32 *)(data->rasterBuffer->scanLine(y)) + x;
- quint32 color =
- qt_gradient_pixel_fixed(&data->gradient, yinc * y + off);
-
- funcSolid(dst, spans->len, color, spans->coverage);
- ++spans;
- }
-
- } else {
- blend_src_generic(count, spans, userData);
- }
-}
-
-static void qt_gradient_quint16(int count, const QSpan *spans, void *userData)
-{
- QSpanData *data = reinterpret_cast<QSpanData *>(userData);
-
- bool isVerticalGradient =
- data->txop <= QTransform::TxScale &&
- data->type == QSpanData::LinearGradient &&
- data->gradient.linear.end.x == data->gradient.linear.origin.x;
-
- if (isVerticalGradient) {
-
- LinearGradientValues linear;
- getLinearGradientValues(&linear, data);
-
- /*
- The logic for vertical gradient calculations is a mathematically
- reduced copy of that in fetchLinearGradient() - which is basically:
-
- qreal ry = data->m22 * (y + 0.5) + data->dy;
- qreal t = linear.dy*ry + linear.off;
- t *= (GRADIENT_STOPTABLE_SIZE - 1);
- quint32 color =
- qt_gradient_pixel_fixed(&data->gradient,
- int(t * FIXPT_SIZE));
-
- This has then been converted to fixed point to improve performance.
- */
- const int gss = GRADIENT_STOPTABLE_SIZE - 1;
- int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
- int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
-
- // Save the fillData since we overwrite it when setting solid.color.
- QGradientData gradient = data->gradient;
- while (count--) {
- int y = spans->y;
-
- data->solid.color = QRgba64::fromArgb32(qt_gradient_pixel_fixed(&gradient, yinc * y + off));
- blend_color_rgb16(1, spans, userData);
- ++spans;
- }
- data->gradient = gradient;
-
- } else {
- blend_src_generic(count, spans, userData);
- }
-}
-
inline static void qt_bitmapblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
@@ -5424,7 +5597,36 @@ inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer,
map, mapWidth, mapHeight, mapStride);
}
-static inline void alphamapblend_generic(int coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorProfile *colorProfile)
+static inline void grayBlendPixel(quint32 *dst, int coverage, QRgba64 srcLinear, const QColorTrcLut *colorProfile)
+{
+ // Do a gammacorrected gray alphablend...
+ const QRgba64 dstLinear = colorProfile ? colorProfile->toLinear64(*dst) : QRgba64::fromArgb32(*dst);
+
+ QRgba64 blend = interpolate255(srcLinear, coverage, dstLinear, 255 - coverage);
+
+ *dst = colorProfile ? colorProfile->fromLinear64(blend) : toArgb32(blend);
+}
+
+static inline void alphamapblend_argb32(quint32 *dst, int coverage, QRgba64 srcLinear, quint32 src, const QColorTrcLut *colorProfile)
+{
+ if (coverage == 0) {
+ // nothing
+ } else if (coverage == 255) {
+ *dst = src;
+ } else if (!colorProfile) {
+ *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage);
+ } else {
+ if (*dst >= 0xff000000) {
+ grayBlendPixel(dst, coverage, srcLinear, colorProfile);
+ } else {
+ // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571
+ *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage);
+ }
+ }
+}
+
+#if QT_CONFIG(raster_64bit)
+static inline void alphamapblend_generic(int coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorTrcLut *colorProfile)
{
if (coverage == 0) {
// nothing
@@ -5459,7 +5661,7 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
if (color.isTransparent())
return;
- const QColorProfile *colorProfile = nullptr;
+ const QColorTrcLut *colorProfile = nullptr;
if (useGammaCorrection)
colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text();
@@ -5472,7 +5674,7 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied();
}
- quint64 buffer[BufferSize];
+ alignas(8) QRgba64 buffer[BufferSize];
const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format];
const DestStoreProc64 destStore64 = destStoreProc64[rasterBuffer->format];
@@ -5482,7 +5684,7 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
int length = mapWidth;
while (length > 0) {
int l = qMin(BufferSize, length);
- QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, i, y + ly, l);
+ QRgba64 *dest = destFetch64(buffer, rasterBuffer, i, y + ly, l);
for (int j=0; j < l; ++j) {
const int coverage = map[j + (i - x)];
alphamapblend_generic(coverage, dest, j, srcColor, color, colorProfile);
@@ -5512,7 +5714,7 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
if (end <= start)
continue;
Q_ASSERT(end - start <= BufferSize);
- QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, start, clip.y, end - start);
+ QRgba64 *dest = destFetch64(buffer, rasterBuffer, start, clip.y, end - start);
for (int xp=start; xp<end; ++xp) {
const int coverage = map[xp - x];
@@ -5525,6 +5727,85 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
} // for (yp -> bottom)
}
}
+#else
+static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
+ int x, int y, const QRgba64 &color,
+ const uchar *map,
+ int mapWidth, int mapHeight, int mapStride,
+ const QClipData *clip, bool useGammaCorrection)
+{
+ if (color.isTransparent())
+ return;
+
+ const quint32 c = color.toArgb32();
+
+ const QColorTrcLut *colorProfile = nullptr;
+
+ if (useGammaCorrection)
+ colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text();
+
+ QRgba64 srcColor = color;
+ if (colorProfile) {
+ if (color.isOpaque())
+ srcColor = colorProfile->toLinear(srcColor);
+ else
+ srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied();
+ }
+
+ quint32 buffer[BufferSize];
+ const DestFetchProc destFetch = destFetchProc[rasterBuffer->format];
+ const DestStoreProc destStore = destStoreProc[rasterBuffer->format];
+
+ if (!clip) {
+ for (int ly = 0; ly < mapHeight; ++ly) {
+ int i = x;
+ int length = mapWidth;
+ while (length > 0) {
+ int l = qMin(BufferSize, length);
+ quint32 *dest = destFetch(buffer, rasterBuffer, i, y + ly, l);
+ for (int j=0; j < l; ++j) {
+ const int coverage = map[j + (i - x)];
+ alphamapblend_argb32(dest + j, coverage, srcColor, c, colorProfile);
+ }
+ if (destStore)
+ destStore(rasterBuffer, i, y + ly, dest, l);
+ length -= l;
+ i += l;
+ }
+ map += mapStride;
+ }
+ } else {
+ int bottom = qMin(y + mapHeight, rasterBuffer->height());
+
+ int top = qMax(y, 0);
+ map += (top - y) * mapStride;
+
+ const_cast<QClipData *>(clip)->initialize();
+ for (int yp = top; yp<bottom; ++yp) {
+ const QClipData::ClipLine &line = clip->m_clipLines[yp];
+
+ for (int i=0; i<line.count; ++i) {
+ const QSpan &clip = line.spans[i];
+
+ int start = qMax<int>(x, clip.x);
+ int end = qMin<int>(x + mapWidth, clip.x + clip.len);
+ if (end <= start)
+ continue;
+ Q_ASSERT(end - start <= BufferSize);
+ quint32 *dest = destFetch(buffer, rasterBuffer, start, clip.y, end - start);
+
+ for (int xp=start; xp<end; ++xp) {
+ const int coverage = map[xp - x];
+ alphamapblend_argb32(dest + xp - x, coverage, srcColor, color, colorProfile);
+ }
+ if (destStore)
+ destStore(rasterBuffer, start, clip.y, dest, end - start);
+ } // for (i -> line.count)
+ map += mapStride;
+ } // for (yp -> bottom)
+ }
+}
+#endif
static inline void alphamapblend_quint16(int coverage, quint16 *dest, int x, const quint16 srcColor)
{
@@ -5585,44 +5866,6 @@ void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
}
}
-static inline void rgbBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorProfile *colorProfile)
-{
- // Do a gammacorrected RGB alphablend...
- const QRgba64 dlinear = colorProfile ? colorProfile->toLinear64(*dst) : QRgba64::fromArgb32(*dst);
-
- QRgba64 blend = rgbBlend(dlinear, slinear, coverage);
-
- *dst = colorProfile ? colorProfile->fromLinear64(blend) : toArgb32(blend);
-}
-
-static inline void grayBlendPixel(quint32 *dst, int coverage, QRgba64 srcLinear, const QColorProfile *colorProfile)
-{
- // Do a gammacorrected gray alphablend...
- const QRgba64 dstLinear = colorProfile ? colorProfile->toLinear64(*dst) : QRgba64::fromArgb32(*dst);
-
- QRgba64 blend = interpolate255(srcLinear, coverage, dstLinear, 255 - coverage);
-
- *dst = colorProfile ? colorProfile->fromLinear64(blend) : toArgb32(blend);
-}
-
-static inline void alphamapblend_argb32(quint32 *dst, int coverage, QRgba64 srcLinear, quint32 src, const QColorProfile *colorProfile)
-{
- if (coverage == 0) {
- // nothing
- } else if (coverage == 255) {
- *dst = src;
- } else if (!colorProfile) {
- *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage);
- } else {
- if (*dst >= 0xff000000) {
- grayBlendPixel(dst, coverage, srcLinear, colorProfile);
- } else {
- // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571
- *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage);
- }
- }
-}
-
static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
@@ -5635,7 +5878,7 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer,
if (color.isTransparent())
return;
- const QColorProfile *colorProfile = nullptr;
+ const QColorTrcLut *colorProfile = nullptr;
if (useGammaCorrection)
colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text();
@@ -5691,6 +5934,16 @@ static inline int qRgbAvg(QRgb rgb)
return (qRed(rgb) * 5 + qGreen(rgb) * 6 + qBlue(rgb) * 5) / 16;
}
+static inline void rgbBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorTrcLut *colorProfile)
+{
+ // Do a gammacorrected RGB alphablend...
+ const QRgba64 dlinear = colorProfile ? colorProfile->toLinear64(*dst) : QRgba64::fromArgb32(*dst);
+
+ QRgba64 blend = rgbBlend(dlinear, slinear, coverage);
+
+ *dst = colorProfile ? colorProfile->fromLinear64(blend) : toArgb32(blend);
+}
+
static inline QRgb rgbBlend(QRgb d, QRgb s, uint rgbAlpha)
{
#if defined(__SSE2__)
@@ -5731,7 +5984,8 @@ static inline QRgb rgbBlend(QRgb d, QRgb s, uint rgbAlpha)
#endif
}
-static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorProfile *colorProfile)
+#if QT_CONFIG(raster_64bit)
+static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorTrcLut *colorProfile)
{
if (coverage == 0xff000000) {
// nothing
@@ -5752,8 +6006,9 @@ static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, co
}
}
}
+#endif
-static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba64 &srcLinear, quint32 src, const QColorProfile *colorProfile)
+static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba64 &srcLinear, quint32 src, const QColorTrcLut *colorProfile)
{
if (coverage == 0xff000000) {
// nothing
@@ -5770,6 +6025,7 @@ static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba
}
}
+#if QT_CONFIG(raster_64bit)
static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uint *src, int mapWidth, int mapHeight, int srcStride,
@@ -5778,7 +6034,7 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
if (color.isTransparent())
return;
- const QColorProfile *colorProfile = nullptr;
+ const QColorTrcLut *colorProfile = nullptr;
if (useGammaCorrection)
colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text();
@@ -5791,7 +6047,7 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied();
}
- quint64 buffer[BufferSize];
+ alignas(8) QRgba64 buffer[BufferSize];
const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format];
const DestStoreProc64 destStore64 = destStoreProc64[rasterBuffer->format];
@@ -5801,7 +6057,7 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
int length = mapWidth;
while (length > 0) {
int l = qMin(BufferSize, length);
- QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, i, y + ly, l);
+ QRgba64 *dest = destFetch64(buffer, rasterBuffer, i, y + ly, l);
for (int j=0; j < l; ++j) {
const uint coverage = src[j + (i - x)];
alphargbblend_generic(coverage, dest, j, srcColor, color, colorProfile);
@@ -5831,7 +6087,7 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
if (end <= start)
continue;
Q_ASSERT(end - start <= BufferSize);
- QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, start, clip.y, end - start);
+ QRgba64 *dest = destFetch64(buffer, rasterBuffer, start, clip.y, end - start);
for (int xp=start; xp<end; ++xp) {
const uint coverage = src[xp - x];
@@ -5844,6 +6100,84 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
} // for (yp -> bottom)
}
}
+#else
+static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
+ int x, int y, const QRgba64 &color,
+ const uint *src, int mapWidth, int mapHeight, int srcStride,
+ const QClipData *clip, bool useGammaCorrection)
+{
+ if (color.isTransparent())
+ return;
+
+ const quint32 c = color.toArgb32();
+
+ const QColorTrcLut *colorProfile = nullptr;
+
+ if (useGammaCorrection)
+ colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text();
+
+ QRgba64 srcColor = color;
+ if (colorProfile) {
+ if (color.isOpaque())
+ srcColor = colorProfile->toLinear(srcColor);
+ else
+ srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied();
+ }
+
+ quint32 buffer[BufferSize];
+ const DestFetchProc destFetch = destFetchProc[rasterBuffer->format];
+ const DestStoreProc destStore = destStoreProc[rasterBuffer->format];
+
+ if (!clip) {
+ for (int ly = 0; ly < mapHeight; ++ly) {
+ int i = x;
+ int length = mapWidth;
+ while (length > 0) {
+ int l = qMin(BufferSize, length);
+ quint32 *dest = destFetch(buffer, rasterBuffer, i, y + ly, l);
+ for (int j=0; j < l; ++j) {
+ const uint coverage = src[j + (i - x)];
+ alphargbblend_argb32(dest + j, coverage, srcColor, c, colorProfile);
+ }
+ if (destStore)
+ destStore(rasterBuffer, i, y + ly, dest, l);
+ length -= l;
+ i += l;
+ }
+ src += srcStride;
+ }
+ } else {
+ int bottom = qMin(y + mapHeight, rasterBuffer->height());
+
+ int top = qMax(y, 0);
+ src += (top - y) * srcStride;
+
+ const_cast<QClipData *>(clip)->initialize();
+ for (int yp = top; yp<bottom; ++yp) {
+ const QClipData::ClipLine &line = clip->m_clipLines[yp];
+
+ for (int i=0; i<line.count; ++i) {
+ const QSpan &clip = line.spans[i];
+
+ int start = qMax<int>(x, clip.x);
+ int end = qMin<int>(x + mapWidth, clip.x + clip.len);
+ if (end <= start)
+ continue;
+ Q_ASSERT(end - start <= BufferSize);
+ quint32 *dest = destFetch(buffer, rasterBuffer, start, clip.y, end - start);
+
+ for (int xp=start; xp<end; ++xp) {
+ const uint coverage = src[xp - x];
+ alphargbblend_argb32(dest + xp - start, coverage, srcColor, c, colorProfile);
+ }
+ if (destStore)
+ destStore(rasterBuffer, start, clip.y, dest, end - start);
+ } // for (i -> line.count)
+ src += srcStride;
+ } // for (yp -> bottom)
+ }
+}
+#endif
static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
@@ -5855,7 +6189,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
const quint32 c = color.toArgb32();
- const QColorProfile *colorProfile = nullptr;
+ const QColorTrcLut *colorProfile = nullptr;
if (useGammaCorrection)
colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text();
@@ -6007,29 +6341,25 @@ static void qt_rectfill_quint64(QRasterBuffer *rasterBuffer,
DrawHelper qDrawHelper[QImage::NImageFormats] =
{
// Format_Invalid,
- { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
// Format_Mono,
{
blend_color_generic,
- blend_src_generic,
0, 0, 0, 0
},
// Format_MonoLSB,
{
blend_color_generic,
- blend_src_generic,
0, 0, 0, 0
},
// Format_Indexed8,
{
blend_color_generic,
- blend_src_generic,
0, 0, 0, 0
},
// Format_RGB32,
{
blend_color_argb,
- qt_gradient_argb32,
qt_bitmapblit_argb32,
qt_alphamapblit_argb32,
qt_alphargbblit_argb32,
@@ -6038,7 +6368,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB32,
{
blend_color_generic,
- blend_src_generic,
qt_bitmapblit_argb32,
qt_alphamapblit_argb32,
qt_alphargbblit_argb32,
@@ -6047,7 +6376,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB32_Premultiplied
{
blend_color_argb,
- qt_gradient_argb32,
qt_bitmapblit_argb32,
qt_alphamapblit_argb32,
qt_alphargbblit_argb32,
@@ -6056,7 +6384,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB16
{
blend_color_rgb16,
- qt_gradient_quint16,
qt_bitmapblit_quint16,
qt_alphamapblit_quint16,
qt_alphargbblit_generic,
@@ -6065,7 +6392,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB8565_Premultiplied
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6074,7 +6400,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB666
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6083,7 +6408,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB6666_Premultiplied
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6092,7 +6416,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB555
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6101,7 +6424,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB8555_Premultiplied
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6110,7 +6432,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB888
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6119,7 +6440,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB444
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6128,7 +6448,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB4444_Premultiplied
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6137,7 +6456,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGBX8888
{
blend_color_generic,
- blend_src_generic,
qt_bitmapblit_rgba8888,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6146,7 +6464,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGBA8888
{
blend_color_generic,
- blend_src_generic,
qt_bitmapblit_rgba8888,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6155,7 +6472,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB8888_Premultiplied
{
blend_color_generic,
- blend_src_generic,
qt_bitmapblit_rgba8888,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6164,7 +6480,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_BGR30
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderBGR>,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6173,7 +6488,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_A2BGR30_Premultiplied
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderBGR>,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6182,7 +6496,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB30
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderRGB>,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6191,7 +6504,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_A2RGB30_Premultiplied
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderRGB>,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6200,7 +6512,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_Alpha8
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6209,7 +6520,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_Grayscale8
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6218,7 +6528,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGBX64
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6227,7 +6536,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGBA64
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6236,82 +6544,98 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGBA64_Premultiplied
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
qt_rectfill_quint64
},
+ // Format_Grayscale16
+ {
+ blend_color_generic_rgb64,
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ qt_rectfill_quint16
+ },
};
-#if defined(Q_CC_MSVC) && !defined(_MIPS_)
-template <class T>
-inline void qt_memfill_template(T *dest, T color, int count)
+#if !defined(__SSE2__)
+void qt_memfill64(quint64 *dest, quint64 color, qsizetype count)
{
- while (count--)
- *dest++ = color;
+ qt_memfill_template<quint64>(dest, color, count);
}
+#endif
-#else
-
-template <class T>
-inline void qt_memfill_template(T *dest, T color, int count)
+#if defined(QT_COMPILER_SUPPORTS_SSSE3) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
+__attribute__((optimize("no-tree-vectorize")))
+#endif
+void qt_memfill24(quint24 *dest, quint24 color, qsizetype count)
{
- int n = (count + 7) / 8;
- switch (count & 0x07)
- {
- case 0: do { *dest++ = color; Q_FALLTHROUGH();
- case 7: *dest++ = color; Q_FALLTHROUGH();
- case 6: *dest++ = color; Q_FALLTHROUGH();
- case 5: *dest++ = color; Q_FALLTHROUGH();
- case 4: *dest++ = color; Q_FALLTHROUGH();
- case 3: *dest++ = color; Q_FALLTHROUGH();
- case 2: *dest++ = color; Q_FALLTHROUGH();
- case 1: *dest++ = color;
- } while (--n > 0);
- }
-}
+# ifdef QT_COMPILER_SUPPORTS_SSSE3
+ extern void qt_memfill24_ssse3(quint24 *, quint24, qsizetype);
+ if (qCpuHasFeature(SSSE3))
+ return qt_memfill24_ssse3(dest, color, count);
+# endif
-template <>
-inline void qt_memfill_template(quint16 *dest, quint16 value, int count)
-{
- if (count < 3) {
- switch (count) {
- case 2: *dest++ = value; Q_FALLTHROUGH();
- case 1: *dest = value;
- }
+ const quint32 v = color;
+ quint24 *end = dest + count;
+
+ // prolog: align dest to 32bit
+ while ((quintptr(dest) & 0x3) && dest < end) {
+ *dest++ = v;
+ }
+ if (dest >= end)
return;
+
+ const uint val1 = qFromBigEndian((v << 8) | (v >> 16));
+ const uint val2 = qFromBigEndian((v << 16) | (v >> 8));
+ const uint val3 = qFromBigEndian((v << 24) | (v >> 0));
+
+ for ( ; dest <= (end - 4); dest += 4) {
+ quint32 *dst = reinterpret_cast<quint32 *>(dest);
+ dst[0] = val1;
+ dst[1] = val2;
+ dst[2] = val3;
}
- const int align = (quintptr)(dest) & 0x3;
- switch (align) {
- case 2: *dest++ = value; --count;
+ // less than 4px left
+ switch (end - dest) {
+ case 3:
+ *dest++ = v;
+ Q_FALLTHROUGH();
+ case 2:
+ *dest++ = v;
+ Q_FALLTHROUGH();
+ case 1:
+ *dest++ = v;
+ }
+}
+
+void qt_memfill16(quint16 *dest, quint16 value, qsizetype count)
+{
+ const int align = quintptr(dest) & 0x3;
+ if (align) {
+ *dest++ = value;
+ --count;
}
- const quint32 value32 = (value << 16) | value;
- qt_memfill(reinterpret_cast<quint32*>(dest), value32, count / 2);
if (count & 0x1)
dest[count - 1] = value;
-}
-#endif
-void qt_memfill64(quint64 *dest, quint64 color, int count)
-{
- qt_memfill_template<quint64>(dest, color, count);
+ const quint32 value32 = (value << 16) | value;
+ qt_memfill32(reinterpret_cast<quint32*>(dest), value32, count / 2);
}
-#if !defined(__SSE2__)
-void qt_memfill16(quint16 *dest, quint16 color, int count)
-{
- qt_memfill_template<quint16>(dest, color, count);
-}
-#endif
#if !defined(__SSE2__) && !defined(__ARM_NEON__) && !defined(__MIPS_DSP__)
-void qt_memfill32(quint32 *dest, quint32 color, int count)
+void qt_memfill32(quint32 *dest, quint32 color, qsizetype count)
{
qt_memfill_template<quint32>(dest, color, count);
}
#endif
+#ifdef __SSE2__
+decltype(qt_memfill32_sse2) *qt_memfill32 = nullptr;
+decltype(qt_memfill64_sse2) *qt_memfill64 = nullptr;
+#endif
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
template<QtPixelOrder> void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count, const QVector<QRgb> *, QDitherInfo *);
@@ -6325,6 +6649,10 @@ static void qInitDrawhelperFunctions()
qInitBlendFunctions();
#ifdef __SSE2__
+# ifndef __AVX2__
+ qt_memfill32 = qt_memfill32_sse2;
+ qt_memfill64 = qt_memfill64_sse2;
+# endif
qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2;
qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2;
qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2;
@@ -6401,6 +6729,14 @@ static void qInitDrawhelperFunctions()
const QVector<QRgb> *, QDitherInfo *);
extern const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_sse4(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertARGB32ToRGBA64PM_sse4(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertRGBA8888ToRGBA64PM_sse4(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM_sse4(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_sse4(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
extern void QT_FASTCALL storeARGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
extern void QT_FASTCALL storeRGBA8888FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
@@ -6413,10 +6749,18 @@ static void qInitDrawhelperFunctions()
const QVector<QRgb> *, QDitherInfo *);
extern void QT_FASTCALL destStore64ARGB32_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
extern void QT_FASTCALL destStore64RGBA8888_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
+# ifndef __AVX2__
qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_sse4;
qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_sse4;
+ qPixelLayouts[QImage::Format_ARGB32].fetchToRGBA64PM = fetchARGB32ToRGBA64PM_sse4;
+ qPixelLayouts[QImage::Format_ARGB32].convertToRGBA64PM = convertARGB32ToRGBA64PM_sse4;
+ qPixelLayouts[QImage::Format_RGBA8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_sse4;
+ qPixelLayouts[QImage::Format_RGBA8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_sse4;
+ qPixelLayouts[QImage::Format_RGBX8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_sse4;
+ qPixelLayouts[QImage::Format_RGBX8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_sse4;
+# endif
qPixelLayouts[QImage::Format_ARGB32].storeFromARGB32PM = storeARGB32FromARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBA8888].storeFromARGB32PM = storeRGBA8888FromARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBX8888].storeFromARGB32PM = storeRGBXFromARGB32PM_sse4;
@@ -6424,13 +6768,17 @@ static void qInitDrawhelperFunctions()
qPixelLayouts[QImage::Format_A2RGB30_Premultiplied].storeFromARGB32PM = storeA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>;
qStoreFromRGBA64PM[QImage::Format_ARGB32] = storeARGB32FromRGBA64PM_sse4;
qStoreFromRGBA64PM[QImage::Format_RGBA8888] = storeRGBA8888FromRGBA64PM_sse4;
+#if QT_CONFIG(raster_64bit)
destStoreProc64[QImage::Format_ARGB32] = destStore64ARGB32_sse4;
destStoreProc64[QImage::Format_RGBA8888] = destStore64RGBA8888_sse4;
+#endif
}
#endif
#if defined(QT_COMPILER_SUPPORTS_AVX2)
if (qCpuHasFeature(ArchHaswell)) {
+ qt_memfill32 = qt_memfill32_avx2;
+ qt_memfill64 = qt_memfill64_avx2;
extern void qt_blend_rgb32_on_rgb32_avx2(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
int w, int h, int const_alpha);
@@ -6447,18 +6795,19 @@ static void qInitDrawhelperFunctions()
qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_avx2;
extern void QT_FASTCALL comp_func_Source_avx2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
- extern void QT_FASTCALL comp_func_Source_rgb64_avx2(QRgba64 *destPixels, const QRgba64 *srcPixels, int length, uint const_alpha);
extern void QT_FASTCALL comp_func_SourceOver_avx2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
- extern void QT_FASTCALL comp_func_SourceOver_rgb64_avx2(QRgba64 *destPixels, const QRgba64 *srcPixels, int length, uint const_alpha);
extern void QT_FASTCALL comp_func_solid_SourceOver_avx2(uint *destPixels, int length, uint color, uint const_alpha);
- extern void QT_FASTCALL comp_func_solid_SourceOver_rgb64_avx2(QRgba64 *destPixels, int length, QRgba64 color, uint const_alpha);
-
qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_avx2;
- qt_functionForMode64_C[QPainter::CompositionMode_Source] = comp_func_Source_rgb64_avx2;
qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_avx2;
- qt_functionForMode64_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_rgb64_avx2;
qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_avx2;
+#if QT_CONFIG(raster_64bit)
+ extern void QT_FASTCALL comp_func_Source_rgb64_avx2(QRgba64 *destPixels, const QRgba64 *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_SourceOver_rgb64_avx2(QRgba64 *destPixels, const QRgba64 *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_solid_SourceOver_rgb64_avx2(QRgba64 *destPixels, int length, QRgba64 color, uint const_alpha);
+ qt_functionForMode64_C[QPainter::CompositionMode_Source] = comp_func_Source_rgb64_avx2;
+ qt_functionForMode64_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_rgb64_avx2;
qt_functionForModeSolid64_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_rgb64_avx2;
+#endif
extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_scale_helper_avx2(uint *b, uint *end, const QTextureData &image,
int &fx, int &fy, int fdx, int /*fdy*/);
@@ -6470,6 +6819,28 @@ static void qInitDrawhelperFunctions()
bilinearFastTransformHelperARGB32PM[0][SimpleScaleTransform] = fetchTransformedBilinearARGB32PM_simple_scale_helper_avx2;
bilinearFastTransformHelperARGB32PM[0][DownscaleTransform] = fetchTransformedBilinearARGB32PM_downscale_helper_avx2;
bilinearFastTransformHelperARGB32PM[0][FastRotateTransform] = fetchTransformedBilinearARGB32PM_fast_rotate_helper_avx2;
+
+ extern void QT_FASTCALL convertARGB32ToARGB32PM_avx2(uint *buffer, int count, const QVector<QRgb> *);
+ extern void QT_FASTCALL convertRGBA8888ToARGB32PM_avx2(uint *buffer, int count, const QVector<QRgb> *);
+ extern const uint *QT_FASTCALL fetchARGB32ToARGB32PM_avx2(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_avx2(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_avx2;
+ qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_avx2;
+ qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_avx2;
+ qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_avx2;
+
+#if QT_CONFIG(raster_64bit)
+ extern const QRgba64 * QT_FASTCALL convertARGB32ToRGBA64PM_avx2(QRgba64 *, const uint *, int, const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertRGBA8888ToRGBA64PM_avx2(QRgba64 *, const uint *, int count, const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM_avx2(QRgba64 *, const uchar *, int, int, const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_avx2(QRgba64 *, const uchar *, int, int, const QVector<QRgb> *, QDitherInfo *);
+ qPixelLayouts[QImage::Format_ARGB32].convertToRGBA64PM = convertARGB32ToRGBA64PM_avx2;
+ qPixelLayouts[QImage::Format_RGBX8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_avx2;
+ qPixelLayouts[QImage::Format_ARGB32].fetchToRGBA64PM = fetchARGB32ToRGBA64PM_avx2;
+ qPixelLayouts[QImage::Format_RGBX8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_avx2;
+#endif
}
#endif
@@ -6505,6 +6876,14 @@ static void qInitDrawhelperFunctions()
const QVector<QRgb> *, QDitherInfo *);
extern const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_neon(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertARGB32ToRGBA64PM_neon(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertRGBA8888ToRGBA64PM_neon(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM_neon(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_neon(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
extern void QT_FASTCALL storeARGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
extern void QT_FASTCALL storeRGBA8888FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
@@ -6514,10 +6893,16 @@ static void qInitDrawhelperFunctions()
qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_neon;
qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_neon;
qPixelLayouts[QImage::Format_ARGB32].storeFromARGB32PM = storeARGB32FromARGB32PM_neon;
+ qPixelLayouts[QImage::Format_ARGB32].fetchToRGBA64PM = fetchARGB32ToRGBA64PM_neon;
+ qPixelLayouts[QImage::Format_ARGB32].convertToRGBA64PM = convertARGB32ToRGBA64PM_neon;
qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_neon;
qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_neon;
qPixelLayouts[QImage::Format_RGBA8888].storeFromARGB32PM = storeRGBA8888FromARGB32PM_neon;
+ qPixelLayouts[QImage::Format_RGBA8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_neon;
+ qPixelLayouts[QImage::Format_RGBA8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_neon;
qPixelLayouts[QImage::Format_RGBX8888].storeFromARGB32PM = storeRGBXFromARGB32PM_neon;
+ qPixelLayouts[QImage::Format_RGBX8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_neon;
+ qPixelLayouts[QImage::Format_RGBX8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_neon;
#endif
#if defined(ENABLE_PIXMAN_DRAWHELPERS)