summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting')
-rw-r--r--src/gui/painting/painting.pri13
-rw-r--r--src/gui/painting/qbrush.cpp81
-rw-r--r--src/gui/painting/qcolor.cpp55
-rw-r--r--src/gui/painting/qdrawhelper.cpp884
-rw-r--r--src/gui/painting/qdrawhelper_avx.cpp70
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp6
-rw-r--r--src/gui/painting/qdrawhelper_neon_p.h4
-rw-r--r--src/gui/painting/qdrawhelper_p.h36
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp38
-rw-r--r--src/gui/painting/qdrawhelper_x86_p.h27
-rw-r--r--src/gui/painting/qdrawingprimitive_sse2_p.h4
-rw-r--r--src/gui/painting/qemulationpaintengine.cpp2
-rw-r--r--src/gui/painting/qpaintbuffer.cpp6
-rw-r--r--src/gui/painting/qpaintengine.cpp1
-rw-r--r--src/gui/painting/qpaintengine.h1
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp38
-rw-r--r--src/gui/painting/qpainter.cpp12
-rw-r--r--src/gui/painting/qpainterpath.cpp24
-rw-r--r--src/gui/painting/qpainterpath.h2
-rw-r--r--src/gui/painting/qpen.cpp4
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp247
-rw-r--r--src/gui/painting/qplatformbackingstore.h34
-rw-r--r--src/gui/painting/qrgb.h43
23 files changed, 1087 insertions, 545 deletions
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index aadcc0f686..6bf80eddbd 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -87,14 +87,15 @@ SOURCES += \
painting/qpaintbuffer.cpp \
painting/qpathsimplifier.cpp
-SSE2_SOURCES += painting/qdrawhelper_sse2.cpp
-SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
+contains(QT_CPU_FEATURES.$$QT_ARCH, sse2) {
+ SOURCES += painting/qdrawhelper_sse2.cpp
+ SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
+}
IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp
-AVX_SOURCES += painting/qdrawhelper_avx.cpp
-!ios {
- NEON_SOURCES += painting/qdrawhelper_neon.cpp
- NEON_HEADERS += painting/qdrawhelper_neon_p.h
+!ios:contains(QT_CPU_FEATURES.$$QT_ARCH, neon) {
+ SOURCES += painting/qdrawhelper_neon.cpp
+ HEADERS += painting/qdrawhelper_neon_p.h
NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
}
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index 8bbe6b6f42..b35fa38ce0 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -56,44 +56,49 @@ QT_BEGIN_NAMESPACE
const uchar *qt_patternForBrush(int brushStyle, bool invert)
{
Q_ASSERT(brushStyle > Qt::SolidPattern && brushStyle < Qt::LinearGradientPattern);
- if(invert) {
- static const uchar dense1_pat[] = { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff };
- static const uchar dense2_pat[] = { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff };
- static const uchar dense3_pat[] = { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee };
- static const uchar dense4_pat[] = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 };
- static const uchar dense5_pat[] = { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 };
- static const uchar dense6_pat[] = { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 };
- static const uchar dense7_pat[] = { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 };
- static const uchar hor_pat[] = { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 };
- static const uchar ver_pat[] = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 };
- static const uchar cross_pat[] = { 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0x10 };
- static const uchar bdiag_pat[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
- static const uchar fdiag_pat[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
- static const uchar dcross_pat[] = { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 };
- static const uchar *const pat_tbl[] = {
- dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat,
- dense6_pat, dense7_pat,
- hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat };
- return pat_tbl[brushStyle - Qt::Dense1Pattern];
- }
- static const uchar dense1_pat[] = { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 };
- static const uchar dense2_pat[] = { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 };
- static const uchar dense3_pat[] = { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 };
- static const uchar dense4_pat[] = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa };
- static const uchar dense5_pat[] = { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee };
- static const uchar dense6_pat[] = { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff };
- static const uchar dense7_pat[] = { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff };
- static const uchar hor_pat[] = { 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff };
- static const uchar ver_pat[] = { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef };
- static const uchar cross_pat[] = { 0xef, 0xef, 0xef, 0x00, 0xef, 0xef, 0xef, 0xef };
- static const uchar bdiag_pat[] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
- static const uchar fdiag_pat[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
- static const uchar dcross_pat[] = { 0x7e, 0xbd, 0xdb, 0xe7, 0xe7, 0xdb, 0xbd, 0x7e };
- static const uchar *const pat_tbl[] = {
- dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat,
- dense6_pat, dense7_pat,
- hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat };
- return pat_tbl[brushStyle - Qt::Dense1Pattern];
+ static const uchar pat_tbl[][2][8] = {
+ {
+ /* dense1 */ { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 },
+ /*~dense1 */ { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff },
+ }, {
+ /* dense2 */ { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 },
+ /*~dense2 */ { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff },
+ }, {
+ /* dense3 */ { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 },
+ /*~dense3 */ { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee },
+ }, {
+ /* dense4 */ { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa },
+ /*~dense4 */ { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 },
+ }, {
+ /* dense5 */ { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee },
+ /*~dense5 */ { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 },
+ }, {
+ /* dense6 */ { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff },
+ /*~dense6 */ { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 },
+ }, {
+ /* dense7 */ { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff },
+ /*~dense7 */ { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 },
+ }, {
+ /* hor */ { 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff },
+ /*~hor */ { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 },
+ }, {
+ /* ver */ { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef },
+ /*~ver */ { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
+ }, {
+ /* cross */ { 0xef, 0xef, 0xef, 0x00, 0xef, 0xef, 0xef, 0xef },
+ /*~cross */ { 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0x10 },
+ }, {
+ /* bdiag */ { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe },
+ /*~bdiag */ { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 },
+ }, {
+ /* fdiag */ { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f },
+ /*~fdiag */ { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 },
+ }, {
+ /* dcross */ { 0x7e, 0xbd, 0xdb, 0xe7, 0xe7, 0xdb, 0xbd, 0x7e },
+ /*~dcross */ { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 },
+ },
+ };
+ return pat_tbl[brushStyle - Qt::Dense1Pattern][invert];
}
QPixmap qt_pixmapForBrush(int brushStyle, bool invert)
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index 706273c151..b9d3ca888e 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -2499,6 +2499,41 @@ QDataStream &operator>>(QDataStream &stream, QColor &color)
}
#endif // QT_NO_DATASTREAM
+// A table of precalculated results of 0x00ff00ff/alpha use by qUnpremultiply:
+const uint qt_inv_premul_factor[256] = {
+ 0, 16711935, 8355967, 5570645, 4177983, 3342387, 2785322, 2387419,
+ 2088991, 1856881, 1671193, 1519266, 1392661, 1285533, 1193709, 1114129,
+ 1044495, 983055, 928440, 879575, 835596, 795806, 759633, 726605,
+ 696330, 668477, 642766, 618960, 596854, 576273, 557064, 539094,
+ 522247, 506422, 491527, 477483, 464220, 451673, 439787, 428511,
+ 417798, 407608, 397903, 388649, 379816, 371376, 363302, 355573,
+ 348165, 341059, 334238, 327685, 321383, 315319, 309480, 303853,
+ 298427, 293191, 288136, 283253, 278532, 273966, 269547, 265268,
+ 261123, 257106, 253211, 249431, 245763, 242201, 238741, 235379,
+ 232110, 228930, 225836, 222825, 219893, 217038, 214255, 211543,
+ 208899, 206320, 203804, 201348, 198951, 196611, 194324, 192091,
+ 189908, 187774, 185688, 183647, 181651, 179698, 177786, 175915,
+ 174082, 172287, 170529, 168807, 167119, 165464, 163842, 162251,
+ 160691, 159161, 157659, 156186, 154740, 153320, 151926, 150557,
+ 149213, 147893, 146595, 145321, 144068, 142837, 141626, 140436,
+ 139266, 138115, 136983, 135869, 134773, 133695, 132634, 131590,
+ 130561, 129549, 128553, 127572, 126605, 125653, 124715, 123792,
+ 122881, 121984, 121100, 120229, 119370, 118524, 117689, 116866,
+ 116055, 115254, 114465, 113686, 112918, 112160, 111412, 110675,
+ 109946, 109228, 108519, 107818, 107127, 106445, 105771, 105106,
+ 104449, 103800, 103160, 102527, 101902, 101284, 100674, 100071,
+ 99475, 98887, 98305, 97730, 97162, 96600, 96045, 95496,
+ 94954, 94417, 93887, 93362, 92844, 92331, 91823, 91322,
+ 90825, 90334, 89849, 89368, 88893, 88422, 87957, 87497,
+ 87041, 86590, 86143, 85702, 85264, 84832, 84403, 83979,
+ 83559, 83143, 82732, 82324, 81921, 81521, 81125, 80733,
+ 80345, 79961, 79580, 79203, 78829, 78459, 78093, 77729,
+ 77370, 77013, 76660, 76310, 75963, 75619, 75278, 74941,
+ 74606, 74275, 73946, 73620, 73297, 72977, 72660, 72346,
+ 72034, 71725, 71418, 71114, 70813, 70514, 70218, 69924,
+ 69633, 69344, 69057, 68773, 68491, 68211, 67934, 67659,
+ 67386, 67116, 66847, 66581, 66317, 66055, 65795, 65537
+};
/*****************************************************************************
QColor global functions (documentation only)
@@ -2581,6 +2616,26 @@ QDataStream &operator>>(QDataStream &stream, QColor &color)
*/
/*!
+ \fn QRgb qPremultiply(QRgb rgb)
+ \since 5.3
+ \relates QColor
+
+ Converts an unpremultiplied ARGB quadruplet \a rgb into a premultiplied ARGB quadruplet.
+
+ \sa qUnpremultiply()
+*/
+
+/*!
+ \fn QRgb qUnpremultiply(QRgb rgb)
+ \since 5.3
+ \relates QColor
+
+ Converts a premultiplied ARGB quadruplet \a rgb into an unpremultiplied ARGB quadruplet.
+
+ \sa qPremultiply()
+*/
+
+/*!
\fn QColor QColor::convertTo(Spec colorSpec) const
Creates a copy of \e this color in the format specified by \a colorSpec.
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index c71d75cf94..66481d4287 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -53,6 +53,13 @@
# endif
#endif
+#include <qglobal.h>
+#ifdef Q_OS_IOS
+// We don't build the NEON drawhelpers as they are implemented partly
+// in GAS syntax assembly, which is not supported by the iOS toolchain.
+#undef __ARM_NEON__
+#endif
+
#include <qstylehints.h>
#include <qguiapplication.h>
#include <qatomic.h>
@@ -84,74 +91,254 @@ enum {
// must be multiple of 4 for easier SIMD implementations
static const int buffer_size = 2048;
+#ifdef Q_COMPILER_CONSTEXPR
+
+template<QImage::Format> Q_DECL_CONSTEXPR uint redWidth();
+template<QImage::Format> Q_DECL_CONSTEXPR uint redShift();
+template<QImage::Format> Q_DECL_CONSTEXPR uint greenWidth();
+template<QImage::Format> Q_DECL_CONSTEXPR uint greenShift();
+template<QImage::Format> Q_DECL_CONSTEXPR uint blueWidth();
+template<QImage::Format> Q_DECL_CONSTEXPR uint blueShift();
+template<QImage::Format> Q_DECL_CONSTEXPR uint alphaWidth();
+template<QImage::Format> Q_DECL_CONSTEXPR uint alphaShift();
+
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB16>() { return 5; }
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB444>() { return 4; }
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB555>() { return 5; }
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB666>() { return 6; }
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; }
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; }
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB8565_Premultiplied>() { return 5; }
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; }
+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; }
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB666>() { return 12; }
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB888>() { return 16; }
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB4444_Premultiplied>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB8555_Premultiplied>() { return 18; }
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB8565_Premultiplied>() { return 19; }
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB6666_Premultiplied>() { return 12; }
+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; }
+template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB666>() { return 6; }
+template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; }
+template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; }
+template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB8565_Premultiplied>() { return 6; }
+template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; }
+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; }
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB666>() { return 6; }
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB4444_Premultiplied>() { return 4; }
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB8555_Premultiplied>() { return 13; }
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB8565_Premultiplied>() { return 13; }
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB6666_Premultiplied>() { return 6; }
+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; }
+template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB666>() { return 6; }
+template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; }
+template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; }
+template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB8565_Premultiplied>() { return 5; }
+template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; }
+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; }
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB666>() { return 0; }
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB888>() { return 0; }
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB4444_Premultiplied>() { return 0; }
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB8555_Premultiplied>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB8565_Premultiplied>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB6666_Premultiplied>() { return 0; }
+template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; }
+template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB8555_Premultiplied>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB8565_Premultiplied>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; }
+template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB4444_Premultiplied>() { return 12; }
+template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB8555_Premultiplied>() { return 0; }
+template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB8565_Premultiplied>() { return 0; }
+template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB6666_Premultiplied>() { return 18; }
+
+template<QImage::Format> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel();
+template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB16>() { return QPixelLayout::BPP16; }
+template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB444>() { return QPixelLayout::BPP16; }
+template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB555>() { return QPixelLayout::BPP16; }
+template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB666>() { return QPixelLayout::BPP24; }
+template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB888>() { return QPixelLayout::BPP24; }
+template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB4444_Premultiplied>() { return QPixelLayout::BPP16; }
+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<QImage::Format Format>
+static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
+ Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
+ Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
+ Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>();
+ Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>();
+ Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>();
+ Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8;
+ Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
+ Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
+
+ for (int i = 0; i < count; ++i) {
+ uint red = (src[i] >> redShift<Format>()) & redMask;
+ uint green = (src[i] >> greenShift<Format>()) & greenMask;
+ uint blue = (src[i] >> blueShift<Format>()) & blueMask;
+
+ red = ((red << redLeftShift) | (red >> redRightShift)) << 16;
+ green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8;
+ blue = (blue << blueLeftShift) | (blue >> blueRightShift);
+ buffer[i] = 0xff000000 | red | green | blue;
+ }
-// 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 QPixelLayout *, const QRgb *clut)
-{
- for (int i = 0; i < count; ++i)
- buffer[i] = PREMUL(clut[src[i]]);
return buffer;
}
-static const uint *QT_FASTCALL convertPassThrough(uint *, const uint *src, int,
- const QPixelLayout *, const QRgb *)
+template<QImage::Format Format>
+static const uint *QT_FASTCALL convertARGBPMToARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
{
- return src;
+ Q_CONSTEXPR uint alphaMask = ((1 << alphaWidth<Format>()) - 1);
+ Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
+ Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
+ Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
+
+ Q_CONSTEXPR uchar alphaLeftShift = 8 - alphaWidth<Format>();
+ Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>();
+ Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>();
+ Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>();
+
+ Q_CONSTEXPR uchar alphaRightShift = 2 * alphaWidth<Format>() - 8;
+ Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8;
+ Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
+ Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
+
+ for (int i = 0; i < count; ++i) {
+ uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
+ uint red = (src[i] >> redShift<Format>()) & redMask;
+ uint green = (src[i] >> greenShift<Format>()) & greenMask;
+ uint blue = (src[i] >> blueShift<Format>()) & blueMask;
+
+ alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift);
+ red = qMin(alpha, (red << redLeftShift) | (red >> redRightShift));
+ green = qMin(alpha, (green << greenLeftShift) | (green >> greenRightShift));
+ blue = qMin(alpha, (blue << blueLeftShift) | (blue >> blueRightShift));
+ buffer[i] = (alpha << 24) | (red << 16) | (green << 8) | blue;
+ }
+
+ return buffer;
}
-static const uint *QT_FASTCALL convertRGB16ToARGB32PM(uint *buffer, const uint *src, int count,
+template<QImage::Format Format>
+static const uint *QT_FASTCALL convertRGBFromARGB32PM(uint *buffer, const uint *src, int count,
const QPixelLayout *, const QRgb *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = qConvertRgb16To32(src[i]);
+ Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
+ Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
+ Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
+
+ Q_CONSTEXPR uchar redRightShift = 24 - redWidth<Format>();
+ Q_CONSTEXPR uchar greenRightShift = 16 - greenWidth<Format>();
+ Q_CONSTEXPR uchar blueRightShift = 8 - blueWidth<Format>();
+
+ for (int i = 0; i < count; ++i) {
+ const uint color = qUnpremultiply(src[i]);
+ const uint red = ((color >> redRightShift) & redMask) << redShift<Format>();
+ const uint green = ((color >> greenRightShift) & greenMask) << greenShift<Format>();
+ const uint blue = ((color >> blueRightShift) & blueMask) << blueShift<Format>();
+ buffer[i] = red | green | blue;
+ }
return buffer;
}
-static const uint *QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count,
- const QPixelLayout *, const QRgb *)
+template<QImage::Format Format>
+static const uint *QT_FASTCALL convertRGBFromRGB32(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = PREMUL(src[i]);
+ Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
+ Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
+ Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
+
+ Q_CONSTEXPR uchar redRightShift = 24 - redWidth<Format>();
+ Q_CONSTEXPR uchar greenRightShift = 16 - greenWidth<Format>();
+ Q_CONSTEXPR uchar blueRightShift = 8 - blueWidth<Format>();
+
+ for (int i = 0; i < count; ++i) {
+ const uint red = ((src[i] >> redRightShift) & redMask) << redShift<Format>();
+ const uint green = ((src[i] >> greenRightShift) & greenMask) << greenShift<Format>();
+ const uint blue = ((src[i] >> blueRightShift) & blueMask) << blueShift<Format>();
+ buffer[i] = red | green | blue;
+ }
return buffer;
}
-static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int count,
- const QPixelLayout *layout, const QRgb *)
+template<QImage::Format Format>
+static const uint *QT_FASTCALL convertARGBPMFromARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
{
- Q_ASSERT(layout->redWidth >= 4);
- Q_ASSERT(layout->greenWidth >= 4);
- Q_ASSERT(layout->blueWidth >= 4);
- Q_ASSERT(layout->alphaWidth == 0);
-
- const uint redMask = ((1 << layout->redWidth) - 1);
- const uint greenMask = ((1 << layout->greenWidth) - 1);
- const uint blueMask = ((1 << layout->blueWidth) - 1);
-
- const uchar redLeftShift = 8 - layout->redWidth;
- const uchar greenLeftShift = 8 - layout->greenWidth;
- const uchar blueLeftShift = 8 - layout->blueWidth;
+ Q_CONSTEXPR uint alphaMask = ((1 << alphaWidth<Format>()) - 1);
+ Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
+ Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
+ Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
- const uchar redRightShift = 2 * layout->redWidth - 8;
- const uchar greenRightShift = 2 * layout->greenWidth - 8;
- const uchar blueRightShift = 2 * layout->blueWidth - 8;
+ Q_CONSTEXPR uchar alphaRightShift = 32 - alphaWidth<Format>();
+ Q_CONSTEXPR uchar redRightShift = 24 - redWidth<Format>();
+ Q_CONSTEXPR uchar greenRightShift = 16 - greenWidth<Format>();
+ Q_CONSTEXPR uchar blueRightShift = 8 - blueWidth<Format>();
for (int i = 0; i < count; ++i) {
- uint red = (src[i] >> layout->redShift) & redMask;
- uint green = (src[i] >> layout->greenShift) & greenMask;
- uint blue = (src[i] >> layout->blueShift) & blueMask;
-
- red = ((red << redLeftShift) | (red >> redRightShift)) << 16;
- green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8;
- blue = (blue << blueLeftShift) | (blue >> blueRightShift);
- buffer[i] = 0xff000000 | red | green | blue;
+ const uint alpha = ((src[i] >> alphaRightShift) & alphaMask) << alphaShift<Format>();
+ const uint red = ((src[i] >> redRightShift) & redMask) << redShift<Format>();
+ const uint green = ((src[i] >> greenRightShift) & greenMask) << greenShift<Format>();
+ const uint blue = ((src[i] >> blueRightShift) & blueMask) << blueShift<Format>();
+ buffer[i] = alpha | red | green | blue;
}
-
return buffer;
}
+template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixelLayoutRGB()
+{
+ return QPixelLayout{
+ redWidth<Format>(), redShift<Format>(),
+ greenWidth<Format>(), greenShift<Format>(),
+ blueWidth<Format>(), blueShift<Format>(),
+ 0, 0,
+ false, bitsPerPixel<Format>(),
+ convertToRGB32<Format>,
+ convertRGBFromARGB32PM<Format>,
+ convertRGBFromRGB32<Format>
+ };
+}
+
+template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixelLayoutARGBPM()
+{
+ return QPixelLayout{
+ redWidth<Format>(), redShift<Format>(),
+ greenWidth<Format>(), greenShift<Format>(),
+ blueWidth<Format>(), blueShift<Format>(),
+ alphaWidth<Format>(), alphaShift<Format>(),
+ true, bitsPerPixel<Format>(),
+ convertARGBPMToARGB32PM<Format>,
+ convertARGBPMFromARGB32PM<Format>,
+ 0
+ };
+}
+
+#else // CONSTEXPR
+
static const uint *QT_FASTCALL convertToARGB32PM(uint *buffer, const uint *src, int count,
const QPixelLayout *layout, const QRgb *)
{
@@ -200,25 +387,42 @@ static const uint *QT_FASTCALL convertToARGB32PM(uint *buffer, const uint *src,
red = (red << redLeftShift) | (red >> redRightShift);
green = (green << greenLeftShift) | (green >> greenRightShift);
blue = (blue << blueLeftShift) | (blue >> blueRightShift);
- buffer[i] = PREMUL((alpha << 24) | (red << 16) | (green << 8) | blue);
+ buffer[i] = qPremultiply((alpha << 24) | (red << 16) | (green << 8) | blue);
}
}
return buffer;
}
-static const uint *QT_FASTCALL convertRGB16FromARGB32PM(uint *buffer, const uint *src, int count,
- const QPixelLayout *, const QRgb *)
+static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int count,
+ const QPixelLayout *layout, const QRgb *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = qConvertRgb32To16(INV_PREMUL(src[i]));
- return buffer;
-}
+ Q_ASSERT(layout->redWidth >= 4);
+ Q_ASSERT(layout->greenWidth >= 4);
+ Q_ASSERT(layout->blueWidth >= 4);
+ Q_ASSERT(layout->alphaWidth == 0);
-static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uint *src, int count,
- const QPixelLayout *, const QRgb *)
-{
- for (int i = 0; i < count; ++i)
- buffer[i] = INV_PREMUL(src[i]);
+ const uint redMask = ((1 << layout->redWidth) - 1);
+ const uint greenMask = ((1 << layout->greenWidth) - 1);
+ const uint blueMask = ((1 << layout->blueWidth) - 1);
+
+ const uchar redLeftShift = 8 - layout->redWidth;
+ const uchar greenLeftShift = 8 - layout->greenWidth;
+ const uchar blueLeftShift = 8 - layout->blueWidth;
+
+ const uchar redRightShift = 2 * layout->redWidth - 8;
+ const uchar greenRightShift = 2 * layout->greenWidth - 8;
+ const uchar blueRightShift = 2 * layout->blueWidth - 8;
+
+ for (int i = 0; i < count; ++i) {
+ uint red = (src[i] >> layout->redShift) & redMask;
+ uint green = (src[i] >> layout->greenShift) & greenMask;
+ uint blue = (src[i] >> layout->blueShift) & blueMask;
+
+ red = (red << redLeftShift) | (red >> redRightShift);
+ green = (green << greenLeftShift) | (green >> greenRightShift);
+ blue = (blue << blueLeftShift) | (blue >> blueRightShift);
+ buffer[i] = 0xff000000 | (red << 16) | (green << 8) | blue;
+ }
return buffer;
}
@@ -242,7 +446,7 @@ static const uint *QT_FASTCALL convertFromARGB32PM(uint *buffer, const uint *src
if (!layout->premultiplied) {
for (int i = 0; i < count; ++i)
- buffer[i] = qAlpha(src[i]) == 255 ? src[i] : INV_PREMUL(src[i]);
+ buffer[i] = qUnpremultiply(src[i]);
src = buffer;
}
for (int i = 0; i < count; ++i) {
@@ -255,13 +459,14 @@ static const uint *QT_FASTCALL convertFromARGB32PM(uint *buffer, const uint *src
return buffer;
}
-static const uint *QT_FASTCALL convertRGBFromARGB32PM(uint *buffer, const uint *src, int count,
- const QPixelLayout *layout, const QRgb *)
+static const uint *QT_FASTCALL convertFromRGB32(uint *buffer, const uint *src, int count,
+ const QPixelLayout *layout, const QRgb *)
{
Q_ASSERT(layout->redWidth <= 8);
Q_ASSERT(layout->greenWidth <= 8);
Q_ASSERT(layout->blueWidth <= 8);
Q_ASSERT(layout->alphaWidth == 0);
+ Q_ASSERT(!layout->premultiplied);
const uint redMask = (1 << layout->redWidth) - 1;
const uint greenMask = (1 << layout->greenWidth) - 1;
@@ -272,16 +477,118 @@ static const uint *QT_FASTCALL convertRGBFromARGB32PM(uint *buffer, const uint *
const uchar blueRightShift = 8 - layout->blueWidth;
for (int i = 0; i < count; ++i) {
- uint color = INV_PREMUL(src[i]);
- uint red = ((color >> redRightShift) & redMask) << layout->redShift;
- uint green = ((color >> greenRightShift) & greenMask) << layout->greenShift;
- uint blue = ((color >> blueRightShift) & blueMask) << layout->blueShift;
- uint alpha = 0xff << layout->alphaShift;
- buffer[i] = red | green | blue | alpha;
+ uint red = ((src[i] >> redRightShift) & redMask) << layout->redShift;
+ uint green = ((src[i] >> greenRightShift) & greenMask) << layout->greenShift;
+ uint blue = ((src[i] >> blueRightShift) & blueMask) << layout->blueShift;
+ buffer[i] = red | green | blue;
}
return buffer;
}
+static const uint *QT_FASTCALL convertRGB16ToRGB32(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qConvertRgb16To32(src[i]);
+ return buffer;
+}
+
+static const uint *QT_FASTCALL convertRGB16FromRGB32(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qConvertRgb32To16(src[i]);
+ return buffer;
+}
+
+static const uint *QT_FASTCALL convertRGB16FromARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qConvertRgb32To16(qUnpremultiply(src[i]));
+ return buffer;
+}
+#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 QPixelLayout *, const QRgb *clut)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qPremultiply(clut[src[i]]);
+ return buffer;
+}
+
+static const uint *QT_FASTCALL convertPassThrough(uint *, const uint *src, int,
+ const QPixelLayout *, const QRgb *)
+{
+ return src;
+}
+
+static const uint *QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qPremultiply(src[i]);
+ return buffer;
+}
+
+static const uint *QT_FASTCALL convertRGBA8888PMToARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = RGBA2ARGB(src[i]);
+ return buffer;
+}
+
+static const uint *QT_FASTCALL convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qPremultiply(RGBA2ARGB(src[i]));
+ return buffer;
+}
+
+static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qUnpremultiply(src[i]);
+ return buffer;
+}
+
+static const uint *QT_FASTCALL convertRGBA8888PMFromARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = ARGB2RGBA(src[i]);
+ return buffer;
+}
+
+static const uint *QT_FASTCALL convertRGBA8888FromARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = ARGB2RGBA(qUnpremultiply(src[i]));
+ return buffer;
+}
+
+static const uint *QT_FASTCALL convertRGBXFromRGB32(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = ARGB2RGBA(0xff000000 | src[i]);
+ return buffer;
+}
+
+static const uint *QT_FASTCALL convertRGBXFromARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply(src[i]));
+ return buffer;
+}
+
template <QPixelLayout::BPP bpp> static
uint QT_FASTCALL fetchPixel(const uchar *src, int index);
@@ -392,30 +699,44 @@ 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 }, // Format_Invalid
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1MSB, convertIndexedToARGB32PM, 0 }, // Format_Mono
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1LSB, convertIndexedToARGB32PM, 0 }, // Format_MonoLSB
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertIndexedToARGB32PM, 0 }, // Format_Indexed8
- { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP32, convertPassThrough, convertPassThrough }, // Format_RGB32
- { 8, 16, 8, 8, 8, 0, 8, 24, false, QPixelLayout::BPP32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM }, // Format_ARGB32
- { 8, 16, 8, 8, 8, 0, 8, 24, true, QPixelLayout::BPP32, convertPassThrough, convertPassThrough }, // Format_ARGB32_Premultiplied
- { 5, 11, 6, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, convertRGB16ToARGB32PM, convertRGB16FromARGB32PM }, // Format_RGB16
- { 5, 19, 6, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM }, // Format_ARGB8565_Premultiplied
- { 6, 12, 6, 6, 6, 0, 0, 0, false, QPixelLayout::BPP24, convertToRGB32, convertFromARGB32PM }, // Format_RGB666
- { 6, 12, 6, 6, 6, 0, 6, 18, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM }, // Format_ARGB6666_Premultiplied
- { 5, 10, 5, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32, convertFromARGB32PM }, // Format_RGB555
- { 5, 18, 5, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM }, // Format_ARGB8555_Premultiplied
- { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP24, convertToRGB32, convertFromARGB32PM }, // Format_RGB888
- { 4, 8, 4, 4, 4, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32, convertFromARGB32PM }, // Format_RGB444
- { 4, 8, 4, 4, 4, 0, 4, 12, true, QPixelLayout::BPP16, convertToARGB32PM, convertFromARGB32PM }, // Format_ARGB4444_Premultiplied
+ { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPPNone, 0, 0, 0 }, // Format_Invalid
+ { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1MSB, convertIndexedToARGB32PM, 0, 0 }, // Format_Mono
+ { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1LSB, convertIndexedToARGB32PM, 0, 0 }, // Format_MonoLSB
+ { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertIndexedToARGB32PM, 0, 0 }, // Format_Indexed8
+ // Technically using convertPassThrough to convert from ARGB32PM to RGB32 is wrong,
+ // but everywhere this generic conversion would be wrong is currently overloaed.
+ { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough }, // Format_RGB32
+ { 8, 16, 8, 8, 8, 0, 8, 24, false, QPixelLayout::BPP32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM, 0 }, // Format_ARGB32
+ { 8, 16, 8, 8, 8, 0, 8, 24, true, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, 0 }, // Format_ARGB32_Premultiplied
+#ifdef Q_COMPILER_CONSTEXPR
+ pixelLayoutRGB<QImage::Format_RGB16>(),
+ pixelLayoutARGBPM<QImage::Format_ARGB8565_Premultiplied>(),
+ pixelLayoutRGB<QImage::Format_RGB666>(),
+ pixelLayoutARGBPM<QImage::Format_ARGB6666_Premultiplied>(),
+ pixelLayoutRGB<QImage::Format_RGB555>(),
+ pixelLayoutARGBPM<QImage::Format_ARGB8555_Premultiplied>(),
+ 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, convertRGB16ToRGB32, convertRGB16FromARGB32PM, convertRGB16FromRGB32 }, // Format_RGB16
+ { 5, 19, 6, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM, 0 }, // Format_ARGB8565_Premultiplied
+ { 6, 12, 6, 6, 6, 0, 0, 0, false, QPixelLayout::BPP24, convertToRGB32, convertFromARGB32PM, convertFromRGB32 }, // Format_RGB666
+ { 6, 12, 6, 6, 6, 0, 6, 18, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM, 0 }, // Format_ARGB6666_Premultiplied
+ { 5, 10, 5, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32, convertFromARGB32PM, convertFromRGB32 }, // Format_RGB555
+ { 5, 18, 5, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM, 0 }, // Format_ARGB8555_Premultiplied
+ { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP24, convertToRGB32, convertFromARGB32PM, convertFromRGB32 }, // Format_RGB888
+ { 4, 8, 4, 4, 4, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32, convertFromARGB32PM, convertFromRGB32 }, // Format_RGB444
+ { 4, 8, 4, 4, 4, 0, 4, 12, true, QPixelLayout::BPP16, convertToARGB32PM, convertFromARGB32PM, 0 }, // Format_ARGB4444_Premultiplied
+#endif
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- { 8, 24, 8, 16, 8, 8, 0, 0, false, QPixelLayout::BPP32, convertToRGB32, convertRGBFromARGB32PM }, // Format_RGBX8888
- { 8, 24, 8, 16, 8, 8, 8, 0, false, QPixelLayout::BPP32, convertToARGB32PM, convertFromARGB32PM }, // Format_RGBA8888
- { 8, 24, 8, 16, 8, 8, 8, 0, true, QPixelLayout::BPP32, convertToARGB32PM, convertFromARGB32PM }, // Format_RGBA8888_Premultiplied
+ { 8, 24, 8, 16, 8, 8, 0, 0, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBX8888
+ { 8, 24, 8, 16, 8, 8, 8, 0, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, 0 }, // Format_RGBA8888
+ { 8, 24, 8, 16, 8, 8, 8, 0, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, 0 }, // Format_RGBA8888_Premultiplied
#else
- { 8, 0, 8, 8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertToRGB32, convertRGBFromARGB32PM }, // Format_RGBX8888
- { 8, 0, 8, 8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertToARGB32PM, convertFromARGB32PM }, // Format_RGBA8888 (ABGR32)
- { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertToARGB32PM, convertFromARGB32PM } // Format_RGBA8888_Premultiplied
+ { 8, 0, 8, 8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBX8888
+ { 8, 0, 8, 8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, 0 }, // Format_RGBA8888 (ABGR32)
+ { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, 0 } // Format_RGBA8888_Premultiplied
#endif
};
@@ -532,9 +853,9 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] =
*/
static inline QRgb findNearestColor(QRgb color, QRasterBuffer *rbuf)
{
- QRgb color_0 = PREMUL(rbuf->destColor0);
- QRgb color_1 = PREMUL(rbuf->destColor1);
- color = PREMUL(color);
+ QRgb color_0 = qPremultiply(rbuf->destColor0);
+ QRgb color_1 = qPremultiply(rbuf->destColor1);
+ color = qPremultiply(color);
int r = qRed(color);
int g = qGreen(color);
@@ -630,7 +951,12 @@ static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, con
uchar *dest = rasterBuffer->scanLine(y);
while (length) {
int l = qMin(length, buffer_size);
- const uint *ptr = layout->convertFromARGB32PM(buf, buffer, l, layout, 0);
+ const uint *ptr = 0;
+ if (layout->convertFromRGB32) {
+ Q_ASSERT(!layout->premultiplied && !layout->alphaWidth);
+ ptr = layout->convertFromRGB32(buf, buffer, l, layout, 0);
+ } else
+ ptr = layout->convertFromARGB32PM(buf, buffer, l, layout, 0);
store(dest, ptr, x, l);
length -= l;
buffer += l;
@@ -891,7 +1217,7 @@ static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, i
{
uint distxy = distx * disty;
//idistx * disty = (16-distx) * disty = 16*disty - distxy
- //idistx * idisty = (16-distx) * (16-disty) = 16*16 - 16*distx -16*dity + distxy
+ //idistx * idisty = (16-distx) * (16-disty) = 16*16 - 16*distx -16*disty + distxy
uint tlrb = (tl & 0x00ff00ff) * (16*16 - 16*distx - 16*disty + distxy);
uint tlag = ((tl & 0xff00ff00) >> 8) * (16*16 - 16*distx - 16*disty + distxy);
uint trrb = ((tr & 0x00ff00ff) * (distx*16 - distxy));
@@ -973,6 +1299,44 @@ static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, i
}
#endif
+#if defined(__SSE2__)
+static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty)
+{
+ // First interpolate right and left pixels in parallel.
+ __m128i vl = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tl), _mm_cvtsi32_si128(bl));
+ __m128i vr = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tr), _mm_cvtsi32_si128(br));
+ vl = _mm_unpacklo_epi8(vl, _mm_setzero_si128());
+ vr = _mm_unpacklo_epi8(vr, _mm_setzero_si128());
+ vl = _mm_mullo_epi16(vl, _mm_set1_epi16(256 - distx));
+ vr = _mm_mullo_epi16(vr, _mm_set1_epi16(distx));
+ __m128i vtb = _mm_add_epi16(vl, vr);
+ vtb = _mm_srli_epi16(vtb, 8);
+ // vtb now contains the result of the first two interpolate calls vtb = unpacked((xbot << 64) | xtop)
+
+ // Now the last interpolate between top and bottom interpolations.
+ const __m128i vidisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(256 - disty), _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128i vdisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(disty), _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128i vmuly = _mm_unpacklo_epi16(vidisty, vdisty);
+ vtb = _mm_unpacklo_epi16(vtb, _mm_srli_si128(vtb, 8));
+ // vtb now contains the colors of top and bottom interleaved { ta, ba, tr, br, tg, bg, tb, bb }
+ vtb = _mm_madd_epi16(vtb, vmuly); // Multiply and horizontal add.
+ vtb = _mm_srli_epi32(vtb, 8);
+ vtb = _mm_packs_epi32(vtb, _mm_setzero_si128());
+ vtb = _mm_packus_epi16(vtb, _mm_setzero_si128());
+ return _mm_cvtsi128_si32(vtb);
+}
+#else
+static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty)
+{
+ uint idistx = 256 - distx;
+ uint idisty = 256 - disty;
+ uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
+ uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
+ return INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
+}
+#endif
+
+
template<TextureBlendType blendType>
void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2);
@@ -1177,7 +1541,6 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
const uint *s1 = (const uint *)data->texture.scanLine(y1);
const uint *s2 = (const uint *)data->texture.scanLine(y2);
int disty = (fy & 0x0000ffff) >> 8;
- int idisty = 256 - disty;
while (b < end) {
int x1 = (fx >> 16);
int x2;
@@ -1186,13 +1549,8 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
uint tr = s1[x2];
uint bl = s2[x1];
uint br = s2[x2];
-
int distx = (fx & 0x0000ffff) >> 8;
- int idistx = 256 - distx;
-
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
+ *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
fx += fdx;
++b;
@@ -1356,12 +1714,8 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
int distx = (fx & 0x0000ffff) >> 8;
int disty = (fy & 0x0000ffff) >> 8;
- int idistx = 256 - distx;
- int idisty = 256 - disty;
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
+ *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
fx += fdx;
fy += fdy;
@@ -1418,8 +1772,6 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
int distx = int((px - x1) * 256);
int disty = int((py - y1) * 256);
- int idistx = 256 - distx;
- int idisty = 256 - disty;
fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
@@ -1432,9 +1784,7 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
uint bl = s2[x1];
uint br = s2[x2];
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
+ *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
fx += fdx;
fy += fdy;
@@ -1606,17 +1956,13 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
if ((fdx < 0 && fdx > -(fixed_scale / 8)) || fabs(data->m22) < (1./8.)) { // scale up more than 8x
int disty = (fy & 0x0000ffff) >> 8;
- int idisty = 256 - disty;
for (int i = 0; i < len; ++i) {
uint tl = buf1[i * 2 + 0];
uint tr = buf1[i * 2 + 1];
uint bl = buf2[i * 2 + 0];
uint br = buf2[i * 2 + 1];
int distx = (fracX & 0x0000ffff) >> 8;
- int idistx = 256 - distx;
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- b[i] = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
+ b[i] = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
fracX += fdx;
}
} else { //scale down
@@ -1677,12 +2023,8 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
int distx = (fracX & 0x0000ffff) >> 8;
int disty = (fracY & 0x0000ffff) >> 8;
- int idistx = 256 - distx;
- int idisty = 256 - disty;
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- b[i] = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
+ b[i] = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
fracX += fdx;
fracY += fdy;
}
@@ -1764,17 +2106,13 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
for (int i = 0; i < len; ++i) {
int distx = distxs[i];
int disty = distys[i];
- int idistx = 256 - distx;
- int idisty = 256 - disty;
uint tl = buf1[i * 2 + 0];
uint tr = buf1[i * 2 + 1];
uint bl = buf2[i * 2 + 0];
uint br = buf2[i * 2 + 1];
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- b[i] = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
+ b[i] = interpolate_4_pixels(tl, tr, bl, br, distx, disty);
}
length -= len;
b += len;
@@ -5071,13 +5409,15 @@ static void blend_transformed_tiled_argb(int count, const QSpan *spans, void *us
int l = qMin(length, buffer_size);
const uint *end = buffer + l;
uint *b = buffer;
+ int px16 = x % (image_width << 16);
+ int py16 = y % (image_height << 16);
+ int px_delta = fdx % (image_width << 16);
+ int py_delta = fdy % (image_height << 16);
while (b < end) {
- int px = x >> 16;
- int py = y >> 16;
- px %= image_width;
- py %= image_height;
- if (px < 0) px += image_width;
- if (py < 0) py += image_height;
+ if (px16 < 0) px16 += image_width << 16;
+ if (py16 < 0) py16 += image_height << 16;
+ int px = px16 >> 16;
+ int py = py16 >> 16;
int y_offset = py * scanline_offset;
Q_ASSERT(px >= 0 && px < image_width);
@@ -5086,6 +5426,12 @@ static void blend_transformed_tiled_argb(int count, const QSpan *spans, void *us
*b = image_bits[y_offset + px];
x += fdx;
y += fdy;
+ px16 += px_delta;
+ if (px16 >= image_width << 16)
+ px16 -= image_width << 16;
+ py16 += py_delta;
+ if (py16 >= image_height << 16)
+ py16 -= image_height << 16;
++b;
}
func(target, buffer, l, coverage);
@@ -5916,7 +6262,7 @@ static void qt_rectfill_nonpremul_argb32(QRasterBuffer *rasterBuffer,
quint32 color)
{
qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()),
- INV_PREMUL(color), x, y, width, height, rasterBuffer->bytesPerLine());
+ qUnpremultiply(color), x, y, width, height, rasterBuffer->bytesPerLine());
}
static void qt_rectfill_rgba(QRasterBuffer *rasterBuffer,
@@ -5932,7 +6278,7 @@ static void qt_rectfill_nonpremul_rgba(QRasterBuffer *rasterBuffer,
quint32 color)
{
qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()),
- ARGB2RGBA(INV_PREMUL(color)), x, y, width, height, rasterBuffer->bytesPerLine());
+ ARGB2RGBA(qUnpremultiply(color)), x, y, width, height, rasterBuffer->bytesPerLine());
}
@@ -6140,110 +6486,73 @@ inline void qt_memfill_template(quint16 *dest, quint16 value, int count)
}
#endif
-static void qt_memfill_quint16(quint16 *dest, quint16 color, int count)
+#if !defined(__SSE2__)
+void qt_memfill16(quint16 *dest, quint16 color, int count)
{
qt_memfill_template<quint16>(dest, color, count);
}
-
-typedef void (*qt_memfill32_func)(quint32 *dest, quint32 value, int count);
-typedef void (*qt_memfill16_func)(quint16 *dest, quint16 value, int count);
-static void qt_memfill32_setup(quint32 *dest, quint32 value, int count);
-static void qt_memfill16_setup(quint16 *dest, quint16 value, int count);
-
-qt_memfill32_func qt_memfill32 = qt_memfill32_setup;
-qt_memfill16_func qt_memfill16 = qt_memfill16_setup;
+#endif
+#if !defined(__SSE2__) && !defined(__ARM_NEON__)
+void qt_memfill32(quint32 *dest, quint32 color, int count)
+{
+# ifdef QT_COMPILER_SUPPORTS_MIPS_DSP
+ extern "C" qt_memfill32_asm_mips_dsp(quint32 *, quint32, int);
+ qt_memfill32_asm_mips_dsp(dest, color, count);
+# else
+ qt_memfill_template<quint32>(dest, color, count);
+# endif
+}
+#endif
void qInitDrawhelperAsm()
{
-
- qt_memfill32 = qt_memfill_template<quint32>;
- qt_memfill16 = qt_memfill_quint16; //qt_memfill_template<quint16>;
-
CompositionFunction *functionForModeAsm = 0;
CompositionFunctionSolid *functionForModeSolidAsm = 0;
const uint features = qCpuFeatures();
- if (false) {
- Q_UNUSED(features);
-#ifdef QT_COMPILER_SUPPORTS_AVX
- } else if (features & AVX) {
- qt_memfill32 = qt_memfill32_avx;
- qt_memfill16 = qt_memfill16_avx;
- qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_avx;
- qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_avx;
- qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_avx;
- qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_avx;
- qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit32_avx;
- qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit32_avx;
- qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit32_avx;
-
- extern void qt_scale_image_argb32_on_argb32_avx(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- const QRectF &targetRect,
- const QRectF &sourceRect,
- const QRect &clip,
- int const_alpha);
- qScaleFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32_avx;
- qScaleFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32_avx;
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qScaleFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32_avx;
- qScaleFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32_avx;
-#endif
-#endif
-#ifdef QT_COMPILER_SUPPORTS_SSE2
- } else if (features & SSE2) {
- qt_memfill32 = qt_memfill32_sse2;
- qt_memfill16 = qt_memfill16_sse2;
- qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2;
- qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2;
- qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2;
- qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse2;
- qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit32_sse2;
- qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit32_sse2;
- qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2;
-
- extern void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- const QRectF &targetRect,
- const QRectF &sourceRect,
- const QRect &clip,
- int const_alpha);
- qScaleFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32_sse2;
- qScaleFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32_sse2;
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qScaleFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32_sse2;
- qScaleFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32_sse2;
-#endif
-#endif
- }
-
-#ifdef QT_COMPILER_SUPPORTS_SSE2
- if (features & SSE2) {
- extern void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha);
- extern void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha);
-
- qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
- qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
- qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
- qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_sse2;
- qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_sse2;
- qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
- qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
-#endif
-
- extern const uint * QT_FASTCALL qt_fetch_radial_gradient_sse2(uint *buffer, const Operator *op, const QSpanData *data,
- int y, int x, int length);
-
- qt_fetch_radial_gradient = qt_fetch_radial_gradient_sse2;
- }
+ Q_UNUSED(features);
+#ifdef __SSE2__
+ qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2;
+ qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2;
+ qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2;
+ qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse2;
+ qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit32_sse2;
+ qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit32_sse2;
+ qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2;
+
+ extern void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha);
+ qScaleFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32_sse2;
+ qScaleFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32_sse2;
+ qScaleFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32_sse2;
+ qScaleFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32_sse2;
+
+ extern void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+ extern void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_sse2;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_sse2;
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
+
+ extern const uint * QT_FASTCALL qt_fetch_radial_gradient_sse2(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length);
+
+ qt_fetch_radial_gradient = qt_fetch_radial_gradient_sse2;
#ifdef QT_COMPILER_SUPPORTS_SSSE3
if (features & SSSE3) {
@@ -6254,65 +6563,13 @@ void qInitDrawhelperAsm()
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
-#endif
}
#endif // SSSE3
-#ifdef QT_COMPILER_SUPPORTS_AVX
- if (features & AVX) {
- extern void qt_blend_rgb32_on_rgb32_avx(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha);
- extern void qt_blend_argb32_on_argb32_avx(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha);
-
- qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_avx;
- qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_avx;
- qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_avx;
- qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_avx;
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_avx;
- qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_avx;
- qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_avx;
- qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_avx;
-#endif
-
- extern const uint * QT_FASTCALL qt_fetch_radial_gradient_avx(uint *buffer, const Operator *op, const QSpanData *data,
- int y, int x, int length);
-
- qt_fetch_radial_gradient = qt_fetch_radial_gradient_avx;
- }
-#endif // AVX
-
-#endif // SSE2
-
-#ifdef QT_COMPILER_SUPPORTS_SSE2
- if (features & SSE2) {
- functionForModeAsm = qt_functionForMode_SSE2;
- functionForModeSolidAsm = qt_functionForModeSolid_SSE2;
- }
-#endif
-#ifdef QT_COMPILER_SUPPORTS_AVX
- if (features & AVX) {
- extern void QT_FASTCALL comp_func_SourceOver_avx(uint *destPixels,
- const uint *srcPixels,
- int length,
- uint const_alpha);
- extern void QT_FASTCALL comp_func_solid_SourceOver_avx(uint *destPixels, int length, uint color, uint const_alpha);
- extern void QT_FASTCALL comp_func_Plus_avx(uint *dst, const uint *src, int length, uint const_alpha);
- extern void QT_FASTCALL comp_func_Source_avx(uint *dst, const uint *src, int length, uint const_alpha);
-
- functionForModeAsm[0] = comp_func_SourceOver_avx;
- functionForModeAsm[QPainter::CompositionMode_Source] = comp_func_Source_avx;
- functionForModeAsm[QPainter::CompositionMode_Plus] = comp_func_Plus_avx;
- functionForModeSolidAsm[0] = comp_func_solid_SourceOver_avx;
- }
+ functionForModeAsm = qt_functionForMode_SSE2;
+ functionForModeSolidAsm = qt_functionForModeSolid_SSE2;
#endif // SSE2
#ifdef QT_COMPILER_SUPPORTS_IWMMXT
@@ -6323,45 +6580,42 @@ void qInitDrawhelperAsm()
}
#endif // IWMMXT
-#if defined(QT_COMPILER_SUPPORTS_NEON) && !defined(Q_OS_IOS)
- if (features & NEON) {
- qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
- qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
- qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
- qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
- qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon;
- qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon;
- qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_neon;
+#if defined(__ARM_NEON__) && !defined(Q_OS_IOS)
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon;
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_neon;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_neon;
- qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_neon;
- qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_neon;
- qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_neon;
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_neon;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_neon;
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_neon;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_neon;
#endif
- qScaleFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_rgb16_neon;
- qScaleFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_scale_image_rgb16_on_rgb16_neon;
+ qScaleFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_rgb16_neon;
+ qScaleFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_scale_image_rgb16_on_rgb16_neon;
- qTransformFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_rgb16_neon;
- qTransformFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_transform_image_rgb16_on_rgb16_neon;
+ qTransformFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_rgb16_neon;
+ qTransformFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_transform_image_rgb16_on_rgb16_neon;
- qDrawHelper[QImage::Format_RGB16].alphamapBlit = qt_alphamapblit_quint16_neon;
+ qDrawHelper[QImage::Format_RGB16].alphamapBlit = qt_alphamapblit_quint16_neon;
- functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon;
- functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon;
- functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_neon;
- destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon;
- destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon;
+ functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon;
+ functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon;
+ functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_neon;
+ destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon;
+ destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon;
- qMemRotateFunctions[QImage::Format_RGB16][0] = qt_memrotate90_16_neon;
- qMemRotateFunctions[QImage::Format_RGB16][2] = qt_memrotate270_16_neon;
- qt_memfill32 = qt_memfill32_neon;
+ qMemRotateFunctions[QImage::Format_RGB16][0] = qt_memrotate90_16_neon;
+ qMemRotateFunctions[QImage::Format_RGB16][2] = qt_memrotate270_16_neon;
- extern const uint * QT_FASTCALL qt_fetch_radial_gradient_neon(uint *buffer, const Operator *op, const QSpanData *data,
- int y, int x, int length);
+ extern const uint * QT_FASTCALL qt_fetch_radial_gradient_neon(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length);
- qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
- }
+ qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
#endif
#if defined(QT_COMPILER_SUPPORTS_MIPS_DSP)
@@ -6385,8 +6639,6 @@ void qInitDrawhelperAsm()
functionForModeSolid_C[QPainter::CompositionMode_Xor] = comp_func_solid_XOR_mips_dsp;
functionForModeSolid_C[QPainter::CompositionMode_SourceOut] = comp_func_solid_SourceOut_mips_dsp;
- qt_memfill32 = qt_memfill32_asm_mips_dsp;
-
qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mips_dsp;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mips_dsp;
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_mips_dsp;
@@ -6427,16 +6679,4 @@ void qInitDrawhelperAsm()
functionForMode = functionForModeAsm;
}
-static void qt_memfill32_setup(quint32 *dest, quint32 value, int count)
-{
- qInitDrawhelperAsm();
- qt_memfill32(dest, value, count);
-}
-
-static void qt_memfill16_setup(quint16 *dest, quint16 value, int count)
-{
- qInitDrawhelperAsm();
- qt_memfill16(dest, value, count);
-}
-
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper_avx.cpp b/src/gui/painting/qdrawhelper_avx.cpp
deleted file mode 100644
index 7da6ce6a20..0000000000
--- a/src/gui/painting/qdrawhelper_avx.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Intel Corporation
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <private/qsimd_p.h>
-
-#ifdef QT_COMPILER_SUPPORTS_AVX
-#define QDRAWHELPER_AVX
-
-#ifndef __AVX__
-#error "AVX not enabled in this file, cannot proceed"
-#endif
-
-#define qt_blend_argb32_on_argb32_ssse3 qt_blend_argb32_on_argb32_avx
-#include "qdrawhelper_ssse3.cpp"
-
-//#define qt_blend_argb32_on_argb32_sse2 qt_blend_argb32_on_argb32_avx
-#define qt_blend_rgb32_on_rgb32_sse2 qt_blend_rgb32_on_rgb32_avx
-#define comp_func_SourceOver_sse2 comp_func_SourceOver_avx
-#define comp_func_Plus_sse2 comp_func_Plus_avx
-#define comp_func_Source_sse2 comp_func_Source_avx
-#define comp_func_solid_SourceOver_sse2 comp_func_solid_SourceOver_avx
-#define qt_memfill32_sse2 qt_memfill32_avx
-#define qt_memfill16_sse2 qt_memfill16_avx
-#define qt_bitmapblit32_sse2 qt_bitmapblit32_avx
-#define qt_bitmapblit16_sse2 qt_bitmapblit16_avx
-#define QSimdSse2 QSimdAvx
-#define qt_fetch_radial_gradient_sse2 qt_fetch_radial_gradient_avx
-#define qt_scale_image_argb32_on_argb32_sse2 qt_scale_image_argb32_on_argb32_avx
-
-#include "qdrawhelper_sse2.cpp"
-
-#endif
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index 541b3ef619..a40166d5be 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -43,7 +43,7 @@
#include <private/qblendfunctions_p.h>
#include <private/qmath_p.h>
-#ifdef QT_COMPILER_SUPPORTS_NEON
+#ifdef __ARM_NEON__
#include <private/qdrawhelper_neon_p.h>
#include <private/qpaintengine_raster_p.h>
@@ -51,7 +51,7 @@
QT_BEGIN_NAMESPACE
-void qt_memfill32_neon(quint32 *dest, quint32 value, int count)
+void qt_memfill32(quint32 *dest, quint32 value, int count)
{
const int epilogueSize = count % 16;
if (count >= 16) {
@@ -998,5 +998,5 @@ const uint * QT_FASTCALL qt_fetch_radial_gradient_neon(uint *buffer, const Opera
QT_END_NAMESPACE
-#endif // QT_COMPILER_SUPPORTS_NEON
+#endif // __ARM_NEON__
diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h
index 475df639f8..cad6fe22e9 100644
--- a/src/gui/painting/qdrawhelper_neon_p.h
+++ b/src/gui/painting/qdrawhelper_neon_p.h
@@ -57,7 +57,7 @@
QT_BEGIN_NAMESPACE
-#ifdef QT_COMPILER_SUPPORTS_NEON
+#ifdef __ARM_NEON__
void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
@@ -139,7 +139,7 @@ void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer,
void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, uint color, uint const_alpha);
void QT_FASTCALL comp_func_Plus_neon(uint *dst, const uint *src, int length, uint const_alpha);
-#endif // QT_COMPILER_SUPPORTS_NEON
+#endif // __ARM_NEON__
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 418294c56d..bbeb73f0af 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -171,6 +171,8 @@ extern MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3];
extern DrawHelper qDrawHelper[QImage::NImageFormats];
void qBlendTexture(int count, const QSpan *spans, void *userData);
+extern void qt_memfill32(quint32 *dest, quint32 value, int count);
+extern void qt_memfill16(quint16 *dest, quint16 value, int count);
typedef void (QT_FASTCALL *CompositionFunction)(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha);
typedef void (QT_FASTCALL *CompositionFunctionSolid)(uint *dest, int length, uint color, uint const_alpha);
@@ -386,8 +388,6 @@ static inline qreal qRadialDeterminant(qreal a, qreal b, qreal c)
return (b * b) - (4 * a * c);
}
-extern void (*qt_memfill32)(quint32 *dest, quint32 value, int count);
-
template <class RadialFetchFunc> Q_STATIC_TEMPLATE_FUNCTION
const uint * QT_FASTCALL qt_fetch_radial_gradient_template(uint *buffer, const Operator *op, const QSpanData *data,
int y, int x, int length)
@@ -599,14 +599,6 @@ static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) {
return (uint(t)) | (uint(t >> 24));
}
-static Q_ALWAYS_INLINE uint PREMUL(uint x) {
- uint a = x >> 24;
- quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
- t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8;
- t &= 0x000000ff00ff00ff;
- return (uint(t)) | (uint(t >> 24)) | (a << 24);
-}
-
#else // 32-bit versions
static Q_ALWAYS_INLINE uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
@@ -639,20 +631,9 @@ static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) {
# pragma pop
#endif
-static Q_ALWAYS_INLINE uint PREMUL(uint x) {
- uint a = x >> 24;
- uint t = (x & 0xff00ff) * a;
- t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
- t &= 0xff00ff;
-
- x = ((x >> 8) & 0xff) * a;
- x = (x + ((x >> 8) & 0xff) + 0x80);
- x &= 0xff00;
- x |= t | (a << 24);
- return x;
-}
#endif
+
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
static Q_ALWAYS_INLINE quint32 RGBA2ARGB(quint32 x) {
quint32 rgb = x >> 8;
@@ -691,12 +672,9 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) {
return t;
}
-#define INV_PREMUL(p) \
- (qAlpha(p) == 0 ? 0 : \
- ((qAlpha(p) << 24) \
- | (((255*qRed(p))/ qAlpha(p)) << 16) \
- | (((255*qGreen(p)) / qAlpha(p)) << 8) \
- | ((255*qBlue(p)) / qAlpha(p))))
+// FIXME: Remove when all Qt modules have stopped using PREMUL and INV_PREMUL
+#define PREMUL(x) qPremultiply(x)
+#define INV_PREMUL(p) qUnpremultiply(p)
struct quint24 {
quint24(uint value);
@@ -726,7 +704,6 @@ template<> inline void qt_memfill(quint32 *dest, quint32 color, int count)
template<> inline void qt_memfill(quint16 *dest, quint16 color, int count)
{
- extern void (*qt_memfill16)(quint16 *dest, quint16 value, int count);
qt_memfill16(dest, color, count);
}
@@ -1031,6 +1008,7 @@ struct QPixelLayout
BPP bpp;
ConvertFunc convertToARGB32PM;
ConvertFunc convertFromARGB32PM;
+ ConvertFunc convertFromRGB32;
};
typedef const uint *(QT_FASTCALL *FetchPixelsFunc)(uint *buffer, const uchar *src, int index, int count);
diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp
index a9dc5a7fb7..f5523f7113 100644
--- a/src/gui/painting/qdrawhelper_sse2.cpp
+++ b/src/gui/painting/qdrawhelper_sse2.cpp
@@ -238,7 +238,7 @@ void QT_FASTCALL comp_func_Source_sse2(uint *dst, const uint *src, int length, u
}
}
-void qt_memfill32_sse2(quint32 *dest, quint32 value, int count)
+void qt_memfill32(quint32 *dest, quint32 value, int count)
{
if (count < 7) {
switch (count) {
@@ -259,33 +259,39 @@ void qt_memfill32_sse2(quint32 *dest, quint32 value, int count)
case 12: *dest++ = value; --count;
}
+ const int rest = count & 0x3;
+ if (rest) {
+ switch (rest) {
+ case 3: dest[count - 3] = value;
+ case 2: dest[count - 2] = value;
+ case 1: dest[count - 1] = value;
+ }
+ }
+
int count128 = count / 4;
__m128i *dst128 = reinterpret_cast<__m128i*>(dest);
+ __m128i *end128 = dst128 + count128;
const __m128i value128 = _mm_set_epi32(value, value, value, value);
- int n = (count128 + 3) / 4;
+ while (dst128 + 3 < end128) {
+ _mm_stream_si128(dst128 + 0, value128);
+ _mm_stream_si128(dst128 + 1, value128);
+ _mm_stream_si128(dst128 + 2, value128);
+ _mm_stream_si128(dst128 + 3, value128);
+ dst128 += 4;
+ }
+
switch (count128 & 0x3) {
- case 0: do { _mm_stream_si128(dst128++, value128);
case 3: _mm_stream_si128(dst128++, value128);
case 2: _mm_stream_si128(dst128++, value128);
case 1: _mm_stream_si128(dst128++, value128);
- } while (--n > 0);
- }
-
- const int rest = count & 0x3;
- if (rest) {
- switch (rest) {
- case 3: dest[count - 3] = value;
- case 2: dest[count - 2] = value;
- case 1: dest[count - 1] = value;
- }
}
}
void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha)
{
if ((const_alpha & qAlpha(color)) == 255) {
- qt_memfill32_sse2(destPixels, color, length);
+ qt_memfill32(destPixels, color, length);
} else {
if (const_alpha != 255)
color = BYTE_MUL(color, const_alpha);
@@ -397,7 +403,7 @@ CompositionFunction qt_functionForMode_SSE2[numCompositionFunctions] = {
};
#endif
-void qt_memfill16_sse2(quint16 *dest, quint16 value, int count)
+void qt_memfill16(quint16 *dest, quint16 value, int count)
{
if (count < 3) {
switch (count) {
@@ -413,7 +419,7 @@ void qt_memfill16_sse2(quint16 *dest, quint16 value, int count)
}
const quint32 value32 = (value << 16) | value;
- qt_memfill32_sse2(reinterpret_cast<quint32*>(dest), value32, count / 2);
+ qt_memfill32(reinterpret_cast<quint32*>(dest), value32, count / 2);
if (count & 0x1)
dest[count - 1] = value;
diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h
index d64b9cec39..699c586cb0 100644
--- a/src/gui/painting/qdrawhelper_x86_p.h
+++ b/src/gui/painting/qdrawhelper_x86_p.h
@@ -57,9 +57,9 @@
QT_BEGIN_NAMESPACE
-#ifdef QT_COMPILER_SUPPORTS_SSE2
-void qt_memfill32_sse2(quint32 *dest, quint32 value, int count);
-void qt_memfill16_sse2(quint16 *dest, quint16 value, int count);
+#ifdef __SSE2__
+void qt_memfill32(quint32 *dest, quint32 value, int count);
+void qt_memfill16(quint16 *dest, quint16 value, int count);
void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y,
quint32 color,
const uchar *src, int width, int height, int stride);
@@ -77,26 +77,7 @@ void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
extern CompositionFunction qt_functionForMode_SSE2[];
extern CompositionFunctionSolid qt_functionForModeSolid_SSE2[];
-#endif // QT_COMPILER_SUPPORTS_SSE2
-
-#ifdef QT_COMPILER_SUPPORTS_AVX
-void qt_memfill32_avx(quint32 *dest, quint32 value, int count);
-void qt_memfill16_avx(quint16 *dest, quint16 value, int count);
-void qt_bitmapblit32_avx(QRasterBuffer *rasterBuffer, int x, int y,
- quint32 color,
- const uchar *src, int width, int height, int stride);
-void qt_bitmapblit16_avx(QRasterBuffer *rasterBuffer, int x, int y,
- quint32 color,
- const uchar *src, int width, int height, int stride);
-void qt_blend_argb32_on_argb32_avx(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha);
-void qt_blend_rgb32_on_rgb32_avx(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha);
-#endif // QT_COMPILER_SUPPORTS_AVX
+#endif // __SSE2__
#ifdef QT_COMPILER_SUPPORTS_IWMMXT
void qt_blend_color_argb_iwmmxt(int count, const QSpan *spans, void *userData);
diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h
index 0e0c06f56c..cdf68b932d 100644
--- a/src/gui/painting/qdrawingprimitive_sse2_p.h
+++ b/src/gui/painting/qdrawingprimitive_sse2_p.h
@@ -44,7 +44,7 @@
#include <private/qsimd_p.h>
-#ifdef QT_COMPILER_SUPPORTS_SSE2
+#ifdef __SSE2__
//
// W A R N I N G
@@ -242,6 +242,6 @@ QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
-#endif // QT_COMPILER_SUPPORTS_SSE2
+#endif // __SSE2__
#endif // QDRAWINGPRIMITIVE_SSE2_P_H
diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp
index bb87b4fd6e..0fb907b6c5 100644
--- a/src/gui/painting/qemulationpaintengine.cpp
+++ b/src/gui/painting/qemulationpaintengine.cpp
@@ -169,7 +169,7 @@ void QEmulationPaintEngine::drawTextItem(const QPointF &p, const QTextItem &text
{
if (state()->bgMode == Qt::OpaqueMode) {
const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
- QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
+ QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent).toReal());
fillBGRect(rect);
}
diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp
index f855e9e32d..421d706230 100644
--- a/src/gui/painting/qpaintbuffer.cpp
+++ b/src/gui/painting/qpaintbuffer.cpp
@@ -70,13 +70,11 @@ QTextItemIntCopy::QTextItemIntCopy(const QTextItem &item)
m_item.chars = chars;
m_item.logClusters = logClusters;
- const int size = QGlyphLayout::spaceNeededForGlyphLayout(m_item.glyphs.numGlyphs);
- char *glyphLayoutData = new char[size];
+ char *glyphLayoutData = new char[m_item.glyphs.numGlyphs * QGlyphLayout::SpaceNeeded];
QGlyphLayout glyphs(glyphLayoutData, m_item.glyphs.numGlyphs);
memcpy(glyphs.offsets, m_item.glyphs.offsets, m_item.glyphs.numGlyphs * sizeof(QFixedPoint));
memcpy(glyphs.glyphs, m_item.glyphs.glyphs, m_item.glyphs.numGlyphs * sizeof(glyph_t));
- memcpy(glyphs.advances_x, m_item.glyphs.advances_x, m_item.glyphs.numGlyphs * sizeof(QFixed));
- memcpy(glyphs.advances_y, m_item.glyphs.advances_y, m_item.glyphs.numGlyphs * sizeof(QFixed));
+ memcpy(glyphs.advances, m_item.glyphs.advances, m_item.glyphs.numGlyphs * sizeof(QFixed));
memcpy(glyphs.justifications, m_item.glyphs.justifications, m_item.glyphs.numGlyphs * sizeof(QGlyphJustification));
memcpy(glyphs.attributes, m_item.glyphs.attributes, m_item.glyphs.numGlyphs * sizeof(QGlyphAttributes));
m_item.glyphs = glyphs;
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index f1eaea0f6b..acab08e794 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -387,6 +387,7 @@ void QPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDraw
\value OpenGL2
\value PaintBuffer
\value Blitter
+ \value Direct2D Windows only, Direct2D based engine
*/
/*!
diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h
index 18b6d84146..7b928ba5f6 100644
--- a/src/gui/painting/qpaintengine.h
+++ b/src/gui/painting/qpaintengine.h
@@ -207,6 +207,7 @@ public:
OpenGL2,
PaintBuffer,
Blitter,
+ Direct2D,
User = 50, // first user type id
MaxUser = 100 // last user type id
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index bdd0d9cd4c..9a2e49618c 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1823,7 +1823,7 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color)
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
- d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity));
+ d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity));
if ((d->solid_color_filler.solid.color & 0xff000000) == 0
&& s->composition_mode == QPainter::CompositionMode_SourceOver) {
return;
@@ -2272,7 +2272,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
| ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00);
break;
default:
- d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color, s->intOpacity));
+ d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color, s->intOpacity));
break;
}
@@ -3662,7 +3662,7 @@ QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color)
QImage sourceImage = image.convertToFormat(QImage::Format_MonoLSB);
QImage dest = QImage(sourceImage.size(), QImage::Format_ARGB32_Premultiplied);
- QRgb fg = PREMUL(color.rgba());
+ QRgb fg = qPremultiply(color.rgba());
QRgb bg = 0;
int height = sourceImage.height();
@@ -3702,8 +3702,8 @@ QImage::Format QRasterBuffer::prepare(QImage *image)
drawHelper = qDrawHelper + format;
if (image->depth() == 1 && image->colorTable().size() == 2) {
monoDestinationWithClut = true;
- destColor0 = PREMUL(image->colorTable()[0]);
- destColor1 = PREMUL(image->colorTable()[1]);
+ destColor0 = qPremultiply(image->colorTable()[0]);
+ destColor1 = qPremultiply(image->colorTable()[1]);
}
return format;
@@ -4260,8 +4260,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
}
if (colorInterpolation) {
- first_color = PREMUL(first_color);
- second_color = PREMUL(second_color);
+ first_color = qPremultiply(first_color);
+ second_color = qPremultiply(second_color);
}
int first_index = qRound(first_stop * (GRADIENT_STOPTABLE_SIZE-1));
@@ -4282,7 +4282,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
if (colorInterpolation)
colorTable[i] = first_color;
else
- colorTable[i] = PREMUL(first_color);
+ colorTable[i] = qPremultiply(first_color);
}
if (i < second_index) {
@@ -4311,7 +4311,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
if (colorInterpolation)
colorTable[i] = color;
else
- colorTable[i] = PREMUL(color);
+ colorTable[i] = qPremultiply(color);
}
}
@@ -4319,7 +4319,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
if (colorInterpolation)
colorTable[i] = second_color;
else
- colorTable[i] = PREMUL(second_color);
+ colorTable[i] = qPremultiply(second_color);
}
return;
@@ -4327,7 +4327,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
uint current_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity);
if (stopCount == 1) {
- current_color = PREMUL(current_color);
+ current_color = qPremultiply(current_color);
for (int i = 0; i < size; ++i)
colorTable[i] = current_color;
return;
@@ -4344,7 +4344,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
qreal dpos = 1.5 * incr; // current position in gradient stop list (0 to 1)
// Up to first point
- colorTable[pos++] = PREMUL(current_color);
+ colorTable[pos++] = qPremultiply(current_color);
while (dpos <= begin_pos) {
colorTable[pos] = colorTable[pos - 1];
++pos;
@@ -4366,8 +4366,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity);
if (colorInterpolation) {
- current_color = PREMUL(current_color);
- next_color = PREMUL(next_color);
+ current_color = qPremultiply(current_color);
+ next_color = qPremultiply(next_color);
}
qreal diff = stops[current_stop+1].first - stops[current_stop].first;
@@ -4384,7 +4384,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
if (colorInterpolation)
colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);
else
- colorTable[pos] = PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
+ colorTable[pos] = qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
++pos;
dpos += incr;
@@ -4408,8 +4408,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
if (colorInterpolation) {
if (skip != 1)
- current_color = PREMUL(current_color);
- next_color = PREMUL(next_color);
+ current_color = qPremultiply(current_color);
+ next_color = qPremultiply(next_color);
}
qreal diff = stops[current_stop+1].first - stops[current_stop].first;
@@ -4421,7 +4421,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
}
// After last point
- current_color = PREMUL(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity));
+ current_color = qPremultiply(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity));
while (pos < size - 1) {
colorTable[pos] = current_color;
++pos;
@@ -4455,7 +4455,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
type = Solid;
QColor c = qbrush_color(brush);
QRgb rgba = c.rgba();
- solid.color = PREMUL(ARGB_COMBINE_ALPHA(rgba, alpha));
+ solid.color = qPremultiply(ARGB_COMBINE_ALPHA(rgba, alpha));
if ((solid.color & 0xff000000) == 0
&& compositionMode == QPainter::CompositionMode_SourceOver) {
type = None;
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 41a2e39fc9..1fc044aa44 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -5617,8 +5617,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positio
textItem.glyphs.numGlyphs = glyphCount;
textItem.glyphs.glyphs = const_cast<glyph_t *>(glyphArray);
textItem.glyphs.offsets = positions;
- textItem.glyphs.advances_x = advances.data();
- textItem.glyphs.advances_y = advances.data();
+ textItem.glyphs.advances = advances.data();
textItem.glyphs.justifications = glyphJustifications.data();
textItem.glyphs.attributes = glyphAttributes.data();
@@ -5846,11 +5845,8 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif
int numGlyphs = len;
QVarLengthGlyphLayoutArray glyphs(len);
QFontEngine *fontEngine = d->state->font.d->engineForScript(QChar::Script_Common);
- if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
- glyphs.resize(numGlyphs);
- if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
- Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
- }
+ if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
+ Q_UNREACHABLE();
QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
drawTextItem(p, gf);
@@ -6354,7 +6350,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
if (!extended && state->bgMode == Qt::OpaqueMode) {
- QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
+ QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent).toReal());
q->fillRect(rect, state->bgBrush);
}
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 156e411154..aa2b9bea54 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -1738,8 +1738,8 @@ QList<QPolygonF> QPainterPath::toFillPolygons(const QMatrix &matrix) const
//same as qt_polygon_isect_line in qpolygon.cpp
static void qt_painterpath_isect_line(const QPointF &p1,
- const QPointF &p2,
- const QPointF &pos,
+ const QPointF &p2,
+ const QPointF &pos,
int *winding)
{
qreal x1 = p1.x();
@@ -2551,6 +2551,26 @@ QPainterPathStroker::QPainterPathStroker()
}
/*!
+ Creates a new stroker based on \a pen.
+
+ \since 5.3
+ */
+QPainterPathStroker::QPainterPathStroker(const QPen &pen)
+ : d_ptr(new QPainterPathStrokerPrivate)
+{
+ setWidth(pen.widthF());
+ setCapStyle(pen.capStyle());
+ setJoinStyle(pen.joinStyle());
+ setMiterLimit(pen.miterLimit());
+ setDashOffset(pen.dashOffset());
+
+ if (pen.style() == Qt::CustomDashLine)
+ setDashPattern(pen.dashPattern());
+ else
+ setDashPattern(pen.style());
+}
+
+/*!
Destroys the stroker.
*/
QPainterPathStroker::~QPainterPathStroker()
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index e22c1729f3..c922867eb9 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -57,6 +57,7 @@ class QPainterPathPrivate;
struct QPainterPathPrivateDeleter;
class QPainterPathData;
class QPainterPathStrokerPrivate;
+class QPen;
class QPolygonF;
class QRegion;
class QVectorPath;
@@ -243,6 +244,7 @@ class Q_GUI_EXPORT QPainterPathStroker
Q_DECLARE_PRIVATE(QPainterPathStroker)
public:
QPainterPathStroker();
+ QPainterPathStroker(const QPen &pen);
~QPainterPathStroker();
void setWidth(qreal width);
diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp
index 6a3eacd67a..c0b3769c2d 100644
--- a/src/gui/painting/qpen.cpp
+++ b/src/gui/painting/qpen.cpp
@@ -455,15 +455,19 @@ QVector<qreal> QPen::dashPattern() const
switch (d->style) {
case Qt::DashLine:
+ dd->dashPattern.reserve(2);
dd->dashPattern << dash << space;
break;
case Qt::DotLine:
+ dd->dashPattern.reserve(2);
dd->dashPattern << dot << space;
break;
case Qt::DashDotLine:
+ dd->dashPattern.reserve(4);
dd->dashPattern << dash << space << dot << space;
break;
case Qt::DashDotDotLine:
+ dd->dashPattern.reserve(6);
dd->dashPattern << dash << space << dot << space << dot << space;
break;
default:
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index feec0c7f3d..15459dd748 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -44,6 +44,16 @@
#include <qpixmap.h>
#include <private/qwindow_p.h>
+#include <qopengl.h>
+#include <qopenglcontext.h>
+#include <QtGui/QMatrix4x4>
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFunctions>
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qopengltextureblitter_p.h>
+#endif
+
QT_BEGIN_NAMESPACE
class QPlatformBackingStorePrivate
@@ -51,13 +61,109 @@ class QPlatformBackingStorePrivate
public:
QPlatformBackingStorePrivate(QWindow *w)
: window(w)
+#ifndef QT_NO_OPENGL
+ , blitter(0)
+#endif
{
}
+ ~QPlatformBackingStorePrivate()
+ {
+#ifndef QT_NO_OPENGL
+ if (blitter)
+ blitter->destroy();
+ delete blitter;
+#endif
+ }
QWindow *window;
QSize size;
+#ifndef QT_NO_OPENGL
+ mutable GLuint textureId;
+ mutable QSize textureSize;
+ QOpenGLTextureBlitter *blitter;
+#endif
};
+#ifndef QT_NO_OPENGL
+
+struct QBackingstoreTextureInfo
+{
+ GLuint textureId;
+ QRect rect;
+};
+
+Q_DECLARE_TYPEINFO(QBackingstoreTextureInfo, Q_MOVABLE_TYPE);
+
+class QPlatformTextureListPrivate : public QObjectPrivate
+{
+public:
+ QPlatformTextureListPrivate()
+ : locked(false)
+ {
+ }
+
+ QList<QBackingstoreTextureInfo> textures;
+ bool locked;
+};
+
+QPlatformTextureList::QPlatformTextureList(QObject *parent)
+: QObject(*new QPlatformTextureListPrivate, parent)
+{
+}
+
+QPlatformTextureList::~QPlatformTextureList()
+{
+}
+
+int QPlatformTextureList::count() const
+{
+ Q_D(const QPlatformTextureList);
+ return d->textures.count();
+}
+
+GLuint QPlatformTextureList::textureId(int index) const
+{
+ Q_D(const QPlatformTextureList);
+ return d->textures.at(index).textureId;
+}
+
+QRect QPlatformTextureList::geometry(int index) const
+{
+ Q_D(const QPlatformTextureList);
+ return d->textures.at(index).rect;
+}
+
+void QPlatformTextureList::lock(bool on)
+{
+ Q_D(QPlatformTextureList);
+ if (on != d->locked) {
+ d->locked = on;
+ emit locked(on);
+ }
+}
+
+bool QPlatformTextureList::isLocked() const
+{
+ Q_D(const QPlatformTextureList);
+ return d->locked;
+}
+
+void QPlatformTextureList::appendTexture(GLuint textureId, const QRect &geometry)
+{
+ Q_D(QPlatformTextureList);
+ QBackingstoreTextureInfo bi;
+ bi.textureId = textureId;
+ bi.rect = geometry;
+ d->textures.append(bi);
+}
+
+void QPlatformTextureList::clear()
+{
+ Q_D(QPlatformTextureList);
+ d->textures.clear();
+}
+#endif // QT_NO_OPENGL
+
/*!
\class QPlatformBackingStore
\since 5.0
@@ -79,6 +185,147 @@ public:
Note that the \a offset parameter is currently unused.
*/
+#ifndef QT_NO_OPENGL
+/*!
+ Flushes the given \a region from the specified \a window onto the
+ screen, and composes it with the specified \a textures.
+
+ The default implementation retrieves the contents using toTexture()
+ and composes using OpenGL. May be reimplemented in subclasses if there
+ is a more efficient native way to do it.
+
+ Note that the \a offset parameter is currently unused.
+ */
+
+void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &region,
+ const QPoint &offset,
+ QPlatformTextureList *textures, QOpenGLContext *context)
+{
+ Q_UNUSED(offset);
+
+ context->makeCurrent(window);
+ glViewport(0, 0, window->width(), window->height());
+
+ if (!d_ptr->blitter) {
+ d_ptr->blitter = new QOpenGLTextureBlitter;
+ d_ptr->blitter->create();
+ }
+
+ d_ptr->blitter->bind();
+
+ QRect windowRect(QPoint(), window->size());
+ for (int i = 0; i < textures->count(); ++i) {
+ GLuint textureId = textures->textureId(i);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+
+ QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), windowRect);
+ d_ptr->blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft);
+ }
+
+ GLuint textureId = toTexture(region);
+ if (!textureId)
+ return;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(windowRect, windowRect);
+ d_ptr->blitter->setSwizzleRB(true);
+ d_ptr->blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
+ d_ptr->blitter->setSwizzleRB(false);
+
+ glDisable(GL_BLEND);
+ d_ptr->blitter->release();
+ context->swapBuffers(window);
+}
+
+/*!
+ Implemented in subclasses to return the content of the backingstore as a QImage.
+
+ If QPlatformIntegration::RasterGLSurface is supported, either this function or
+ toTexture() must be implemented.
+
+ \sa toTexture()
+ */
+QImage QPlatformBackingStore::toImage() const
+{
+ return QImage();
+}
+
+/*!
+ May be reimplemented in subclasses to return the content of the
+ backingstore as an OpenGL texture. \a dirtyRegion is the part of the
+ backingstore which may have changed since the last call to this function. The
+ caller of this function must ensure that there is a current context.
+
+ The ownership of the texture is not transferred. The caller must not store
+ the return value between calls, but instead call this function before each use.
+
+ The default implementation returns a cached texture if \a dirtyRegion is
+ empty and the window has not been resized, otherwise it retrieves the
+ content using toImage() and performs a texture upload.
+ */
+
+GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion) const
+{
+ QImage image = toImage();
+ QSize imageSize = image.size();
+ if (imageSize.isEmpty())
+ return 0;
+
+ bool resized = d_ptr->textureSize != imageSize;
+ if (dirtyRegion.isEmpty() && !resized)
+ return d_ptr->textureId;
+
+ if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_RGBA8888)
+ image = image.convertToFormat(QImage::Format_RGBA8888);
+
+ if (resized) {
+ if (d_ptr->textureId)
+ glDeleteTextures(1, &d_ptr->textureId);
+ glGenTextures(1, &d_ptr->textureId);
+ glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
+#ifndef QT_OPENGL_ES_2
+ if (!QOpenGLFunctions::isES()) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ }
+#endif
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageSize.width(), imageSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ const_cast<uchar*>(image.constBits()));
+ d_ptr->textureSize = imageSize;
+ } else {
+ glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
+ QRect imageRect = image.rect();
+ QRect rect = dirtyRegion.boundingRect() & imageRect;
+ // if the rect is wide enough it's cheaper to just
+ // extend it instead of doing an image copy
+ if (rect.width() >= imageRect.width() / 2) {
+ rect.setX(0);
+ rect.setWidth(imageRect.width());
+ }
+
+ // if the sub-rect is full-width we can pass the image data directly to
+ // OpenGL instead of copying, since there's no gap between scanlines
+
+ if (rect.width() == imageRect.width()) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ image.constScanLine(rect.y()));
+ } else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ image.copy(rect).constBits());
+ }
+ }
+
+ return d_ptr->textureId;
+}
+#endif // QT_NO_OPENGL
+
/*!
\fn QPaintDevice* QPlatformBackingStore::paintDevice()
diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h
index 1b19b2c379..76fd3d40b4 100644
--- a/src/gui/painting/qplatformbackingstore.h
+++ b/src/gui/painting/qplatformbackingstore.h
@@ -52,9 +52,11 @@
//
#include <QtCore/qrect.h>
+#include <QtCore/qobject.h>
#include <QtGui/qwindow.h>
#include <QtGui/qregion.h>
+#include <QtGui/qopengl.h>
QT_BEGIN_NAMESPACE
@@ -65,6 +67,33 @@ class QPoint;
class QImage;
class QPlatformBackingStorePrivate;
class QPlatformWindow;
+class QPlatformTextureList;
+class QPlatformTextureListPrivate;
+class QOpenGLContext;
+
+#ifndef QT_NO_OPENGL
+class Q_GUI_EXPORT QPlatformTextureList : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QPlatformTextureList)
+public:
+ explicit QPlatformTextureList(QObject *parent = 0);
+ ~QPlatformTextureList();
+
+ int count() const;
+ bool isEmpty() const { return count() == 0; }
+ GLuint textureId(int index) const;
+ QRect geometry(int index) const;
+ void lock(bool on);
+ bool isLocked() const;
+
+ void appendTexture(GLuint textureId, const QRect &geometry);
+ void clear();
+
+ Q_SIGNALS:
+ void locked(bool);
+};
+#endif
class Q_GUI_EXPORT QPlatformBackingStore
{
@@ -79,6 +108,11 @@ public:
// 'window' can be a child window, in which case 'region' is in child window coordinates and
// offset is the (child) window's offset in relation to the window surface.
virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset) = 0;
+#ifndef QT_NO_OPENGL
+ virtual void composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset, QPlatformTextureList *textures, QOpenGLContext *context);
+ virtual QImage toImage() const;
+ virtual GLuint toTexture(const QRegion &dirtyRegion) const;
+#endif
virtual void resize(const QSize &size, const QRegion &staticContents) = 0;
diff --git a/src/gui/painting/qrgb.h b/src/gui/painting/qrgb.h
index 3c2bc5b97a..d8e19302d1 100644
--- a/src/gui/painting/qrgb.h
+++ b/src/gui/painting/qrgb.h
@@ -43,6 +43,7 @@
#define QRGB_H
#include <QtCore/qglobal.h>
+#include <QtCore/qprocessordetection.h>
QT_BEGIN_NAMESPACE
@@ -79,6 +80,48 @@ inline Q_DECL_CONSTEXPR int qGray(QRgb rgb) // convert RGB to gra
inline Q_DECL_CONSTEXPR bool qIsGray(QRgb rgb)
{ return qRed(rgb) == qGreen(rgb) && qRed(rgb) == qBlue(rgb); }
+
+#if Q_PROCESSOR_WORDSIZE == 8 // 64-bit version
+inline QRgb qPremultiply(QRgb x)
+{
+ const uint a = qAlpha(x);
+ quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
+ t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8;
+ t &= 0x000000ff00ff00ff;
+ return (uint(t)) | (uint(t >> 24)) | (a << 24);
+}
+#else // 32-bit version
+inline QRgb qPremultiply(QRgb x)
+{
+ const uint a = qAlpha(x);
+ uint t = (x & 0xff00ff) * a;
+ t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
+ t &= 0xff00ff;
+
+ x = ((x >> 8) & 0xff) * a;
+ x = (x + ((x >> 8) & 0xff) + 0x80);
+ x &= 0xff00;
+ x |= t | (a << 24);
+ return x;
+}
+#endif
+
+Q_GUI_EXPORT extern const uint qt_inv_premul_factor[];
+
+inline QRgb qUnpremultiply(QRgb p)
+{
+ const uint alpha = qAlpha(p);
+ // Alpha 255 and 0 are the two most common values, which makes them beneficial to short-cut.
+ if (alpha == 255)
+ return p;
+ if (alpha == 0)
+ return 0;
+ // (p*(0x00ff00ff/alpha)) >> 16 == (p*255)/alpha for all p and alpha <= 256.
+ const uint invAlpha = qt_inv_premul_factor[alpha];
+ // We add 0x8000 to get even rounding. The rounding also ensures that qPremultiply(qUnpremultiply(p)) == p for all p.
+ return qRgba((qRed(p)*invAlpha + 0x8000)>>16, (qGreen(p)*invAlpha + 0x8000)>>16, (qBlue(p)*invAlpha + 0x8000)>>16, alpha);
+}
+
QT_END_NAMESPACE
#endif // QRGB_H