Commit 6d5392e634 for ffmpeg

commit 6d5392e634f9fb3a15a7a616401a31e6b18acf0a
Author: Niklas Haas <git@haasn.dev>
Date:   Sun Sep 27 16:04:41 2026 +0200

    swscale/ops: add SwsPixelType to SwsClearOp

    Since SwsOp.type will be deprecated. This is an array, to make my life easier
    w.r.t. the LINEAR -> CLEAR promotion.

    Signed-off-by: Niklas Haas <git@haasn.dev>

diff --git a/libswscale/format.c b/libswscale/format.c
index a8988d00ba..7e653c5101 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -1058,16 +1058,22 @@ static SwsClearOp fmt_clear(const SwsFormat *fmt)
     const AVPixFmtDescriptor *desc = fmt_desc_decoded(fmt->format);
     const bool has_chroma = desc->nb_components >= 3;
     const bool has_alpha  = desc->flags & AV_PIX_FMT_FLAG_ALPHA;
+    const SwsPixelType type = fmt_pixel_type(desc);
+
+    SwsClearOp c = {
+        .mask = SWS_COMP_NONE,
+    };

-    SwsClearOp c = {0};
     if (!has_chroma) {
         c.mask |= SWS_COMP(1) | SWS_COMP(2);
         c.value[1] = c.value[2] = Q(0);
+        c.type[1] = c.type[2] = type;
     }

     if (!has_alpha) {
         c.mask |= SWS_COMP(3);
         c.value[3] = Q(0);
+        c.type[3] = type;
     }

     return c;
@@ -1200,6 +1206,7 @@ static int encode_pixfmt(SwsOpList *ops, const SwsFormat *fmt)
         RET(ff_sws_op_list_append(ops, &(SwsOp) {
             .op   = SWS_OP_CLEAR,
             .type = pixel_type,
+            .clear.type[3] = pixel_type,
             .clear.mask = SWS_COMP(3),
             .clear.value[3] = Q(0),
         }));
diff --git a/libswscale/ops.h b/libswscale/ops.h
index ec866f4914..8f5b8bbf9d 100644
--- a/libswscale/ops.h
+++ b/libswscale/ops.h
@@ -146,7 +146,8 @@ typedef struct SwsShiftOp {
 } SwsShiftOp;

 typedef struct SwsClearOp {
-    SwsCompMask mask;    /* mask of components to clear */
+    SwsPixelType type[4];  /* type of each value */
+    SwsCompMask mask;      /* mask of components to clear */
     AVRational64 value[4]; /* value to set */
 } SwsClearOp;

diff --git a/libswscale/ops_memcpy.c b/libswscale/ops_memcpy.c
index 5940381ea0..52ba64b0c3 100644
--- a/libswscale/ops_memcpy.c
+++ b/libswscale/ops_memcpy.c
@@ -112,7 +112,7 @@ static int compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
                  * can't memset on multi-byte sequences */
                 uint8_t val = op->clear.value[i].num & 0xFF;
                 uint32_t ref = val;
-                switch (ff_sws_pixel_type_size(op->type)) {
+                switch (ff_sws_pixel_type_size(op->clear.type[i])) {
                 case 2: ref *= 0x101; break;
                 case 4: ref *= 0x1010101; break;
                 }
diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
index 0d7f2438df..4726ca9bf2 100644
--- a/libswscale/ops_optimizer.c
+++ b/libswscale/ops_optimizer.c
@@ -43,6 +43,8 @@ static bool op_commute_clear(SwsOp *op, SwsOp *next)
     av_assert1(op->op == SWS_OP_CLEAR);
     switch (next->op) {
     case SWS_OP_CONVERT:
+        for (int i = 0; i < 4; i++)
+            op->clear.type[i] = next->convert.to;
         op->type = next->convert.to;
         av_fallthrough;
     case SWS_OP_LSHIFT:
@@ -56,12 +58,18 @@ static bool op_commute_clear(SwsOp *op, SwsOp *next)
         return true;
     case SWS_OP_FILTER_H:
     case SWS_OP_FILTER_V:
+        for (int i = 0; i < 4; i++)
+            op->clear.type[i] = next->filter.type;
         op->type = next->filter.type;
         return true;
-    case SWS_OP_SWIZZLE:
+    case SWS_OP_SWIZZLE: {
+        const SwsClearOp orig = op->clear;
+        for (int i = 0; i < 4; i++)
+            op->clear.type[i] = orig.type[next->swizzle.in[i]];
         ff_sws_comp_mask_swizzle(&op->clear.mask, &next->swizzle);
         ff_sws_apply_op_q(next, op->clear.value);
         return true;
+    }
     case SWS_OP_SWAP_BYTES:
         switch (next->type) {
         case SWS_PIXEL_U16:
@@ -280,6 +288,7 @@ static bool extract_constant_rows(SwsLinearOp *c, const SwsOpPad inputs[4],
         if (const_row && (mask & SWS_MASK_ROW(i))) {
             clear.mask |= SWS_COMP(i);
             clear.value[i] = c->m[i][4];
+            clear.type[i] = c->type[i];
             for (int j = 0; j < 5; j++)
                 c->m[i][j] = Q(i == j);
             ret = true;
@@ -490,8 +499,10 @@ retry:
             /* Transitive clear */
             if (next->op == SWS_OP_CLEAR) {
                 for (int i = 0; i < 4; i++) {
-                    if (SWS_COMP_TEST(next->clear.mask, i))
+                    if (SWS_COMP_TEST(next->clear.mask, i)) {
                         op->clear.value[i] = next->clear.value[i];
+                        op->clear.type[i]  = next->clear.type[i];
+                    }
                 }
                 op->clear.mask |= next->clear.mask;
                 ff_sws_op_list_remove_at(ops, n + 1, 1);
@@ -508,7 +519,7 @@ retry:
                     for (int i = 0; i < 4; i++) {
                         if (!next->lin.m[i][j].num)
                             continue;
-                        av_assert0(next->lin.type[i] == op->type);
+                        av_assert0(next->lin.type[i] == op->clear.type[j]);
                         const AVRational64 kx = ff_mul_q64(next->lin.m[i][j], x);
                         next->lin.m[i][4] = ff_add_q64(next->lin.m[i][4], kx);
                         next->lin.m[i][j] = Q(0);