Commit 429133adf3 for ffmpeg

commit 429133adf34fa7fb9e1c762c80f01865f78f8539
Author: Ramiro Polla <ramiro.polla@gmail.com>
Date:   Mon Nov 9 17:11:17 2026 +0100

    swscale/aarch64: implement SWS_UOP_ADD

    Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>

diff --git a/libswscale/aarch64/ops.c b/libswscale/aarch64/ops.c
index d479eaa4f8..b35882c854 100644
--- a/libswscale/aarch64/ops.c
+++ b/libswscale/aarch64/ops.c
@@ -137,6 +137,7 @@ static int aarch64_setup(const SwsUOp *uop, const SwsAArch64OpImplParams *p,
         break;
     }
     case SWS_UOP_CLEAR:
+    case SWS_UOP_ADD:
     case SWS_UOP_MIN:
     case SWS_UOP_MAX: {
         int ret = ff_sws_setup_vec4(&(const SwsImplParams) { .uop = uop }, out);
@@ -233,7 +234,7 @@ static int compile_ops_aarch64(SwsContext *ctx, const SwsOpList *ops,
     if (!uops)
         return AVERROR(ENOMEM);

-    SwsUOpFlags flags = SWS_UOP_FLAG_PUNNING;
+    SwsUOpFlags flags = SWS_UOP_FLAG_PUNNING | SWS_UOP_FLAG_ADD;
     if (!(ctx->flags & SWS_BITEXACT))
         flags |= SWS_UOP_FLAG_FMA;
     int ret = ff_sws_ops_translate(ctx, ops, flags, uops);
diff --git a/libswscale/aarch64/ops_asmgen.c b/libswscale/aarch64/ops_asmgen.c
index f698915b61..ffd5e8cbad 100644
--- a/libswscale/aarch64/ops_asmgen.c
+++ b/libswscale/aarch64/ops_asmgen.c
@@ -753,6 +753,25 @@ static void asmgen_op_expand(SwsAArch64Context *s, const SwsAArch64OpImplParams
     }
 }

+/*********************************************************************/
+/* SWS_UOP_ADD: add vec4 to masked components */
+
+static void asmgen_op_add(SwsAArch64Context *s, const SwsAArch64OpImplParams *p,
+                          SwsAArch64OpRegs *regs)
+{
+    RasmContext *r = s->rctx;
+    RasmOp *sl = regs->sl;
+    RasmOp *sh = regs->sh;
+    RasmOp *dl = regs->dl;
+    RasmOp *dh = regs->dh;
+    RasmOp *vk = regs->vk;
+
+    av_assert0(p->type == SWS_PIXEL_F32);
+
+    LOOP_MASK      (p, i) { i_fadd(r, dl[i], sl[i], vk[i]);         CMTF("vl[%u] += vadd%u;", i, i); }
+    LOOP_MASK_VH(s, p, i) { i_fadd(r, dh[i], sh[i], vk[i]);         CMTF("vh[%u] += vadd%u;", i, i); }
+}
+
 /*********************************************************************/
 /* SWS_UOP_MIN: min(x, vec4) on masked components */

diff --git a/libswscale/aarch64/ops_impl.h b/libswscale/aarch64/ops_impl.h
index 10447638b3..7a6b2370a6 100644
--- a/libswscale/aarch64/ops_impl.h
+++ b/libswscale/aarch64/ops_impl.h
@@ -92,6 +92,7 @@ static inline int aarch64_priv_size(const SwsAArch64OpImplParams *params)
     case SWS_UOP_READ_BIT:
     case SWS_UOP_WRITE_BIT:
     case SWS_UOP_CLEAR:
+    case SWS_UOP_ADD:
     case SWS_UOP_MIN:
     case SWS_UOP_MAX:
         return 16; /* one full vector register */
diff --git a/libswscale/aarch64/ops_static.c b/libswscale/aarch64/ops_static.c
index 52af60ee08..7dbaff726d 100644
--- a/libswscale/aarch64/ops_static.c
+++ b/libswscale/aarch64/ops_static.c
@@ -246,6 +246,18 @@ static void asmgen_setup_clear(SwsAArch64Context *s, const SwsAArch64OpImplParam
     }
 }

+static void asmgen_setup_add(SwsAArch64Context *s, const SwsAArch64OpImplParams *p,
+                             SwsAArch64OpRegs *regs)
+{
+    RasmContext *r = s->rctx;
+    RasmOp *vk = regs->vk;
+
+    RasmOp add_vec = regs->vt[0];
+    i_ldr(r, v_q(add_vec), IMPL_PRIV(s));                           CMT("v128 add_vec = impl->priv.v128;");
+    asmgen_set_load_cont_node(s);
+    LOOP_MASK(p, i) { i_dup(r, vk[i], a64op_elem(add_vec, i));      CMTF("v128 vadd%u = add_vec[%u];", i, i); }
+}
+
 static void asmgen_setup_min(SwsAArch64Context *s, const SwsAArch64OpImplParams *p,
                              SwsAArch64OpRegs *regs)
 {
@@ -584,6 +596,7 @@ static void asmgen_op_cps(SwsAArch64Context *s, const SwsAArch64OpEntry *entry)
     case SWS_UOP_WRITE_BIT:    asmgen_setup_write_bit(s, p, &s->regs);    break;
     case SWS_UOP_UNPACK:       asmgen_setup_unpack(s, p, &s->regs);       break;
     case SWS_UOP_CLEAR:        asmgen_setup_clear(s, p, &s->regs);        break;
+    case SWS_UOP_ADD:          asmgen_setup_add(s, p, &s->regs);          break;
     case SWS_UOP_MIN:          asmgen_setup_min(s, p, &s->regs);          break;
     case SWS_UOP_MAX:          asmgen_setup_max(s, p, &s->regs);          break;
     case SWS_UOP_SCALE:        asmgen_setup_scale(s, p, &s->regs);        break;
@@ -618,6 +631,7 @@ static void asmgen_op_cps(SwsAArch64Context *s, const SwsAArch64OpEntry *entry)
     case SWS_UOP_TO_F32:       asmgen_op_convert(s, p, &s->regs);      break;
     case SWS_UOP_EXPAND_PAIR:  asmgen_op_expand(s, p, &s->regs);       break;
     case SWS_UOP_EXPAND_QUAD:  asmgen_op_expand(s, p, &s->regs);       break;
+    case SWS_UOP_ADD:          asmgen_op_add(s, p, &s->regs);          break;
     case SWS_UOP_MIN:          asmgen_op_min(s, p, &s->regs);          break;
     case SWS_UOP_MAX:          asmgen_op_max(s, p, &s->regs);          break;
     case SWS_UOP_SCALE:        asmgen_op_scale(s, p, &s->regs);        break;
diff --git a/libswscale/tests/sws_ops_aarch64.c b/libswscale/tests/sws_ops_aarch64.c
index 3a56d71f59..97bc2c37e5 100644
--- a/libswscale/tests/sws_ops_aarch64.c
+++ b/libswscale/tests/sws_ops_aarch64.c
@@ -201,7 +201,7 @@ static int collect_ops_compile(SwsContext *ctx, const SwsOpList *ops,
     if (!uops)
         return AVERROR(ENOMEM);

-    SwsUOpFlags flags = SWS_UOP_FLAG_PUNNING;
+    SwsUOpFlags flags = SWS_UOP_FLAG_PUNNING | SWS_UOP_FLAG_ADD;
     if (!(ctx->flags & SWS_BITEXACT))
         flags |= SWS_UOP_FLAG_FMA;
     ret = ff_sws_ops_translate(ctx, ops, flags, uops);
@@ -298,6 +298,7 @@ static const char op_type_names[SWS_UOP_TYPE_NB][16] = {
     [SWS_UOP_TO_F32        ] = "to_f32",
     [SWS_UOP_EXPAND_PAIR   ] = "expand_pair",
     [SWS_UOP_EXPAND_QUAD   ] = "expand_quad",
+    [SWS_UOP_ADD           ] = "add",
     [SWS_UOP_MIN           ] = "min",
     [SWS_UOP_MAX           ] = "max",
     [SWS_UOP_SCALE         ] = "scale",
@@ -336,6 +337,7 @@ static const char uop_types[SWS_UOP_TYPE_NB][32] = {
     [SWS_UOP_TO_F32        ] = "SWS_UOP_TO_F32",
     [SWS_UOP_EXPAND_PAIR   ] = "SWS_UOP_EXPAND_PAIR",
     [SWS_UOP_EXPAND_QUAD   ] = "SWS_UOP_EXPAND_QUAD",
+    [SWS_UOP_ADD           ] = "SWS_UOP_ADD",
     [SWS_UOP_MIN           ] = "SWS_UOP_MIN",
     [SWS_UOP_MAX           ] = "SWS_UOP_MAX",
     [SWS_UOP_SCALE         ] = "SWS_UOP_SCALE",