diff options
Diffstat (limited to 'src/gui/painting/qdrawhelper.cpp')
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 611 |
1 files changed, 443 insertions, 168 deletions
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 533ad39b86..e5f752b94e 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -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> @@ -88,6 +88,7 @@ template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB444>() { return 4; } template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB555>() { return 5; } template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB666>() { return 6; } template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_BGR888>() { return 8; } template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; } template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; } template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB8565_Premultiplied>() { return 5; } @@ -101,6 +102,7 @@ template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB444>() { return 8; template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB555>() { return 10; } template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB666>() { return 12; } template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB888>() { return 16; } +template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_BGR888>() { return 0; } template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB4444_Premultiplied>() { return 8; } template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB8555_Premultiplied>() { return 18; } template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB8565_Premultiplied>() { return 19; } @@ -119,6 +121,7 @@ template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB444>() { return 4; template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB555>() { return 5; } template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB666>() { return 6; } template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_BGR888>() { return 8; } template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; } template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; } template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB8565_Premultiplied>() { return 6; } @@ -132,6 +135,7 @@ template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB444>() { return 4; template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB555>() { return 5; } template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB666>() { return 6; } template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_BGR888>() { return 8; } template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB4444_Premultiplied>() { return 4; } template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB8555_Premultiplied>() { return 13; } template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB8565_Premultiplied>() { return 13; } @@ -150,6 +154,7 @@ template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB444>() { return 4; template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB555>() { return 5; } template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB666>() { return 6; } template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_BGR888>() { return 8; } template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; } template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; } template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB8565_Premultiplied>() { return 5; } @@ -163,6 +168,7 @@ template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB444>() { return 0; template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB555>() { return 0; } template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB666>() { return 0; } template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB888>() { return 0; } +template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_BGR888>() { return 16; } template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB4444_Premultiplied>() { return 0; } template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB8555_Premultiplied>() { return 8; } template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB8565_Premultiplied>() { return 8; } @@ -181,6 +187,7 @@ template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB444>() { return 0; template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB555>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB666>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB888>() { return 0; } +template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_BGR888>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; } template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB8555_Premultiplied>() { return 8; } template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB8565_Premultiplied>() { return 8; } @@ -194,6 +201,7 @@ template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB444>() { return 0; template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB555>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB666>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB888>() { return 0; } +template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_BGR888>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB4444_Premultiplied>() { return 12; } template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB8555_Premultiplied>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB8565_Premultiplied>() { return 0; } @@ -214,6 +222,7 @@ template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB444>() { r template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB555>() { return QPixelLayout::BPP16; } template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB666>() { return QPixelLayout::BPP24; } template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB888>() { return QPixelLayout::BPP24; } +template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_BGR888>() { return QPixelLayout::BPP24; } template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB4444_Premultiplied>() { return QPixelLayout::BPP16; } template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB8555_Premultiplied>() { return QPixelLayout::BPP24; } template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB8565_Premultiplied>() { return QPixelLayout::BPP24; } @@ -660,8 +669,7 @@ static void QT_FASTCALL rbSwap_rgb30(uchar *d, const uchar *s, int count) { const uint *src = reinterpret_cast<const uint *>(s); uint *dest = reinterpret_cast<uint *>(d); - for (int i = 0; i < count; ++i) - dest[i] = qRgbSwapRgb30(src[i]); + UNALIASED_CONVERSION_LOOP(dest, src, count, qRgbSwapRgb30); } template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixelLayoutRGB() @@ -1117,6 +1125,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) @@ -1126,6 +1135,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 *) @@ -1526,7 +1536,8 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = { { false, false, QPixelLayout::BPP16, nullptr, convertGrayscale16ToRGB32, convertGrayscale16ToRGBA64, fetchGrayscale16ToRGB32, fetchGrayscale16ToRGBA64, - storeGrayscale16FromARGB32PM, storeGrayscale16FromRGB32 } // Format_Grayscale16 + storeGrayscale16FromARGB32PM, storeGrayscale16FromRGB32 }, // Format_Grayscale16 + pixelLayoutRGB<QImage::Format_BGR888>(), }; Q_STATIC_ASSERT(sizeof(qPixelLayouts) / sizeof(*qPixelLayouts) == QImage::NImageFormats); @@ -1641,7 +1652,8 @@ ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = { storeRGBX64FromRGBA64PM, storeRGBA64FromRGBA64PM, storeRGBA64PMFromRGBA64PM, - storeGray16FromRGBA64PM + storeGray16FromRGBA64PM, + storeGenericFromRGBA64PM<QImage::Format_BGR888>, }; /* @@ -1699,22 +1711,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 @@ -1746,8 +1742,26 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] = destFetch, // Format_RGBA64 destFetch, // Format_RGBA64_Premultiplied destFetch, // Format_Grayscale16 + destFetch, // Format_BGR888 }; +#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 @@ -1779,7 +1793,9 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] = destFetch64, // Format_RGBA64 destFetchRGB64, // Format_RGBA64_Premultiplied destFetch64, // Format_Grayscale16 + destFetch64, // Format_BGR888 }; +#endif /* Returns the color in the mono destination color table @@ -1887,21 +1903,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 @@ -1933,8 +1934,25 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] = destStore, // Format_RGBA64 destStore, // Format_RGBA64_Premultiplied destStore, // Format_Grayscale16 + destStore, // Format_BGR888 }; +#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 @@ -1966,7 +1984,9 @@ static DestStoreProc64 destStoreProc64[QImage::NImageFormats] = destStore64RGBA64, // Format_RGBA64 0, // Format_RGBA64_Premultiplied destStore64, // Format_Grayscale16 + destStore64, // Format_BGR888 }; +#endif /* Source fetches @@ -2017,6 +2037,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) { @@ -2030,6 +2051,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) @@ -2237,6 +2259,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) @@ -2257,6 +2280,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. @@ -3558,6 +3582,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) @@ -3878,6 +3903,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] = { @@ -3910,6 +3936,7 @@ static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = { fetchUntransformed, // RGBA64 fetchUntransformed, // RGBA64_Premultiplied fetchUntransformed, // Grayscale16 + fetchUntransformed, // BGR888 }; static const SourceFetchProc sourceFetchGeneric[NBlendTypes] = { @@ -3948,6 +3975,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 @@ -3966,25 +4007,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 @@ -3996,11 +4025,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) { @@ -4034,6 +4065,7 @@ public: } }; +#if QT_CONFIG(raster_64bit) class GradientBase64 { public: @@ -4052,6 +4084,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( @@ -4129,11 +4162,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) { @@ -4195,11 +4230,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( @@ -4258,23 +4295,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) { @@ -4306,41 +4349,58 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in case QSpanData::Solid: 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; @@ -4357,18 +4417,25 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in // 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; } @@ -4475,6 +4542,7 @@ 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, nullptr, 0); if (!op.funcSolid64) { @@ -4509,6 +4577,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) @@ -4689,6 +4760,7 @@ public: } }; +#if QT_CONFIG(raster_64bit) class BlendSrcGenericRGB64 : public QBlendBase<QRgba64> { public: @@ -4719,6 +4791,7 @@ public: op.destStore64(data->rasterBuffer, x, y, dest, len); } }; +#endif static void blend_src_generic(int count, const QSpan *spans, void *userData) { @@ -4727,6 +4800,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); @@ -4740,6 +4814,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) { @@ -4787,6 +4862,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); @@ -4836,6 +4912,7 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi } } } +#endif static void blend_untransformed_argb(int count, const QSpan *spans, void *userData) { @@ -5036,6 +5113,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); @@ -5131,6 +5209,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) { @@ -5307,6 +5386,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 @@ -5315,6 +5395,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) { @@ -5328,6 +5409,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: @@ -5342,6 +5424,7 @@ void qBlendTexture(int count, const QSpan *spans, void *userData) case QImage::Format_Grayscale16: proc = processTextureSpansGeneric64[blendType]; break; +#endif // QT_CONFIG(raster_64bit) case QImage::Format_Invalid: Q_UNREACHABLE(); return; @@ -5409,7 +5492,11 @@ static void blend_vertical_gradient(int count, const QSpan *spans, void *userDat 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; } @@ -5432,6 +5519,7 @@ void qBlendGradient(int count, const QSpan *spans, void *userData) 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: @@ -5446,6 +5534,7 @@ void qBlendGradient(int count, const QSpan *spans, void *userData) 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: @@ -5555,29 +5644,77 @@ 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) { - dest[x] = src; + } else if (coverage == 255 || !colorProfile) { + blend_pixel(*dst, src, coverage); + } else if (*dst < 0xff000000) { + // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571 + blend_pixel(*dst, src, coverage); + } else if (src >= 0xff000000) { + grayBlendPixel(dst, coverage, srcLinear, colorProfile); } else { - QRgba64 dstColor = dest[x]; - if (colorProfile) { - if (dstColor.isOpaque()) - dstColor = colorProfile->toLinear(dstColor); - else if (!dstColor.isTransparent()) - dstColor = colorProfile->toLinear(dstColor.unpremultiplied()).premultiplied(); - } + // First do naive blend with text-color + QRgb s = *dst; + blend_pixel(s, src); + // Then gamma-corrected blend with glyph shape + QRgba64 s64 = colorProfile ? colorProfile->toLinear64(s) : QRgba64::fromArgb32(s); + grayBlendPixel(dst, coverage, s64, colorProfile); + } +} - dstColor = interpolate255(srcLinear, coverage, dstColor, 255 - coverage); - if (colorProfile) { - if (dstColor.isOpaque()) - dstColor = colorProfile->fromLinear(dstColor); - else if (!dstColor.isTransparent()) - dstColor = colorProfile->fromLinear(dstColor.unpremultiplied()).premultiplied(); - } - dest[x] = dstColor; +#if QT_CONFIG(raster_64bit) + +static inline void grayBlendPixel(QRgba64 &dst, int coverage, QRgba64 srcLinear, const QColorTrcLut *colorProfile) +{ + // Do a gammacorrected gray alphablend... + QRgba64 dstColor = dst; + if (colorProfile) { + if (dstColor.isOpaque()) + dstColor = colorProfile->toLinear(dstColor); + else if (!dstColor.isTransparent()) + dstColor = colorProfile->toLinear(dstColor.unpremultiplied()).premultiplied(); + } + + blend_pixel(dstColor, srcLinear, coverage); + + if (colorProfile) { + if (dstColor.isOpaque()) + dstColor = colorProfile->fromLinear(dstColor); + else if (!dstColor.isTransparent()) + dstColor = colorProfile->fromLinear(dstColor.unpremultiplied()).premultiplied(); + } + dst = dstColor; +} + +static inline void alphamapblend_generic(int coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorTrcLut *colorProfile) +{ + if (coverage == 0) { + // nothing + } else if (coverage == 255) { + blend_pixel(dest[x], src); + } else if (src.isOpaque()) { + grayBlendPixel(dest[x], coverage, srcLinear, colorProfile); + } else { + // First do naive blend with text-color + QRgba64 s = dest[x]; + blend_pixel(s, src); + // Then gamma-corrected blend with glyph shape + if (colorProfile) + s = colorProfile->toLinear(s); + grayBlendPixel(dest[x], coverage, s, colorProfile); } } @@ -5590,18 +5727,14 @@ 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(); QRgba64 srcColor = color; - if (colorProfile) { - if (color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); - else - srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); - } + if (colorProfile && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); alignas(8) QRgba64 buffer[BufferSize]; const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format]; @@ -5656,6 +5789,81 @@ 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 && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); + + 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) { @@ -5675,7 +5883,7 @@ void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, int mapWidth, int mapHeight, int mapStride, const QClipData *clip, bool useGammaCorrection) { - if (useGammaCorrection) { + if (useGammaCorrection || !color.isOpaque()) { qt_alphamapblit_generic(rasterBuffer, x, y, color, map, mapWidth, mapHeight, mapStride, clip, useGammaCorrection); return; } @@ -5716,44 +5924,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, @@ -5766,18 +5936,14 @@ 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(); QRgba64 srcColor = color; - if (colorProfile) { - if (color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); - else - srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); - } + if (colorProfile && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); if (!clip) { quint32 *dest = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x; @@ -5822,6 +5988,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__) @@ -5862,42 +6038,59 @@ 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) +static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba64 &srcLinear, quint32 src, const QColorTrcLut *colorProfile) { if (coverage == 0xff000000) { // nothing - } else if (coverage == 0xffffffff) { - dest[x] = src; + } else if (coverage == 0xffffffff && qAlpha(src) == 255) { + blend_pixel(*dst, src); + } else if (!colorProfile) { + *dst = rgbBlend(*dst, src, coverage); + } else if (*dst < 0xff000000) { + // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571 + blend_pixel(*dst, src, qRgbAvg(coverage)); + } else if (srcLinear.isOpaque()) { + rgbBlendPixel(dst, coverage, srcLinear, colorProfile); } else { - QRgba64 dstColor = dest[x]; - if (dstColor.isOpaque()) { - if (colorProfile) - dstColor = colorProfile->toLinear(dstColor); - dstColor = rgbBlend(dstColor, srcLinear, coverage); - if (colorProfile) - dstColor = colorProfile->fromLinear(dstColor); - dest[x] = dstColor; - } else { - // Do a gray alphablend. - alphamapblend_generic(qRgbAvg(coverage), dest, x, srcLinear, src, colorProfile); - } + // First do naive blend with text-color + QRgb s = *dst; + blend_pixel(s, src); + // Then gamma-corrected blend with glyph shape + QRgba64 s64 = colorProfile ? colorProfile->toLinear64(s) : QRgba64::fromArgb32(s); + rgbBlendPixel(dst, coverage, s64, colorProfile); } } -static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba64 &srcLinear, quint32 src, const QColorProfile *colorProfile) +#if QT_CONFIG(raster_64bit) +static inline void rgbBlendPixel(QRgba64 &dst, int coverage, QRgba64 slinear, const QColorTrcLut *colorProfile) +{ + // Do a gammacorrected RGB alphablend... + const QRgba64 dlinear = colorProfile ? colorProfile->toLinear64(dst) : dst; + + QRgba64 blend = rgbBlend(dlinear, slinear, coverage); + + dst = colorProfile ? colorProfile->fromLinear(blend) : blend; +} + +static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorTrcLut *colorProfile) { if (coverage == 0xff000000) { // nothing } else if (coverage == 0xffffffff) { - *dst = src; - } else if (*dst < 0xff000000) { - // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571 - const int a = qRgbAvg(coverage); - *dst = INTERPOLATE_PIXEL_255(src, a, *dst, 255 - a); - } else if (!colorProfile) { - *dst = rgbBlend(*dst, src, coverage); - } else { - rgbBlendPixel(dst, coverage, srcLinear, colorProfile); + blend_pixel(dest[x], src); + } else if (!dest[x].isOpaque()) { + // Do a gray alphablend. + alphamapblend_generic(qRgbAvg(coverage), dest, x, srcLinear, src, colorProfile); + } else if (src.isOpaque()) { + rgbBlendPixel(dest[x], coverage, srcLinear, colorProfile); + } else { + // First do naive blend with text-color + QRgba64 s = dest[x]; + blend_pixel(s, src); + // Then gamma-corrected blend with glyph shape + if (colorProfile) + s = colorProfile->toLinear(s); + rgbBlendPixel(dest[x], coverage, s, colorProfile); } } @@ -5909,18 +6102,14 @@ 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(); QRgba64 srcColor = color; - if (colorProfile) { - if (color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); - else - srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); - } + if (colorProfile && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); alignas(8) QRgba64 buffer[BufferSize]; const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format]; @@ -5975,6 +6164,80 @@ 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 && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); + + 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, @@ -5986,18 +6249,14 @@ 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(); QRgba64 srcColor = color; - if (colorProfile) { - if (color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); - else - srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); - } + if (colorProfile && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); if (!clip) { quint32 *dst = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x; @@ -6354,6 +6613,14 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = qt_alphargbblit_generic, qt_rectfill_quint16 }, + // Format_BGR888 + { + blend_color_generic, + 0, + qt_alphamapblit_generic, + qt_alphargbblit_generic, + qt_rectfill_quint24 + }, }; #if !defined(__SSE2__) @@ -6515,6 +6782,9 @@ static void qInitDrawhelperFunctions() qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; sourceFetchUntransformed[QImage::Format_RGB888] = qt_fetchUntransformed_888_ssse3; + extern void QT_FASTCALL rbSwap_888_ssse3(uchar *dst, const uchar *src, int count); + qPixelLayouts[QImage::Format_RGB888].rbSwap = rbSwap_888_ssse3; + qPixelLayouts[QImage::Format_BGR888].rbSwap = rbSwap_888_ssse3; } #endif // SSSE3 @@ -6565,8 +6835,10 @@ 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 @@ -6590,18 +6862,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*/); @@ -6625,6 +6898,7 @@ static void qInitDrawhelperFunctions() 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 *); @@ -6633,6 +6907,7 @@ static void qInitDrawhelperFunctions() qPixelLayouts[QImage::Format_RGBX8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_avx2; qPixelLayouts[QImage::Format_ARGB32].fetchToRGBA64PM = fetchARGB32ToRGBA64PM_avx2; qPixelLayouts[QImage::Format_RGBX8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_avx2; +#endif } #endif |