summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qdrawhelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting/qdrawhelper.cpp')
-rw-r--r--src/gui/painting/qdrawhelper.cpp841
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;
}