diff options
Diffstat (limited to 'src/gui/painting/qdrawhelper_neon.cpp')
-rw-r--r-- | src/gui/painting/qdrawhelper_neon.cpp | 101 |
1 files changed, 84 insertions, 17 deletions
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index 7e12e62151..e3f5d5bac7 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -31,21 +31,20 @@ ** ****************************************************************************/ -#include <private/qdrawhelper_p.h> +#include <private/qdrawhelper_neon_p.h> #include <private/qblendfunctions_p.h> #include <private/qmath_p.h> #ifdef __ARM_NEON__ -#include <private/qdrawhelper_neon_p.h> #include <private/qpaintengine_raster_p.h> -#include <arm_neon.h> 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); @@ -60,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) { @@ -120,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(ENABLE_PIXMAN_DRAWHELPERS) extern "C" void pixman_composite_over_8888_0565_asm_neon (int32_t w, int32_t h, @@ -166,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, @@ -206,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) { @@ -331,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(ENABLE_PIXMAN_DRAWHELPERS) 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); } @@ -351,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(ENABLE_PIXMAN_DRAWHELPERS) 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); @@ -465,8 +530,9 @@ void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl, } } +#if defined(ENABLE_PIXMAN_DRAWHELPERS) void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride, const QClipData *) @@ -475,8 +541,9 @@ void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); uchar *mask = const_cast<uchar *>(bitmap); + const uint c = color.toArgb32(); - pixman_composite_over_n_8_0565_asm_neon(mapWidth, mapHeight, dest, destStride, color, 0, mask, mapStride); + pixman_composite_over_n_8_0565_asm_neon(mapWidth, mapHeight, dest, destStride, c, 0, mask, mapStride); } extern "C" void blend_8_pixels_rgb16_on_rgb16_neon(quint16 *dst, const quint16 *src, int const_alpha); @@ -704,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) { @@ -755,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); @@ -803,6 +868,7 @@ void QT_FASTCALL comp_func_Plus_neon(uint *dst, const uint *src, int length, uin } } +#if defined(ENABLE_PIXMAN_DRAWHELPERS) static const int tileSize = 32; extern "C" void qt_rotate90_16_neon(quint16 *dst, const quint16 *src, int sstride, int dstride, int count); @@ -946,6 +1012,7 @@ void qt_memrotate270_16_neon(const uchar *srcPixels, int w, int h, } } } +#endif class QSimdNeon { @@ -985,7 +1052,7 @@ public: const uint * QT_FASTCALL qt_fetch_radial_gradient_neon(uint *buffer, const Operator *op, const QSpanData *data, int y, int x, int length) { - return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdNeon> >(buffer, op, data, y, x, length); + return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdNeon>,uint>(buffer, op, data, y, x, length); } QT_END_NAMESPACE |