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.

Reply via email to