diff options
Diffstat (limited to 'src/gui/painting/qdrawhelper.cpp')
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 841 |
1 files changed, 388 insertions, 453 deletions
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index f3df62b855..6d55803e80 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -73,9 +73,6 @@ enum { half_point = 1 << 15 }; -// must be multiple of 4 for easier SIMD implementations -static const int buffer_size = 2048; - template<QImage::Format> Q_DECL_CONSTEXPR uint redWidth(); template<QImage::Format> Q_DECL_CONSTEXPR uint redShift(); template<QImage::Format> Q_DECL_CONSTEXPR uint greenWidth(); @@ -94,6 +91,10 @@ template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB4444_Premultiplied> template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; } template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB8565_Premultiplied>() { return 5; } template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; } +template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGBX8888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGBA8888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; } + template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB16>() { return 11; } template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB444>() { return 8; } template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB555>() { return 10; } @@ -103,6 +104,15 @@ template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB4444_Premultiplied> template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB8555_Premultiplied>() { return 18; } template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB8565_Premultiplied>() { return 19; } template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB6666_Premultiplied>() { return 12; } +#if Q_BYTE_ORDER == Q_BIG_ENDIAN +template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBX8888>() { return 24; } +template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBA8888>() { return 24; } +template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBA8888_Premultiplied>() { return 24; } +#else +template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBX8888>() { return 0; } +template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBA8888>() { return 0; } +template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBA8888_Premultiplied>() { return 0; } +#endif template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB16>() { return 6; } template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB444>() { return 4; } template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB555>() { return 5; } @@ -112,6 +122,10 @@ template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB4444_Premultiplie template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; } template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB8565_Premultiplied>() { return 6; } template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; } +template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGBX8888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGBA8888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; } + template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB16>() { return 5; } template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB444>() { return 4; } template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB555>() { return 5; } @@ -121,6 +135,15 @@ template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB4444_Premultiplie template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB8555_Premultiplied>() { return 13; } template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB8565_Premultiplied>() { return 13; } template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB6666_Premultiplied>() { return 6; } +#if Q_BYTE_ORDER == Q_BIG_ENDIAN +template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBX8888>() { return 16; } +template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBA8888>() { return 16; } +template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBA8888_Premultiplied>() { return 16; } +#else +template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBX8888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBA8888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBA8888_Premultiplied>() { return 8; } +#endif template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB16>() { return 5; } template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB444>() { return 4; } template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB555>() { return 5; } @@ -130,6 +153,10 @@ template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB4444_Premultiplied template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; } template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB8565_Premultiplied>() { return 5; } template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; } +template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGBX8888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGBA8888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; } + template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB16>() { return 0; } template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB444>() { return 0; } template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB555>() { return 0; } @@ -139,6 +166,15 @@ template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB4444_Premultiplied template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB8555_Premultiplied>() { return 8; } template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB8565_Premultiplied>() { return 8; } template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB6666_Premultiplied>() { return 0; } +#if Q_BYTE_ORDER == Q_BIG_ENDIAN +template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBX8888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBA8888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBA8888_Premultiplied>() { return 8; } +#else +template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBX8888>() { return 16; } +template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBA8888>() { return 16; } +template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBA8888_Premultiplied>() { return 16; } +#endif template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB16>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB444>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB555>() { return 0; } @@ -148,6 +184,10 @@ template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB4444_Premultiplie template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB8555_Premultiplied>() { return 8; } template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB8565_Premultiplied>() { return 8; } template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; } +template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGBX8888>() { return 0; } +template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGBA8888>() { return 8; } +template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; } + template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB16>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB444>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB555>() { return 0; } @@ -157,6 +197,15 @@ template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB4444_Premultiplie template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB8555_Premultiplied>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB8565_Premultiplied>() { return 0; } template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB6666_Premultiplied>() { return 18; } +#if Q_BYTE_ORDER == Q_BIG_ENDIAN +template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBX8888>() { return 0; } +template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBA8888>() { return 0; } +template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBA8888_Premultiplied>() { return 0; } +#else +template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBX8888>() { return 24; } +template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBA8888>() { return 24; } +template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBA8888_Premultiplied>() { return 24; } +#endif template<QImage::Format> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel(); template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB16>() { return QPixelLayout::BPP16; } @@ -168,6 +217,9 @@ template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB44 template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB8555_Premultiplied>() { return QPixelLayout::BPP24; } template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB8565_Premultiplied>() { return QPixelLayout::BPP24; } template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB6666_Premultiplied>() { return QPixelLayout::BPP24; } +template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGBX8888>() { return QPixelLayout::BPP32; } +template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGBA8888>() { return QPixelLayout::BPP32; } +template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGBA8888_Premultiplied>() { return QPixelLayout::BPP32; } template<QImage::Format Format> @@ -450,16 +502,68 @@ static const uint *QT_FASTCALL convertARGBPMFromARGB32PM(uint *buffer, const uin return buffer; } +template<QImage::Format Format> +static const uint *QT_FASTCALL rbSwap(uint *buffer, const uint *src, int count) +{ + Q_CONSTEXPR uchar aWidth = alphaWidth<Format>(); + Q_CONSTEXPR uchar aShift = alphaShift<Format>(); + Q_CONSTEXPR uchar rWidth = redWidth<Format>(); + Q_CONSTEXPR uchar rShift = redShift<Format>(); + Q_CONSTEXPR uchar gWidth = greenWidth<Format>(); + Q_CONSTEXPR uchar gShift = greenShift<Format>(); + Q_CONSTEXPR uchar bWidth = blueWidth<Format>(); + Q_CONSTEXPR uchar bShift = blueShift<Format>(); #ifdef Q_COMPILER_CONSTEXPR + Q_STATIC_ASSERT(rWidth == bWidth); +#endif + Q_CONSTEXPR uint redBlueMask = (1 << rWidth) - 1; + Q_CONSTEXPR uint alphaGreenMask = (((1 << aWidth) - 1) << aShift) + | (((1 << gWidth) - 1) << gShift); + + for (int i = 0; i < count; ++i) { + const uint c = src[i]; + const uint r = (c >> rShift) & redBlueMask; + const uint b = (c >> bShift) & redBlueMask; + buffer[i] = (c & alphaGreenMask) + | (r << bShift) + | (b << rShift); + } + return buffer; +} + +static const uint *QT_FASTCALL rbSwap_rgb32(uint *buffer, const uint *src, int count) +{ + for (int i = 0; i < count; ++i) { + const uint c = src[i]; + const uint ag = c & 0xff00ff00; + const uint rb = c & 0x00ff00ff; + buffer[i] = ag | (rb << 16) | (rb >> 16); + } + return buffer; +} + +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN +template<> +const uint *QT_FASTCALL rbSwap<QImage::Format_RGBA8888>(uint *buffer, const uint *src, int count) +{ + return rbSwap_rgb32(buffer, src, count); +} +#endif + +static const uint *QT_FASTCALL rbSwap_rgb30(uint *buffer, const uint *src, int count) +{ + for (int i = 0; i < count; ++i) + buffer[i] = qRgbSwapRgb30(src[i]); + return buffer; +} template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixelLayoutRGB() { return QPixelLayout{ - uchar(redWidth<Format>()), uchar(redShift<Format>()), - uchar(greenWidth<Format>()), uchar(greenShift<Format>()), - uchar(blueWidth<Format>()), uchar(blueShift<Format>()), - 0, 0, - false, bitsPerPixel<Format>(), + false, + false, + bitsPerPixel<Format>(), + rbSwap<Format>, convertToRGB32<Format>, convertRGBFromARGB32PM<Format, false>, convertRGBFromARGB32PM<Format, true>, @@ -470,11 +574,10 @@ template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixe template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixelLayoutARGBPM() { return QPixelLayout{ - uchar(redWidth<Format>()), uchar(redShift<Format>()), - uchar(greenWidth<Format>()), uchar(greenShift<Format>()), - uchar(blueWidth<Format>()), uchar(blueShift<Format>()), - uchar(alphaWidth<Format>()), uchar(alphaShift<Format>()), - true, bitsPerPixel<Format>(), + true, + true, + bitsPerPixel<Format>(), + rbSwap<Format>, convertARGBPMToARGB32PM<Format>, convertARGBPMFromARGB32PM<Format, false>, convertARGBPMFromARGB32PM<Format, true>, @@ -482,8 +585,6 @@ template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixe }; } -#endif - // To convert in place, let 'dest' and 'src' be the same. static const uint *QT_FASTCALL convertIndexedToARGB32PM(uint *buffer, const uint *src, int count, const QVector<QRgb> *clut, QDitherInfo *) @@ -953,16 +1054,15 @@ inline void QT_FASTCALL storePixels<QPixelLayout::BPP32>(uchar *dest, const uint // convertFromArgb32() assumes that no color channel is more than 8 bits. // QImage::rgbSwapped() assumes that the red and blue color channels have the same number of bits. QPixelLayout qPixelLayouts[QImage::NImageFormats] = { - { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPPNone, 0, 0, 0, 0 }, // Format_Invalid - { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1MSB, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_Mono - { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1LSB, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_MonoLSB - { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_Indexed8 + { false, false, QPixelLayout::BPPNone, nullptr, nullptr, nullptr, nullptr, nullptr }, // Format_Invalid + { false, false, QPixelLayout::BPP1MSB, nullptr, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_Mono + { false, false, QPixelLayout::BPP1LSB, nullptr, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_MonoLSB + { false, false, QPixelLayout::BPP8, nullptr, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_Indexed8 // Technically using convertPassThrough to convert from ARGB32PM to RGB32 is wrong, // but everywhere this generic conversion would be wrong is currently overloaded. - { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB32ToRGB64 }, // Format_RGB32 - { 8, 16, 8, 8, 8, 0, 8, 24, false, QPixelLayout::BPP32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM, convertPassThrough, convertARGB32ToARGB64PM }, // Format_ARGB32 - { 8, 16, 8, 8, 8, 0, 8, 24, true, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough, convertARGB32PMToARGB64PM }, // Format_ARGB32_Premultiplied -#ifdef Q_COMPILER_CONSTEXPR + { false, false, QPixelLayout::BPP32, rbSwap_rgb32, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB32ToRGB64 }, // Format_RGB32 + { true, false, QPixelLayout::BPP32, rbSwap_rgb32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM, convertPassThrough, convertARGB32ToARGB64PM }, // Format_ARGB32 + { true, true, QPixelLayout::BPP32, rbSwap_rgb32, convertPassThrough, convertPassThrough, convertPassThrough, convertARGB32PMToARGB64PM }, // Format_ARGB32_Premultiplied pixelLayoutRGB<QImage::Format_RGB16>(), pixelLayoutARGBPM<QImage::Format_ARGB8565_Premultiplied>(), pixelLayoutRGB<QImage::Format_RGB666>(), @@ -972,77 +1072,15 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = { pixelLayoutRGB<QImage::Format_RGB888>(), pixelLayoutRGB<QImage::Format_RGB444>(), pixelLayoutARGBPM<QImage::Format_ARGB4444_Premultiplied>(), -#else - { 5, 11, 6, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, - convertToRGB32<QImage::Format_RGB16>, - convertRGBFromARGB32PM<QImage::Format_RGB16, false>, - convertRGBFromARGB32PM<QImage::Format_RGB16, true>, - convertToRGB64<QImage::Format_RGB16>, - }, - { 5, 19, 6, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, - convertARGBPMToARGB32PM<QImage::Format_ARGB8565_Premultiplied>, - convertARGBPMFromARGB32PM<QImage::Format_ARGB8565_Premultiplied, false>, - convertARGBPMFromARGB32PM<QImage::Format_ARGB8565_Premultiplied, true>, - convertARGBPMToARGB64PM<QImage::Format_ARGB8565_Premultiplied>, - }, - { 6, 12, 6, 6, 6, 0, 0, 0, false, QPixelLayout::BPP24, - convertToRGB32<QImage::Format_RGB666>, - convertRGBFromARGB32PM<QImage::Format_RGB666, false>, - convertRGBFromARGB32PM<QImage::Format_RGB666, true>, - convertToRGB64<QImage::Format_RGB666>, - }, - { 6, 12, 6, 6, 6, 0, 6, 18, true, QPixelLayout::BPP24, - convertARGBPMToARGB32PM<QImage::Format_ARGB6666_Premultiplied>, - convertARGBPMFromARGB32PM<QImage::Format_ARGB6666_Premultiplied, false>, - convertARGBPMFromARGB32PM<QImage::Format_ARGB6666_Premultiplied, true>, - convertARGBPMToARGB64PM<QImage::Format_ARGB6666_Premultiplied>, - }, - { 5, 10, 5, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, - convertToRGB32<QImage::Format_RGB555>, - convertRGBFromARGB32PM<QImage::Format_RGB555, false>, - convertRGBFromARGB32PM<QImage::Format_RGB555, true>, - convertToRGB64<QImage::Format_RGB555>, - }, - { 5, 18, 5, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, - convertARGBPMToARGB32PM<QImage::Format_ARGB8555_Premultiplied>, - convertARGBPMFromARGB32PM<QImage::Format_ARGB8555_Premultiplied, false>, - convertARGBPMFromARGB32PM<QImage::Format_ARGB8555_Premultiplied, true>, - convertARGBPMToARGB64PM<QImage::Format_ARGB8555_Premultiplied>, - }, - { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP24, - convertToRGB32<QImage::Format_RGB888>, - convertRGBFromARGB32PM<QImage::Format_RGB888, false>, - convertRGBFromARGB32PM<QImage::Format_RGB888, true>, - convertToRGB64<QImage::Format_RGB888>, - }, - { 4, 8, 4, 4, 4, 0, 0, 0, false, QPixelLayout::BPP16, - convertToRGB32<QImage::Format_RGB444>, - convertRGBFromARGB32PM<QImage::Format_RGB444, false>, - convertRGBFromARGB32PM<QImage::Format_RGB444, true>, - convertToRGB64<QImage::Format_RGB444>, - }, - { 4, 8, 4, 4, 4, 0, 4, 12, true, QPixelLayout::BPP16, - convertARGBPMToARGB32PM<QImage::Format_ARGB4444_Premultiplied>, - convertARGBPMFromARGB32PM<QImage::Format_ARGB4444_Premultiplied, false>, - convertARGBPMFromARGB32PM<QImage::Format_ARGB4444_Premultiplied, true>, - convertARGBPMToARGB64PM<QImage::Format_ARGB4444_Premultiplied>, - }, -#endif -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - { 8, 24, 8, 16, 8, 8, 0, 0, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBX8888 - { 8, 24, 8, 16, 8, 8, 8, 0, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToARGB64PM }, // Format_RGBA8888 - { 8, 24, 8, 16, 8, 8, 8, 0, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM}, // Format_RGBA8888_Premultiplied -#else - { 8, 0, 8, 8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBX8888 - { 8, 0, 8, 8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToARGB64PM }, // Format_RGBA8888 (ABGR32) - { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBA8888_Premultiplied -#endif - { 10, 20, 10, 10, 10, 0, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertRGB30FromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_BGR30 - { 10, 20, 10, 10, 10, 0, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertA2RGB30PMFromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_A2BGR30_Premultiplied - { 10, 0, 10, 10, 10, 20, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertRGB30FromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_RGB30 - { 10, 0, 10, 10, 10, 20, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertA2RGB30PMFromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied - { 0, 0, 0, 0, 0, 0, 8, 0, true, QPixelLayout::BPP8, convertAlpha8ToRGB32, convertAlpha8FromARGB32PM, 0, convertAlpha8ToRGB64 }, // Format_Alpha8 - { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertGrayscale8ToRGB32, convertGrayscale8FromARGB32PM, convertGrayscale8FromRGB32, convertGrayscale8ToRGB64 } // Format_Grayscale8 + { false, false, QPixelLayout::BPP32, rbSwap<QImage::Format_RGBA8888>, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBX8888 + { true, false, QPixelLayout::BPP32, rbSwap<QImage::Format_RGBA8888>, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToARGB64PM }, // Format_RGBA8888 (ABGR32) + { true, true, QPixelLayout::BPP32, rbSwap<QImage::Format_RGBA8888>, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBA8888_Premultiplied + { false, false, QPixelLayout::BPP32, rbSwap_rgb30, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertRGB30FromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_BGR30 + { true, true, QPixelLayout::BPP32, rbSwap_rgb30, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertA2RGB30PMFromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_A2BGR30_Premultiplied + { false, false, QPixelLayout::BPP32, rbSwap_rgb30, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertRGB30FromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_RGB30 + { true, true, QPixelLayout::BPP32, rbSwap_rgb30, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertA2RGB30PMFromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied + { true, true, QPixelLayout::BPP8, nullptr, convertAlpha8ToRGB32, convertAlpha8FromARGB32PM, 0, convertAlpha8ToRGB64 }, // Format_Alpha8 + { false, false, QPixelLayout::BPP8, nullptr, convertGrayscale8ToRGB32, convertGrayscale8FromARGB32PM, convertGrayscale8FromRGB32, convertGrayscale8ToRGB64 } // Format_Grayscale8 }; const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = { @@ -1131,7 +1169,7 @@ static uint *QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer, in static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) { const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format]; - uint buffer32[buffer_size]; + uint buffer32[BufferSize]; const uint *ptr = qFetchPixels[layout->bpp](buffer32, rasterBuffer->scanLine(y), x, length); return const_cast<QRgba64 *>(layout->convertToARGB64PM(buffer, ptr, length, 0, 0)); } @@ -1304,14 +1342,14 @@ static void QT_FASTCALL destStoreRGB16(QRasterBuffer *rasterBuffer, int x, int y static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) { - uint buf[buffer_size]; + uint buf[BufferSize]; const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format]; StorePixelsFunc store = qStorePixels[layout->bpp]; uchar *dest = rasterBuffer->scanLine(y); while (length) { - int l = qMin(length, buffer_size); + int l = qMin(length, BufferSize); const uint *ptr = 0; - if (!layout->premultiplied && !layout->alphaWidth) + if (!layout->premultiplied && !layout->hasAlphaChannel) ptr = layout->convertFromRGB32(buf, buffer, l, 0, 0); else ptr = layout->convertFromARGB32PM(buf, buffer, l, 0, 0); @@ -1331,15 +1369,15 @@ static void QT_FASTCALL convertFromRgb64(uint *dest, const QRgba64 *src, int len static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length) { - uint buf[buffer_size]; + uint buf[BufferSize]; const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format]; StorePixelsFunc store = qStorePixels[layout->bpp]; uchar *dest = rasterBuffer->scanLine(y); while (length) { - int l = qMin(length, buffer_size); + int l = qMin(length, BufferSize); const uint *ptr = 0; convertFromRgb64(buf, buffer, l); - if (!layout->premultiplied && !layout->alphaWidth) + if (!layout->premultiplied && !layout->hasAlphaChannel) ptr = layout->convertFromRGB32(buf, buf, l, 0, 0); else ptr = layout->convertFromARGB32PM(buf, buf, l, 0, 0); @@ -1554,7 +1592,7 @@ static const QRgba64 *QT_FASTCALL fetchUntransformed64(QRgba64 *buffer, const Op { const QPixelLayout *layout = &qPixelLayouts[data->texture.format]; if (layout->bpp != QPixelLayout::BPP32) { - uint buffer32[buffer_size]; + uint buffer32[BufferSize]; const uint *ptr = qFetchPixels[layout->bpp](buffer32, data->texture.scanLine(y), x, length); return layout->convertToARGB64PM(buffer, ptr, length, data->texture.colorTable, 0); } else { @@ -1673,7 +1711,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper FetchPixelFunc fetch = qFetchPixel[layout->bpp]; const QVector<QRgb> *clut = data->texture.colorTable; - uint buffer32[buffer_size]; + uint buffer32[BufferSize]; QRgba64 *b = buffer; if (data->fast_matrix) { // The increment pr x in the scanline @@ -1687,9 +1725,9 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper int i = 0, j = 0; while (i < length) { - if (j == buffer_size) { - layout->convertToARGB64PM(b, buffer32, buffer_size, clut, 0); - b += buffer_size; + if (j == BufferSize) { + layout->convertToARGB64PM(b, buffer32, BufferSize, clut, 0); + b += BufferSize; j = 0; } int px = fx >> 16; @@ -1725,9 +1763,9 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper int i = 0, j = 0; while (i < length) { - if (j == buffer_size) { - layout->convertToARGB64PM(b, buffer32, buffer_size, clut, 0); - b += buffer_size; + if (j == BufferSize) { + layout->convertToARGB64PM(b, buffer32, BufferSize, clut, 0); + b += BufferSize; j = 0; } const qreal iw = fw == 0 ? 1 : 1 / fw; @@ -1921,7 +1959,7 @@ inline void fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(int, } enum FastTransformTypes { - SimpleUpscaleTransform, + SimpleScaleTransform, UpscaleTransform, DownscaleTransform, RotateTransform, @@ -1929,11 +1967,38 @@ enum FastTransformTypes { NFastTransformTypes }; +// Completes the partial interpolation stored in IntermediateBuffer. +// by performing the x-axis interpolation and joining the RB and AG buffers. +static void QT_FASTCALL intermediate_adder(uint *b, uint *end, const IntermediateBuffer &intermediate, int offset, int &fx, int fdx) +{ +#if defined(QT_COMPILER_SUPPORTS_AVX2) + extern void QT_FASTCALL intermediate_adder_avx2(uint *b, uint *end, const IntermediateBuffer &intermediate, int offset, int &fx, int fdx); + if (qCpuHasFeature(AVX2)) + return intermediate_adder_avx2(b, end, intermediate, offset, fx, fdx); +#endif + + // Switch to intermediate buffer coordinates + fx -= offset * fixed_scale; + + while (b < end) { + const int x = (fx >> 16); + + const uint distx = (fx & 0x0000ffff) >> 8; + const uint idistx = 256 - distx; + const uint rb = (intermediate.buffer_rb[x] * idistx + intermediate.buffer_rb[x + 1] * distx) & 0xff00ff00; + const uint ag = (intermediate.buffer_ag[x] * idistx + intermediate.buffer_ag[x + 1] * distx) & 0xff00ff00; + *b = (rb >> 8) | ag; + b++; + fx += fdx; + } + fx += offset * fixed_scale; +} + typedef void (QT_FASTCALL *BilinearFastTransformHelper)(uint *b, uint *end, const QTextureData &image, int &fx, int &fy, int fdx, int fdy); template<TextureBlendType blendType> -static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(uint *b, uint *end, const QTextureData &image, - int &fx, int &fy, int fdx, int /*fdy*/) +static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_scale_helper(uint *b, uint *end, const QTextureData &image, + int &fx, int &fy, int fdx, int /*fdy*/) { int y1 = (fy >> 16); int y2; @@ -1950,16 +2015,12 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(u const int offset = (fx + adjust) >> 16; int x = offset; - // The idea is first to do the interpolation between the row s1 and the row s2 - // into an intermediate buffer, then we interpolate between two pixel of this buffer. - - // intermediate_buffer[0] is a buffer of red-blue component of the pixel, in the form 0x00RR00BB - // intermediate_buffer[1] is the alpha-green component of the pixel, in the form 0x00AA00GG - // +1 for the last pixel to interpolate with, and +1 for rounding errors. - quint32 intermediate_buffer[2][buffer_size + 2]; - // count is the size used in the intermediate_buffer. + IntermediateBuffer intermediate; + // count is the size used in the intermediate.buffer. int count = (qint64(length) * qAbs(fdx) + fixed_scale - 1) / fixed_scale + 2; - Q_ASSERT(count <= buffer_size + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case + // length is supposed to be <= BufferSize either because data->m11 < 1 or + // data->m11 < 2, and any larger buffers split + Q_ASSERT(count <= BufferSize + 2); int f = 0; int lim = count; if (blendType == BlendTransformedBilinearTiled) { @@ -1974,8 +2035,8 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(u quint32 rb = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; quint32 ag = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; do { - intermediate_buffer[0][f] = rb; - intermediate_buffer[1][f] = ag; + intermediate.buffer_rb[f] = rb; + intermediate.buffer_ag[f] = ag; f++; x++; } while (x < image.x1 && f < lim); @@ -2008,10 +2069,10 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(u // Add the values, and shift to only keep 8 significant bits per colors __m128i rAG =_mm_add_epi16(topAG, bottomAG); rAG = _mm_srli_epi16(rAG, 8); - _mm_storeu_si128((__m128i*)(&intermediate_buffer[1][f]), rAG); + _mm_storeu_si128((__m128i*)(&intermediate.buffer_ag[f]), rAG); __m128i rRB =_mm_add_epi16(topRB, bottomRB); rRB = _mm_srli_epi16(rRB, 8); - _mm_storeu_si128((__m128i*)(&intermediate_buffer[0][f]), rRB); + _mm_storeu_si128((__m128i*)(&intermediate.buffer_rb[f]), rRB); } #elif defined(__ARM_NEON__) const int16x8_t disty_ = vdupq_n_s16(disty); @@ -2038,10 +2099,10 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(u // Add the values, and shift to only keep 8 significant bits per colors int16x8_t rAG = vaddq_s16(topAG, bottomAG); rAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(rAG), 8)); - vst1q_s16((int16_t*)(&intermediate_buffer[1][f]), rAG); + vst1q_s16((int16_t*)(&intermediate.buffer_ag[f]), rAG); int16x8_t rRB = vaddq_s16(topRB, bottomRB); rRB = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(rRB), 8)); - vst1q_s16((int16_t*)(&intermediate_buffer[0][f]), rRB); + vst1q_s16((int16_t*)(&intermediate.buffer_rb[f]), rRB); } #endif } @@ -2055,28 +2116,13 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(u uint t = s1[x]; uint b = s2[x]; - intermediate_buffer[0][f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; - intermediate_buffer[1][f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; + intermediate.buffer_rb[f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; + intermediate.buffer_ag[f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; x++; } - // Now interpolate the values from the intermediate_buffer to get the final result. - fx -= offset * fixed_scale; // Switch to intermediate buffer coordinates - - while (b < end) { - int x1 = (fx >> 16); - int x2 = x1 + 1; - Q_ASSERT(x1 >= 0); - Q_ASSERT(x2 < count); - - int distx = (fx & 0x0000ffff) >> 8; - int idistx = 256 - distx; - int rb = ((intermediate_buffer[0][x1] * idistx + intermediate_buffer[0][x2] * distx) >> 8) & 0xff00ff; - int ag = (intermediate_buffer[1][x1] * idistx + intermediate_buffer[1][x2] * distx) & 0xff00ff00; - *b = rb | ag; - b++; - fx += fdx; - } + // Now interpolate the values from the intermediate.buffer to get the final result. + intermediate_adder(b, end, intermediate, offset, fx, fdx); } template<TextureBlendType blendType> @@ -2542,14 +2588,14 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint static BilinearFastTransformHelper bilinearFastTransformHelperARGB32PM[2][NFastTransformTypes] = { { - fetchTransformedBilinearARGB32PM_simple_upscale_helper<BlendTransformedBilinear>, + fetchTransformedBilinearARGB32PM_simple_scale_helper<BlendTransformedBilinear>, fetchTransformedBilinearARGB32PM_upscale_helper<BlendTransformedBilinear>, fetchTransformedBilinearARGB32PM_downscale_helper<BlendTransformedBilinear>, fetchTransformedBilinearARGB32PM_rotate_helper<BlendTransformedBilinear>, fetchTransformedBilinearARGB32PM_fast_rotate_helper<BlendTransformedBilinear> }, { - fetchTransformedBilinearARGB32PM_simple_upscale_helper<BlendTransformedBilinearTiled>, + fetchTransformedBilinearARGB32PM_simple_scale_helper<BlendTransformedBilinearTiled>, fetchTransformedBilinearARGB32PM_upscale_helper<BlendTransformedBilinearTiled>, fetchTransformedBilinearARGB32PM_downscale_helper<BlendTransformedBilinearTiled>, fetchTransformedBilinearARGB32PM_rotate_helper<BlendTransformedBilinearTiled>, @@ -2584,7 +2630,13 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c if (fdy == 0) { // simple scale, no rotation or shear if (qAbs(fdx) <= fixed_scale) { // simple scale up on X - bilinearFastTransformHelperARGB32PM[tiled][SimpleUpscaleTransform](b, end, data->texture, fx, fy, fdx, fdy); + bilinearFastTransformHelperARGB32PM[tiled][SimpleScaleTransform](b, end, data->texture, fx, fy, fdx, fdy); + } else if (qAbs(fdx) <= 2 * fixed_scale) { + // simple scale down on X, less than 2x + const int mid = (length * 2 < BufferSize) ? length : ((length + 1) / 2); + bilinearFastTransformHelperARGB32PM[tiled][SimpleScaleTransform](buffer, buffer + mid, data->texture, fx, fy, fdx, fdy); + if (mid != length) + bilinearFastTransformHelperARGB32PM[tiled][SimpleScaleTransform](buffer + mid, buffer + length, data->texture, fx, fy, fdx, fdy); } else if (qAbs(data->m22) < qreal(1./8.)) { // scale up more than 8x (on Y) bilinearFastTransformHelperARGB32PM[tiled][UpscaleTransform](b, end, data->texture, fx, fy, fdx, fdy); @@ -2653,8 +2705,8 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c } template<TextureBlendType blendType, QPixelLayout::BPP bpp> -static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b, uint *end, const QTextureData &image, - int &fx, int &fy, int fdx, int /*fdy*/) +static void QT_FASTCALL fetchTransformedBilinear_simple_scale_helper(uint *b, uint *end, const QTextureData &image, + int &fx, int &fy, int fdx, int /*fdy*/) { const QPixelLayout *layout = &qPixelLayouts[image.format]; const QVector<QRgb> *clut = image.colorTable; @@ -2678,16 +2730,14 @@ static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b, const int offset = (fx + adjust) >> 16; int x = offset; - // The idea is first to do the interpolation between the row s1 and the row s2 - // into an intermediate buffer, then we interpolate between two pixel of this buffer. - // +1 for the last pixel to interpolate with, and +1 for rounding errors. - uint buf1[buffer_size + 2]; - uint buf2[buffer_size + 2]; + IntermediateBuffer intermediate; + uint *buf1 = intermediate.buffer_rb; + uint *buf2 = intermediate.buffer_ag; const uint *ptr1; const uint *ptr2; int count = (qint64(length) * qAbs(fdx) + fixed_scale - 1) / fixed_scale + 2; - Q_ASSERT(count <= buffer_size + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case + Q_ASSERT(count <= BufferSize + 2); if (blendType == BlendTransformedBilinearTiled) { x %= image.width; @@ -2719,6 +2769,7 @@ static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b, buf2[i + len1] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff; } } + // Generate the rest by repeatedly repeating the previous set of pixels for (int i = image.width; i < count; ++i) { buf1[i] = buf1[i - image.width]; buf2[i] = buf2[i - image.width]; @@ -2751,22 +2802,8 @@ static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b, } } - // Now interpolate the values from the intermediate_buffer to get the final result. - fx -= offset * fixed_scale; // Switch to intermediate buffer coordinates - - while (b < end) { - int x1 = (fx >> 16); - int x2 = x1 + 1; - Q_ASSERT(x1 >= 0); - Q_ASSERT(x2 < count); - - int distx = (fx & 0x0000ffff) >> 8; - int idistx = 256 - distx; - int rb = ((buf1[x1] * idistx + buf1[x2] * distx) >> 8) & 0xff00ff; - int ag = (buf2[x1] * idistx + buf2[x2] * distx) & 0xff00ff00; - *b++ = rb | ag; - fx += fdx; - } + // Now interpolate the values from the intermediate.buffer to get the final result. + intermediate_adder(b, end, intermediate, offset, fx, fdx); } @@ -2916,15 +2953,20 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper if (fdy == 0) { // simple scale, no rotation or shear if (qAbs(fdx) <= fixed_scale) { // scale up on X - fetchTransformedBilinear_simple_upscale_helper<blendType, bpp>(buffer, buffer + length, data->texture, fx, fy, fdx, fdy); + fetchTransformedBilinear_simple_scale_helper<blendType, bpp>(buffer, buffer + length, data->texture, fx, fy, fdx, fdy); + } else if (qAbs(fdx) <= 2 * fixed_scale) { // scale down on X less than 2x + const int mid = (length * 2 < BufferSize) ? length : ((length + 1) / 2); + fetchTransformedBilinear_simple_scale_helper<blendType, bpp>(buffer, buffer + mid, data->texture, fx, fy, fdx, fdy); + if (mid != length) + fetchTransformedBilinear_simple_scale_helper<blendType, bpp>(buffer + mid, buffer + length, data->texture, fx, fy, fdx, fdy); } else { const BilinearFastTransformFetcher fetcher = fetchTransformedBilinear_fetcher<blendType,bpp>; - uint buf1[buffer_size]; - uint buf2[buffer_size]; + uint buf1[BufferSize]; + uint buf2[BufferSize]; uint *b = buffer; while (length) { - int len = qMin(length, buffer_size / 2); + int len = qMin(length, BufferSize / 2); fetcher(buf1, buf2, len, data->texture, fx, fy, fdx, 0); layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0); layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0); @@ -2955,11 +2997,11 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper } else { // rotation or shear const BilinearFastTransformFetcher fetcher = fetchTransformedBilinear_fetcher<blendType,bpp>; - uint buf1[buffer_size]; - uint buf2[buffer_size]; + uint buf1[BufferSize]; + uint buf2[BufferSize]; uint *b = buffer; while (length) { - int len = qMin(length, buffer_size / 2); + int len = qMin(length, BufferSize / 2); fetcher(buf1, buf2, len, data->texture, fx, fy, fdx, fdy); layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0); layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0); @@ -3009,15 +3051,15 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper qreal fy = data->m22 * cy + data->m12 * cx + data->dy; qreal fw = data->m23 * cy + data->m13 * cx + data->m33; - uint buf1[buffer_size]; - uint buf2[buffer_size]; + uint buf1[BufferSize]; + uint buf2[BufferSize]; uint *b = buffer; - int distxs[buffer_size / 2]; - int distys[buffer_size / 2]; + int distxs[BufferSize / 2]; + int distys[BufferSize / 2]; while (length) { - int len = qMin(length, buffer_size / 2); + int len = qMin(length, BufferSize / 2); for (int i = 0; i < len; ++i) { const qreal iw = fw == 0 ? 1 : 1 / fw; const qreal px = fx * iw - qreal(0.5); @@ -3094,13 +3136,13 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co if (fdy == 0) { //simple scale, no rotation - uint sbuf1[buffer_size]; - uint sbuf2[buffer_size]; - quint64 buf1[buffer_size]; - quint64 buf2[buffer_size]; + uint sbuf1[BufferSize]; + uint sbuf2[BufferSize]; + quint64 buf1[BufferSize]; + quint64 buf2[BufferSize]; QRgba64 *b = buffer; while (length) { - int len = qMin(length, buffer_size / 2); + int len = qMin(length, BufferSize / 2); int disty = (fy & 0x0000ffff); #if defined(__SSE2__) const __m128i vdy = _mm_set1_epi16(disty); @@ -3138,15 +3180,15 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co b += len; } } else { //rotation - uint sbuf1[buffer_size]; - uint sbuf2[buffer_size]; - quint64 buf1[buffer_size]; - quint64 buf2[buffer_size]; + uint sbuf1[BufferSize]; + uint sbuf2[BufferSize]; + quint64 buf1[BufferSize]; + quint64 buf2[BufferSize]; QRgba64 *end = buffer + length; QRgba64 *b = buffer; while (b < end) { - int len = qMin(length, buffer_size / 2); + int len = qMin(length, BufferSize / 2); fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy); @@ -3177,17 +3219,17 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co qreal fw = data->m23 * cy + data->m13 * cx + data->m33; FetchPixelFunc fetch = qFetchPixel[layout->bpp]; - uint sbuf1[buffer_size]; - uint sbuf2[buffer_size]; - quint64 buf1[buffer_size]; - quint64 buf2[buffer_size]; + uint sbuf1[BufferSize]; + uint sbuf2[BufferSize]; + quint64 buf1[BufferSize]; + quint64 buf2[BufferSize]; QRgba64 *b = buffer; - int distxs[buffer_size / 2]; - int distys[buffer_size / 2]; + int distxs[BufferSize / 2]; + int distys[BufferSize / 2]; while (length) { - int len = qMin(length, buffer_size / 2); + int len = qMin(length, BufferSize / 2); for (int i = 0; i < len; ++i) { const qreal iw = fw == 0 ? 1 : 1 / fw; const qreal px = fx * iw - qreal(0.5); @@ -3292,6 +3334,15 @@ static SourceFetchProc sourceFetchARGB32PM[NBlendTypes] = { fetchTransformedBilinearARGB32PM<BlendTransformedBilinearTiled> // BilinearTiled }; +static SourceFetchProc sourceFetchAny16[NBlendTypes] = { + fetchUntransformed, // Untransformed + fetchUntransformed, // Tiled + fetchTransformed<BlendTransformed, QPixelLayout::BPP16>, // Transformed + fetchTransformed<BlendTransformedTiled, QPixelLayout::BPP16>, // TransformedTiled + fetchTransformedBilinear<BlendTransformedBilinear, QPixelLayout::BPP16>, // TransformedBilinear + fetchTransformedBilinear<BlendTransformedBilinearTiled, QPixelLayout::BPP16> // TransformedBilinearTiled +}; + static SourceFetchProc sourceFetchAny32[NBlendTypes] = { fetchUntransformed, // Untransformed fetchUntransformed, // Tiled @@ -3316,6 +3367,8 @@ static inline SourceFetchProc getSourceFetch(TextureBlendType blendType, QImage: 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]; @@ -3717,7 +3770,7 @@ static void blend_color_generic(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); - uint buffer[buffer_size]; + uint buffer[BufferSize]; Operator op = getOperator(data, spans, count); const uint color = data->solid.color.toArgb32(); @@ -3725,7 +3778,7 @@ void blend_color_generic(int count, const QSpan *spans, void *userData) int x = spans->x; int length = spans->len; while (length) { - int l = qMin(buffer_size, length); + int l = qMin(BufferSize, length); uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; op.funcSolid(dest, l, color, spans->coverage); if (op.destStore) @@ -3777,14 +3830,27 @@ void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData) return blend_color_generic(count, spans, userData); } - quint64 buffer[buffer_size]; + quint64 buffer[BufferSize]; const QRgba64 color = data->solid.color; + 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; while (count--) { int x = spans->x; int length = spans->len; + if (solidFill && isBpp32 && spans->coverage == 255) { + // 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; + } + } + while (length) { - int l = qMin(buffer_size, length); + int l = qMin(BufferSize, length); QRgba64 *dest = op.destFetch64((QRgba64 *)buffer, data->rasterBuffer, x, spans->y, l); op.funcSolid64(dest, l, color, spans->coverage); op.destStore64(data->rasterBuffer, x, spans->y, dest, l); @@ -3889,7 +3955,7 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle int length = right - x; while (length) { - int l = qMin(buffer_size, length); + int l = qMin(BufferSize, length); length -= l; int process_length = l; @@ -3936,8 +4002,8 @@ struct QBlendBase BlendType *dest; - BlendType buffer[buffer_size]; - BlendType src_buffer[buffer_size]; + BlendType buffer[BufferSize]; + BlendType src_buffer[BufferSize]; }; class BlendSrcGeneric : public QBlendBase<uint> @@ -4021,8 +4087,8 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use { QSpanData *data = reinterpret_cast<QSpanData *>(userData); - uint buffer[buffer_size]; - uint src_buffer[buffer_size]; + uint buffer[BufferSize]; + uint src_buffer[BufferSize]; Operator op = getOperator(data, spans, count); const int image_width = data->texture.width; @@ -4046,7 +4112,7 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use if (length > 0) { const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; while (length) { - int l = qMin(buffer_size, length); + int l = qMin(BufferSize, length); const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l); uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; op.func(dest, src, l, coverage); @@ -4071,8 +4137,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[buffer_size]; - quint64 src_buffer[buffer_size]; + quint64 buffer[BufferSize]; + quint64 src_buffer[BufferSize]; const int image_width = data->texture.width; const int image_height = data->texture.height; @@ -4095,7 +4161,7 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi if (length > 0) { const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; while (length) { - int l = qMin(buffer_size, 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); op.func64(dest, src, l, coverage); @@ -4259,8 +4325,8 @@ static void blend_tiled_generic(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); - uint buffer[buffer_size]; - uint src_buffer[buffer_size]; + uint buffer[BufferSize]; + uint src_buffer[BufferSize]; Operator op = getOperator(data, spans, count); const int image_width = data->texture.width; @@ -4286,8 +4352,8 @@ static void blend_tiled_generic(int count, const QSpan *spans, void *userData) const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; while (length) { int l = qMin(image_width - sx, length); - if (buffer_size < l) - l = buffer_size; + if (BufferSize < l) + l = BufferSize; const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l); uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; op.func(dest, src, l, coverage); @@ -4312,8 +4378,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[buffer_size]; - quint64 src_buffer[buffer_size]; + quint64 buffer[BufferSize]; + quint64 src_buffer[BufferSize]; const int image_width = data->texture.width; const int image_height = data->texture.height; @@ -4325,6 +4391,50 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD if (yoff < 0) yoff += image_height; + bool isBpp32 = qPixelLayouts[data->rasterBuffer->format].bpp == QPixelLayout::BPP32; + if (op.destFetch64 == destFetch64Undefined && image_width <= BufferSize && isBpp32) { + // If destination isn't blended into the result, we can do the tiling directly on destination pixels. + while (count--) { + int x = spans->x; + int y = spans->y; + int length = spans->len; + int sx = (xoff + spans->x) % image_width; + int sy = (spans->y + yoff) % image_height; + if (sx < 0) + sx += image_width; + if (sy < 0) + sy += image_height; + + 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); + op.destStore64(data->rasterBuffer, x, y, src, l); + x += l; + sx += l; + sl -= l; + if (sx >= image_width) + sx = 0; + } + if (sl > 0) { + Q_ASSERT(sx == 0); + const QRgba64 *src = op.srcFetch64((QRgba64 *)src_buffer, &op, data, sy, sx, sl); + op.destStore64(data->rasterBuffer, x, y, src, sl); + x += sl; + sx += sl; + sl -= sl; + if (sx >= image_width) + sx = 0; + } + uint *dest = (uint*)data->rasterBuffer->scanLine(y) + x - image_width; + for (int i = image_width; i < length; ++i) { + dest[i] = dest[i - image_width]; + } + ++spans; + } + return; + } + while (count--) { int x = spans->x; int length = spans->len; @@ -4338,8 +4448,8 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; while (length) { int l = qMin(image_width - sx, length); - if (buffer_size < l) - l = buffer_size; + 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); op.func64(dest, src, l, coverage); @@ -4388,8 +4498,8 @@ static void blend_tiled_argb(int count, const QSpan *spans, void *userData) const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; while (length) { int l = qMin(image_width - sx, length); - if (buffer_size < l) - l = buffer_size; + if (BufferSize < l) + l = BufferSize; const uint *src = (const uint *)data->texture.scanLine(sy) + sx; uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; op.func(dest, src, l, coverage); @@ -4448,8 +4558,8 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData) int tx = x; while (length) { int l = qMin(image_width - sx, length); - if (buffer_size < l) - l = buffer_size; + if (BufferSize < l) + l = BufferSize; quint16 *dest = ((quint16 *)data->rasterBuffer->scanLine(spans->y)) + tx; const quint16 *src = (const quint16 *)data->texture.scanLine(sy) + sx; memcpy(dest, src, l * sizeof(quint16)); @@ -4484,8 +4594,8 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData) if (alpha > 0) { while (length) { int l = qMin(image_width - sx, length); - if (buffer_size < l) - l = buffer_size; + if (BufferSize < l) + l = BufferSize; quint16 *dest = ((quint16 *)data->rasterBuffer->scanLine(spans->y)) + x; const quint16 *src = (const quint16 *)data->texture.scanLine(sy) + sx; blend_sourceOver_rgb16_rgb16(dest, src, l, alpha, ialpha); @@ -4501,199 +4611,6 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData) } } -static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans, void *userData) -{ - QSpanData *data = reinterpret_cast<QSpanData*>(userData); - QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; - - if (data->texture.format != QImage::Format_RGB16 - || (mode != QPainter::CompositionMode_SourceOver - && mode != QPainter::CompositionMode_Source)) - { - blend_src_generic(count, spans, userData); - return; - } - - quint16 buffer[buffer_size]; - - const int src_minx = data->texture.x1; - const int src_miny = data->texture.y1; - const int src_maxx = data->texture.x2 - 1; - const int src_maxy = data->texture.y2 - 1; - - if (data->fast_matrix) { - // The increment pr x in the scanline - const int fdx = (int)(data->m11 * fixed_scale); - const int fdy = (int)(data->m12 * fixed_scale); - - while (count--) { - const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; - const quint8 alpha = (coverage + 1) >> 3; - const quint8 ialpha = 0x20 - alpha; - if (alpha == 0) { - ++spans; - continue; - } - - quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x; - const qreal cx = spans->x + qreal(0.5); - const qreal cy = spans->y + qreal(0.5); - int x = int((data->m21 * cy - + data->m11 * cx + data->dx) * fixed_scale) - half_point; - int y = int((data->m22 * cy - + data->m12 * cx + data->dy) * fixed_scale) - half_point; - int length = spans->len; - - while (length) { - int l; - quint16 *b; - if (ialpha == 0) { - l = length; - b = dest; - } else { - l = qMin(length, buffer_size); - b = buffer; - } - const quint16 *end = b + l; - - while (b < end) { - int x1 = (x >> 16); - int x2; - int y1 = (y >> 16); - int y2; - - fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_minx, src_maxx, x1, x2); - fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_miny, src_maxy, y1, y2); - - const quint16 *src1 = (const quint16*)data->texture.scanLine(y1); - const quint16 *src2 = (const quint16*)data->texture.scanLine(y2); - quint16 tl = src1[x1]; - const quint16 tr = src1[x2]; - quint16 bl = src2[x1]; - const quint16 br = src2[x2]; - - const uint distxsl8 = x & 0xff00; - const uint distysl8 = y & 0xff00; - const uint distx = distxsl8 >> 8; - const uint disty = distysl8 >> 8; - const uint distxy = distx * disty; - - const uint tlw = 0x10000 - distxsl8 - distysl8 + distxy; // (256 - distx) * (256 - disty) - const uint trw = distxsl8 - distxy; // distx * (256 - disty) - const uint blw = distysl8 - distxy; // (256 - distx) * disty - const uint brw = distxy; // distx * disty - uint red = ((tl & 0xf800) * tlw + (tr & 0xf800) * trw - + (bl & 0xf800) * blw + (br & 0xf800) * brw) & 0xf8000000; - uint green = ((tl & 0x07e0) * tlw + (tr & 0x07e0) * trw - + (bl & 0x07e0) * blw + (br & 0x07e0) * brw) & 0x07e00000; - uint blue = ((tl & 0x001f) * tlw + (tr & 0x001f) * trw - + (bl & 0x001f) * blw + (br & 0x001f) * brw); - *b = quint16((red | green | blue) >> 16); - - ++b; - x += fdx; - y += fdy; - } - - if (ialpha != 0) - blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha); - - dest += l; - length -= l; - } - ++spans; - } - } else { - const qreal fdx = data->m11; - const qreal fdy = data->m12; - const qreal fdw = data->m13; - - while (count--) { - const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; - const quint8 alpha = (coverage + 1) >> 3; - const quint8 ialpha = 0x20 - alpha; - if (alpha == 0) { - ++spans; - continue; - } - - quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x; - - const qreal cx = spans->x + qreal(0.5); - const qreal cy = spans->y + qreal(0.5); - - qreal x = data->m21 * cy + data->m11 * cx + data->dx; - qreal y = data->m22 * cy + data->m12 * cx + data->dy; - qreal w = data->m23 * cy + data->m13 * cx + data->m33; - - int length = spans->len; - while (length) { - int l; - quint16 *b; - if (ialpha == 0) { - l = length; - b = dest; - } else { - l = qMin(length, buffer_size); - b = buffer; - } - const quint16 *end = b + l; - - while (b < end) { - const qreal iw = w == 0 ? 1 : 1 / w; - const qreal px = x * iw - qreal(0.5); - const qreal py = y * iw - qreal(0.5); - - int x1 = int(px) - (px < 0); - int x2; - int y1 = int(py) - (py < 0); - int y2; - - fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_minx, src_maxx, x1, x2); - fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_miny, src_maxy, y1, y2); - - const quint16 *src1 = (const quint16 *)data->texture.scanLine(y1); - const quint16 *src2 = (const quint16 *)data->texture.scanLine(y2); - quint16 tl = src1[x1]; - const quint16 tr = src1[x2]; - quint16 bl = src2[x1]; - const quint16 br = src2[x2]; - - const uint distx = uint((px - x1) * 256); - const uint disty = uint((py - y1) * 256); - const uint distxsl8 = distx << 8; - const uint distysl8 = disty << 8; - const uint distxy = distx * disty; - - const uint tlw = 0x10000 - distxsl8 - distysl8 + distxy; // (256 - distx) * (256 - disty) - const uint trw = distxsl8 - distxy; // distx * (256 - disty) - const uint blw = distysl8 - distxy; // (256 - distx) * disty - const uint brw = distxy; // distx * disty - uint red = ((tl & 0xf800) * tlw + (tr & 0xf800) * trw - + (bl & 0xf800) * blw + (br & 0xf800) * brw) & 0xf8000000; - uint green = ((tl & 0x07e0) * tlw + (tr & 0x07e0) * trw - + (bl & 0x07e0) * blw + (br & 0x07e0) * brw) & 0x07e00000; - uint blue = ((tl & 0x001f) * tlw + (tr & 0x001f) * trw - + (bl & 0x001f) * blw + (br & 0x001f) * brw); - *b = quint16((red | green | blue) >> 16); - - ++b; - x += fdx; - y += fdy; - w += fdw; - } - - if (ialpha != 0) - blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha); - - dest += l; - length -= l; - } - ++spans; - } - } -} - static void blend_transformed_argb(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); @@ -4704,7 +4621,7 @@ static void blend_transformed_argb(int count, const QSpan *spans, void *userData } CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode]; - uint buffer[buffer_size]; + uint buffer[BufferSize]; quint32 mask = (data->texture.format == QImage::Format_RGB32) ? 0xff000000 : 0; const int image_x1 = data->texture.x1; @@ -4733,7 +4650,7 @@ static void blend_transformed_argb(int count, const QSpan *spans, void *userData int length = spans->len; const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; while (length) { - int l = qMin(length, buffer_size); + int l = qMin(length, BufferSize); const uint *end = buffer + l; uint *b = buffer; while (b < end) { @@ -4770,7 +4687,7 @@ static void blend_transformed_argb(int count, const QSpan *spans, void *userData int length = spans->len; const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; while (length) { - int l = qMin(length, buffer_size); + int l = qMin(length, BufferSize); const uint *end = buffer + l; uint *b = buffer; while (b < end) { @@ -4809,7 +4726,7 @@ static void blend_transformed_rgb565(int count, const QSpan *spans, void *userDa return; } - quint16 buffer[buffer_size]; + quint16 buffer[BufferSize]; const int image_x1 = data->texture.x1; const int image_y1 = data->texture.y1; const int image_x2 = data->texture.x2 - 1; @@ -4845,7 +4762,7 @@ static void blend_transformed_rgb565(int count, const QSpan *spans, void *userDa l = length; b = dest; } else { - l = qMin(length, buffer_size); + l = qMin(length, BufferSize); b = buffer; } const quint16 *end = b + l; @@ -4900,7 +4817,7 @@ static void blend_transformed_rgb565(int count, const QSpan *spans, void *userDa l = length; b = dest; } else { - l = qMin(length, buffer_size); + l = qMin(length, BufferSize); b = buffer; } const quint16 *end = b + l; @@ -4942,7 +4859,7 @@ static void blend_transformed_tiled_argb(int count, const QSpan *spans, void *us } CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode]; - uint buffer[buffer_size]; + uint buffer[BufferSize]; int image_width = data->texture.width; int image_height = data->texture.height; @@ -4970,7 +4887,7 @@ static void blend_transformed_tiled_argb(int count, const QSpan *spans, void *us const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; int length = spans->len; while (length) { - int l = qMin(length, buffer_size); + int l = qMin(length, BufferSize); const uint *end = buffer + l; uint *b = buffer; int px16 = x % (image_width << 16); @@ -5024,7 +4941,7 @@ static void blend_transformed_tiled_argb(int count, const QSpan *spans, void *us const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; int length = spans->len; while (length) { - int l = qMin(length, buffer_size); + int l = qMin(length, BufferSize); const uint *end = buffer + l; uint *b = buffer; while (b < end) { @@ -5075,7 +4992,7 @@ static void blend_transformed_tiled_rgb565(int count, const QSpan *spans, void * return; } - quint16 buffer[buffer_size]; + quint16 buffer[BufferSize]; const int image_width = data->texture.width; const int image_height = data->texture.height; @@ -5109,7 +5026,7 @@ static void blend_transformed_tiled_rgb565(int count, const QSpan *spans, void * l = length; b = dest; } else { - l = qMin(length, buffer_size); + l = qMin(length, BufferSize); b = buffer; } const quint16 *end = b + l; @@ -5169,7 +5086,7 @@ static void blend_transformed_tiled_rgb565(int count, const QSpan *spans, void * l = length; b = dest; } else { - l = qMin(length, buffer_size); + l = qMin(length, BufferSize); b = buffer; } const quint16 *end = b + l; @@ -5227,7 +5144,7 @@ static const ProcessSpans processTextureSpansRGB16[NBlendTypes] = { blend_tiled_rgb565, // Tiled blend_transformed_rgb565, // Transformed blend_transformed_tiled_rgb565, // TransformedTiled - blend_transformed_bilinear_rgb565, // TransformedBilinear + blend_src_generic, // TransformedBilinear blend_src_generic // TransformedBilinearTiled }; @@ -5523,7 +5440,7 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer, srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); } - quint64 buffer[buffer_size]; + quint64 buffer[BufferSize]; const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format]; const DestStoreProc64 destStore64 = destStoreProc64[rasterBuffer->format]; @@ -5532,7 +5449,7 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer, int i = x; int length = mapWidth; while (length > 0) { - int l = qMin(buffer_size, length); + int l = qMin(BufferSize, length); QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, i, y + ly, l); for (int j=0; j < l; ++j) { const int coverage = map[j + (i - x)]; @@ -5561,7 +5478,7 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer, int end = qMin<int>(x + mapWidth, clip.x + clip.len); if (end <= start) continue; - Q_ASSERT(end - start <= buffer_size); + Q_ASSERT(end - start <= BufferSize); QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, start, clip.y, end - start); for (int xp=start; xp<end; ++xp) { @@ -5800,7 +5717,7 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer, srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); } - quint64 buffer[buffer_size]; + quint64 buffer[BufferSize]; const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format]; const DestStoreProc64 destStore64 = destStoreProc64[rasterBuffer->format]; @@ -5809,7 +5726,7 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer, int i = x; int length = mapWidth; while (length > 0) { - int l = qMin(buffer_size, length); + int l = qMin(BufferSize, length); QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, i, y + ly, l); for (int j=0; j < l; ++j) { const uint coverage = src[j + (i - x)]; @@ -5838,7 +5755,7 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer, int end = qMin<int>(x + mapWidth, clip.x + clip.len); if (end <= start) continue; - Q_ASSERT(end - start <= buffer_size); + Q_ASSERT(end - start <= BufferSize); QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, start, clip.y, end - start); for (int xp=start; xp<end; ++xp) { @@ -5928,8 +5845,26 @@ static void qt_rectfill_quint16(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, const QRgba64 &color) { + const QPixelLayout &layout = qPixelLayouts[rasterBuffer->format]; + quint32 c32 = color.toArgb32(); + layout.convertFromARGB32PM(&c32, &c32, 1, nullptr, nullptr); + quint16 c16; + storePixel<QPixelLayout::BPP16>(reinterpret_cast<uchar *>(&c16), 0, c32); qt_rectfill<quint16>(reinterpret_cast<quint16 *>(rasterBuffer->buffer()), - color.toRgb16(), x, y, width, height, rasterBuffer->bytesPerLine()); + c16, x, y, width, height, rasterBuffer->bytesPerLine()); +} + +static void qt_rectfill_quint24(QRasterBuffer *rasterBuffer, + int x, int y, int width, int height, + const QRgba64 &color) +{ + const QPixelLayout &layout = qPixelLayouts[rasterBuffer->format]; + quint32 c32 = color.toArgb32(); + layout.convertFromARGB32PM(&c32, &c32, 1, nullptr, nullptr); + quint24 c24; + storePixel<QPixelLayout::BPP24>(reinterpret_cast<uchar *>(&c24), 0, c32); + qt_rectfill<quint24>(reinterpret_cast<quint24 *>(rasterBuffer->buffer()), + c24, x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_nonpremul_argb32(QRasterBuffer *rasterBuffer, @@ -6049,7 +5984,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = 0, qt_alphamapblit_generic, qt_alphargbblit_generic, - 0 + qt_rectfill_quint24 }, // Format_RGB666 { @@ -6058,7 +5993,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = 0, qt_alphamapblit_generic, qt_alphargbblit_generic, - 0 + qt_rectfill_quint24 }, // Format_ARGB6666_Premultiplied { @@ -6067,7 +6002,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = 0, qt_alphamapblit_generic, qt_alphargbblit_generic, - 0 + qt_rectfill_quint24 }, // Format_RGB555 { @@ -6076,7 +6011,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = 0, qt_alphamapblit_generic, qt_alphargbblit_generic, - 0 + qt_rectfill_quint16 }, // Format_ARGB8555_Premultiplied { @@ -6085,7 +6020,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = 0, qt_alphamapblit_generic, qt_alphargbblit_generic, - 0 + qt_rectfill_quint24 }, // Format_RGB888 { @@ -6094,7 +6029,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = 0, qt_alphamapblit_generic, qt_alphargbblit_generic, - 0 + qt_rectfill_quint24 }, // Format_RGB444 { @@ -6103,7 +6038,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = 0, qt_alphamapblit_generic, qt_alphargbblit_generic, - 0 + qt_rectfill_quint16 }, // Format_ARGB4444_Premultiplied { @@ -6112,7 +6047,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = 0, qt_alphamapblit_generic, qt_alphargbblit_generic, - 0 + qt_rectfill_quint16 }, // Format_RGBX8888 { @@ -6401,14 +6336,14 @@ static void qInitDrawhelperFunctions() qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_avx2; qt_functionForModeSolid64_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_rgb64_avx2; - extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper_avx2(uint *b, uint *end, const QTextureData &image, - int &fx, int &fy, int fdx, int /*fdy*/); + extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_scale_helper_avx2(uint *b, uint *end, const QTextureData &image, + int &fx, int &fy, int fdx, int /*fdy*/); extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_downscale_helper_avx2(uint *b, uint *end, const QTextureData &image, int &fx, int &fy, int fdx, int /*fdy*/); extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper_avx2(uint *b, uint *end, const QTextureData &image, int &fx, int &fy, int fdx, int fdy); - bilinearFastTransformHelperARGB32PM[0][SimpleUpscaleTransform] = fetchTransformedBilinearARGB32PM_simple_upscale_helper_avx2; + bilinearFastTransformHelperARGB32PM[0][SimpleScaleTransform] = fetchTransformedBilinearARGB32PM_simple_scale_helper_avx2; bilinearFastTransformHelperARGB32PM[0][DownscaleTransform] = fetchTransformedBilinearARGB32PM_downscale_helper_avx2; bilinearFastTransformHelperARGB32PM[0][FastRotateTransform] = fetchTransformedBilinearARGB32PM_fast_rotate_helper_avx2; } |