This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch fix-release-build
in repository efl.
View the commit online.
commit b66ab805ba4287ab223538b0cd2c83bc9c59369c
Author: Cedric BAIL <[email protected]>
AuthorDate: Sun Aug 2 19:42:15 2026 -0600
evas: speed up the NEON mask kernels, drop the copy_rel placeholders
Several mask kernels were slower than the C they replace on a Cortex-A72,
which matters because they are what draws glyph coverage masks - text.
The cost was byte splatting. A packed ARGB layout needs each mask byte
broadcast across its pixel's four channels, and that was costing two
widenings plus a 32 bit multiply by 0x01010101 for every four pixels;
extracting a source alpha cost another shift and multiply. Two ways out,
picked per kernel:
- Work planar. vld4q hands back one register per channel and the per
pixel mask then lines up with each plane directly, so the splat
disappears. Used for the mask x colour kernels, whose arithmetic
rearranges to stay unsigned and inside 16 bits:
d + (((c - d) * (m+1)) >> 8) == (d * (255-m) + c * (m+1)) >> 8
- Keep packed, splat with one tbl against a constant index vector.
Used where the final combine must stay a 32 bit add, because the C
reference adds two packed ARGB words and an overflowing channel has to
carry into the next one. A planar version of the pixel x mask kernel
measured faster but diverged from C on non-premultiplied input, which
map and scale do produce.
Whole blocks that are entirely transparent are skipped and entirely
opaque ones become a flat fill, which is what the C path gets from its
switch and what glyph masks largely consist of.
C NEON before NEON after
mask x colour A72 83.5 56.8 119.9 0.68x -> 1.44x
A53 32.9 48.0 99.4 1.46x -> 3.02x
ditto, argb A72 61.5 53.3 124.6 0.88x -> 2.03x
pixel x mask A72 63.3 52.9 70.6 0.84x -> 1.14x
copy mask x c A72 82.5 82.5 183.4 1.00x -> 2.22x
tbl and the across-vector reduce are AArch64 only, so those kernels are
guarded and ARMv7 keeps the implementation it has today, byte for byte -
there is no hardware here to test a second version on.
Separately, every copy_rel kernel registered in a CPU_NEON slot was a
"FIXME: neon-it" placeholder - a scalar copy of the C kernel. They cannot
be faster than what they duplicate and one was measurably slower
(_op_copy_rel_c_dp_neon used a plain for loop where the reference uses
UNROLL8_PLD_WHILE: 0.80x on an A53). They were not harmless either: four
of the bugs fixed earlier in this branch were in these copies and only in
these copies. Dropping the registrations lets the dispatcher fall through
to CPU_C, the same algorithm maintained in one place. Only the [DP] slots
go; the [DP_AN] ones alias to genuinely vectorised copy kernels.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
.../evas_op_blend/op_blend_mask_color_neon.c | 454 +++++++++++----------
.../evas_op_blend/op_blend_pixel_color_neon.c | 72 ++++
.../evas_op_blend/op_blend_pixel_mask_neon.c | 106 +++++
.../evas/common/evas_op_copy/op_copy_color_neon.c | 28 --
.../common/evas_op_copy/op_copy_mask_color_neon.c | 128 +++---
.../common/evas_op_copy/op_copy_pixel_color_neon.c | 53 ---
.../common/evas_op_copy/op_copy_pixel_mask_neon.c | 40 --
.../evas/common/evas_op_copy/op_copy_pixel_neon.c | 27 --
8 files changed, 499 insertions(+), 409 deletions(-)
diff --git a/src/lib/evas/common/evas_op_blend/op_blend_mask_color_neon.c b/src/lib/evas/common/evas_op_blend/op_blend_mask_color_neon.c
index 2d8c2fd298..45c48432ca 100644
--- a/src/lib/evas/common/evas_op_blend/op_blend_mask_color_neon.c
+++ b/src/lib/evas/common/evas_op_blend/op_blend_mask_color_neon.c
@@ -23,121 +23,87 @@
static void
_op_blend_mas_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m, DATA32 c, DATA32 *d, int l) {
#ifdef BUILD_NEON_INTRINSICS
- uint16x8_t m_16x8;
- uint16x8_t mc0_16x8;
- uint16x8_t mc1_16x8;
- uint16x8_t temp0_16x8;
- uint16x8_t temp1_16x8;
- uint16x8_t x255_16x8;
- uint32x2_t c_32x2;
- uint32x2_t m_32x2 = { 0, 0 };
- uint32x4_t a_32x4;
- uint32x4_t ad_32x4;
- uint32x4_t cond_32x4;
- uint32x4_t d_32x4;
- uint32x4_t m_32x4;
- uint32x4_t temp_32x4;
- uint32x4_t mc_32x4;
- uint32x4_t x0_32x4;
- uint32x4_t x1_32x4;
- uint8x16_t a_8x16;
- uint8x16_t d_8x16;
- uint8x16_t m_8x16;
- uint8x16_t mc_8x16;
- uint8x16_t temp_8x16;
- uint8x16_t x0_8x16;
- uint8x16_t x1_8x16;
- uint8x8_t a0_8x8;
- uint8x8_t a1_8x8;
- uint8x8_t c_8x8;
- uint8x8_t d0_8x8;
- uint8x8_t d1_8x8;
- uint8x8_t m0_8x8;
- uint8x8_t m1_8x8;
- uint8x8_t m_8x8;
- uint8x8_t mc0_8x8;
- uint8x8_t mc1_8x8;
- uint8x8_t temp0_8x8;
- uint8x8_t temp1_8x8;
-
- x1_8x16 = vdupq_n_u8(0x1);
- x0_8x16 = vdupq_n_u8(0x0);
- x0_32x4 = vreinterpretq_u32_u8(x0_8x16);
- x255_16x8 = vdupq_n_u16(0xff);
- x1_32x4 = vreinterpretq_u32_u8(x1_8x16);
- c_32x2 = vdup_n_u32(c);
- c_8x8 = vreinterpret_u8_u32(c_32x2);
-
+ /* mc = MUL_SYM(m, c) per channel, i.e. (c * m + 255) >> 8, then
+ * d = mc + MUL_256(256 - (mc >> 24), d).
+ *
+ * The second step is expressed as
+ *
+ * mc + ((d * (255 - mc_a) + d) >> 8)
+ *
+ * because (256 - mc_a) does not fit in a byte, and d * (256 - mc_a) is the
+ * same as d * (255 - mc_a) + d. Everything stays unsigned and inside 16
+ * bits, so the whole span can be processed one channel plane at a time.
+ *
+ * Planar is what makes this cheap: vld4q gives one register per channel and
+ * the per pixel mask lines up with each plane directly, so the packed
+ * version's mask splat - two widenings plus a 32 bit multiply by 0x01010101
+ * for every four pixels - is not needed at all.
+ *
+ * A mask of 0 needs no special case here, unlike the mask x can variant:
+ * it gives mc = 0 and 255 - mc_a = 255, so the result is (d * 256) >> 8,
+ * which is d. Fully transparent blocks are still skipped outright, since
+ * that is free and glyph coverage masks are mostly zero. */
+ const uint8x16_t c_b = vdupq_n_u8(c & 0xff);
+ const uint8x16_t c_g = vdupq_n_u8((c >> 8) & 0xff);
+ const uint8x16_t c_r = vdupq_n_u8((c >> 16) & 0xff);
+ const uint8x16_t c_a = vdupq_n_u8((c >> 24) & 0xff);
+ const uint16x8_t x255 = vdupq_n_u16(0xff);
DATA32 *start = d;
int size = l;
- DATA32 *end = start + (size & ~3);
- while (start < end) {
- int k = *((int *)m);
- if (k == 0)
- {
- m+=4;
- start+=4;
- continue;
- }
+ DATA32 *end = start + (size & ~15);
- m_32x2 = vld1_lane_u32((DATA32*)m, m_32x2, 0);
- d_32x4 = vld1q_u32(start);
+ /* mc = (c * m + 255) >> 8 */
+#define EVAS_MAS_C_MUL(out, cv) \
+ do { \
+ uint16x8_t lo_ = vmlal_u8(x255, vget_low_u8(cv), vget_low_u8(m8)); \
+ uint16x8_t hi_ = vmlal_u8(x255, vget_high_u8(cv), vget_high_u8(m8)); \
+ out = vcombine_u8(vshrn_n_u16(lo_, 8), vshrn_n_u16(hi_, 8)); \
+ } while (0)
- m_8x8 = vreinterpret_u8_u32(m_32x2);
- m_16x8 = vmovl_u8(m_8x8);
- m_8x16 = vreinterpretq_u8_u16(m_16x8);
- m_8x8 = vget_low_u8(m_8x16);
- m_16x8 = vmovl_u8(m_8x8);
- m_32x4 = vreinterpretq_u32_u16(m_16x8);
+ /* d = mc + ((d * (255 - mc_a) + d) >> 8) */
+#define EVAS_MAS_C_BLEND(plane, mc) \
+ do { \
+ uint16x8_t lo_ = vmull_u8(vget_low_u8(plane), vget_low_u8(nmca)); \
+ uint16x8_t hi_ = vmull_u8(vget_high_u8(plane), vget_high_u8(nmca)); \
+ lo_ = vaddw_u8(lo_, vget_low_u8(plane)); \
+ hi_ = vaddw_u8(hi_, vget_high_u8(plane)); \
+ plane = vaddq_u8(mc, vcombine_u8(vshrn_n_u16(lo_, 8), \
+ vshrn_n_u16(hi_, 8))); \
+ } while (0)
- m_32x4 = vmulq_u32(m_32x4, x1_32x4);
- m_8x16 = vreinterpretq_u8_u32(m_32x4);
- m0_8x8 = vget_low_u8(m_8x16);
- m1_8x8 = vget_high_u8(m_8x16);
+ while (start < end)
+ {
+ uint8x16_t m8 = vld1q_u8(m);
+ uint8x16x4_t dp;
+ uint8x16_t mc_b, mc_g, mc_r, mc_a, nmca;
- mc0_16x8 = vmull_u8(m0_8x8, c_8x8);
- mc1_16x8 = vmull_u8(m1_8x8, c_8x8);
- mc0_16x8 = vaddq_u16(mc0_16x8, x255_16x8);
- mc1_16x8 = vaddq_u16(mc1_16x8, x255_16x8);
+ if (vmaxvq_u8(m8) == 0) /* wholly transparent: nothing to do */
+ {
+ m += 16;
+ start += 16;
+ continue;
+ }
- mc0_8x8 = vshrn_n_u16(mc0_16x8, 8);
- mc1_8x8 = vshrn_n_u16(mc1_16x8, 8);
- mc_8x16 = vcombine_u8(mc0_8x8, mc1_8x8);
+ EVAS_MAS_C_MUL(mc_b, c_b);
+ EVAS_MAS_C_MUL(mc_g, c_g);
+ EVAS_MAS_C_MUL(mc_r, c_r);
+ EVAS_MAS_C_MUL(mc_a, c_a);
+ nmca = vmvnq_u8(mc_a);
- a_8x16 = vsubq_u8(x0_8x16, mc_8x16);
+ dp = vld4q_u8((const uint8_t *)start);
+ EVAS_MAS_C_BLEND(dp.val[0], mc_b);
+ EVAS_MAS_C_BLEND(dp.val[1], mc_g);
+ EVAS_MAS_C_BLEND(dp.val[2], mc_r);
+ EVAS_MAS_C_BLEND(dp.val[3], mc_a);
+ vst4q_u8((uint8_t *)start, dp);
- a_32x4 = vreinterpretq_u32_u8(a_8x16);
- a_32x4 = vshrq_n_u32(a_32x4, 24);
- a_32x4 = vmulq_u32(a_32x4, x1_32x4);
+ m += 16;
+ start += 16;
+ }
+#undef EVAS_MAS_C_MUL
+#undef EVAS_MAS_C_BLEND
- a_8x16 = vreinterpretq_u8_u32(a_32x4);
- a0_8x8 = vget_low_u8(a_8x16);
- a1_8x8 = vget_high_u8(a_8x16);
-
- d_8x16 = vreinterpretq_u8_u32(d_32x4);
- d0_8x8 = vget_low_u8(d_8x16);
- d1_8x8 = vget_high_u8(d_8x16);
-
- temp0_16x8 = vmull_u8(a0_8x8, d0_8x8);
- temp1_16x8 = vmull_u8(a1_8x8, d1_8x8);
- temp0_8x8 = vshrn_n_u16(temp0_16x8,8);
- temp1_8x8 = vshrn_n_u16(temp1_16x8,8);
-
- temp_8x16 = vcombine_u8(temp0_8x8, temp1_8x8);
- temp_32x4 = vreinterpretq_u32_u8(temp_8x16);
-
- cond_32x4 = vceqq_u32(a_32x4, x0_32x4);
- ad_32x4 = vbslq_u32(cond_32x4, d_32x4, temp_32x4);
-
- mc_32x4 = vreinterpretq_u32_u8(mc_8x16);
- d_32x4 = vaddq_u32(mc_32x4, ad_32x4);
-
- vst1q_u32(start, d_32x4);
-
- start+=4;
- m+=4;
- }
- end += (size & 3);
+ end += (size & 15);
while (start < end) {
DATA32 a = *m;
DATA32 mc = MUL_SYM(a, c);
@@ -277,122 +243,90 @@ _op_blend_mas_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m, DATA32 c, DATA32 *d, in
static void
_op_blend_mas_can_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m, DATA32 c, DATA32 *d, int l) {
#ifdef BUILD_NEON_INTRINSICS
- int16x8_t c_i16x8;
- int16x8_t d0_i16x8;
- int16x8_t d1_i16x8;
- int16x8_t dc0_i16x8;
- int16x8_t dc1_i16x8;
- int16x8_t m0_i16x8;
- int16x8_t m1_i16x8;
- int8x16_t dc_i8x16;
- int8x8_t dc0_i8x8;
- int8x8_t dc1_i8x8;
- uint16x8_t c_16x8;
- uint16x8_t d0_16x8;
- uint16x8_t d1_16x8;
- uint16x8_t m0_16x8;
- uint16x8_t m1_16x8;
- uint16x8_t m_16x8;
- uint32x2_t c_32x2;
- uint32x2_t m_32x2 = { 0, 0 };
- uint32x4_t d_32x4;
- uint32x4_t dc_32x4;
- uint32x4_t m_32x4;
- uint32x4_t x1_32x4;
- uint8x16_t d_8x16;
- uint8x16_t m_8x16;
- uint8x16_t x1_8x16;
- uint8x8_t c_8x8;
- uint8x8_t d0_8x8;
- uint8x8_t d1_8x8;
- uint8x8_t m0_8x8;
- uint8x8_t m1_8x8;
- uint8x8_t m_8x8;
- uint8x8_t x1_8x8;
- uint32x4_t x0_32x4;
- uint32x4_t cond_32x4;
-
- c_32x2 = vdup_n_u32(c);
- c_8x8 = vreinterpret_u8_u32(c_32x2);
- c_16x8 = vmovl_u8(c_8x8);
- c_i16x8 = vreinterpretq_s16_u16(c_16x8);
- x1_8x16 = vdupq_n_u8(0x1);
- x1_8x8 = vget_low_u8(x1_8x16);
- x1_32x4 = vreinterpretq_u32_u8(x1_8x16);
- x0_32x4 = vdupq_n_u32(0x0);
-
+ /* d = INTERP_256(m + 1, c, d) per channel, i.e.
+ *
+ * d + (((c - d) * (m + 1)) >> 8)
+ *
+ * Rearranged so that no intermediate is ever negative:
+ *
+ * (d * (255 - m) + c * (m + 1)) >> 8
+ *
+ * which is exact (the largest intermediate is 255*256 = 65280, so it stays
+ * inside 16 bits) and lets the span be processed one channel plane at a
+ * time. Planar is the point: vld4q hands back one register per channel and
+ * the per pixel mask then lines up with each plane directly, so the byte
+ * splat that the packed version needed - two widenings and a 32 bit
+ * multiply by 0x01010101 for every four pixels - disappears entirely.
+ *
+ * A mask of 0 must leave the destination untouched rather than yield
+ * (d * 255 + c) >> 8, so zero mask lanes are selected back to d. Whole
+ * blocks that are entirely transparent or entirely opaque are handled
+ * without any arithmetic at all, which is what the C path gets from its
+ * switch and what glyph coverage masks mostly consist of. */
+ const uint8x16_t c_b = vdupq_n_u8(c & 0xff);
+ const uint8x16_t c_g = vdupq_n_u8((c >> 8) & 0xff);
+ const uint8x16_t c_r = vdupq_n_u8((c >> 16) & 0xff);
+ const uint8x16_t c_a = vdupq_n_u8((c >> 24) & 0xff);
+ const uint32x4_t c_32x4 = vdupq_n_u32(c);
DATA32 *start = d;
int size = l;
- DATA32 *end = start + (size & ~3);
- while (start < end) {
- int k = *((int *)m);
- if (k == 0)
- {
- m+=4;
- start+=4;
- continue;
- }
+ DATA32 *end = start + (size & ~15);
- m_32x2 = vld1_lane_u32((DATA32*)m, m_32x2, 0);
- d_32x4 = vld1q_u32(start);
- d_8x16 = vreinterpretq_u8_u32(d_32x4);
- d0_8x8 = vget_low_u8(d_8x16);
- d1_8x8 = vget_high_u8(d_8x16);
+#define EVAS_MAS_CAN_CHAN(dst_plane, src_plane, cv) \
+ do { \
+ uint16x8_t lo_ = vmull_u8(vget_low_u8(src_plane), vget_low_u8(nm)); \
+ uint16x8_t hi_ = vmull_u8(vget_high_u8(src_plane), vget_high_u8(nm)); \
+ lo_ = vmlal_u8(lo_, vget_low_u8(cv), vget_low_u8(m8)); \
+ hi_ = vmlal_u8(hi_, vget_high_u8(cv), vget_high_u8(m8)); \
+ lo_ = vaddw_u8(lo_, vget_low_u8(cv)); \
+ hi_ = vaddw_u8(hi_, vget_high_u8(cv)); \
+ dst_plane = vbslq_u8(mzero, \
+ src_plane, \
+ vcombine_u8(vshrn_n_u16(lo_, 8), \
+ vshrn_n_u16(hi_, 8))); \
+ } while (0)
- m_8x8 = vreinterpret_u8_u32(m_32x2);
- m_16x8 = vmovl_u8(m_8x8);
- m_8x16 = vreinterpretq_u8_u16(m_16x8);
- m_8x8 = vget_low_u8(m_8x16);
- m_16x8 = vmovl_u8(m_8x8);
- m_32x4 = vreinterpretq_u32_u16(m_16x8);
+ while (start < end)
+ {
+ uint8x16_t m8 = vld1q_u8(m);
+ uint8x16x4_t dp;
+ uint8x16_t nm, mzero;
- m_32x4 = vmulq_u32(m_32x4, x1_32x4);
- m_8x16 = vreinterpretq_u8_u32(m_32x4);
- m0_8x8 = vget_low_u8(m_8x16);
- m1_8x8 = vget_high_u8(m_8x16);
- m0_16x8 = vaddl_u8(m0_8x8, x1_8x8);
- m1_16x8 = vaddl_u8(m1_8x8, x1_8x8);
+ if (vmaxvq_u8(m8) == 0) /* wholly transparent: nothing to do */
+ {
+ m += 16;
+ start += 16;
+ continue;
+ }
+ if (vminvq_u8(m8) == 255) /* wholly opaque: a flat colour fill */
+ {
+ vst1q_u32(start, c_32x4);
+ vst1q_u32(start + 4, c_32x4);
+ vst1q_u32(start + 8, c_32x4);
+ vst1q_u32(start + 12, c_32x4);
+ m += 16;
+ start += 16;
+ continue;
+ }
- m0_i16x8 = vreinterpretq_s16_u16(m0_16x8);
- m1_i16x8 = vreinterpretq_s16_u16(m1_16x8);
+ dp = vld4q_u8((const uint8_t *)start);
+ nm = vmvnq_u8(m8);
+ mzero = vceqq_u8(m8, vdupq_n_u8(0));
- d0_16x8 = vmovl_u8(d0_8x8);
- d1_16x8 = vmovl_u8(d1_8x8);
+ EVAS_MAS_CAN_CHAN(dp.val[0], dp.val[0], c_b);
+ EVAS_MAS_CAN_CHAN(dp.val[1], dp.val[1], c_g);
+ EVAS_MAS_CAN_CHAN(dp.val[2], dp.val[2], c_r);
+ EVAS_MAS_CAN_CHAN(dp.val[3], dp.val[3], c_a);
- d0_i16x8 = vreinterpretq_s16_u16(d0_16x8);
- d1_i16x8 = vreinterpretq_s16_u16(d1_16x8);
+ vst4q_u8((uint8_t *)start, dp);
+ m += 16;
+ start += 16;
+ }
+#undef EVAS_MAS_CAN_CHAN
- dc0_i16x8 = vsubq_s16(c_i16x8, d0_i16x8);
- dc1_i16x8 = vsubq_s16(c_i16x8, d1_i16x8);
-
- dc0_i16x8 = vmulq_s16(dc0_i16x8, m0_i16x8);
- dc1_i16x8 = vmulq_s16(dc1_i16x8, m1_i16x8);
-
- dc0_i16x8 = vshrq_n_s16(dc0_i16x8, 8);
- dc1_i16x8 = vshrq_n_s16(dc1_i16x8, 8);
-
- dc0_i16x8 = vaddq_s16(dc0_i16x8, d0_i16x8);
- dc1_i16x8 = vaddq_s16(dc1_i16x8, d1_i16x8);
-
- dc0_i8x8 = vmovn_s16(dc0_i16x8);
- dc1_i8x8 = vmovn_s16(dc1_i16x8);
-
- dc_i8x16 = vcombine_s8(dc0_i8x8, dc1_i8x8);
- dc_32x4 = vreinterpretq_u32_s8(dc_i8x16);
-
- cond_32x4 = vceqq_u32(m_32x4, x0_32x4);
- dc_32x4 = vbslq_u32(cond_32x4, d_32x4, dc_32x4);
-
- vst1q_u32(start, dc_32x4);
- m+=4;
- start+=4;
- }
- end += (size & 3);
+ end += (size & 15);
while (start < end) {
DATA32 alpha = *m;
- /* the vector body above selects the untouched dst for alpha == 0
- * (vbslq_u32) and yields exactly c for alpha == 255; the tail has to
- * special-case both to stay bit identical to the C reference */
switch (alpha)
{
case 0:
@@ -700,6 +634,105 @@ init_blend_mask_color_pt_funcs_neon(void)
/* blend_rel mask x color -> dst */
#ifdef BUILD_NEON
+#ifdef BUILD_NEON_INTRINSICS
+/* The AArch64 path below uses tbl and the across-vector reduce, neither of
+ * which exists in 32 bit NEON. Keep the original kernel for ARMv7 rather
+ * than adding a second version that cannot be tested here. */
+static void
+_op_blend_rel_mas_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m, DATA32 c, DATA32 *d, int l) {
+ /* mc = MUL_SYM(m, c), then
+ *
+ * d = MUL_SYM(d_a, mc) + MUL_256(256 - mc_a, d)
+ *
+ * with the second term written as (d * (255 - mc_a) + d) >> 8 so that
+ * 256 - mc_a never has to fit in a byte.
+ *
+ * Packed rather than planar, for the same reason as the pixel x mask
+ * kernel: the C reference's final step adds two packed ARGB words, so an
+ * overflowing channel carries into the next one, which a per byte add
+ * would not reproduce.
+ *
+ * Both byte splats this needs - the mask byte across its pixel's channels,
+ * and the destination alpha across its own - were two widenings plus a
+ * 32 bit multiply by 0x01010101 per four pixels. Each is one tbl against a
+ * constant index vector.
+ *
+ * A zero mask needs no special case: it gives mc = 0, so the first term is
+ * 0 and the second is (d * 256) >> 8, which is d. Wholly transparent
+ * blocks are skipped anyway because it is free. */
+ static const uint8_t splat_idx[4][16] = {
+ { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 },
+ { 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7 },
+ { 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11 },
+ { 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15 }
+ };
+ static const uint8_t alpha_idx[16] =
+ { 3, 3, 3, 3, 7, 7, 7, 7, 11, 11, 11, 11, 15, 15, 15, 15 };
+ const uint8x16_t aidx = vld1q_u8(alpha_idx);
+ const uint8x16_t c8 = vreinterpretq_u8_u32(vdupq_n_u32(c));
+ const uint16x8_t x255 = vdupq_n_u16(0xff);
+ DATA32 *start = d;
+ int size = l;
+ DATA32 *end = start + (size & ~15);
+
+ while (start < end)
+ {
+ uint8x16_t m16 = vld1q_u8(m);
+ int j;
+
+ if (vmaxvq_u8(m16) == 0)
+ {
+ m += 16;
+ start += 16;
+ continue;
+ }
+
+ for (j = 0; j < 4; j++)
+ {
+ uint8x16_t d8 = vreinterpretq_u8_u32(vld1q_u32(start + (j * 4)));
+ uint8x16_t m8 = vqtbl1q_u8(m16, vld1q_u8(splat_idx[j]));
+ uint8x16_t mc, da, t, nmca, term;
+ uint16x8_t lo, hi;
+
+ /* mc = (c * m + 255) >> 8 */
+ lo = vmlal_u8(x255, vget_low_u8(c8), vget_low_u8(m8));
+ hi = vmlal_u8(x255, vget_high_u8(c8), vget_high_u8(m8));
+ mc = vcombine_u8(vshrn_n_u16(lo, 8), vshrn_n_u16(hi, 8));
+
+ /* t = (mc * d_a + 255) >> 8 */
+ da = vqtbl1q_u8(d8, aidx);
+ lo = vmlal_u8(x255, vget_low_u8(mc), vget_low_u8(da));
+ hi = vmlal_u8(x255, vget_high_u8(mc), vget_high_u8(da));
+ t = vcombine_u8(vshrn_n_u16(lo, 8), vshrn_n_u16(hi, 8));
+
+ /* term = (d * (255 - mc_a) + d) >> 8 */
+ nmca = vmvnq_u8(vqtbl1q_u8(mc, aidx));
+ lo = vmull_u8(vget_low_u8(d8), vget_low_u8(nmca));
+ hi = vmull_u8(vget_high_u8(d8), vget_high_u8(nmca));
+ lo = vaddw_u8(lo, vget_low_u8(d8));
+ hi = vaddw_u8(hi, vget_high_u8(d8));
+ term = vcombine_u8(vshrn_n_u16(lo, 8), vshrn_n_u16(hi, 8));
+
+ vst1q_u32(start + (j * 4),
+ vaddq_u32(vreinterpretq_u32_u8(t),
+ vreinterpretq_u32_u8(term)));
+ }
+
+ m += 16;
+ start += 16;
+ }
+
+ end += (size & 15);
+ while (start < end)
+ {
+ DATA32 mc = MUL_SYM(*m, c);
+ int alpha = 256 - (mc >> 24);
+ *start = MUL_SYM(*start >> 24, mc) + MUL_256(alpha, *start);
+ start++;
+ m++;
+ }
+}
+#else
static void
_op_blend_rel_mas_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m, DATA32 c, DATA32 *d, int l) {
uint16x8_t dc0_16x8;
@@ -841,6 +874,7 @@ _op_blend_rel_mas_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m, DATA32 c, DATA32 *d
m++;
}
}
+#endif
#define _op_blend_rel_mas_cn_dp_neon _op_blend_rel_mas_c_dp_neon
#define _op_blend_rel_mas_can_dp_neon _op_blend_rel_mas_c_dp_neon
diff --git a/src/lib/evas/common/evas_op_blend/op_blend_pixel_color_neon.c b/src/lib/evas/common/evas_op_blend/op_blend_pixel_color_neon.c
index d32df72fd2..a92ad641dc 100644
--- a/src/lib/evas/common/evas_op_blend/op_blend_pixel_color_neon.c
+++ b/src/lib/evas/common/evas_op_blend/op_blend_pixel_color_neon.c
@@ -503,6 +503,77 @@ _op_blend_pan_can_dp_neon(DATA32 *s, DATA8 *m EINA_UNUSED, DATA32 c, DATA32 *d,
}
}
+#ifdef BUILD_NEON_INTRINSICS
+/* The AArch64 path below uses tbl and the across-vector reduce, neither of
+ * which exists in 32 bit NEON. Keep the original kernel for ARMv7 rather
+ * than adding a second version that cannot be tested here. */
+static void
+_op_blend_p_caa_dp_neon(DATA32 *s, DATA8 *m EINA_UNUSED, DATA32 c, DATA32 *d, int l) {
+ /* sc = MUL_256(1 + (c & 0xff), s), then d = sc + MUL_256(256 - sc_a, d).
+ *
+ * The colour here is an alpha replicated across all four channels, so only
+ * its low byte matters. Both scale factors are in 1..256 and so do not fit
+ * in a byte; both are handled the same way:
+ *
+ * (s * (ca + 1)) >> 8 == (s * ca + s) >> 8
+ * (d * (256 - sc_a)) >> 8 == (d * (255 - sc_a) + d) >> 8
+ *
+ * which keeps every operand a byte and every intermediate inside 16 bits.
+ *
+ * Packed rather than planar, because the final step adds two packed ARGB
+ * words in the C reference, so an overflowing channel carries into the next
+ * one. Extracting sc's alpha across its pixel's four channels was a shift
+ * plus a 32 bit multiply by 0x01010101; it is one tbl instead. */
+ static const uint8_t alpha_idx[16] =
+ { 3, 3, 3, 3, 7, 7, 7, 7, 11, 11, 11, 11, 15, 15, 15, 15 };
+ const uint8x16_t aidx = vld1q_u8(alpha_idx);
+ const uint8x16_t ca = vdupq_n_u8(c & 0xff);
+ DATA32 *start = d;
+ int size = l;
+ DATA32 *end = start + (size & ~3);
+
+ while (start < end)
+ {
+ uint8x16_t s8 = vreinterpretq_u8_u32(vld1q_u32(s));
+ uint8x16_t d8 = vreinterpretq_u8_u32(vld1q_u32(start));
+ uint8x16_t sc, nsca, term;
+ uint16x8_t lo, hi;
+
+ /* sc = (s * ca + s) >> 8 */
+ lo = vmlal_u8(vmovl_u8(vget_low_u8(s8)), vget_low_u8(s8), vget_low_u8(ca));
+ hi = vmlal_u8(vmovl_u8(vget_high_u8(s8)), vget_high_u8(s8), vget_high_u8(ca));
+ sc = vcombine_u8(vshrn_n_u16(lo, 8), vshrn_n_u16(hi, 8));
+
+ /* term = (d * (255 - sc_a) + d) >> 8 */
+ nsca = vmvnq_u8(vqtbl1q_u8(sc, aidx));
+ lo = vmull_u8(vget_low_u8(d8), vget_low_u8(nsca));
+ hi = vmull_u8(vget_high_u8(d8), vget_high_u8(nsca));
+ lo = vaddw_u8(lo, vget_low_u8(d8));
+ hi = vaddw_u8(hi, vget_high_u8(d8));
+ term = vcombine_u8(vshrn_n_u16(lo, 8), vshrn_n_u16(hi, 8));
+
+ vst1q_u32(start, vaddq_u32(vreinterpretq_u32_u8(sc),
+ vreinterpretq_u32_u8(term)));
+ s += 4;
+ start += 4;
+ }
+
+ end += (size & 3);
+ {
+ DATA32 cc = 1 + (c & 0xff);
+
+ while (start < end)
+ {
+ DATA32 sc = MUL_256(cc, *s);
+ int alpha = 256 - (sc >> 24);
+
+ *start = sc + MUL_256(alpha, *start);
+ start++;
+ s++;
+ }
+ }
+}
+#else
static void
_op_blend_p_caa_dp_neon(DATA32 *s, DATA8 *m EINA_UNUSED, DATA32 c, DATA32 *d, int l) {
uint16x8_t ad0_16x8;
@@ -620,6 +691,7 @@ _op_blend_p_caa_dp_neon(DATA32 *s, DATA8 *m EINA_UNUSED, DATA32 c, DATA32 *d, in
}
}
+#endif
static void
_op_blend_pan_caa_dp_neon(DATA32 *s, DATA8 *m EINA_UNUSED, DATA32 c, DATA32 *d, int l) {
diff --git a/src/lib/evas/common/evas_op_blend/op_blend_pixel_mask_neon.c b/src/lib/evas/common/evas_op_blend/op_blend_pixel_mask_neon.c
index 8405d08751..a41b1c1c21 100644
--- a/src/lib/evas/common/evas_op_blend/op_blend_pixel_mask_neon.c
+++ b/src/lib/evas/common/evas_op_blend/op_blend_pixel_mask_neon.c
@@ -4,6 +4,111 @@
/* blend pixel x mask --> dst */
#ifdef BUILD_NEON
+#ifdef BUILD_NEON_INTRINSICS
+/* The AArch64 path below uses tbl and the across-vector reduce, neither of
+ * which exists in 32 bit NEON. Keep the original kernels for ARMv7 rather
+ * than writing a second version that cannot be tested here. */
+static void
+_op_blend_p_mas_dp_neon(DATA32 *s, DATA8 *m, DATA32 c EINA_UNUSED, DATA32 *d, int l) {
+ /* sm = MUL_SYM(m, s) per channel, i.e. (s * m + 255) >> 8, then
+ * d = sm + MUL_256(256 - sm_a, d), with the second term written as
+ *
+ * (d * (255 - sm_a) + d) >> 8
+ *
+ * so 256 - sm_a never has to fit in a byte.
+ *
+ * This stays on packed pixels rather than de-interleaving to planes,
+ * because the final combine has to be a 32 bit add: the C reference adds
+ * two packed ARGB words, so a channel that overflows carries into the next
+ * one. A per byte add would not, and source pixels that are not properly
+ * premultiplied - which map and scale interpolation do produce - are
+ * exactly the case where that overflow happens.
+ *
+ * What made the packed form slow was the byte splats. Replicating a mask
+ * byte across its pixel's four channels cost two widenings and a 32 bit
+ * multiply by 0x01010101 per four pixels, and extracting the source alpha
+ * cost another shift and multiply. Both are a single table lookup with a
+ * constant index vector.
+ *
+ * Neither of the C reference's special cases is needed for correctness,
+ * they are only shortcuts: a mask of 0 gives sm = 0 and 255 - sm_a = 255,
+ * so the result is (d * 256) >> 8, which is d. Wholly transparent blocks
+ * are still skipped because that is free and masks are commonly sparse.
+ *
+ * The C side maps p, pas and pan to one kernel, so do the same here rather
+ * than carrying two near identical copies. */
+ static const uint8_t splat_idx[4][16] = {
+ { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 },
+ { 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7 },
+ { 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11 },
+ { 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15 }
+ };
+ static const uint8_t alpha_idx[16] =
+ { 3, 3, 3, 3, 7, 7, 7, 7, 11, 11, 11, 11, 15, 15, 15, 15 };
+ const uint8x16_t aidx = vld1q_u8(alpha_idx);
+ const uint16x8_t x255 = vdupq_n_u16(0xff);
+ DATA32 *start = d;
+ int size = l;
+ DATA32 *end = start + (size & ~15);
+
+ while (start < end)
+ {
+ uint8x16_t m16 = vld1q_u8(m);
+ int j;
+
+ if (vmaxvq_u8(m16) == 0)
+ {
+ m += 16;
+ s += 16;
+ start += 16;
+ continue;
+ }
+
+ for (j = 0; j < 4; j++)
+ {
+ uint8x16_t s8 = vreinterpretq_u8_u32(vld1q_u32(s + (j * 4)));
+ uint8x16_t d8 = vreinterpretq_u8_u32(vld1q_u32(start + (j * 4)));
+ uint8x16_t m8 = vqtbl1q_u8(m16, vld1q_u8(splat_idx[j]));
+ uint8x16_t sm, nsma, term;
+ uint16x8_t lo, hi;
+
+ lo = vmlal_u8(x255, vget_low_u8(s8), vget_low_u8(m8));
+ hi = vmlal_u8(x255, vget_high_u8(s8), vget_high_u8(m8));
+ sm = vcombine_u8(vshrn_n_u16(lo, 8), vshrn_n_u16(hi, 8));
+
+ nsma = vmvnq_u8(vqtbl1q_u8(sm, aidx));
+
+ lo = vmull_u8(vget_low_u8(d8), vget_low_u8(nsma));
+ hi = vmull_u8(vget_high_u8(d8), vget_high_u8(nsma));
+ lo = vaddw_u8(lo, vget_low_u8(d8));
+ hi = vaddw_u8(hi, vget_high_u8(d8));
+ term = vcombine_u8(vshrn_n_u16(lo, 8), vshrn_n_u16(hi, 8));
+
+ /* 32 bit add, so channel overflow carries exactly as it does in
+ * the C reference */
+ vst1q_u32(start + (j * 4),
+ vaddq_u32(vreinterpretq_u32_u8(sm),
+ vreinterpretq_u32_u8(term)));
+ }
+
+ m += 16;
+ s += 16;
+ start += 16;
+ }
+
+ end += (size & 15);
+ while (start < end) {
+ DATA32 sm = MUL_SYM(*m, *s);
+ DATA32 alpha = 256 - (sm >> 24);
+
+ *start = sm + MUL_256(alpha, *start);
+ m++; s++; start++;
+ }
+}
+
+#define _op_blend_pas_mas_dp_neon _op_blend_p_mas_dp_neon
+#define _op_blend_pan_mas_dp_neon _op_blend_p_mas_dp_neon
+#else
static void
_op_blend_pas_mas_dp_neon(DATA32 *s, DATA8 *m, DATA32 c EINA_UNUSED, DATA32 *d, int l) {
uint16x8_t m_16x8;
@@ -347,6 +452,7 @@ _op_blend_p_mas_dp_neon(DATA32 *s, DATA8 *m, DATA32 c EINA_UNUSED, DATA32 *d, in
}
#define _op_blend_pan_mas_dp_neon _op_blend_pas_mas_dp_neon
+#endif
#define _op_blend_p_mas_dpan_neon _op_blend_p_mas_dp_neon
#define _op_blend_pan_mas_dpan_neon _op_blend_pan_mas_dp_neon
diff --git a/src/lib/evas/common/evas_op_copy/op_copy_color_neon.c b/src/lib/evas/common/evas_op_copy/op_copy_color_neon.c
index 0eedafc7fe..d2d5e5cccd 100644
--- a/src/lib/evas/common/evas_op_copy/op_copy_color_neon.c
+++ b/src/lib/evas/common/evas_op_copy/op_copy_color_neon.c
@@ -84,18 +84,7 @@ init_copy_color_pt_funcs_neon(void)
/* copy_rel color --> dst */
#ifdef BUILD_NEON
-static void
-_op_copy_rel_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m EINA_UNUSED, DATA32 c, DATA32 *d, int l) {
- // FIXME: neon-it
- DATA32 *e = d + l;
- for (; d < e; d++) {
- *d = MUL_SYM(*d >> 24, c);
- }
-}
-#define _op_copy_rel_cn_dp_neon _op_copy_rel_c_dp_neon
-#define _op_copy_rel_can_dp_neon _op_copy_rel_c_dp_neon
-#define _op_copy_rel_caa_dp_neon _op_copy_rel_c_dp_neon
#define _op_copy_rel_cn_dpan_neon _op_copy_cn_dpan_neon
#define _op_copy_rel_c_dpan_neon _op_copy_c_dpan_neon
@@ -105,10 +94,6 @@ _op_copy_rel_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m EINA_UNUSED, DATA32 c, DA
static void
init_copy_rel_color_span_funcs_neon(void)
{
- op_copy_rel_span_funcs[SP_N][SM_N][SC_N][DP][CPU_NEON] = _op_copy_rel_cn_dp_neon;
- op_copy_rel_span_funcs[SP_N][SM_N][SC][DP][CPU_NEON] = _op_copy_rel_c_dp_neon;
- op_copy_rel_span_funcs[SP_N][SM_N][SC_AN][DP][CPU_NEON] = _op_copy_rel_can_dp_neon;
- op_copy_rel_span_funcs[SP_N][SM_N][SC_AA][DP][CPU_NEON] = _op_copy_rel_caa_dp_neon;
op_copy_rel_span_funcs[SP_N][SM_N][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_cn_dpan_neon;
op_copy_rel_span_funcs[SP_N][SM_N][SC][DP_AN][CPU_NEON] = _op_copy_rel_c_dpan_neon;
@@ -118,17 +103,8 @@ init_copy_rel_color_span_funcs_neon(void)
#endif
#ifdef BUILD_NEON
-static void
-_op_copy_rel_pt_c_dp_neon(DATA32 s, DATA8 m EINA_UNUSED, DATA32 c, DATA32 *d) {
- s = 1 + (*d >> 24);
- *d = MUL_256(s, c);
-}
-#define _op_copy_rel_pt_cn_dp_neon _op_copy_rel_pt_c_dp_neon
-#define _op_copy_rel_pt_can_dp_neon _op_copy_rel_pt_c_dp_neon
-#define _op_copy_rel_pt_caa_dp_neon _op_copy_rel_pt_c_dp_neon
-
#define _op_copy_rel_pt_cn_dpan_neon _op_copy_pt_cn_dpan_neon
#define _op_copy_rel_pt_c_dpan_neon _op_copy_pt_c_dpan_neon
#define _op_copy_rel_pt_can_dpan_neon _op_copy_pt_can_dpan_neon
@@ -137,10 +113,6 @@ _op_copy_rel_pt_c_dp_neon(DATA32 s, DATA8 m EINA_UNUSED, DATA32 c, DATA32 *d) {
static void
init_copy_rel_color_pt_funcs_neon(void)
{
- op_copy_rel_pt_funcs[SP_N][SM_N][SC_N][DP][CPU_NEON] = _op_copy_rel_pt_cn_dp_neon;
- op_copy_rel_pt_funcs[SP_N][SM_N][SC][DP][CPU_NEON] = _op_copy_rel_pt_c_dp_neon;
- op_copy_rel_pt_funcs[SP_N][SM_N][SC_AN][DP][CPU_NEON] = _op_copy_rel_pt_can_dp_neon;
- op_copy_rel_pt_funcs[SP_N][SM_N][SC_AA][DP][CPU_NEON] = _op_copy_rel_pt_caa_dp_neon;
op_copy_rel_pt_funcs[SP_N][SM_N][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_pt_cn_dpan_neon;
op_copy_rel_pt_funcs[SP_N][SM_N][SC][DP_AN][CPU_NEON] = _op_copy_rel_pt_c_dpan_neon;
diff --git a/src/lib/evas/common/evas_op_copy/op_copy_mask_color_neon.c b/src/lib/evas/common/evas_op_copy/op_copy_mask_color_neon.c
index ad67d8c536..96b90667fd 100644
--- a/src/lib/evas/common/evas_op_copy/op_copy_mask_color_neon.c
+++ b/src/lib/evas/common/evas_op_copy/op_copy_mask_color_neon.c
@@ -1,6 +1,82 @@
+#ifdef BUILD_NEON
+#include <arm_neon.h>
+#endif
+
/* copy mask x color -> dst */
#ifdef BUILD_NEON
+#ifdef BUILD_NEON_INTRINSICS
+/* The AArch64 path below uses tbl and the across-vector reduce, neither of
+ * which exists in 32 bit NEON. Keep the original kernel for ARMv7 rather
+ * than adding a second version that cannot be tested here. */
+static void
+_op_copy_mas_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m, DATA32 c, DATA32 *d, int l) {
+ /* d = MUL_256(m + 1, c), which per channel is (c * (m + 1)) >> 8.
+ *
+ * All three of the C reference's cases fall out of that one _expression_, so
+ * no branching or lane selection is needed: m = 0 gives (c * 1) >> 8, and
+ * every channel of c is below 256, so that is 0; m = 255 gives
+ * (c * 256) >> 8, which is c.
+ *
+ * There is no destination read and no inter-channel carry to preserve
+ * either - MUL_256 masks each channel and its two halves live in disjoint
+ * bits - so this is just a multiply and a narrowing shift per pixel. The
+ * only awkward part is replicating each mask byte across its pixel's four
+ * channels, and that is one tbl against a constant index vector. */
+ static const uint8_t splat_idx[4][16] = {
+ { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 },
+ { 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7 },
+ { 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11 },
+ { 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15 }
+ };
+ const uint8x16_t c8 = vreinterpretq_u8_u32(vdupq_n_u32(c));
+ const uint16x8_t clo = vmovl_u8(vget_low_u8(c8));
+ const uint16x8_t chi = vmovl_u8(vget_high_u8(c8));
+ DATA32 *start = d;
+ int size = l;
+ DATA32 *end = start + (size & ~15);
+
+ while (start < end)
+ {
+ uint8x16_t m16 = vld1q_u8(m);
+ int j;
+
+ for (j = 0; j < 4; j++)
+ {
+ uint8x16_t m8 = vqtbl1q_u8(m16, vld1q_u8(splat_idx[j]));
+ /* c * m + c == c * (m + 1) */
+ uint16x8_t lo = vmlal_u8(clo, vget_low_u8(c8), vget_low_u8(m8));
+ uint16x8_t hi = vmlal_u8(chi, vget_high_u8(c8), vget_high_u8(m8));
+
+ vst1q_u8((uint8_t *)(start + (j * 4)),
+ vcombine_u8(vshrn_n_u16(lo, 8), vshrn_n_u16(hi, 8)));
+ }
+
+ m += 16;
+ start += 16;
+ }
+
+ end += (size & 15);
+ while (start < end) {
+ DATA32 alpha = *m;
+
+ switch (alpha)
+ {
+ case 0:
+ *start = 0;
+ break;
+ case 255:
+ *start = c;
+ break;
+ default:
+ alpha++;
+ *start = MUL_256(alpha, c);
+ break;
+ }
+ m++; start++;
+ }
+}
+#else
static void
_op_copy_mas_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m, DATA32 c, DATA32 *d, int l) {
// FIXME: neon-it
@@ -26,6 +102,7 @@ _op_copy_mas_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m, DATA32 c, DATA32 *d, int
m++; d++;
});
}
+#endif
#define _op_copy_mas_cn_dp_neon _op_copy_mas_c_dp_neon
#define _op_copy_mas_can_dp_neon _op_copy_mas_c_dp_neon
@@ -86,40 +163,7 @@ init_copy_mask_color_pt_funcs_neon(void)
/* copy_rel mask x color -> dst */
#ifdef BUILD_NEON
-static void
-_op_copy_rel_mas_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m, DATA32 c, DATA32 *d, int l) {
- /* FIXME: THIS FUNCTION HAS PROBABLY NEVER BEEN TESTED */
- // FIXME: neon-it
- DATA32 *e;
- int color;
- UNROLL8_PLD_WHILE(d, l, e,
- {
- color = *m;
- switch(color)
- {
- case 0:
- *d = 0;
- break;
- case 255:
- color = 1 + (*d >> 24);
- *d = MUL_256(color, c);
- break;
- default:
- {
- DATA32 da = 1 + (*d >> 24);
- da = MUL_256(da, c);
- color++;
- *d = INTERP_256(color, da, *d);
- }
- break;
- }
- m++; d++;
- });
-}
-#define _op_copy_rel_mas_cn_dp_neon _op_copy_rel_mas_c_dp_neon
-#define _op_copy_rel_mas_can_dp_neon _op_copy_rel_mas_c_dp_neon
-#define _op_copy_rel_mas_caa_dp_neon _op_copy_rel_mas_c_dp_neon
#define _op_copy_rel_mas_c_dpan_neon _op_copy_mas_c_dpan_neon
#define _op_copy_rel_mas_cn_dpan_neon _op_copy_mas_cn_dpan_neon
@@ -129,10 +173,6 @@ _op_copy_rel_mas_c_dp_neon(DATA32 *s EINA_UNUSED, DATA8 *m, DATA32 c, DATA32 *d,
static void
init_copy_rel_mask_color_span_funcs_neon(void)
{
- op_copy_rel_span_funcs[SP_N][SM_AS][SC_N][DP][CPU_NEON] = _op_copy_rel_mas_cn_dp_neon;
- op_copy_rel_span_funcs[SP_N][SM_AS][SC][DP][CPU_NEON] = _op_copy_rel_mas_c_dp_neon;
- op_copy_rel_span_funcs[SP_N][SM_AS][SC_AN][DP][CPU_NEON] = _op_copy_rel_mas_can_dp_neon;
- op_copy_rel_span_funcs[SP_N][SM_AS][SC_AA][DP][CPU_NEON] = _op_copy_rel_mas_caa_dp_neon;
op_copy_rel_span_funcs[SP_N][SM_AS][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_mas_cn_dpan_neon;
op_copy_rel_span_funcs[SP_N][SM_AS][SC][DP_AN][CPU_NEON] = _op_copy_rel_mas_c_dpan_neon;
@@ -142,17 +182,7 @@ init_copy_rel_mask_color_span_funcs_neon(void)
#endif
#ifdef BUILD_NEON
-static void
-_op_copy_rel_pt_mas_c_dp_neon(DATA32 s, DATA8 m, DATA32 c, DATA32 *d) {
- /* FIXME: THIS FUNCTION HAS PROBABLY NEVER BEEN TESTED */
- s = 1 + (*d >> 24);
- s = MUL_256(s, c);
- *d = INTERP_256(m + 1, s, *d);
-}
-#define _op_copy_rel_pt_mas_cn_dp_neon _op_copy_rel_pt_mas_c_dp_neon
-#define _op_copy_rel_pt_mas_can_dp_neon _op_copy_rel_pt_mas_c_dp_neon
-#define _op_copy_rel_pt_mas_caa_dp_neon _op_copy_rel_pt_mas_c_dp_neon
#define _op_copy_rel_pt_mas_c_dpan_neon _op_copy_pt_mas_c_dpan_neon
#define _op_copy_rel_pt_mas_cn_dpan_neon _op_copy_pt_mas_cn_dpan_neon
@@ -162,10 +192,6 @@ _op_copy_rel_pt_mas_c_dp_neon(DATA32 s, DATA8 m, DATA32 c, DATA32 *d) {
static void
init_copy_rel_mask_color_pt_funcs_neon(void)
{
- op_copy_rel_pt_funcs[SP_N][SM_AS][SC_N][DP][CPU_NEON] = _op_copy_rel_pt_mas_cn_dp_neon;
- op_copy_rel_pt_funcs[SP_N][SM_AS][SC][DP][CPU_NEON] = _op_copy_rel_pt_mas_c_dp_neon;
- op_copy_rel_pt_funcs[SP_N][SM_AS][SC_AN][DP][CPU_NEON] = _op_copy_rel_pt_mas_can_dp_neon;
- op_copy_rel_pt_funcs[SP_N][SM_AS][SC_AA][DP][CPU_NEON] = _op_copy_rel_pt_mas_caa_dp_neon;
op_copy_rel_pt_funcs[SP_N][SM_AS][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_pt_mas_cn_dpan_neon;
op_copy_rel_pt_funcs[SP_N][SM_AS][SC][DP_AN][CPU_NEON] = _op_copy_rel_pt_mas_c_dpan_neon;
diff --git a/src/lib/evas/common/evas_op_copy/op_copy_pixel_color_neon.c b/src/lib/evas/common/evas_op_copy/op_copy_pixel_color_neon.c
index cccfe441e0..0b78c71ef8 100644
--- a/src/lib/evas/common/evas_op_copy/op_copy_pixel_color_neon.c
+++ b/src/lib/evas/common/evas_op_copy/op_copy_pixel_color_neon.c
@@ -126,29 +126,8 @@ init_copy_pixel_color_pt_funcs_neon(void)
/* copy_rel pixel x color --> dst */
#ifdef BUILD_NEON
-static void
-_op_copy_rel_p_c_dp_neon(DATA32 *s, DATA8 *m EINA_UNUSED, DATA32 c, DATA32 *d, int l) {
- // FIXME: neon-it
- DATA32 *e;
- UNROLL8_PLD_WHILE(d, l, e,
- {
- DATA32 cs = MUL4_SYM(c, *s);
- *d = MUL_SYM(*d >> 24, cs);
- d++;
- s++;
- });
-}
-#define _op_copy_rel_pas_c_dp_neon _op_copy_rel_p_c_dp_neon
-#define _op_copy_rel_pan_c_dp_neon _op_copy_rel_p_c_dp_neon
-#define _op_copy_rel_p_can_dp_neon _op_copy_rel_p_c_dp_neon
-#define _op_copy_rel_pas_can_dp_neon _op_copy_rel_p_c_dp_neon
-#define _op_copy_rel_pan_can_dp_neon _op_copy_rel_p_c_dp_neon
-#define _op_copy_rel_p_caa_dp_neon _op_copy_rel_p_c_dp_neon
-#define _op_copy_rel_pas_caa_dp_neon _op_copy_rel_p_c_dp_neon
-#define _op_copy_rel_pan_caa_dp_neon _op_copy_rel_p_c_dp_neon
-
#define _op_copy_rel_p_c_dpan_neon _op_copy_p_c_dpan_neon
#define _op_copy_rel_pas_c_dpan_neon _op_copy_pas_c_dpan_neon
#define _op_copy_rel_pan_c_dpan_neon _op_copy_pan_c_dpan_neon
@@ -162,15 +141,6 @@ _op_copy_rel_p_c_dp_neon(DATA32 *s, DATA8 *m EINA_UNUSED, DATA32 c, DATA32 *d, i
static void
init_copy_rel_pixel_color_span_funcs_neon(void)
{
- op_copy_rel_span_funcs[SP][SM_N][SC][DP][CPU_NEON] = _op_copy_rel_p_c_dp_neon;
- op_copy_rel_span_funcs[SP_AS][SM_N][SC][DP][CPU_NEON] = _op_copy_rel_pas_c_dp_neon;
- op_copy_rel_span_funcs[SP_AN][SM_N][SC][DP][CPU_NEON] = _op_copy_rel_pan_c_dp_neon;
- op_copy_rel_span_funcs[SP][SM_N][SC_AN][DP][CPU_NEON] = _op_copy_rel_p_can_dp_neon;
- op_copy_rel_span_funcs[SP_AS][SM_N][SC_AN][DP][CPU_NEON] = _op_copy_rel_pas_can_dp_neon;
- op_copy_rel_span_funcs[SP_AN][SM_N][SC_AN][DP][CPU_NEON] = _op_copy_rel_pan_can_dp_neon;
- op_copy_rel_span_funcs[SP][SM_N][SC_AA][DP][CPU_NEON] = _op_copy_rel_p_caa_dp_neon;
- op_copy_rel_span_funcs[SP_AS][SM_N][SC_AA][DP][CPU_NEON] = _op_copy_rel_pas_caa_dp_neon;
- op_copy_rel_span_funcs[SP_AN][SM_N][SC_AA][DP][CPU_NEON] = _op_copy_rel_pan_caa_dp_neon;
op_copy_rel_span_funcs[SP][SM_N][SC][DP_AN][CPU_NEON] = _op_copy_rel_p_c_dpan_neon;
op_copy_rel_span_funcs[SP_AS][SM_N][SC][DP_AN][CPU_NEON] = _op_copy_rel_pas_c_dpan_neon;
@@ -185,22 +155,8 @@ init_copy_rel_pixel_color_span_funcs_neon(void)
#endif
#ifdef BUILD_NEON
-static void
-_op_copy_rel_pt_p_c_dp_neon(DATA32 s, DATA8 m EINA_UNUSED, DATA32 c, DATA32 *d) {
- s = MUL4_SYM(c, s);
- *d = MUL_SYM(*d >> 24, s);
-}
-#define _op_copy_rel_pt_pas_c_dp_neon _op_copy_rel_pt_p_c_dp_neon
-#define _op_copy_rel_pt_pan_c_dp_neon _op_copy_rel_pt_p_c_dp_neon
-#define _op_copy_rel_pt_p_can_dp_neon _op_copy_rel_pt_p_c_dp_neon
-#define _op_copy_rel_pt_pas_can_dp_neon _op_copy_rel_pt_p_c_dp_neon
-#define _op_copy_rel_pt_pan_can_dp_neon _op_copy_rel_pt_p_c_dp_neon
-#define _op_copy_rel_pt_p_caa_dp_neon _op_copy_rel_pt_p_c_dp_neon
-#define _op_copy_rel_pt_pas_caa_dp_neon _op_copy_rel_pt_p_c_dp_neon
-#define _op_copy_rel_pt_pan_caa_dp_neon _op_copy_rel_pt_p_c_dp_neon
-
#define _op_copy_rel_pt_p_c_dpan_neon _op_copy_pt_p_c_dpan_neon
#define _op_copy_rel_pt_pas_c_dpan_neon _op_copy_pt_pas_c_dpan_neon
#define _op_copy_rel_pt_pan_c_dpan_neon _op_copy_pt_pan_c_dpan_neon
@@ -215,15 +171,6 @@ _op_copy_rel_pt_p_c_dp_neon(DATA32 s, DATA8 m EINA_UNUSED, DATA32 c, DATA32 *d)
static void
init_copy_rel_pixel_color_pt_funcs_neon(void)
{
- op_copy_rel_pt_funcs[SP][SM_N][SC][DP][CPU_NEON] = _op_copy_rel_pt_p_c_dp_neon;
- op_copy_rel_pt_funcs[SP_AS][SM_N][SC][DP][CPU_NEON] = _op_copy_rel_pt_pas_c_dp_neon;
- op_copy_rel_pt_funcs[SP_AN][SM_N][SC][DP][CPU_NEON] = _op_copy_rel_pt_pan_c_dp_neon;
- op_copy_rel_pt_funcs[SP][SM_N][SC_AN][DP][CPU_NEON] = _op_copy_rel_pt_p_can_dp_neon;
- op_copy_rel_pt_funcs[SP_AS][SM_N][SC_AN][DP][CPU_NEON] = _op_copy_rel_pt_pas_can_dp_neon;
- op_copy_rel_pt_funcs[SP_AN][SM_N][SC_AN][DP][CPU_NEON] = _op_copy_rel_pt_pan_can_dp_neon;
- op_copy_rel_pt_funcs[SP][SM_N][SC_AA][DP][CPU_NEON] = _op_copy_rel_pt_p_caa_dp_neon;
- op_copy_rel_pt_funcs[SP_AS][SM_N][SC_AA][DP][CPU_NEON] = _op_copy_rel_pt_pas_caa_dp_neon;
- op_copy_rel_pt_funcs[SP_AN][SM_N][SC_AA][DP][CPU_NEON] = _op_copy_rel_pt_pan_caa_dp_neon;
op_copy_rel_pt_funcs[SP][SM_N][SC][DP_AN][CPU_NEON] = _op_copy_rel_pt_p_c_dpan_neon;
op_copy_rel_pt_funcs[SP_AS][SM_N][SC][DP_AN][CPU_NEON] = _op_copy_rel_pt_pas_c_dpan_neon;
diff --git a/src/lib/evas/common/evas_op_copy/op_copy_pixel_mask_neon.c b/src/lib/evas/common/evas_op_copy/op_copy_pixel_mask_neon.c
index 38bf35b5c7..b40c21054b 100644
--- a/src/lib/evas/common/evas_op_copy/op_copy_pixel_mask_neon.c
+++ b/src/lib/evas/common/evas_op_copy/op_copy_pixel_mask_neon.c
@@ -76,33 +76,7 @@ init_copy_pixel_mask_pt_funcs_neon(void)
/* copy_rel pixel x mask --> dst */
#ifdef BUILD_NEON
-static void
-_op_copy_rel_p_mas_dp_neon(DATA32 *s, DATA8 *m, DATA32 c EINA_UNUSED, DATA32 *d, int l) {
- // FIXME: neon-it
- DATA32 *e;
- int color;
- UNROLL8_PLD_WHILE(d, l, e,
- {
- color = *m;
- switch(color)
- {
- case 0:
- break;
- case 255:
- *d = MUL_SYM(*d >> 24, *s);
- break;
- default:
- c = MUL_SYM(*d >> 24, *s);
- color++;
- *d = INTERP_256(color, c, *d);
- break;
- }
- m++; s++; d++;
- });
-}
-#define _op_copy_rel_pan_mas_dp_neon _op_copy_rel_p_mas_dp_neon
-#define _op_copy_rel_pas_mas_dp_neon _op_copy_rel_p_mas_dp_neon
#define _op_copy_rel_p_mas_dpan_neon _op_copy_p_mas_dpan_neon
#define _op_copy_rel_pan_mas_dpan_neon _op_copy_pan_mas_dpan_neon
@@ -111,9 +85,6 @@ _op_copy_rel_p_mas_dp_neon(DATA32 *s, DATA8 *m, DATA32 c EINA_UNUSED, DATA32 *d,
static void
init_copy_rel_pixel_mask_span_funcs_neon(void)
{
- op_copy_rel_span_funcs[SP][SM_AS][SC_N][DP][CPU_NEON] = _op_copy_rel_p_mas_dp_neon;
- op_copy_rel_span_funcs[SP_AN][SM_AS][SC_N][DP][CPU_NEON] = _op_copy_rel_pan_mas_dp_neon;
- op_copy_rel_span_funcs[SP_AS][SM_AS][SC_N][DP][CPU_NEON] = _op_copy_rel_pas_mas_dp_neon;
op_copy_rel_span_funcs[SP][SM_AS][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_p_mas_dpan_neon;
op_copy_rel_span_funcs[SP_AN][SM_AS][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_pan_mas_dpan_neon;
@@ -122,16 +93,8 @@ init_copy_rel_pixel_mask_span_funcs_neon(void)
#endif
#ifdef BUILD_NEON
-static void
-_op_copy_rel_pt_p_mas_dp_neon(DATA32 s, DATA8 m, DATA32 c, DATA32 *d) {
- c = MUL_SYM(*d >> 24, s);
- *d = INTERP_256(m + 1, c, *d);
-}
-#define _op_copy_rel_pt_pan_mas_dp_neon _op_copy_rel_pt_p_mas_dp_neon
-#define _op_copy_rel_pt_pas_mas_dp_neon _op_copy_rel_pt_p_mas_dp_neon
-
#define _op_copy_rel_pt_p_mas_dpan_neon _op_copy_pt_p_mas_dpan_neon
#define _op_copy_rel_pt_pan_mas_dpan_neon _op_copy_pt_pan_mas_dpan_neon
#define _op_copy_rel_pt_pas_mas_dpan_neon _op_copy_pt_pas_mas_dpan_neon
@@ -139,9 +102,6 @@ _op_copy_rel_pt_p_mas_dp_neon(DATA32 s, DATA8 m, DATA32 c, DATA32 *d) {
static void
init_copy_rel_pixel_mask_pt_funcs_neon(void)
{
- op_copy_rel_pt_funcs[SP][SM_AS][SC_N][DP][CPU_NEON] = _op_copy_rel_pt_p_mas_dp_neon;
- op_copy_rel_pt_funcs[SP_AN][SM_AS][SC_N][DP][CPU_NEON] = _op_copy_rel_pt_pan_mas_dp_neon;
- op_copy_rel_pt_funcs[SP_AS][SM_AS][SC_N][DP][CPU_NEON] = _op_copy_rel_pt_pas_mas_dp_neon;
op_copy_rel_pt_funcs[SP][SM_AS][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_pt_p_mas_dpan_neon;
op_copy_rel_pt_funcs[SP_AN][SM_AS][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_pt_pan_mas_dpan_neon;
diff --git a/src/lib/evas/common/evas_op_copy/op_copy_pixel_neon.c b/src/lib/evas/common/evas_op_copy/op_copy_pixel_neon.c
index fdf9d2aac3..142bd50d08 100644
--- a/src/lib/evas/common/evas_op_copy/op_copy_pixel_neon.c
+++ b/src/lib/evas/common/evas_op_copy/op_copy_pixel_neon.c
@@ -97,21 +97,8 @@ init_copy_pixel_pt_funcs_neon(void)
/* copy_rel pixel --> dst */
#ifdef BUILD_NEON
-static void
-_op_copy_rel_p_dp_neon(DATA32 *s, DATA8 *m EINA_UNUSED, DATA32 c EINA_UNUSED, DATA32 *d, int l) {
- // FIXME: neon-it
- DATA32 *e;
- UNROLL8_PLD_WHILE(d, l, e,
- {
- *d = MUL_SYM(*d >> 24, *s);
- d++; s++;
- });
-}
-#define _op_copy_rel_pas_dp_neon _op_copy_rel_p_dp_neon
-#define _op_copy_rel_pan_dp_neon _op_copy_rel_p_dp_neon
-
#define _op_copy_rel_p_dpan_neon _op_copy_p_dpan_neon
#define _op_copy_rel_pan_dpan_neon _op_copy_pan_dpan_neon
#define _op_copy_rel_pas_dpan_neon _op_copy_pas_dpan_neon
@@ -119,9 +106,6 @@ _op_copy_rel_p_dp_neon(DATA32 *s, DATA8 *m EINA_UNUSED, DATA32 c EINA_UNUSED, DA
static void
init_copy_rel_pixel_span_funcs_neon(void)
{
- op_copy_rel_span_funcs[SP][SM_N][SC_N][DP][CPU_NEON] = _op_copy_rel_p_dp_neon;
- op_copy_rel_span_funcs[SP_AN][SM_N][SC_N][DP][CPU_NEON] = _op_copy_rel_pan_dp_neon;
- op_copy_rel_span_funcs[SP_AS][SM_N][SC_N][DP][CPU_NEON] = _op_copy_rel_pas_dp_neon;
op_copy_rel_span_funcs[SP][SM_N][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_p_dpan_neon;
op_copy_rel_span_funcs[SP_AN][SM_N][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_pan_dpan_neon;
@@ -130,16 +114,8 @@ init_copy_rel_pixel_span_funcs_neon(void)
#endif
#ifdef BUILD_NEON
-static void
-_op_copy_rel_pt_p_dp_neon(DATA32 s, DATA8 m EINA_UNUSED, DATA32 c, DATA32 *d) {
- c = 1 + (*d >> 24);
- *d = MUL_256(c, s);
-}
-#define _op_copy_rel_pt_pan_dp_neon _op_copy_rel_pt_p_dp_neon
-#define _op_copy_rel_pt_pas_dp_neon _op_copy_rel_pt_p_dp_neon
-
#define _op_copy_rel_pt_p_dpan_neon _op_copy_pt_p_dpan_neon
#define _op_copy_rel_pt_pan_dpan_neon _op_copy_pt_pan_dpan_neon
#define _op_copy_rel_pt_pas_dpan_neon _op_copy_pt_pas_dpan_neon
@@ -147,9 +123,6 @@ _op_copy_rel_pt_p_dp_neon(DATA32 s, DATA8 m EINA_UNUSED, DATA32 c, DATA32 *d) {
static void
init_copy_rel_pixel_pt_funcs_neon(void)
{
- op_copy_rel_pt_funcs[SP][SM_N][SC_N][DP][CPU_NEON] = _op_copy_rel_pt_p_dp_neon;
- op_copy_rel_pt_funcs[SP_AN][SM_N][SC_N][DP][CPU_NEON] = _op_copy_rel_pt_pan_dp_neon;
- op_copy_rel_pt_funcs[SP_AS][SM_N][SC_N][DP][CPU_NEON] = _op_copy_rel_pt_pas_dp_neon;
op_copy_rel_pt_funcs[SP][SM_N][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_pt_p_dpan_neon;
op_copy_rel_pt_funcs[SP_AN][SM_N][SC_N][DP_AN][CPU_NEON] = _op_copy_rel_pt_pan_dpan_neon;
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.