diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-11-27 11:33:07 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-11-30 11:06:45 +0000 |
commit | eff8fb07040ec68a7d2195a06144e7d61250dc80 (patch) | |
tree | cab09b11aeab2177218ca596645ca24fcea551ce /src/gui/painting/qdrawhelper_neon.cpp | |
parent | 9b23e36bbdd44f443cff607b524b23fe66ffd9e1 (diff) |
Enable AArch64 versions of ARGB32 NEON drawhelpers
Fix the ARGB32 NEON-optimized drawhelpers so they also build on AArch64.
The RGB16 NEON-drawhelpers are not converted as they use more assembly.
Change-Id: I8b75fadf5bad74360a2ab6aec9a6bf50df80c1b9
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
Diffstat (limited to 'src/gui/painting/qdrawhelper_neon.cpp')
-rw-r--r-- | src/gui/painting/qdrawhelper_neon.cpp | 90 |
1 files changed, 79 insertions, 11 deletions
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index bf4758afd2..413fddcfdc 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -44,6 +44,7 @@ QT_BEGIN_NAMESPACE void qt_memfill32(quint32 *dest, quint32 value, int count) { const int epilogueSize = count % 16; +#if !defined(Q_PROCESSOR_ARM_64) if (count >= 16) { quint32 *const neonEnd = dest + count - epilogueSize; register uint32x4_t valueVector1 asm ("q0") = vdupq_n_u32(value); @@ -58,6 +59,22 @@ void qt_memfill32(quint32 *dest, quint32 value, int count) ); } } +#else + if (count >= 16) { + quint32 *const neonEnd = dest + count - epilogueSize; + register uint32x4_t valueVector1 asm ("v0") = vdupq_n_u32(value); + register uint32x4_t valueVector2 asm ("v1") = valueVector1; + while (dest != neonEnd) { + asm volatile ( + "st2 { v0.4s, v1.4s }, [%[DST]], #32 \n\t" + "st2 { v0.4s, v1.4s }, [%[DST]], #32 \n\t" + : [DST]"+r" (dest) + : [VALUE1]"w"(valueVector1), [VALUE2]"w"(valueVector2) + : "memory" + ); + } + } +#endif switch (epilogueSize) { @@ -118,6 +135,7 @@ static inline uint16x8_t qvsource_over_u16(uint16x8_t src16, uint16x8_t dst16, u return vaddq_u16(src16, qvbyte_mul_u16(dst16, alpha16, half)); } +#if !defined(Q_PROCESSOR_ARM_64) extern "C" void pixman_composite_over_8888_0565_asm_neon (int32_t w, int32_t h, @@ -164,7 +182,6 @@ pixman_composite_src_0565_0565_asm_neon (int32_t w, int32_t dst_stride, uint16_t *src, int32_t src_stride); - // qblendfunctions.cpp void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, @@ -204,6 +221,7 @@ void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl, int w, int h, int const_alpha); + template <int N> static inline void scanLineBlit16(quint16 *dst, quint16 *src, int dstride) { @@ -329,11 +347,16 @@ void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl, pixman_composite_over_8888_0565_asm_neon(w, h, dst, dbpl / 2, src, sbpl / 4); } +#endif void qt_blend_argb32_on_argb32_scanline_neon(uint *dest, const uint *src, int length, uint const_alpha) { if (const_alpha == 255) { +#if !defined(Q_PROCESSOR_ARM_64) pixman_composite_scanline_over_asm_neon(length, dest, src); +#else + qt_blend_argb32_on_argb32_neon((uchar *)dest, 4 * length, (uchar *)src, 4 * length, length, 1, 256); +#endif } else { qt_blend_argb32_on_argb32_neon((uchar *)dest, 4 * length, (uchar *)src, 4 * length, length, 1, (const_alpha * 256) / 255); } @@ -349,7 +372,51 @@ void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl, uint16x8_t half = vdupq_n_u16(0x80); uint16x8_t full = vdupq_n_u16(0xff); if (const_alpha == 256) { +#if !defined(Q_PROCESSOR_ARM_64) pixman_composite_over_8888_8888_asm_neon(w, h, (uint32_t *)destPixels, dbpl / 4, (uint32_t *)srcPixels, sbpl / 4); +#else + for (int y=0; y<h; ++y) { + int x = 0; + for (; x < w-3; x += 4) { + if (src[x] | src[x+1] | src[x+2] | src[x+3]) { + uint32x4_t src32 = vld1q_u32((uint32_t *)&src[x]); + uint32x4_t dst32 = vld1q_u32((uint32_t *)&dst[x]); + + const uint8x16_t src8 = vreinterpretq_u8_u32(src32); + const uint8x16_t dst8 = vreinterpretq_u8_u32(dst32); + + const uint8x8_t src8_low = vget_low_u8(src8); + const uint8x8_t dst8_low = vget_low_u8(dst8); + + const uint8x8_t src8_high = vget_high_u8(src8); + const uint8x8_t dst8_high = vget_high_u8(dst8); + + const uint16x8_t src16_low = vmovl_u8(src8_low); + const uint16x8_t dst16_low = vmovl_u8(dst8_low); + + const uint16x8_t src16_high = vmovl_u8(src8_high); + const uint16x8_t dst16_high = vmovl_u8(dst8_high); + + const uint16x8_t result16_low = qvsource_over_u16(src16_low, dst16_low, half, full); + const uint16x8_t result16_high = qvsource_over_u16(src16_high, dst16_high, half, full); + + const uint32x2_t result32_low = vreinterpret_u32_u8(vmovn_u16(result16_low)); + const uint32x2_t result32_high = vreinterpret_u32_u8(vmovn_u16(result16_high)); + + vst1q_u32((uint32_t *)&dst[x], vcombine_u32(result32_low, result32_high)); + } + } + for (; x<w; ++x) { + uint s = src[x]; + if (s >= 0xff000000) + dst[x] = s; + else if (s != 0) + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); + } + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + } +#endif } else if (const_alpha != 0) { const_alpha = (const_alpha * 255) >> 8; uint16x8_t const_alpha16 = vdupq_n_u16(const_alpha); @@ -463,6 +530,7 @@ void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl, } } +#if !defined(Q_PROCESSOR_ARM_64) void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 &color, const uchar *bitmap, @@ -703,6 +771,7 @@ void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer, int x, int data[i + j] = dstBuffer[j]; } } +#endif void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, uint color, uint const_alpha) { @@ -754,16 +823,13 @@ void QT_FASTCALL comp_func_Plus_neon(uint *dst, const uint *src, int length, uin uint *const neonEnd = end - 3; while (dst < neonEnd) { - asm volatile ( - "vld2.8 { d0, d1 }, [%[SRC]] !\n\t" - "vld2.8 { d2, d3 }, [%[DST]]\n\t" - "vqadd.u8 q0, q0, q1\n\t" - "vst2.8 { d0, d1 }, [%[DST]] !\n\t" - : [DST]"+r" (dst), [SRC]"+r" (src) - : - : "memory", "d0", "d1", "d2", "d3", "q0", "q1" - ); - } + uint8x16_t vs = vld1q_u8((const uint8_t*)src); + const uint8x16_t vd = vld1q_u8((uint8_t*)dst); + vs = vqaddq_u8(vs, vd); + vst1q_u8((uint8_t*)dst, vs); + src += 4; + dst += 4; + }; while (dst != end) { *dst = comp_func_Plus_one_pixel(*dst, *src); @@ -802,6 +868,7 @@ void QT_FASTCALL comp_func_Plus_neon(uint *dst, const uint *src, int length, uin } } +#if !defined(Q_PROCESSOR_ARM_64) static const int tileSize = 32; extern "C" void qt_rotate90_16_neon(quint16 *dst, const quint16 *src, int sstride, int dstride, int count); @@ -945,6 +1012,7 @@ void qt_memrotate270_16_neon(const uchar *srcPixels, int w, int h, } } } +#endif class QSimdNeon { |