Commit 215ad35715 for ffmpeg

commit 215ad35715ea0aaf88c5348d2d6a6756fbeb511d
Author: Niklas Haas <git@haasn.dev>
Date:   Fri Aug 14 10:59:57 2026 +0200

    swscale/ops_optimizer: unpromote integer-only linear ops

    This avoids a whole class of unnecessary round trips through F32 for exact
    integer-only linear ops.

    This is a huge win especially for the x86 backend which no longer needs to
    worry about cross-lane shuffles when internally expanding and repacking the
    32-bit intermediate results.

    Affects a large number of ops lists, including but not limited to:

     monow 16x16 -> rgb24 16x16:
       [ u8 +XXX] SWS_OP_READ         : 1 elem(s) planar >> 3
         min: {0 _ _ _}, max: {1 _ _ _}
    -  [ u8 +XXX] SWS_OP_CONVERT      : u8 -> f32
    -    min: {0 _ _ _}, max: {1 _ _ _}
    -  [f32 +++X] SWS_OP_SWIZZLE      : 0003
    +  [ u8 +++X] SWS_OP_SWIZZLE      : 0003
         min: {0 0 0 _}, max: {1 1 1 _}
    -  [f32 +++X] SWS_OP_LINEAR       : diag3+off3 [[-255 0 0 0 255] [0 -255 0 0 255] [0 0 -255 0 255] [0 0 0 1 0]]
    -    min: {0 0 0 _}, max: {255 255 255 _}
    -  [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
    +  [ u8 +++X] SWS_OP_LINEAR       : diag3+off3 [[-255 0 0 0 255] [0 -255 0 0 255] [0 0 -255 0 255] [0 0 0 1 0]]
         min: {0 0 0 _}, max: {255 255 255 _}
       [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
         (X = unused, z = byteswapped, + = exact, 0 = zero)
      translated micro-ops:
         u8_read_bit_x
    -    u8_to_f32_x
    -    u32_copy_yz_xx
    -    f32_linear_xyz_x000x_0x00x_00x0x
    -    f32_to_u8_xyz
    +    u8_copy_yz_xx
    +    u8_linear_xyz_x000x_0x00x_00x0x
         u8_write_packed_xyz

     bgr4 16x16 -> rgb48le 16x16:
       [ u8 +XXX] SWS_OP_READ         : 1 elem(s) packed >> 1
       [ u8 +++X] SWS_OP_UNPACK       : {1 2 1 0}
         min: {0 0 0 _}, max: {1 3 1 _}
    -  [ u8 +++X] SWS_OP_CONVERT      : u8 -> f32
    +  [ u8 +++X] SWS_OP_CONVERT      : u8 -> u16
         min: {0 0 0 _}, max: {1 3 1 _}
    -  [f32 +++X] SWS_OP_SWIZZLE      : 2103
    +  [u16 +++X] SWS_OP_SWIZZLE      : 2103
         min: {0 0 0 _}, max: {1 3 1 _}
    -  [f32 +++X] SWS_OP_LINEAR       : diag3 [[65535 0 0 0 0] [0 21845 0 0 0] [0 0 65535 0 0] [0 0 0 1 0]]
    -    min: {0 0 0 _}, max: {65535 65535 65535 _}
    -  [f32 +++X] SWS_OP_CONVERT      : f32 -> u16
    +  [u16 +++X] SWS_OP_LINEAR       : diag3 [[65535 0 0 0 0] [0 21845 0 0 0] [0 0 65535 0 0] [0 0 0 1 0]]
         min: {0 0 0 _}, max: {65535 65535 65535 _}
       [u16 XXXX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
         (X = unused, z = byteswapped, + = exact, 0 = zero)
      translated micro-ops:
         u8_read_nibble_x
         u8_unpack_xyz_121
    -    u8_to_f32_xyz
    -    u32_permute_xz_zx
    -    f32_linear_xyz_x0000_0x000_00x00
    -    f32_to_u16_xyz
    +    u8_to_u16_xyz
    +    u16_permute_xz_zx
    +    u16_linear_xyz_x0000_0x000_00x00
         u16_write_packed_xyz

     uyva 16x16 -> yuva444p16le 16x16:
       [ u8 ++++] SWS_OP_READ         : 4 elem(s) packed >> 0
         min: {0 0 0 0}, max: {255 255 255 255}
    -  [ u8 ++++] SWS_OP_CONVERT      : u8 -> f32
    +  [ u8 ++++] SWS_OP_CONVERT      : u8 -> u16
         min: {0 0 0 0}, max: {255 255 255 255}
    -  [f32 ++++] SWS_OP_SWIZZLE      : 1023
    +  [u16 ++++] SWS_OP_SWIZZLE      : 1023
         min: {0 0 0 0}, max: {255 255 255 255}
    -  [f32 ++++] SWS_OP_LINEAR       : diag4 [[256 0 0 0 0] [0 256 0 0 0] [0 0 256 0 0] [0 0 0 257 0]]
    -    min: {0 0 0 0}, max: {65280 65280 65280 65535}
    -  [f32 ++++] SWS_OP_CONVERT      : f32 -> u16
    +  [u16 ++++] SWS_OP_LINEAR       : diag4 [[256 0 0 0 0] [0 256 0 0 0] [0 0 256 0 0] [0 0 0 257 0]]
         min: {0 0 0 0}, max: {65280 65280 65280 65535}
       [u16 XXXX] SWS_OP_WRITE        : 4 elem(s) planar >> 0
         (X = unused, z = byteswapped, + = exact, 0 = zero)
      translated micro-ops:
         u8_read_packed_xyzw
    -    u8_to_f32_xyzw
    -    u32_permute_xy_yx
    -    f32_linear_xyzw_x0000_0x000_00x00_000x0
    -    f32_to_u16_xyzw
    +    u8_to_u16_xyzw
    +    u16_permute_xy_yx
    +    u16_linear_xyzw_x0000_0x000_00x00_000x0
         u16_write_planar_xyzw

    Sponsored-by: Sovereign Tech Fund
    Signed-off-by: Niklas Haas <git@haasn.dev>
    Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>

diff --git a/libswscale/aarch64/ops_entries.c b/libswscale/aarch64/ops_entries.c
index cd42184715..2f99ace3e0 100644
--- a/libswscale/aarch64/ops_entries.c
+++ b/libswscale/aarch64/ops_entries.c
@@ -76,6 +76,7 @@ ENTRY(ff_sws_write_packed_16_u16_1111_neon,         { .uop = SWS_UOP_WRITE_PACKE
 ENTRY(ff_sws_write_nibble_8_u8_0001_neon,           { .uop = SWS_UOP_WRITE_NIBBLE, .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0x1 })
 ENTRY(ff_sws_write_nibble_16_u8_0001_neon,          { .uop = SWS_UOP_WRITE_NIBBLE, .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x1 })
 ENTRY(ff_sws_write_bit_8_u8_0001_neon,              { .uop = SWS_UOP_WRITE_BIT,    .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0x1 })
+ENTRY(ff_sws_write_bit_16_u8_0001_neon,             { .uop = SWS_UOP_WRITE_BIT,    .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x1 })
 ENTRY(ff_sws_permute_000000000001_32_u8_0001_neon,  { .uop = SWS_UOP_PERMUTE,      .block_size = 32, .type = SWS_PIXEL_U8,  .mask = 0x1, .par.move = { .num_moves = 1, .dst = {0, 0, 0, 0, 0, 0}, .src = {1, 0, 0, 0, 0, 0} } })
 ENTRY(ff_sws_permute_000000000002_32_u8_0001_neon,  { .uop = SWS_UOP_PERMUTE,      .block_size = 32, .type = SWS_PIXEL_U8,  .mask = 0x1, .par.move = { .num_moves = 1, .dst = {0, 0, 0, 0, 0, 0}, .src = {2, 0, 0, 0, 0, 0} } })
 ENTRY(ff_sws_permute_000000000003_8_u8_0001_neon,   { .uop = SWS_UOP_PERMUTE,      .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0x1, .par.move = { .num_moves = 1, .dst = {0, 0, 0, 0, 0, 0}, .src = {3, 0, 0, 0, 0, 0} } })
@@ -88,6 +89,7 @@ ENTRY(ff_sws_permute_000000000013_8_u8_0010_neon,   { .uop = SWS_UOP_PERMUTE,
 ENTRY(ff_sws_permute_000000000013_16_u8_0010_neon,  { .uop = SWS_UOP_PERMUTE,      .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x2, .par.move = { .num_moves = 1, .dst = {1, 0, 0, 0, 0, 0}, .src = {3, 0, 0, 0, 0, 0} } })
 ENTRY(ff_sws_permute_000000000013_32_u8_0010_neon,  { .uop = SWS_UOP_PERMUTE,      .block_size = 32, .type = SWS_PIXEL_U8,  .mask = 0x2, .par.move = { .num_moves = 1, .dst = {1, 0, 0, 0, 0, 0}, .src = {3, 0, 0, 0, 0, 0} } })
 ENTRY(ff_sws_permute_000000000020_8_u8_0100_neon,   { .uop = SWS_UOP_PERMUTE,      .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0x4, .par.move = { .num_moves = 1, .dst = {2, 0, 0, 0, 0, 0}, .src = {0, 0, 0, 0, 0, 0} } })
+ENTRY(ff_sws_permute_000000000020_16_u8_0100_neon,  { .uop = SWS_UOP_PERMUTE,      .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x4, .par.move = { .num_moves = 1, .dst = {2, 0, 0, 0, 0, 0}, .src = {0, 0, 0, 0, 0, 0} } })
 ENTRY(ff_sws_permute_000000000020_32_u8_0100_neon,  { .uop = SWS_UOP_PERMUTE,      .block_size = 32, .type = SWS_PIXEL_U8,  .mask = 0x4, .par.move = { .num_moves = 1, .dst = {2, 0, 0, 0, 0, 0}, .src = {0, 0, 0, 0, 0, 0} } })
 ENTRY(ff_sws_permute_000000000030_8_u8_1000_neon,   { .uop = SWS_UOP_PERMUTE,      .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0x8, .par.move = { .num_moves = 1, .dst = {3, 0, 0, 0, 0, 0}, .src = {0, 0, 0, 0, 0, 0} } })
 ENTRY(ff_sws_permute_000000000030_16_u8_1000_neon,  { .uop = SWS_UOP_PERMUTE,      .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x8, .par.move = { .num_moves = 1, .dst = {3, 0, 0, 0, 0, 0}, .src = {0, 0, 0, 0, 0, 0} } })
@@ -203,6 +205,7 @@ ENTRY(ff_sws_to_u16_8_f32_1111_neon,                { .uop = SWS_UOP_TO_U16,
 ENTRY(ff_sws_to_u16_16_u8_0001_neon,                { .uop = SWS_UOP_TO_U16,       .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x1 })
 ENTRY(ff_sws_to_u16_16_u8_0111_neon,                { .uop = SWS_UOP_TO_U16,       .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x7 })
 ENTRY(ff_sws_to_u16_16_u8_1110_neon,                { .uop = SWS_UOP_TO_U16,       .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0xe })
+ENTRY(ff_sws_to_u16_16_u8_1111_neon,                { .uop = SWS_UOP_TO_U16,       .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0xf })
 ENTRY(ff_sws_to_u32_8_u8_0001_neon,                 { .uop = SWS_UOP_TO_U32,       .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0x1 })
 ENTRY(ff_sws_to_u32_8_u8_0111_neon,                 { .uop = SWS_UOP_TO_U32,       .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0x7 })
 ENTRY(ff_sws_to_u32_8_u16_0001_neon,                { .uop = SWS_UOP_TO_U32,       .block_size =  8, .type = SWS_PIXEL_U16, .mask = 0x1 })
@@ -324,12 +327,16 @@ ENTRY(ff_sws_clear_0fff_8_u8_1011_neon,             { .uop = SWS_UOP_CLEAR,
 ENTRY(ff_sws_clear_0fff_8_u16_1000_neon,            { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U16, .mask = 0x8, .par.clear = { .one = 0x0, .zero = 0x8 } })
 ENTRY(ff_sws_clear_0fff_8_u16_1101_neon,            { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U16, .mask = 0xd, .par.clear = { .one = 0x0, .zero = 0x8 } })
 ENTRY(ff_sws_clear_0fff_16_u8_1000_neon,            { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x8, .par.clear = { .one = 0x0, .zero = 0x8 } })
+ENTRY(ff_sws_clear_0fff_16_u8_1011_neon,            { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0xb, .par.clear = { .one = 0x0, .zero = 0x8 } })
 ENTRY(ff_sws_clear_0fff_16_u16_1000_neon,           { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x8, .par.clear = { .one = 0x0, .zero = 0x8 } })
+ENTRY(ff_sws_clear_0fff_16_u16_1101_neon,           { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0xd, .par.clear = { .one = 0x0, .zero = 0x8 } })
 ENTRY(ff_sws_clear_1fff_8_u8_1000_neon,             { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0x8, .par.clear = { .one = 0x8, .zero = 0x0 } })
 ENTRY(ff_sws_clear_1fff_8_u8_1011_neon,             { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0xb, .par.clear = { .one = 0x8, .zero = 0x0 } })
 ENTRY(ff_sws_clear_1fff_8_u8_1101_neon,             { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0xd, .par.clear = { .one = 0x8, .zero = 0x0 } })
 ENTRY(ff_sws_clear_1fff_8_u16_1000_neon,            { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U16, .mask = 0x8, .par.clear = { .one = 0x8, .zero = 0x0 } })
 ENTRY(ff_sws_clear_1fff_16_u8_1000_neon,            { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x8, .par.clear = { .one = 0x8, .zero = 0x0 } })
+ENTRY(ff_sws_clear_1fff_16_u8_1011_neon,            { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0xb, .par.clear = { .one = 0x8, .zero = 0x0 } })
+ENTRY(ff_sws_clear_1fff_16_u8_1101_neon,            { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0xd, .par.clear = { .one = 0x8, .zero = 0x0 } })
 ENTRY(ff_sws_clear_1fff_16_u16_1000_neon,           { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x8, .par.clear = { .one = 0x8, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ff1f_8_u8_0010_neon,             { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0x2, .par.clear = { .one = 0x2, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ff1f_8_u16_0010_neon,            { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U16, .mask = 0x2, .par.clear = { .one = 0x2, .zero = 0x0 } })
@@ -343,8 +350,10 @@ ENTRY(ff_sws_clear_fff1_8_u16_0001_neon,            { .uop = SWS_UOP_CLEAR,
 ENTRY(ff_sws_clear_fff1_8_u16_1101_neon,            { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U16, .mask = 0xd, .par.clear = { .one = 0x1, .zero = 0x0 } })
 ENTRY(ff_sws_clear_fff1_16_u8_0001_neon,            { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x1, .par.clear = { .one = 0x1, .zero = 0x0 } })
 ENTRY(ff_sws_clear_fff1_16_u8_0111_neon,            { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x7, .par.clear = { .one = 0x1, .zero = 0x0 } })
+ENTRY(ff_sws_clear_fff1_16_u8_1101_neon,            { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0xd, .par.clear = { .one = 0x1, .zero = 0x0 } })
 ENTRY(ff_sws_clear_fff1_16_u16_0001_neon,           { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x1, .par.clear = { .one = 0x1, .zero = 0x0 } })
 ENTRY(ff_sws_clear_fff1_16_u16_0111_neon,           { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x7, .par.clear = { .one = 0x1, .zero = 0x0 } })
+ENTRY(ff_sws_clear_fff1_16_u16_1101_neon,           { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0xd, .par.clear = { .one = 0x1, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ffff_8_u8_0011_neon,             { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0x3, .par.clear = { .one = 0x0, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ffff_8_u8_0101_neon,             { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0x5, .par.clear = { .one = 0x0, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ffff_8_u8_1100_neon,             { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U8,  .mask = 0xc, .par.clear = { .one = 0x0, .zero = 0x0 } })
@@ -357,19 +366,30 @@ ENTRY(ff_sws_clear_ffff_8_u32_1010_neon,            { .uop = SWS_UOP_CLEAR,
 ENTRY(ff_sws_clear_ffff_8_u32_1011_neon,            { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U32, .mask = 0xb, .par.clear = { .one = 0x0, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ffff_8_u32_1101_neon,            { .uop = SWS_UOP_CLEAR,        .block_size =  8, .type = SWS_PIXEL_U32, .mask = 0xd, .par.clear = { .one = 0x0, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ffff_16_u8_0011_neon,            { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x3, .par.clear = { .one = 0x0, .zero = 0x0 } })
+ENTRY(ff_sws_clear_ffff_16_u8_0101_neon,            { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x5, .par.clear = { .one = 0x0, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ffff_16_u8_0110_neon,            { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x6, .par.clear = { .one = 0x0, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ffff_16_u16_0001_neon,           { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x1, .par.clear = { .one = 0x0, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ffff_16_u16_0011_neon,           { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x3, .par.clear = { .one = 0x0, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ffff_16_u16_0111_neon,           { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x7, .par.clear = { .one = 0x0, .zero = 0x0 } })
 ENTRY(ff_sws_clear_ffff_16_u16_1000_neon,           { .uop = SWS_UOP_CLEAR,        .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x8, .par.clear = { .one = 0x0, .zero = 0x0 } })
+ENTRY(ff_sws_linear_000000000f_8_u32_0001_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_U32, .mask = 0x1, .par.lin = { .one = 0x0, .zero = 0xfffee } })
 ENTRY(ff_sws_linear_000000000f_8_f32_0001_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x1, .par.lin = { .one = 0x0, .zero = 0xfffee } })
+ENTRY(ff_sws_linear_000000000f_16_u8_0001_neon,     { .uop = SWS_UOP_LINEAR,       .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x1, .par.lin = { .one = 0x0, .zero = 0xfffee } })
+ENTRY(ff_sws_linear_000000000f_16_u16_0001_neon,    { .uop = SWS_UOP_LINEAR,       .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x1, .par.lin = { .one = 0x0, .zero = 0xfffee } })
 ENTRY(ff_sws_linear_00000000fc_8_f32_0001_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x1, .par.lin = { .one = 0x0, .zero = 0xffff8 } })
 ENTRY(ff_sws_linear_00000000ff_8_f32_0001_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x1, .par.lin = { .one = 0x0, .zero = 0xfffe8 } })
 ENTRY(ff_sws_linear_000000c000_8_f32_0010_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x2, .par.lin = { .one = 0x0, .zero = 0xfffbf } })
+ENTRY(ff_sws_linear_000000c000_16_u8_0010_neon,     { .uop = SWS_UOP_LINEAR,       .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x2, .par.lin = { .one = 0x0, .zero = 0xfffbf } })
 ENTRY(ff_sws_linear_000373dcc7_8_f32_0111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x7, .par.lin = { .one = 0x421, .zero = 0xfb10a } })
 ENTRY(ff_sws_linear_0003f3fccf_8_f32_0111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x7, .par.lin = { .one = 0x0, .zero = 0xfb10a } })
+ENTRY(ff_sws_linear_000c00c00c_8_u32_0111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_U32, .mask = 0x7, .par.lin = { .one = 0x0, .zero = 0xfefbe } })
 ENTRY(ff_sws_linear_000c00c00c_8_f32_0111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x7, .par.lin = { .one = 0x0, .zero = 0xfefbe } })
+ENTRY(ff_sws_linear_000c00c00c_16_u8_0111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x7, .par.lin = { .one = 0x0, .zero = 0xfefbe } })
+ENTRY(ff_sws_linear_000c00c00c_16_u16_0111_neon,    { .uop = SWS_UOP_LINEAR,       .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x7, .par.lin = { .one = 0x0, .zero = 0xfefbe } })
+ENTRY(ff_sws_linear_000c30cc0f_8_u32_0111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_U32, .mask = 0x7, .par.lin = { .one = 0x0, .zero = 0xfadae } })
 ENTRY(ff_sws_linear_000c30cc0f_8_f32_0111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x7, .par.lin = { .one = 0x0, .zero = 0xfadae } })
+ENTRY(ff_sws_linear_000c30cc0f_16_u8_0111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size = 16, .type = SWS_PIXEL_U8,  .mask = 0x7, .par.lin = { .one = 0x0, .zero = 0xfadae } })
+ENTRY(ff_sws_linear_000c30cc0f_16_u16_0111_neon,    { .uop = SWS_UOP_LINEAR,       .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x7, .par.lin = { .one = 0x0, .zero = 0xfadae } })
 ENTRY(ff_sws_linear_000ff3fcfc_8_f32_0111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x7, .par.lin = { .one = 0x0, .zero = 0xfa118 } })
 ENTRY(ff_sws_linear_000ff3fcff_8_f32_0111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x7, .par.lin = { .one = 0x0, .zero = 0xfa108 } })
 ENTRY(ff_sws_linear_c000000000_8_f32_1000_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x8, .par.lin = { .one = 0x0, .zero = 0xbffff } })
@@ -377,6 +397,7 @@ ENTRY(ff_sws_linear_c00000000f_8_f32_1001_neon,     { .uop = SWS_UOP_LINEAR,
 ENTRY(ff_sws_linear_c0000000fc_8_f32_1001_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x9, .par.lin = { .one = 0x0, .zero = 0xbfff8 } })
 ENTRY(ff_sws_linear_c003f3fccf_8_f32_1111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0xf, .par.lin = { .one = 0x0, .zero = 0xbb10a } })
 ENTRY(ff_sws_linear_c00c00c00c_8_f32_1111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0xf, .par.lin = { .one = 0x0, .zero = 0xbefbe } })
+ENTRY(ff_sws_linear_c00c00c00c_16_u16_1111_neon,    { .uop = SWS_UOP_LINEAR,       .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0xf, .par.lin = { .one = 0x0, .zero = 0xbefbe } })
 ENTRY(ff_sws_linear_c00ff3fcff_8_f32_1111_neon,     { .uop = SWS_UOP_LINEAR,       .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0xf, .par.lin = { .one = 0x0, .zero = 0xba108 } })
 ENTRY(ff_sws_linear_fma_000000000f_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR_FMA,   .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x1, .par.lin = { .one = 0x0, .zero = 0xfffee } })
 ENTRY(ff_sws_linear_fma_00000000fc_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR_FMA,   .block_size =  8, .type = SWS_PIXEL_F32, .mask = 0x1, .par.lin = { .one = 0x0, .zero = 0xffff8 } })
diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
index fe621dd610..64b7adadd8 100644
--- a/libswscale/ops_optimizer.c
+++ b/libswscale/ops_optimizer.c
@@ -802,6 +802,18 @@ retry:
                 goto retry;
             }
             break;
+
+        case SWS_OP_LINEAR:
+            /* Exact integer linear transformation */
+            if (next->op == SWS_OP_CONVERT &&
+                ff_sws_pixel_type_is_int(next->convert.to) &&
+                op_result_is_exact(op))
+            {
+                op->type = next->convert.to;
+                FFSWAP(SwsOp, *op, *next);
+                goto retry;
+            }
+            break;
         }
     }

diff --git a/libswscale/uops_macros.h b/libswscale/uops_macros.h
index d2f9793692..00d9ce0c58 100644
--- a/libswscale/uops_macros.h
+++ b/libswscale/uops_macros.h
@@ -246,11 +246,13 @@
 #define SWS_FOR_U8_TO_U16(MACRO, ...) \
     MACRO(__VA_ARGS__, u8_to_u16_x                             , SWS_PIXEL_U8 , SWS_UOP_TO_U16          , 0x1) \
     MACRO(__VA_ARGS__, u8_to_u16_xyz                           , SWS_PIXEL_U8 , SWS_UOP_TO_U16          , 0x7) \
-    MACRO(__VA_ARGS__, u8_to_u16_yzw                           , SWS_PIXEL_U8 , SWS_UOP_TO_U16          , 0xe)
+    MACRO(__VA_ARGS__, u8_to_u16_yzw                           , SWS_PIXEL_U8 , SWS_UOP_TO_U16          , 0xe) \
+    MACRO(__VA_ARGS__, u8_to_u16_xyzw                          , SWS_PIXEL_U8 , SWS_UOP_TO_U16          , 0xf)
 #define SWS_FOR_STRUCT_U8_TO_U16(MACRO, ...) \
     MACRO(__VA_ARGS__, u8_to_u16_x                             , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_TO_U16          , .mask = 0x1) \
     MACRO(__VA_ARGS__, u8_to_u16_xyz                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_TO_U16          , .mask = 0x7) \
-    MACRO(__VA_ARGS__, u8_to_u16_yzw                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_TO_U16          , .mask = 0xe)
+    MACRO(__VA_ARGS__, u8_to_u16_yzw                           , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_TO_U16          , .mask = 0xe) \
+    MACRO(__VA_ARGS__, u8_to_u16_xyzw                          , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_TO_U16          , .mask = 0xf)
 #define SWS_FOR_U8_TO_U32(MACRO, ...) \
     MACRO(__VA_ARGS__, u8_to_u32_x                             , SWS_PIXEL_U8 , SWS_UOP_TO_U32          , 0x1) \
     MACRO(__VA_ARGS__, u8_to_u32_xyz                           , SWS_PIXEL_U8 , SWS_UOP_TO_U32          , 0x7)
@@ -337,8 +339,16 @@
     MACRO(__VA_ARGS__, u8_clear_zw_xx                          , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_CLEAR           , .mask = 0xc, .par.clear.one = 0x0, .par.clear.zero = 0x0) \
     MACRO(__VA_ARGS__, u8_clear_xzw_1xx                        , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_CLEAR           , .mask = 0xd, .par.clear.one = 0x1, .par.clear.zero = 0x0) \
     MACRO(__VA_ARGS__, u8_clear_xzw_xx1                        , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_CLEAR           , .mask = 0xd, .par.clear.one = 0x8, .par.clear.zero = 0x0)
-#define SWS_FOR_U8_LINEAR(MACRO, ...)
-#define SWS_FOR_STRUCT_U8_LINEAR(MACRO, ...)
+#define SWS_FOR_U8_LINEAR(MACRO, ...) \
+    MACRO(__VA_ARGS__, u8_linear_x_x000x                       , SWS_PIXEL_U8 , SWS_UOP_LINEAR          , 0x1, 0x00000, 0xfffee) \
+    MACRO(__VA_ARGS__, u8_linear_y_0x000                       , SWS_PIXEL_U8 , SWS_UOP_LINEAR          , 0x2, 0x00000, 0xfffbf) \
+    MACRO(__VA_ARGS__, u8_linear_xyz_x000x_0x00x_00x0x         , SWS_PIXEL_U8 , SWS_UOP_LINEAR          , 0x7, 0x00000, 0xfadae) \
+    MACRO(__VA_ARGS__, u8_linear_xyz_x0000_0x000_00x00         , SWS_PIXEL_U8 , SWS_UOP_LINEAR          , 0x7, 0x00000, 0xfefbe)
+#define SWS_FOR_STRUCT_U8_LINEAR(MACRO, ...) \
+    MACRO(__VA_ARGS__, u8_linear_x_x000x                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_LINEAR          , .mask = 0x1, .par.lin.one = 0x0, .par.lin.zero = 0xfffee) \
+    MACRO(__VA_ARGS__, u8_linear_y_0x000                       , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_LINEAR          , .mask = 0x2, .par.lin.one = 0x0, .par.lin.zero = 0xfffbf) \
+    MACRO(__VA_ARGS__, u8_linear_xyz_x000x_0x00x_00x0x         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_LINEAR          , .mask = 0x7, .par.lin.one = 0x0, .par.lin.zero = 0xfadae) \
+    MACRO(__VA_ARGS__, u8_linear_xyz_x0000_0x000_00x00         , .type = SWS_PIXEL_U8 , .uop = SWS_UOP_LINEAR          , .mask = 0x7, .par.lin.one = 0x0, .par.lin.zero = 0xfefbe)
 #define SWS_FOR_U8_LINEAR_FMA(MACRO, ...)
 #define SWS_FOR_STRUCT_U8_LINEAR_FMA(MACRO, ...)
 #define SWS_FOR_U8_DITHER(MACRO, ...)
@@ -621,8 +631,16 @@
     MACRO(__VA_ARGS__, u16_clear_zw_xx                         , .type = SWS_PIXEL_U16, .uop = SWS_UOP_CLEAR           , .mask = 0xc, .par.clear.one = 0x0, .par.clear.zero = 0x0) \
     MACRO(__VA_ARGS__, u16_clear_xzw_xx0                       , .type = SWS_PIXEL_U16, .uop = SWS_UOP_CLEAR           , .mask = 0xd, .par.clear.one = 0x0, .par.clear.zero = 0x8) \
     MACRO(__VA_ARGS__, u16_clear_xzw_1xx                       , .type = SWS_PIXEL_U16, .uop = SWS_UOP_CLEAR           , .mask = 0xd, .par.clear.one = 0x1, .par.clear.zero = 0x0)
-#define SWS_FOR_U16_LINEAR(MACRO, ...)
-#define SWS_FOR_STRUCT_U16_LINEAR(MACRO, ...)
+#define SWS_FOR_U16_LINEAR(MACRO, ...) \
+    MACRO(__VA_ARGS__, u16_linear_x_x000x                      , SWS_PIXEL_U16, SWS_UOP_LINEAR          , 0x1, 0x00000, 0xfffee) \
+    MACRO(__VA_ARGS__, u16_linear_xyz_x000x_0x00x_00x0x        , SWS_PIXEL_U16, SWS_UOP_LINEAR          , 0x7, 0x00000, 0xfadae) \
+    MACRO(__VA_ARGS__, u16_linear_xyz_x0000_0x000_00x00        , SWS_PIXEL_U16, SWS_UOP_LINEAR          , 0x7, 0x00000, 0xfefbe) \
+    MACRO(__VA_ARGS__, u16_linear_xyzw_x0000_0x000_00x00_000x0 , SWS_PIXEL_U16, SWS_UOP_LINEAR          , 0xf, 0x00000, 0xbefbe)
+#define SWS_FOR_STRUCT_U16_LINEAR(MACRO, ...) \
+    MACRO(__VA_ARGS__, u16_linear_x_x000x                      , .type = SWS_PIXEL_U16, .uop = SWS_UOP_LINEAR          , .mask = 0x1, .par.lin.one = 0x0, .par.lin.zero = 0xfffee) \
+    MACRO(__VA_ARGS__, u16_linear_xyz_x000x_0x00x_00x0x        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_LINEAR          , .mask = 0x7, .par.lin.one = 0x0, .par.lin.zero = 0xfadae) \
+    MACRO(__VA_ARGS__, u16_linear_xyz_x0000_0x000_00x00        , .type = SWS_PIXEL_U16, .uop = SWS_UOP_LINEAR          , .mask = 0x7, .par.lin.one = 0x0, .par.lin.zero = 0xfefbe) \
+    MACRO(__VA_ARGS__, u16_linear_xyzw_x0000_0x000_00x00_000x0 , .type = SWS_PIXEL_U16, .uop = SWS_UOP_LINEAR          , .mask = 0xf, .par.lin.one = 0x0, .par.lin.zero = 0xbefbe)
 #define SWS_FOR_U16_LINEAR_FMA(MACRO, ...)
 #define SWS_FOR_STRUCT_U16_LINEAR_FMA(MACRO, ...)
 #define SWS_FOR_U16_DITHER(MACRO, ...)
@@ -843,8 +861,14 @@
     MACRO(__VA_ARGS__, u32_clear_yw_xx                         , .type = SWS_PIXEL_U32, .uop = SWS_UOP_CLEAR           , .mask = 0xa, .par.clear.one = 0x0, .par.clear.zero = 0x0) \
     MACRO(__VA_ARGS__, u32_clear_xyw_xxx                       , .type = SWS_PIXEL_U32, .uop = SWS_UOP_CLEAR           , .mask = 0xb, .par.clear.one = 0x0, .par.clear.zero = 0x0) \
     MACRO(__VA_ARGS__, u32_clear_xzw_xxx                       , .type = SWS_PIXEL_U32, .uop = SWS_UOP_CLEAR           , .mask = 0xd, .par.clear.one = 0x0, .par.clear.zero = 0x0)
-#define SWS_FOR_U32_LINEAR(MACRO, ...)
-#define SWS_FOR_STRUCT_U32_LINEAR(MACRO, ...)
+#define SWS_FOR_U32_LINEAR(MACRO, ...) \
+    MACRO(__VA_ARGS__, u32_linear_x_x000x                      , SWS_PIXEL_U32, SWS_UOP_LINEAR          , 0x1, 0x00000, 0xfffee) \
+    MACRO(__VA_ARGS__, u32_linear_xyz_x000x_0x00x_00x0x        , SWS_PIXEL_U32, SWS_UOP_LINEAR          , 0x7, 0x00000, 0xfadae) \
+    MACRO(__VA_ARGS__, u32_linear_xyz_x0000_0x000_00x00        , SWS_PIXEL_U32, SWS_UOP_LINEAR          , 0x7, 0x00000, 0xfefbe)
+#define SWS_FOR_STRUCT_U32_LINEAR(MACRO, ...) \
+    MACRO(__VA_ARGS__, u32_linear_x_x000x                      , .type = SWS_PIXEL_U32, .uop = SWS_UOP_LINEAR          , .mask = 0x1, .par.lin.one = 0x0, .par.lin.zero = 0xfffee) \
+    MACRO(__VA_ARGS__, u32_linear_xyz_x000x_0x00x_00x0x        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_LINEAR          , .mask = 0x7, .par.lin.one = 0x0, .par.lin.zero = 0xfadae) \
+    MACRO(__VA_ARGS__, u32_linear_xyz_x0000_0x000_00x00        , .type = SWS_PIXEL_U32, .uop = SWS_UOP_LINEAR          , .mask = 0x7, .par.lin.one = 0x0, .par.lin.zero = 0xfefbe)
 #define SWS_FOR_U32_LINEAR_FMA(MACRO, ...)
 #define SWS_FOR_STRUCT_U32_LINEAR_FMA(MACRO, ...)
 #define SWS_FOR_U32_DITHER(MACRO, ...)
diff --git a/tests/ref/fate/sws-ops-list b/tests/ref/fate/sws-ops-list
index 96acb787ca..7819781c4a 100644
--- a/tests/ref/fate/sws-ops-list
+++ b/tests/ref/fate/sws-ops-list
@@ -1 +1 @@
-41b97cc2b41ce3afd672ee14ad9d544d
+bc046cee81413c33100cc3c71f058e9d