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