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