Commit Graph

3512 Commits

Author SHA1 Message Date
Michael Niedermayer
97e169f6ce swscale/output: avoid signed overflow in yuv2rgb_write_full luma scaling
Fixes: 523522305/clusterfuzz-testcase-minimized-ffmpeg_SWS_fuzzer-4574409678716928
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
(cherry picked from commit f50e22c68d)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-07-21 22:59:53 +02:00
Lynne
ca089c35c4 vulkan: remove runtime shader compilation support
No longer needed.

(cherry picked from commit 9e9ac0dcd9)
2026-07-14 00:14:28 +09:00
Lynne
4c6017946b swscale: remove GLSL backend
No longer needed. The SPIR-V version is pretty clean and neat.

(cherry picked from commit aa6aa4ec3e)
2026-07-14 00:14:28 +09:00
Lynne
716d2a47c5 swscale/ops_dispatch: fix use-after-free when adding opaque ops passes
comp points into p, which is freed before comp->backend is read.
Use the copy taken before the free.

(cherry picked from commit 4b9c4b9cfb)
2026-07-13 19:17:30 +09:00
Lynne
c79f25b757 swscale/vulkan: fix invalid SPIR-V generation for plane-remapped passes
The CLEAR codegen iterated components by value[i].den, while the
constants pass iterates by clear.mask; unmasked components may hold
leftover values with a nonzero denominator, consuming more constant
IDs than were registered and emitting ID 0 into the instruction
stream.

The image handle arrays were also sized by the number of planes an
op touches, but plane_src/plane_dst contain actual frame plane
indices, so a pass writing only e.g. the alpha plane references
handle 3 while only handle 0 was loaded.

Either results in invalid SPIR-V, which crashes RADV inside
spirv_to_nir when creating the shader object.

(cherry picked from commit b2b0429d15)
2026-07-13 19:17:30 +09:00
Michael Niedermayer
47e9d68e20 Bump minor for release/9.0
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-26 02:43:34 +02:00
Niklas Haas
fe3e67556b swscale/ops_optimizer: remove unneeded 32-bit overflow check
No longer needed with AVRational64. Now we can just apply_op_q(), on
everything except floating point types (which are still not representable
in AVRational64 and likely never will be, though this is mostly a moot
point as the uops layer can still optimize this further).

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-25 01:20:48 +02:00
Niklas Haas
1257f26120 swscale/ops: make ff_sws_apply_op_q slightly more robust
Switch on the exact pixel type and add a range assertion.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-25 01:20:48 +02:00
Niklas Haas
b9481ae3c2 swscale/format: remove no longer needed overflow check
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-25 01:20:48 +02:00
Niklas Haas
3743d2851d swscale/ops: switch from AVRational to AVRational64
This has two immediate consequences:

1. Fixes overflow in the range tracker for some 32-bit packed formats:

 rgb24 -> v30xbe:
   [ u8 +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 +++X] SWS_OP_CONVERT      : u8 -> f32
     min: {0 0 0 _}, max: {255 255 255 _}
   [f32 ...X] SWS_OP_LINEAR       : matrix3+off3 [...]
     min: {64 64 64 _}, max: {940 960 960 _}
   [f32 ...X] SWS_OP_DITHER       : 16x16 matrix + {0 3 2 -1}
     min: {64.001953 64.001953 64.001953 _}, max: {940.998047 960.998047 960.998047 _}
   [f32 +++X] SWS_OP_CONVERT      : f32 -> u32
     min: {64 64 64 _}, max: {940 960 960 _}
   [u32 +++X] SWS_OP_SWIZZLE      : 2013
     min: {64 64 64 _}, max: {960 940 960 _}
   [u32 ++++] SWS_OP_CLEAR        : {_ _ _ 1}
     min: {64 64 64 1}, max: {960 940 960 1}
   [u32 +XXX] SWS_OP_PACK         : {10 10 10 2}
-    min: {268697857 _ _ _}, max: {-264581375 _ _ _}
+    min: {268697857 _ _ _}, max: {4030385921 _ _ _}
   [u32 zXXX] SWS_OP_SWAP_BYTES
-    min: {268697857 _ _ _}, max: {-264581375 _ _ _}
+    min: {268697857 _ _ _}, max: {4030385921 _ _ _}

2. Slightly increases the accuracy of intermediate values for some linear ops:

 yuv444p10be -> rgb48be:
   [u16 zzzX] SWS_OP_READ         : 3 elem(s) planar >> 0
     min: {0 0 0 _}, max: {1023 1023 1023 _}
   [u16 +++X] SWS_OP_SWAP_BYTES
     min: {0 0 0 _}, max: {1023 1023 1023 _}
   [u16 +++X] SWS_OP_CONVERT      : u16 -> f32
     min: {0 0 0 _}, max: {1023 1023 1023 _}
   [f32 ...X] SWS_OP_LINEAR       : matrix3+off3 [...]
46.813777] [0 0 0 1 0]]
-    min: {-57290.842348 -44341.337325 -71146.813777 _}, max: {124144.718860 111375.162457 137973.627845 _}
+    min: {-57290.842348 -44341.337326 -71146.813777 _}, max: {124144.718860 111375.162457 137973.627845 _}
   [f32 ...X] SWS_OP_MAX          : {0 0 0 _} <= x
     min: {0 0 0 _}, max: {124144.718860 111375.162457 137973.627845 _}
   [f32 ...X] SWS_OP_MIN          : x <= {65535 65535 65535 _}
     min: {0 0 0 _}, max: {65535 65535 65535 _}
   [f32 +++X] SWS_OP_CONVERT      : f32 -> u16
     min: {0 0 0 _}, max: {65535 65535 65535 _}
   [u16 zzzX] SWS_OP_SWAP_BYTES
     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)

Importantly, none of the changes affect the actual operation list, just the
range tracking metadata.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-25 01:20:44 +02:00
Niklas Haas
aff6d64ecd swscale/ops_optimizer: omit overflow check on SWS_OP_SCALE
1. This is currently impossible to trigger
2. We're about to switch to AVRational64, eliminating this concern
3. The AVRational64 API intentionally doesn't expose av_reduce64()

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-25 01:20:15 +02:00
Niklas Haas
845a3bfcec swscale/format: factor out intmax_q() and make more robust
This formulation is generally preferred as it avoids the risk of (1 << depth)
overflowing when depth is 32/64/etc.

I also wanted to have these in a common place to make the upcoming changes
easier.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-25 01:20:15 +02:00
Niklas Haas
eda15846b2 swscale/format: avoid Q0/Q1 macros
These come with some challenging ambiguity in the following patch to switch
from AVRational to AVRational64, so best just avoid them and have individual
usage sites define them locally with the correct type.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-25 01:20:15 +02:00
Niklas Haas
82a73428e1 swscale/ops: don't re-define Q() macro
It's already in ops_internal.h

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-25 01:20:15 +02:00
Niklas Haas
b568f20f32 swscale/rational64: add 64-bit rational type
This is needed by the ops code, to represent intermediate values for 32-bit
formats, which can exceed the value range of int32_t (especially for
intermediate products).

I copied the math almost 1:1 from rational.c, but adapted to use the 128-bit
integer wrappers defined by int128.h. I added a generous amount of tests in
any case.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-25 01:20:15 +02:00
Ramiro Polla
46997547a6 swscale/uops: reduce size of uop_names[] array
Uses an offset into the full name to get the macro name. Also spells
out the names of the types to make the code easier to grep.
2026-06-24 22:39:31 +00:00
Ramiro Polla
49e73395b7 swscale/uops: move SWS_MASK* from ops.h to uops.h
These helpers are also needed for uops.
2026-06-24 13:14:35 +00:00
Ramiro Polla
fde02c904c swscale/ops: remove friendly linear mask names
These names are not really useful and the uops list already shows the
shape of the mask.
2026-06-24 13:14:35 +00:00
Andreas Rheinhardt
762b94e672 libs: Bump major version of all libraries
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2026-06-23 19:15:57 +02:00
Andreas Rheinhardt
2d3776b8cc avutil/x86/emms: Unavpriv avpriv_emms_asm()
This fallback function is used if external MMX is available,
while inline MMX and intrinsics for emitting emms are unavailable.
It is implemented as an avpriv function, which has several
drawbacks for shared builds:
1. The function is so small (3 bytes; 16 with padding)
that the overhead of exporting and importing it dwarfs
the gains from code deduplication.
2. A call to an external library has more overhead than
a library-internal one.
3. It may cause linking failures when a libavutil not exporting
avpriv_emms_asm() is paired with a library needing it
(if inline assembly and intrinsics were unavailable when building
the dependent library). I am not aware of this ever happening.
4. We would be forced to keep avpriv_emms_asm() around for ABI stability
even after it is no longer needed.

This commit therefore uses the STLIBOBJS, SHLIBOBJS approach
to duplicating it into each library on its own if needed.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2026-06-23 19:15:57 +02:00
Niklas Haas
30155f9c3a swscale/uops: split planes when generating ops lists
This updates uops_macros.h and the graph.c implementation in lockstep,
otherwise we'd have an intermediate commit with a bunch of broken formats.

Overall speedup=1.008x faster, min=0.144x max=5.550x

The min/max numbers are mostly measurement noise, but the real speedup for
affected formats is anywhere from 0.9x to around 2x-3x.

It's worth noting that the speedup for the formats which currently regress
is because we don't yet refcopy the planes, but I have another series in the
works which will take care of this soon.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
09c0cd6837 swscale/tests/sws_ops: split passes when printing ops lists
This affects a large number of conversions across the board, either:

1. Lifting a constant alpha/chroma clear out from the conversion pass:

 rgb24 16x16 -> yuva444p 16x16:
+  [ u8 $XXX] SWS_OP_CLEAR        : {255 _ _ _}
+  [ u8 XXXX] SWS_OP_WRITE        : 1 elem(s) planar >> 0, via {3}
+    ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
+ translated micro-ops:
+    u8_clear_x_1
+    u8_write_planar_x
+ Sub-pass #1:
   [ u8 +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
   [ u8 +++X] SWS_OP_CONVERT      : u8 -> f32
   [f32 ...X] SWS_OP_LINEAR       : matrix3+off3 [...]
   [f32 ...X] SWS_OP_DITHER       : 16x16 matrix + {0 3 2 -1}
   [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
-  [ u8 +++$] SWS_OP_CLEAR        : {_ _ _ 255}
-  [ u8 XXXX] SWS_OP_WRITE        : 4 elem(s) planar >> 0
+  [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) planar >> 0
     ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)

 gray 16x16 -> yuv444p 16x16:
+  [ u8 $$XX] SWS_OP_CLEAR        : {128 128 _ _}
+  [ u8 XXXX] SWS_OP_WRITE        : 2 elem(s) planar >> 0, via {2, 1}
+    ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
+ translated micro-ops:
+    u8_clear_xy_xx
+    u8_write_planar_xy
+ Sub-pass #1:
   [ u8 =XXX] SWS_OP_READ         : 1 elem(s) planar >> 0
   [ u8 =XXX] SWS_OP_CONVERT      : u8 -> f32
   [f32 .XXX] SWS_OP_LINEAR       : luma [...]
   [f32 .XXX] SWS_OP_DITHER       : 16x16 matrix + {0 -1 -1 -1}
   [f32 +XXX] SWS_OP_CONVERT      : f32 -> u8
-  [ u8 +$$X] SWS_OP_CLEAR        : {_ 128 128 _}
-  [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) planar >> 0
+  [ u8 XXXX] SWS_OP_WRITE        : 1 elem(s) planar >> 0
     ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
  translated micro-ops:
     u8_read_planar_x
     u8_to_f32_x
     f32_linear_x_x000x
     f32_dither_x_0_16x16
     f32_to_u8_x
-    u8_clear_yz_xx
-    u8_write_planar_xyz
+    u8_write_planar_x

or

2. Passing through a plane that was previously unmodified by an ops chain:

 gbrap 16x16 -> yuva444p 16x16:
-  [ u8 ====] SWS_OP_READ         : 4 elem(s) planar >> 0, via {2, 0, 1, 3}
-  [ u8 ====] SWS_OP_CONVERT      : u8 -> f32
-  [f32 ...=] SWS_OP_LINEAR       : matrix3+off3 [...]
-  [f32 ...=] SWS_OP_DITHER       : 16x16 matrix + {0 3 2 -1}
-  [f32 +++=] SWS_OP_CONVERT      : f32 -> u8
-  [ u8 XXXX] SWS_OP_WRITE        : 4 elem(s) planar >> 0
+  [ u8 =XXX] SWS_OP_READ         : 1 elem(s) planar >> 0, via {3}
+  [ u8 XXXX] SWS_OP_WRITE        : 1 elem(s) planar >> 0, via {3}
     ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
  translated micro-ops:
-    u8_read_planar_xyzw
-    u8_to_f32_xyzw
+    u8_read_planar_x
+    u8_write_planar_x
+ Sub-pass #1:
+  [ u8 ===X] SWS_OP_READ         : 3 elem(s) planar >> 0, via {2, 0, 1}
+  [ u8 ===X] SWS_OP_CONVERT      : u8 -> f32
+  [f32 ...X] SWS_OP_LINEAR       : matrix3+off3 [...]
+  [f32 ...X] SWS_OP_DITHER       : 16x16 matrix + {0 3 2 -1}
+  [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
+  [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) planar >> 0
+    ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
+ translated micro-ops:
+    u8_read_planar_xyz
+    u8_to_f32_xyz
     f32_linear_xyz_xxx0x_xxx0x_xxx0x
     f32_dither_xyz_0_3_2_16x16
-    f32_to_u8_xyzw
-    u8_write_planar_xyzw
+    f32_to_u8_xyz
+    u8_write_planar_xyz

(Op lists are abridged slightly for brevity)

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
0901ca4108 swscale/ops_dispatch: add option to split const/copied subpasses
This already helps performance as-is, but will help performance massively
once we add the ability for the memcpy backend to do a refcopy instead of
an actual copy.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
65197f67ff swscale/ops_dispatch: add option to link subpass outputs together
Not needed currently but will be used for parallel splits.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
291e849ee3 swscale/ops_optimizer: add ff_sws_op_list_split_planes()
Can be used to extract a reduced subset of operations affecting only certain
output planes, e.g. splitting an op list into a "memcpy" and a "non-memcpy"
part, or splitting apart op lists for independent or subsampled planes.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
ed12cf7515 swscale/uops: simplify uop mask printing slightly
We can re-use the helper we just added.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
4f6d5c1794 swscale/uops: add a helper to print a comp mask as a string
For debugging/logging purposes exclusively.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
b494a82321 swscale/ops: remove now-unneeded function
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
2eb254c5fd swscale/ops_dispatch: avoid possible infinite recursion
If the filter cannot actually be optimized into the read (for whatever
reason), this code would previously loop infinitely. Bail out cleanly
instead.

The FFSWAP is there to make the error message print the remainder (the one
containing unsplittable ops), rather than the noop list.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
848753352d swscale/ops_dispatch: substantially refactor subpass compilation
Instead of a loop with fixed structure, this function now recursively calls
itself as many times as needed to satisfy all criteria.

This is absolutely needed for the upcoming refactor which will allow for
also splitting apart ops lists as needed to e.g. handle partially subsampled
ops lists, which may need a complex sequence of filtering and merge steps
to be fully satisfied.

This does modify the way in which subpasses are compiled slightly, in that
each new subpass first tried again un-split, rather than a single split
resulting in all subsequent passes being split as well. This is mostly a
benign change, though it might matter one day.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
2509eb3e8c swscale/ops_optimizer: extract subpass splitting logic to helper
I will also delete the old name in an upcoming commit.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
409b870bd6 swscale/tests/sws_ops: only print actually compiled ops lists
We already have the unoptimized reference ops; printing each intermediate
stage here is just noise that makes this file harder to scroll through IMO.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
17154619e5 swscale/ops_dispatch: group compilation args into struct
This will make it easier to keep passing around these parameters in helper
functions in the upcoming refactor.

Take the opportunity to also rename the plain `compile` function to
`compile_single`.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
27ff50f6ab swscale/ops_dispatch: add SWS_OP_FLAG_DRY_RUN
Avoids us having to write awkward code like `output ? &pass : NULL`.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
e3d15d4606 swscale/ops_dispatch: move compile flags from ops.h
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
07e6ee54e7 swscale/ops_dispatch: move no-op check after optimization pass
Otherwise, this will false negative if the redundant operations haven't
been optimized away yet, resulting in unnecessary memcpy operations.

Fixes: a534156083
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
d86f0ae534 swscale/ops_dispatch: don't assume first operation is a read
Makes ff_sws_compile_pass() more robust; will be needed for plane splitting.
Besides, it's perfectly valid to have an operation list that starts with
e.g. SWS_OP_CLEAR.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
c1eee3d4d8 swscale/graph: add a function to allow reusing output buffers
Used for plane splitting, among other things. (e.g. plane passthrough)

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
aecca98488 swscale/ops: fix noop check ignoring read/write filters
Fixes a few cases where we previously didn't actually scale:

 gbrpf32le 16x16 -> gbrpf32le 16x32:
-  (no-op)
+  [f32 ...X] SWS_OP_READ         : 3 elem(s) planar >> 0 + 2 tap bilinear filter (V)
+    min: {nan nan nan _}, max: {nan nan nan _}
+  [f32 XXXX] SWS_OP_WRITE        : 3 elem(s) planar >> 0
+    ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
+ translated micro-ops:
+    f32_read_planar_fv_xyz_f32
+    u32_write_planar_xyz

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
cd2109b3a6 swscale/ops: fix stale comment
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
b992479539 swscale/ops: keep track of copied/cleared components
These represent components which have not (yet) been modified from their
input values (i.e. after a read, or clear). Such components can be
basically passed through via a refcopy (where applicable), as well as helping
to distinguish dissimilar types of plane for (plane splitting).

Generates benign diffs like:

 gray 16x16 -> yuv444p 16x16:
-  [ u8 +XXX] SWS_OP_READ         : 1 elem(s) planar >> 0
+  [ u8 =XXX] SWS_OP_READ         : 1 elem(s) planar >> 0
     min: {0 _ _ _}, max: {255 _ _ _}
-  [ u8 +XXX] SWS_OP_CONVERT      : u8 -> f32
+  [ u8 =XXX] SWS_OP_CONVERT      : u8 -> f32
     min: {0 _ _ _}, max: {255 _ _ _}
   [f32 .XXX] SWS_OP_LINEAR       : luma [[73/85 0 0 0 16] [0 1 0 0 0] [0 0 1 0 0] [0 0 0 1 0]]
     min: {16 _ _ _}, max: {235 _ _ _}
   [f32 .XXX] SWS_OP_DITHER       : 16x16 matrix + {0 -1 -1 -1}
     min: {16.001953 _ _ _}, max: {235.998047 _ _ _}
   [f32 +XXX] SWS_OP_CONVERT      : f32 -> u8
     min: {16 _ _ _}, max: {235 _ _ _}
-  [ u8 +++X] SWS_OP_CLEAR        : {_ 128 128 _}
+  [ u8 +$$X] SWS_OP_CLEAR        : {_ 128 128 _}
     min: {16 128 128 _}, max: {235 128 128 _}
   [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) planar >> 0
-    (X = unused, z = byteswapped, + = exact, 0 = zero)
+    ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
  translated micro-ops:
     u8_read_planar_x
     u8_to_f32_x
     f32_linear_x_x000x
     f32_dither_x_0_16x16
     f32_to_u8_x
     u8_clear_yz_xx
     u8_write_planar_xyz

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Ramiro Polla
d09330e578 swscale/aarch64/ops: mark more operations as type-invariant
This prevents the generation of a few more duplicate functions (where
there would be both f32 and u32 functions).

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-22 13:56:31 +02:00
Ramiro Polla
a016f34d17 swscale/aarch64/ops: remove redundant linear combinations
There is no easy optimization that can be triggered by knowing that the
offset is exactly 1. This led to identical functions being instantiated
for different params.

Also simplified the AVRational comparisons a bit.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-22 13:56:31 +02:00
Ramiro Polla
7fc637fc0c swscale/aarch64/ops: fix mask for swizzle ops
The mask for swizzle ops assumed that merely having a component assigned
to itself was enough to detect whether the swizzle was needed for that
component, but that wasn't correct. We should also take into account
whether the component is needed for the next operation or not.

Additionally, prevent duplicate functions from being generated by
clearing the swizzle index for unused components.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-22 13:56:31 +02:00
Ramiro Polla
083089e047 swscale/aarch64/ops: remove redundant single-component packed read/write
These functions are essentially the same as single-component planar
read/write, and are actually never instantiated. This was left over
from the initial implementation.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-22 13:56:31 +02:00
Niklas Haas
9cbd889670 swscale/x86/ops: add AVX2/SSE4 path for SWS_UOP_READ_PALETTE
The AVX2 is a fairly straightforward vpgatherdd + 4x4 transpose. The SSE4
fallback is an unrolled scalar loop, for lack of anything better to do.

checkasm:
 - CPU: AMD Ryzen 9 9950X3D 16-Core Processor (00B40F40)
 - Timing source: x86 (rdtsc)
 - Bench duration: 10000 µs per function (45898205 cycles)
 - Random seed: 2518020648

Benchmark results:
  name                             cycles (vs ref)
  u8_read_palette_xyzw_c:          2877.5
  u8_read_palette_xyzw_x86_sse4:   1951.9 ( 1.47x)
  u8_read_palette_xyzw_x86_avx2:   1051.6 ( 2.74x)

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-20 14:08:49 +00:00
Niklas Haas
d4b9b94ccb swscale/format: add support for AV_PIX_FMT_PAL8
This is handled using the new SWS_RW_PALETTE read op mode. We need to be a bit
careful to use the correct pixfmt descriptor downstream, because the descriptor
for PAL8 itself merely describes the *index*, rather than the actual data
values.

Accomplish this by introducing a new function to map the palette format to the
resulting pixel format after applying the palette (explicitly documented as
AV_PIX_FMT_RGB32).

+pal8 16x16 -> rgb24 16x16:
+  [ u8 +++X] SWS_OP_READ         : 4 elem(s) palette >> 0
+    min: {0 0 0 _}, max: {255 255 255 _}
+  [ u8 +++X] SWS_OP_SWIZZLE      : 2103
+    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_palette_xyzw
+    u8_permute_xz_zx
+    u8_write_packed_xyz
...

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-20 14:08:49 +00:00
Niklas Haas
ffd6855a50 swscale/vulkan/ops: properly error out for unsupported read modes
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-20 14:08:49 +00:00
Niklas Haas
6217350269 swscale/uops_backend: add SWS_UOP_READ_PALETTE reference implementation
This does not actually generate any code yet as the macro is still empty,
but that will change once I add support for generated palette reads to
the format handling code. This logic merely needs to be in place first
to avoid introducing broken intermediate states where palette uops are
generated but not implemented by the reference backend.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-20 14:08:49 +00:00
Niklas Haas
5163b05552 swscale/uops: add SWS_UOP_READ_PALETTE
This commit only adds the uop itself; it does not yet add any implementations.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-20 14:08:49 +00:00