Revert "qt4: Updated to v4.7.3"
[openembedded.git] / recipes / qt4 / qt-4.6.0 / 1165-NEON-configure-detection-and-initial-blend-function-.patch
1
2 Adds new NEON configure test and -no-neon configure option. NEON
3 implementations can also be turned off by setting the QT_NO_NEON
4 environment variable.
5
6 Performance improvements (in frames per second):
7 - Blending ARGB32 on RGB32/ARGB32, mostly opaque: 71 %
8 - Blending ARGB32 on RGB32/ARGB32, no opaque pixels: 108 %
9 - Blending ARGB32 on RGB32/ARGB32, with 0.5 opacity: 158 %
10 - Blending RGB32 on RGB32/ARGB32, with 0.5 opacity: 189 %
11
12 Task-number: QTBUG-6684
13 Reviewed-by: Gunnar Sletta
14 Reviewed-by: Paul Olav Tvete
15 ---
16  config.tests/unix/neon/neon.cpp       |   51 +++++++
17  config.tests/unix/neon/neon.pro       |    2 +
18  configure                             |   22 +++-
19  src/gui/painting/painting.pri         |    7 +
20  src/gui/painting/qblendfunctions.cpp  |    2 +-
21  src/gui/painting/qdrawhelper.cpp      |   16 ++-
22  src/gui/painting/qdrawhelper_neon.cpp |  260 +++++++++++++++++++++++++++++++++
23  src/gui/painting/qdrawhelper_neon_p.h |   76 ++++++++++
24  8 files changed, 432 insertions(+), 4 deletions(-)
25  create mode 100644 config.tests/unix/neon/neon.cpp
26  create mode 100644 config.tests/unix/neon/neon.pro
27  create mode 100644 src/gui/painting/qdrawhelper_neon.cpp
28  create mode 100644 src/gui/painting/qdrawhelper_neon_p.h
29
30 diff --git a/config.tests/unix/neon/neon.cpp b/config.tests/unix/neon/neon.cpp
31 new file mode 100644
32 index 0000000..c31a9fd
33 --- /dev/null
34 +++ b/config.tests/unix/neon/neon.cpp
35 @@ -0,0 +1,51 @@
36 +/****************************************************************************
37 +**
38 +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
39 +** All rights reserved.
40 +** Contact: Nokia Corporation (qt-info@nokia.com)
41 +**
42 +** This file is part of the config.tests of the Qt Toolkit.
43 +**
44 +** $QT_BEGIN_LICENSE:LGPL$
45 +** No Commercial Usage
46 +** This file contains pre-release code and may not be distributed.
47 +** You may use this file in accordance with the terms and conditions
48 +** contained in the Technology Preview License Agreement accompanying
49 +** this package.
50 +**
51 +** GNU Lesser General Public License Usage
52 +** Alternatively, this file may be used under the terms of the GNU Lesser
53 +** General Public License version 2.1 as published by the Free Software
54 +** Foundation and appearing in the file LICENSE.LGPL included in the
55 +** packaging of this file.  Please review the following information to
56 +** ensure the GNU Lesser General Public License version 2.1 requirements
57 +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
58 +**
59 +** In addition, as a special exception, Nokia gives you certain additional
60 +** rights.  These rights are described in the Nokia Qt LGPL Exception
61 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
62 +**
63 +** If you have questions regarding the use of this file, please contact
64 +** Nokia at qt-info@nokia.com.
65 +**
66 +**
67 +**
68 +**
69 +**
70 +**
71 +**
72 +**
73 +** $QT_END_LICENSE$
74 +**
75 +****************************************************************************/
76 +
77 +#include <arm_neon.h>
78 +
79 +int main(int, char**)
80 +{
81 +    int32x4_t null = vdupq_n_s32(0x0);
82 +
83 +    int result;
84 +    vst1q_lane_s32(&result, null, 0);
85 +    return result;
86 +}
87 diff --git a/config.tests/unix/neon/neon.pro b/config.tests/unix/neon/neon.pro
88 new file mode 100644
89 index 0000000..de20c4e
90 --- /dev/null
91 +++ b/config.tests/unix/neon/neon.pro
92 @@ -0,0 +1,2 @@
93 +SOURCES = neon.cpp
94 +CONFIG -= x11 qt
95 diff --git a/configure b/configure
96 index 2114863..22e6bd4 100755
97 --- a/configure
98 +++ b/configure
99 @@ -745,6 +745,7 @@ CFG_HOST_ENDIAN=auto
100  CFG_DOUBLEFORMAT=auto
101  CFG_ARMFPA=auto
102  CFG_IWMMXT=no
103 +CFG_NEON=auto
104  CFG_CLOCK_GETTIME=auto
105  CFG_CLOCK_MONOTONIC=auto
106  CFG_MREMAP=auto
107 @@ -1604,6 +1605,13 @@ while [ "$#" -gt 0 ]; do
108      iwmmxt)
109         CFG_IWMMXT="yes"
110         ;;
111 +    neon)
112 +        if [ "$VAL" = "no" ]; then
113 +            CFG_NEON="$VAL"
114 +        else
115 +            UNKNOWN_OPT=yes
116 +        fi
117 +        ;;
118      reduce-relocations)
119          if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
120              CFG_REDUCE_RELOCATIONS="$VAL"
121 @@ -3889,6 +3897,7 @@ Qt for Embedded Linux only:
122      -iwmmxt ............ Compile using the iWMMXt instruction set
123                           (available on some XScale CPUs).
124  
125 +    -no-neon ........... Do not compile with use of NEON instructions.
126  EOF
127  fi
128  
129 @@ -4509,6 +4518,15 @@ if [ "$CFG_IWMMXT" = "yes" ]; then
130      fi
131  fi
132  
133 +# detect neon support
134 +if ([ "${CFG_ARCH}" = "arm" ] || [ "${CFG_ARCH}" = "armv6" ]) && [ "${CFG_NEON}" = "auto" ]; then
135 +    if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/neon "neon" $L_FLAGS $I_FLAGS $l_FLAGS "-mfpu=neon"; then
136 +       CFG_NEON=yes
137 +    else
138 +       CFG_NEON=no
139 +    fi
140 +fi
141 +
142  # detect zlib
143  if [ "$CFG_ZLIB" = "no" ]; then
144      # Note: Qt no longer support builds without zlib
145 @@ -6124,6 +6142,7 @@ fi
146  [ "$CFG_SSE" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse"
147  [ "$CFG_SSE2" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse2"
148  [ "$CFG_IWMMXT" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG iwmmxt"
149 +[ "$CFG_NEON" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG neon"
150  [ "$PLATFORM_MAC" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG $CFG_MAC_ARCHS"
151  if [ "$CFG_IPV6" = "yes" ]; then
152      QT_CONFIG="$QT_CONFIG ipv6"
153 @@ -7416,8 +7435,9 @@ echo "Declarative module .. $CFG_DECLARATIVE"
154  echo "STL support ......... $CFG_STL"
155  echo "PCH support ......... $CFG_PRECOMPILE"
156  echo "MMX/3DNOW/SSE/SSE2..  ${CFG_MMX}/${CFG_3DNOW}/${CFG_SSE}/${CFG_SSE2}"
157 -if [ "${CFG_ARCH}" = "arm" ]; then
158 +if [ "${CFG_ARCH}" = "arm" ] || [ "${CFG_ARCH}" = "armv6" ]; then
159      echo "iWMMXt support ...... ${CFG_IWMMXT}"
160 +    echo "NEON support ........ ${CFG_NEON}"
161  fi
162  [ "${PLATFORM_QWS}" != "yes" ] && echo "Graphics System ..... $CFG_GRAPHICS_SYSTEM"
163  echo "IPv6 support ........ $CFG_IPV6"
164 diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
165 index 628a109..0b1e79a 100644
166 --- a/src/gui/painting/painting.pri
167 +++ b/src/gui/painting/painting.pri
168 @@ -379,6 +379,13 @@ symbian {
169          QMAKE_CXXFLAGS.ARMCC *= -O3
170  }
171  
172 +neon {
173 +    DEFINES += QT_HAVE_NEON
174 +    HEADERS += painting/qdrawhelper_neon_p.h
175 +    SOURCES += painting/qdrawhelper_neon.cpp
176 +    
177 +}
178 +
179  contains(QT_CONFIG, zlib) {
180     INCLUDEPATH += ../3rdparty/zlib
181  } else:!contains(QT_CONFIG, no-zlib) {
182 diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
183 index 1d15dac..81d1515 100644
184 --- a/src/gui/painting/qblendfunctions.cpp
185 +++ b/src/gui/painting/qblendfunctions.cpp
186 @@ -605,7 +605,7 @@ static void qt_blend_argb32_on_argb32(uchar *destPixels, int dbpl,
187  }
188  
189  
190 -static void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
191 +void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
192                               const uchar *srcPixels, int sbpl,
193                               int w, int h,
194                               int const_alpha)
195 diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
196 index 23236ec..84cf5cc 100644
197 --- a/src/gui/painting/qdrawhelper.cpp
198 +++ b/src/gui/painting/qdrawhelper.cpp
199 @@ -44,6 +44,7 @@
200  #include <private/qpainter_p.h>
201  #include <private/qdrawhelper_x86_p.h>
202  #include <private/qdrawhelper_armv6_p.h>
203 +#include <private/qdrawhelper_neon_p.h>
204  #include <private/qmath_p.h>
205  #include <qmath.h>
206  
207 @@ -7725,7 +7726,8 @@ enum CPUFeatures {
208      SSE         = 0x10,
209      SSE2        = 0x20,
210      CMOV        = 0x40,
211 -    IWMMXT      = 0x80
212 +    IWMMXT      = 0x80,
213 +    NEON        = 0x100
214  };
215  
216  static uint detectCPUFeatures()
217 @@ -7751,6 +7753,9 @@ static uint detectCPUFeatures()
218      // runtime detection only available when running as a previlegied process
219      static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt();
220      return doIWMMXT ? IWMMXT : 0;
221 +#elif defined(QT_HAVE_NEON)
222 +    static const bool doNEON = !qgetenv("QT_NO_NEON").toInt();
223 +    return doNEON ? NEON : 0;
224  #else
225      uint features = 0;
226  #if defined(__x86_64__) || defined(Q_OS_WIN64)
227 @@ -8122,7 +8127,14 @@ void qInitDrawhelperAsm()
228          qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6;
229          qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
230          qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
231 -#endif // Q_CC_RVCT && QT_HAVE_ARMV6
232 +#elif defined(QT_HAVE_NEON)
233 +        if (features & NEON) {
234 +            qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
235 +            qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
236 +            qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
237 +            qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
238 +        }
239 +#endif
240  
241      if (functionForModeSolidAsm) {
242          const int destinationMode = QPainter::CompositionMode_Destination;
243 diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
244 new file mode 100644
245 index 0000000..7fe11bf
246 --- /dev/null
247 +++ b/src/gui/painting/qdrawhelper_neon.cpp
248 @@ -0,0 +1,260 @@
249 +/****************************************************************************
250 +**
251 +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
252 +** All rights reserved.
253 +** Contact: Nokia Corporation (qt-info@nokia.com)
254 +**
255 +** This file is part of the QtGui module of the Qt Toolkit.
256 +**
257 +** $QT_BEGIN_LICENSE:LGPL$
258 +** No Commercial Usage
259 +** This file contains pre-release code and may not be distributed.
260 +** You may use this file in accordance with the terms and conditions
261 +** contained in the Technology Preview License Agreement accompanying
262 +** this package.
263 +**
264 +** GNU Lesser General Public License Usage
265 +** Alternatively, this file may be used under the terms of the GNU Lesser
266 +** General Public License version 2.1 as published by the Free Software
267 +** Foundation and appearing in the file LICENSE.LGPL included in the
268 +** packaging of this file.  Please review the following information to
269 +** ensure the GNU Lesser General Public License version 2.1 requirements
270 +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
271 +**
272 +** In addition, as a special exception, Nokia gives you certain additional
273 +** rights.  These rights are described in the Nokia Qt LGPL Exception
274 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
275 +**
276 +** If you have questions regarding the use of this file, please contact
277 +** Nokia at qt-info@nokia.com.
278 +**
279 +**
280 +**
281 +**
282 +**
283 +**
284 +**
285 +**
286 +** $QT_END_LICENSE$
287 +**
288 +****************************************************************************/
289 +
290 +#include <private/qdrawhelper_p.h>
291 +
292 +#ifdef QT_HAVE_NEON
293 +
294 +#include <private/qdrawhelper_neon_p.h>
295 +#include <arm_neon.h>
296 +
297 +QT_BEGIN_NAMESPACE
298 +
299 +static inline int16x8_t qvdiv_255_s16(int16x8_t x, int16x8_t half)
300 +{
301 +    // result = (x + (x >> 8) + 0x80) >> 8
302 +
303 +    const int16x8_t temp = vshrq_n_s16(x, 8); // x >> 8
304 +    const int16x8_t sum_part = vaddq_s16(x, half); // x + 0x80
305 +    const int16x8_t sum = vaddq_s16(temp, sum_part);
306 +
307 +    return vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(sum), 8));
308 +}
309 +
310 +static inline int16x8_t qvbyte_mul_s16(int16x8_t x, int16x8_t alpha, int16x8_t half)
311 +{
312 +    // t = qRound(x * alpha / 255.0)
313 +
314 +    const int16x8_t t = vmulq_s16(x, alpha); // t
315 +    return qvdiv_255_s16(t, half);
316 +}
317 +
318 +static inline int16x8_t qvinterpolate_pixel_255(int16x8_t x, int16x8_t a, int16x8_t y, int16x8_t b, int16x8_t half)
319 +{
320 +    // t = x * a + y * b
321 +
322 +    const int16x8_t ta = vmulq_s16(x, a);
323 +    const int16x8_t tb = vmulq_s16(y, b);
324 +
325 +    return qvdiv_255_s16(vaddq_s16(ta, tb), half);
326 +}
327 +
328 +static inline int16x8_t qvsource_over_s16(int16x8_t src16, int16x8_t dst16, int16x8_t half, int16x8_t full)
329 +{
330 +    const int16x4_t alpha16_high = vdup_lane_s16(vget_high_s16(src16), 3);
331 +    const int16x4_t alpha16_low = vdup_lane_s16(vget_low_s16(src16), 3);
332 +
333 +    const int16x8_t alpha16 = vsubq_s16(full, vcombine_s16(alpha16_low, alpha16_high));
334 +
335 +    return vaddq_s16(src16, qvbyte_mul_s16(dst16, alpha16, half));
336 +}
337 +
338 +void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl,
339 +                                    const uchar *srcPixels, int sbpl,
340 +                                    int w, int h,
341 +                                    int const_alpha)
342 +{
343 +    const uint *src = (const uint *) srcPixels;
344 +    uint *dst = (uint *) destPixels;
345 +    int16x8_t half = vdupq_n_s16(0x80);
346 +    int16x8_t full = vdupq_n_s16(0xff);
347 +    if (const_alpha == 256) {
348 +        for (int y = 0; y < h; ++y) {
349 +            int x = 0;
350 +            for (; x < w-3; x += 4) {
351 +                int32x4_t src32 = vld1q_s32((int32_t *)&src[x]);
352 +                if ((src[x] & src[x+1] & src[x+2] & src[x+3]) >= 0xff000000) {
353 +                    // all opaque
354 +                    vst1q_s32((int32_t *)&dst[x], src32);
355 +                } else if (src[x] | src[x+1] | src[x+2] | src[x+3]) {
356 +                    int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]);
357 +
358 +                    const uint8x16_t src8 = vreinterpretq_u8_s32(src32);
359 +                    const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32);
360 +
361 +                    const uint8x8_t src8_low = vget_low_u8(src8);
362 +                    const uint8x8_t dst8_low = vget_low_u8(dst8);
363 +
364 +                    const uint8x8_t src8_high = vget_high_u8(src8);
365 +                    const uint8x8_t dst8_high = vget_high_u8(dst8);
366 +
367 +                    const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low));
368 +                    const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low));
369 +
370 +                    const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high));
371 +                    const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high));
372 +
373 +                    const int16x8_t result16_low = qvsource_over_s16(src16_low, dst16_low, half, full);
374 +                    const int16x8_t result16_high = qvsource_over_s16(src16_high, dst16_high, half, full);
375 +
376 +                    const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low));
377 +                    const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high));
378 +
379 +                    vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high));
380 +                }
381 +            }
382 +            for (; x<w; ++x) {
383 +                uint s = src[x];
384 +                if (s >= 0xff000000)
385 +                    dst[x] = s;
386 +                else if (s != 0)
387 +                    dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
388 +            }
389 +            dst = (quint32 *)(((uchar *) dst) + dbpl);
390 +            src = (const quint32 *)(((const uchar *) src) + sbpl);
391 +        }
392 +    } else if (const_alpha != 0) {
393 +        const_alpha = (const_alpha * 255) >> 8;
394 +        int16x8_t const_alpha16 = vdupq_n_s16(const_alpha);
395 +        for (int y = 0; y < h; ++y) {
396 +            int x = 0;
397 +            for (; x < w-3; x += 4) {
398 +                if (src[x] | src[x+1] | src[x+2] | src[x+3]) {
399 +                    int32x4_t src32 = vld1q_s32((int32_t *)&src[x]);
400 +                    int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]);
401 +
402 +                    const uint8x16_t src8 = vreinterpretq_u8_s32(src32);
403 +                    const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32);
404 +
405 +                    const uint8x8_t src8_low = vget_low_u8(src8);
406 +                    const uint8x8_t dst8_low = vget_low_u8(dst8);
407 +
408 +                    const uint8x8_t src8_high = vget_high_u8(src8);
409 +                    const uint8x8_t dst8_high = vget_high_u8(dst8);
410 +
411 +                    const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low));
412 +                    const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low));
413 +
414 +                    const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high));
415 +                    const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high));
416 +
417 +                    const int16x8_t srcalpha16_low = qvbyte_mul_s16(src16_low, const_alpha16, half);
418 +                    const int16x8_t srcalpha16_high = qvbyte_mul_s16(src16_high, const_alpha16, half);
419 +
420 +                    const int16x8_t result16_low = qvsource_over_s16(srcalpha16_low, dst16_low, half, full);
421 +                    const int16x8_t result16_high = qvsource_over_s16(srcalpha16_high, dst16_high, half, full);
422 +
423 +                    const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low));
424 +                    const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high));
425 +
426 +                    vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high));
427 +                }
428 +            }
429 +            for (; x<w; ++x) {
430 +                uint s = src[x];
431 +                if (s != 0) {
432 +                    s = BYTE_MUL(s, const_alpha);
433 +                    dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
434 +                }
435 +            }
436 +            dst = (quint32 *)(((uchar *) dst) + dbpl);
437 +            src = (const quint32 *)(((const uchar *) src) + sbpl);
438 +        }
439 +    }
440 +}
441 +
442 +// qblendfunctions.cpp
443 +void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
444 +                             const uchar *srcPixels, int sbpl,
445 +                             int w, int h,
446 +                             int const_alpha);
447 +
448 +void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl,
449 +                                  const uchar *srcPixels, int sbpl,
450 +                                  int w, int h,
451 +                                  int const_alpha)
452 +{
453 +    if (const_alpha != 256) {
454 +        if (const_alpha != 0) {
455 +            const uint *src = (const uint *) srcPixels;
456 +            uint *dst = (uint *) destPixels;
457 +            int16x8_t half = vdupq_n_s16(0x80);
458 +            const_alpha = (const_alpha * 255) >> 8;
459 +            int one_minus_const_alpha = 255 - const_alpha;
460 +            int16x8_t const_alpha16 = vdupq_n_s16(const_alpha);
461 +            int16x8_t one_minus_const_alpha16 = vdupq_n_s16(255 - const_alpha);
462 +            for (int y = 0; y < h; ++y) {
463 +                int x = 0;
464 +                for (; x < w-3; x += 4) {
465 +                    int32x4_t src32 = vld1q_s32((int32_t *)&src[x]);
466 +                    int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]);
467 +
468 +                    const uint8x16_t src8 = vreinterpretq_u8_s32(src32);
469 +                    const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32);
470 +
471 +                    const uint8x8_t src8_low = vget_low_u8(src8);
472 +                    const uint8x8_t dst8_low = vget_low_u8(dst8);
473 +
474 +                    const uint8x8_t src8_high = vget_high_u8(src8);
475 +                    const uint8x8_t dst8_high = vget_high_u8(dst8);
476 +
477 +                    const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low));
478 +                    const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low));
479 +
480 +                    const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high));
481 +                    const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high));
482 +
483 +                    const int16x8_t result16_low = qvinterpolate_pixel_255(src16_low, const_alpha16, dst16_low, one_minus_const_alpha16, half);
484 +                    const int16x8_t result16_high = qvinterpolate_pixel_255(src16_high, const_alpha16, dst16_high, one_minus_const_alpha16, half);
485 +
486 +                    const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low));
487 +                    const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high));
488 +
489 +                    vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high));
490 +                }
491 +                for (; x<w; ++x) {
492 +                    uint s = src[x];
493 +                    s = BYTE_MUL(s, const_alpha);
494 +                    dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha);
495 +                }
496 +                dst = (quint32 *)(((uchar *) dst) + dbpl);
497 +                src = (const quint32 *)(((const uchar *) src) + sbpl);
498 +            }
499 +        }
500 +    } else {
501 +        qt_blend_rgb32_on_rgb32(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
502 +    }
503 +}
504 +
505 +QT_END_NAMESPACE
506 +
507 +#endif // QT_HAVE_NEON
508 +
509 diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h
510 new file mode 100644
511 index 0000000..cb9a0d6
512 --- /dev/null
513 +++ b/src/gui/painting/qdrawhelper_neon_p.h
514 @@ -0,0 +1,76 @@
515 +/****************************************************************************
516 +**
517 +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
518 +** All rights reserved.
519 +** Contact: Nokia Corporation (qt-info@nokia.com)
520 +**
521 +** This file is part of the QtGui module of the Qt Toolkit.
522 +**
523 +** $QT_BEGIN_LICENSE:LGPL$
524 +** No Commercial Usage
525 +** This file contains pre-release code and may not be distributed.
526 +** You may use this file in accordance with the terms and conditions
527 +** contained in the Technology Preview License Agreement accompanying
528 +** this package.
529 +**
530 +** GNU Lesser General Public License Usage
531 +** Alternatively, this file may be used under the terms of the GNU Lesser
532 +** General Public License version 2.1 as published by the Free Software
533 +** Foundation and appearing in the file LICENSE.LGPL included in the
534 +** packaging of this file.  Please review the following information to
535 +** ensure the GNU Lesser General Public License version 2.1 requirements
536 +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
537 +**
538 +** In addition, as a special exception, Nokia gives you certain additional
539 +** rights.  These rights are described in the Nokia Qt LGPL Exception
540 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
541 +**
542 +** If you have questions regarding the use of this file, please contact
543 +** Nokia at qt-info@nokia.com.
544 +**
545 +**
546 +**
547 +**
548 +**
549 +**
550 +**
551 +**
552 +** $QT_END_LICENSE$
553 +**
554 +****************************************************************************/
555 +
556 +#ifndef QDRAWHELPER_NEON_P_H
557 +#define QDRAWHELPER_NEON_P_H
558 +
559 +//
560 +//  W A R N I N G
561 +//  -------------
562 +//
563 +// This file is not part of the Qt API.  It exists purely as an
564 +// implementation detail.  This header file may change from version to
565 +// version without notice, or even be removed.
566 +//
567 +// We mean it.
568 +//
569 +
570 +#include <private/qdrawhelper_p.h>
571 +
572 +QT_BEGIN_NAMESPACE
573 +
574 +#ifdef QT_HAVE_NEON
575 +
576 +void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl,
577 +                                            const uchar *srcPixels, int sbpl,
578 +                                            int w, int h,
579 +                                            int const_alpha);
580 +
581 +void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl,
582 +                                  const uchar *srcPixels, int sbpl,
583 +                                  int w, int h,
584 +                                  int const_alpha);
585 +
586 +#endif // QT_HAVE_NEON
587 +
588 +QT_END_NAMESPACE
589 +
590 +#endif // QDRAWHELPER_NEON_P_H
591 -- 
592 1.6.5
593