| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (C) 2026 Ramiro Polla | ||
| 3 | * | ||
| 4 | * This file is part of FFmpeg. | ||
| 5 | * | ||
| 6 | * FFmpeg is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU Lesser General Public | ||
| 8 | * License as published by the Free Software Foundation; either | ||
| 9 | * version 2.1 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * Lesser General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU Lesser General Public | ||
| 17 | * License along with FFmpeg; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <stdio.h> | ||
| 22 | |||
| 23 | #include "libavutil/avassert.h" | ||
| 24 | #include "libavutil/bprint.h" | ||
| 25 | #include "libavutil/mem.h" | ||
| 26 | #include "libavutil/tree.h" | ||
| 27 | #include "libswscale/graph.h" | ||
| 28 | #include "libswscale/ops.h" | ||
| 29 | #include "libswscale/ops_chain.h" | ||
| 30 | #include "libswscale/op_list_gen_template.c" | ||
| 31 | #include "libswscale/ops_dispatch.h" | ||
| 32 | |||
| 33 | #include "libswscale/aarch64/ops_impl_conv.c" | ||
| 34 | |||
| 35 | #ifdef _WIN32 | ||
| 36 | #include <io.h> | ||
| 37 | #include <fcntl.h> | ||
| 38 | #endif | ||
| 39 | |||
| 40 | /*********************************************************************/ | ||
| 41 | 51683 | static uint16_t clear_to_mask(const SwsClearUOp *clear) | |
| 42 | { | ||
| 43 | 51683 | uint16_t mask = 0; | |
| 44 |
2/2✓ Branch 0 taken 206732 times.
✓ Branch 1 taken 51683 times.
|
258415 | for (int i = 0; i < 4; i++) { |
| 45 |
2/2✓ Branch 0 taken 196789 times.
✓ Branch 1 taken 9943 times.
|
206732 | if (clear->zero & SWS_COMP(i)) { |
| 46 | /* no-op */ | ||
| 47 |
2/2✓ Branch 0 taken 23016 times.
✓ Branch 1 taken 173773 times.
|
196789 | } else if (clear->one & SWS_COMP(i)) { |
| 48 | 23016 | NIBBLE_SET(mask, i, 1); | |
| 49 | } else { | ||
| 50 | 173773 | NIBBLE_SET(mask, i, 0xf); | |
| 51 | } | ||
| 52 | } | ||
| 53 | 51683 | return mask; | |
| 54 | } | ||
| 55 | |||
| 56 | 104349 | static uint64_t move_to_mask(const SwsMoveUOp *move) | |
| 57 | { | ||
| 58 | 104349 | uint64_t mask = 0; | |
| 59 |
2/2✓ Branch 0 taken 325168 times.
✓ Branch 1 taken 104349 times.
|
429517 | for (int i = 0; i < move->num_moves; i++) { |
| 60 |
2/2✓ Branch 0 taken 254106 times.
✓ Branch 1 taken 71062 times.
|
325168 | uint8_t dst = move->dst[i] < 0 ? 0xf : move->dst[i]; |
| 61 |
2/2✓ Branch 0 taken 254106 times.
✓ Branch 1 taken 71062 times.
|
325168 | uint8_t src = move->src[i] < 0 ? 0xf : move->src[i]; |
| 62 | 325168 | uint64_t pair = src | (dst << 4); | |
| 63 | 325168 | mask |= pair << (i * 8); | |
| 64 | } | ||
| 65 | 104349 | return mask; | |
| 66 | } | ||
| 67 | |||
| 68 | 46468 | static uint16_t pack_to_mask(const SwsPackUOp *pack) | |
| 69 | { | ||
| 70 | 46468 | uint16_t mask = 0; | |
| 71 |
2/2✓ Branch 0 taken 185872 times.
✓ Branch 1 taken 46468 times.
|
232340 | for (int i = 0; i < 4; i++) |
| 72 | 185872 | NIBBLE_SET(mask, i, pack->pattern[i]); | |
| 73 | 46468 | return mask; | |
| 74 | } | ||
| 75 | |||
| 76 | 132642 | static uint64_t linear_to_mask(const SwsLinearUOp *linear) | |
| 77 | { | ||
| 78 | 132642 | uint64_t mask = 0; | |
| 79 |
2/2✓ Branch 0 taken 530568 times.
✓ Branch 1 taken 132642 times.
|
663210 | for (int i = 0; i < 4; i++) { |
| 80 |
2/2✓ Branch 0 taken 2652840 times.
✓ Branch 1 taken 530568 times.
|
3183408 | for (int j = 0; j < 5; j++) { |
| 81 |
2/2✓ Branch 0 taken 2122272 times.
✓ Branch 1 taken 530568 times.
|
2652840 | int jj = (j == 0) ? 4 : (j - 1); |
| 82 |
2/2✓ Branch 0 taken 8193 times.
✓ Branch 1 taken 2644647 times.
|
2652840 | if (linear->one & SWS_MASK(i, jj)) |
| 83 | 8193 | mask |= 1ULL << (2 * ((5 * i + j))); | |
| 84 |
2/2✓ Branch 0 taken 870251 times.
✓ Branch 1 taken 1774396 times.
|
2644647 | else if (!(linear->zero & SWS_MASK(i, jj))) |
| 85 | 870251 | mask |= 3ULL << (2 * ((5 * i + j))); | |
| 86 | } | ||
| 87 | } | ||
| 88 | 132642 | return mask; | |
| 89 | } | ||
| 90 | |||
| 91 | 43980 | static uint16_t dither_to_mask(const SwsAArch64OpImplParams *p, const SwsDitherUOp *dither) | |
| 92 | { | ||
| 93 | 43980 | uint16_t mask = 0; | |
| 94 |
2/2✓ Branch 0 taken 175920 times.
✓ Branch 1 taken 43980 times.
|
219900 | for (int i = 0; i < 4; i++) { |
| 95 |
2/2✓ Branch 0 taken 115279 times.
✓ Branch 1 taken 60641 times.
|
175920 | if (p->mask & SWS_COMP(i)) { |
| 96 | 115279 | NIBBLE_SET(mask, i, dither->y_offset[i]); | |
| 97 | } else { | ||
| 98 | 60641 | NIBBLE_SET(mask, i, 0xf); | |
| 99 | } | ||
| 100 | } | ||
| 101 | 43980 | return mask; | |
| 102 | } | ||
| 103 | |||
| 104 | 1096180 | static int aarch64_op_impl_cmp(const void *a, const void *b) | |
| 105 | { | ||
| 106 | 1096180 | const SwsAArch64OpImplParams *pa = (const SwsAArch64OpImplParams *) a; | |
| 107 | 1096180 | const SwsAArch64OpImplParams *pb = (const SwsAArch64OpImplParams *) b; | |
| 108 | 1096180 | const SwsUOpParams *para = &pa->par; | |
| 109 | 1096180 | const SwsUOpParams *parb = &pb->par; | |
| 110 | |||
| 111 |
2/2✓ Branch 0 taken 592320 times.
✓ Branch 1 taken 503860 times.
|
1096180 | if (pa->uop != pb->uop) |
| 112 | 592320 | return (int) pa->uop - pb->uop; | |
| 113 | |||
| 114 |
7/7✓ Branch 0 taken 52132 times.
✓ Branch 1 taken 23219 times.
✓ Branch 2 taken 7394 times.
✓ Branch 3 taken 25820 times.
✓ Branch 4 taken 66305 times.
✓ Branch 5 taken 21979 times.
✓ Branch 6 taken 307011 times.
|
503860 | switch (pa->uop) { |
| 115 | 52132 | case SWS_UOP_PERMUTE: | |
| 116 | case SWS_UOP_COPY: { | ||
| 117 | 52132 | uint64_t ia = move_to_mask(¶->move); | |
| 118 | 52132 | uint64_t ib = move_to_mask(&parb->move); | |
| 119 |
2/2✓ Branch 0 taken 31553 times.
✓ Branch 1 taken 20579 times.
|
52132 | if (ia != ib) |
| 120 |
2/2✓ Branch 0 taken 12160 times.
✓ Branch 1 taken 19393 times.
|
31553 | return (int64_t) (ia - ib) < 0 ? -1 : 1; |
| 121 | 20579 | break; | |
| 122 | } | ||
| 123 | 23219 | case SWS_UOP_UNPACK: | |
| 124 | case SWS_UOP_PACK: { | ||
| 125 | 23219 | uint16_t ia = pack_to_mask(¶->pack); | |
| 126 | 23219 | uint16_t ib = pack_to_mask(&parb->pack); | |
| 127 |
2/2✓ Branch 0 taken 15123 times.
✓ Branch 1 taken 8096 times.
|
23219 | if (ia != ib) |
| 128 | 15123 | return (int) ia - ib; | |
| 129 | 8096 | break; | |
| 130 | } | ||
| 131 | 7394 | case SWS_UOP_LSHIFT: | |
| 132 | case SWS_UOP_RSHIFT: | ||
| 133 |
2/2✓ Branch 0 taken 2715 times.
✓ Branch 1 taken 4679 times.
|
7394 | if (para->shift.amount != parb->shift.amount) |
| 134 | 2715 | return (int) para->shift.amount - parb->shift.amount; | |
| 135 | 4679 | break; | |
| 136 | 25820 | case SWS_UOP_CLEAR: { | |
| 137 | 25820 | uint16_t ia = clear_to_mask(¶->clear); | |
| 138 | 25820 | uint16_t ib = clear_to_mask(&parb->clear); | |
| 139 |
2/2✓ Branch 0 taken 10636 times.
✓ Branch 1 taken 15184 times.
|
25820 | if (ia != ib) |
| 140 | 10636 | return (int) ia - ib; | |
| 141 | 15184 | break; | |
| 142 | } | ||
| 143 | 66305 | case SWS_UOP_LINEAR: | |
| 144 | case SWS_UOP_LINEAR_FMA: { | ||
| 145 | 66305 | uint64_t ia = linear_to_mask(¶->lin); | |
| 146 | 66305 | uint64_t ib = linear_to_mask(&parb->lin); | |
| 147 |
2/2✓ Branch 0 taken 44677 times.
✓ Branch 1 taken 21628 times.
|
66305 | if (ia != ib) |
| 148 |
2/2✓ Branch 0 taken 18454 times.
✓ Branch 1 taken 26223 times.
|
44677 | return (int64_t) (ia - ib) < 0 ? -1 : 1; |
| 149 | 21628 | break; | |
| 150 | } | ||
| 151 | 21979 | case SWS_UOP_DITHER: { | |
| 152 | 21979 | uint16_t ia = dither_to_mask(pa, ¶->dither); | |
| 153 | 21979 | uint16_t ib = dither_to_mask(pb, &parb->dither); | |
| 154 |
2/2✓ Branch 0 taken 13413 times.
✓ Branch 1 taken 8566 times.
|
21979 | if (ia != ib) |
| 155 | 13413 | return (int) ia - ib; | |
| 156 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8566 times.
|
8566 | if (para->dither.size_log2 != parb->dither.size_log2) |
| 157 | ✗ | return (int) para->dither.size_log2 - parb->dither.size_log2; | |
| 158 | 8566 | break; | |
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 |
2/2✓ Branch 0 taken 66809 times.
✓ Branch 1 taken 318934 times.
|
385743 | if (pa->block_size != pb->block_size) |
| 163 | 66809 | return (int) pa->block_size - pb->block_size; | |
| 164 |
2/2✓ Branch 0 taken 74048 times.
✓ Branch 1 taken 244886 times.
|
318934 | if (pa->type != pb->type) |
| 165 | 74048 | return (int) pa->type - pb->type; | |
| 166 |
2/2✓ Branch 0 taken 90023 times.
✓ Branch 1 taken 154863 times.
|
244886 | if (pa->mask != pb->mask) |
| 167 | 90023 | return (int) pa->mask - pb->mask; | |
| 168 | |||
| 169 | 154863 | return 0; | |
| 170 | } | ||
| 171 | |||
| 172 | /*********************************************************************/ | ||
| 173 | /* Insert the SwsAArch64OpImplParams structure into the AVTreeNode. */ | ||
| 174 | 155276 | static int aarch64_collect_op(const SwsAArch64OpImplParams *params, struct AVTreeNode **root) | |
| 175 | { | ||
| 176 | 155276 | int ret = 0; | |
| 177 | |||
| 178 | 155276 | struct AVTreeNode *node = av_tree_node_alloc(); | |
| 179 | 155276 | SwsAArch64OpImplParams *copy = av_memdup(params, sizeof(*params)); | |
| 180 |
2/4✓ Branch 0 taken 155276 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 155276 times.
|
155276 | if (!node || !copy) { |
| 181 | ✗ | ret = AVERROR(ENOMEM); | |
| 182 | ✗ | goto error; | |
| 183 | } | ||
| 184 | 155276 | av_tree_insert(root, copy, aarch64_op_impl_cmp, &node); | |
| 185 |
2/2✓ Branch 0 taken 154863 times.
✓ Branch 1 taken 413 times.
|
155276 | if (!node) |
| 186 | 413 | copy = NULL; | |
| 187 | |||
| 188 | 154863 | error: | |
| 189 | 155276 | av_free(node); | |
| 190 | 155276 | av_free(copy); | |
| 191 | 155276 | return ret; | |
| 192 | } | ||
| 193 | |||
| 194 | 19519 | static int collect_ops_compile(SwsContext *ctx, const SwsOpList *ops, | |
| 195 | SwsCompiledOp *out) | ||
| 196 | { | ||
| 197 | 19519 | struct AVTreeNode **root = (struct AVTreeNode **) ctx->opaque; | |
| 198 | int ret; | ||
| 199 | |||
| 200 | /* Use at most two full vregs during the widest precision section */ | ||
| 201 |
2/2✓ Branch 1 taken 15967 times.
✓ Branch 2 taken 3552 times.
|
19519 | int block_size = (ff_sws_op_list_max_size(ops) == 4) ? 8 : 16; |
| 202 | |||
| 203 |
2/2✓ Branch 0 taken 144578 times.
✓ Branch 1 taken 19519 times.
|
164097 | for (int i = 0; i < ops->num_ops; i++) { |
| 204 | 144578 | SwsAArch64OpImplParams params = { 0 }; | |
| 205 | 144578 | ret = convert_to_aarch64_impl(ctx, ops, i, block_size, ¶ms); | |
| 206 |
2/2✓ Branch 0 taken 132 times.
✓ Branch 1 taken 144446 times.
|
144578 | if (ret == AVERROR(ENOTSUP)) |
| 207 | 132 | continue; | |
| 208 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 144446 times.
|
144446 | if (ret < 0) |
| 209 | ✗ | goto end; | |
| 210 | 144446 | ret = aarch64_collect_op(¶ms, root); | |
| 211 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 144446 times.
|
144446 | if (ret < 0) |
| 212 | ✗ | goto end; | |
| 213 |
2/2✓ Branch 0 taken 10830 times.
✓ Branch 1 taken 133616 times.
|
144446 | if (params.uop == SWS_UOP_LINEAR_FMA) { |
| 214 | /** | ||
| 215 | * Generate both sets of linear op functions that do use | ||
| 216 | * and do not use fmla (selected by SWS_BITEXACT). | ||
| 217 | */ | ||
| 218 | 10830 | params.uop = SWS_UOP_LINEAR; | |
| 219 | 10830 | ret = aarch64_collect_op(¶ms, root); | |
| 220 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10830 times.
|
10830 | if (ret < 0) |
| 221 | ✗ | goto end; | |
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | 19519 | *out = (SwsCompiledOp) { 0 }; | |
| 226 | 19519 | ret = 0; | |
| 227 | |||
| 228 | 19519 | end: | |
| 229 | 19519 | return ret; | |
| 230 | } | ||
| 231 | |||
| 232 | static const SwsOpBackend backend_collect = { | ||
| 233 | .name = "collect_ops", | ||
| 234 | .compile = collect_ops_compile, | ||
| 235 | }; | ||
| 236 | |||
| 237 | /*********************************************************************/ | ||
| 238 | 70224 | static int register_op(SwsContext *ctx, void *opaque, SwsOpList *ops) | |
| 239 | { | ||
| 240 | /* Skip ops lists which include filtering, since this is still not | ||
| 241 | * supported. */ | ||
| 242 |
2/2✓ Branch 0 taken 278146 times.
✓ Branch 1 taken 17556 times.
|
295702 | for (int i = 0; i < ops->num_ops; i++) { |
| 243 | 278146 | const SwsOp *op = &ops->ops[i]; | |
| 244 |
3/3✓ Branch 0 taken 87780 times.
✓ Branch 1 taken 39996 times.
✓ Branch 2 taken 150370 times.
|
278146 | switch (op->op) { |
| 245 | 87780 | case SWS_OP_READ: | |
| 246 | case SWS_OP_WRITE: | ||
| 247 |
2/2✓ Branch 0 taken 12672 times.
✓ Branch 1 taken 75108 times.
|
87780 | if (op->rw.filter.op) |
| 248 | 12672 | return 0; | |
| 249 | 75108 | break; | |
| 250 | 39996 | case SWS_OP_FILTER_H: | |
| 251 | case SWS_OP_FILTER_V: | ||
| 252 | 39996 | return 0; | |
| 253 | } | ||
| 254 | } | ||
| 255 | |||
| 256 | /* ff_sws_compile_pass() takes over ownership of `ops` */ | ||
| 257 | 17556 | SwsOpList *copy = ff_sws_op_list_duplicate(ops); | |
| 258 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17556 times.
|
17556 | if (!copy) |
| 259 | ✗ | return AVERROR(ENOMEM); | |
| 260 | |||
| 261 | 17556 | const int flags = SWS_OP_FLAG_DRY_RUN | SWS_OP_FLAG_SPLIT_MEMCPY; | |
| 262 | 17556 | return ff_sws_compile_pass(opaque, &backend_collect, ©, flags, NULL, NULL); | |
| 263 | } | ||
| 264 | |||
| 265 | /*********************************************************************/ | ||
| 266 | static const char op_type_names[SWS_UOP_TYPE_NB][16] = { | ||
| 267 | [SWS_UOP_READ_BIT ] = "read_bit", | ||
| 268 | [SWS_UOP_READ_NIBBLE ] = "read_nibble", | ||
| 269 | [SWS_UOP_READ_PACKED ] = "read_packed", | ||
| 270 | [SWS_UOP_READ_PLANAR ] = "read_planar", | ||
| 271 | [SWS_UOP_WRITE_BIT ] = "write_bit", | ||
| 272 | [SWS_UOP_WRITE_NIBBLE ] = "write_nibble", | ||
| 273 | [SWS_UOP_WRITE_PACKED ] = "write_packed", | ||
| 274 | [SWS_UOP_WRITE_PLANAR ] = "write_planar", | ||
| 275 | [SWS_UOP_SWAP_BYTES ] = "swap_bytes", | ||
| 276 | [SWS_UOP_PERMUTE ] = "permute", | ||
| 277 | [SWS_UOP_COPY ] = "copy", | ||
| 278 | [SWS_UOP_UNPACK ] = "unpack", | ||
| 279 | [SWS_UOP_PACK ] = "pack", | ||
| 280 | [SWS_UOP_LSHIFT ] = "lshift", | ||
| 281 | [SWS_UOP_RSHIFT ] = "rshift", | ||
| 282 | [SWS_UOP_CLEAR ] = "clear", | ||
| 283 | [SWS_UOP_TO_U8 ] = "to_u8", | ||
| 284 | [SWS_UOP_TO_U16 ] = "to_u16", | ||
| 285 | [SWS_UOP_TO_U32 ] = "to_u32", | ||
| 286 | [SWS_UOP_TO_F32 ] = "to_f32", | ||
| 287 | [SWS_UOP_EXPAND_PAIR ] = "expand_pair", | ||
| 288 | [SWS_UOP_EXPAND_QUAD ] = "expand_quad", | ||
| 289 | [SWS_UOP_MIN ] = "min", | ||
| 290 | [SWS_UOP_MAX ] = "max", | ||
| 291 | [SWS_UOP_SCALE ] = "scale", | ||
| 292 | [SWS_UOP_LINEAR ] = "linear", | ||
| 293 | [SWS_UOP_LINEAR_FMA ] = "linear_fma", | ||
| 294 | [SWS_UOP_DITHER ] = "dither", | ||
| 295 | }; | ||
| 296 | |||
| 297 | static const char pixel_type_names[SWS_PIXEL_TYPE_NB][4] = { | ||
| 298 | [SWS_PIXEL_U8 ] = "u8", | ||
| 299 | [SWS_PIXEL_U16] = "u16", | ||
| 300 | [SWS_PIXEL_U32] = "u32", | ||
| 301 | [SWS_PIXEL_F32] = "f32", | ||
| 302 | }; | ||
| 303 | |||
| 304 | static const char uop_types[SWS_UOP_TYPE_NB][32] = { | ||
| 305 | [SWS_UOP_READ_BIT ] = "SWS_UOP_READ_BIT", | ||
| 306 | [SWS_UOP_READ_NIBBLE ] = "SWS_UOP_READ_NIBBLE", | ||
| 307 | [SWS_UOP_READ_PACKED ] = "SWS_UOP_READ_PACKED", | ||
| 308 | [SWS_UOP_READ_PLANAR ] = "SWS_UOP_READ_PLANAR", | ||
| 309 | [SWS_UOP_WRITE_BIT ] = "SWS_UOP_WRITE_BIT", | ||
| 310 | [SWS_UOP_WRITE_NIBBLE ] = "SWS_UOP_WRITE_NIBBLE", | ||
| 311 | [SWS_UOP_WRITE_PACKED ] = "SWS_UOP_WRITE_PACKED", | ||
| 312 | [SWS_UOP_WRITE_PLANAR ] = "SWS_UOP_WRITE_PLANAR", | ||
| 313 | [SWS_UOP_SWAP_BYTES ] = "SWS_UOP_SWAP_BYTES", | ||
| 314 | [SWS_UOP_PERMUTE ] = "SWS_UOP_PERMUTE", | ||
| 315 | [SWS_UOP_COPY ] = "SWS_UOP_COPY", | ||
| 316 | [SWS_UOP_UNPACK ] = "SWS_UOP_UNPACK", | ||
| 317 | [SWS_UOP_PACK ] = "SWS_UOP_PACK", | ||
| 318 | [SWS_UOP_LSHIFT ] = "SWS_UOP_LSHIFT", | ||
| 319 | [SWS_UOP_RSHIFT ] = "SWS_UOP_RSHIFT", | ||
| 320 | [SWS_UOP_CLEAR ] = "SWS_UOP_CLEAR", | ||
| 321 | [SWS_UOP_TO_U8 ] = "SWS_UOP_TO_U8", | ||
| 322 | [SWS_UOP_TO_U16 ] = "SWS_UOP_TO_U16", | ||
| 323 | [SWS_UOP_TO_U32 ] = "SWS_UOP_TO_U32", | ||
| 324 | [SWS_UOP_TO_F32 ] = "SWS_UOP_TO_F32", | ||
| 325 | [SWS_UOP_EXPAND_PAIR ] = "SWS_UOP_EXPAND_PAIR", | ||
| 326 | [SWS_UOP_EXPAND_QUAD ] = "SWS_UOP_EXPAND_QUAD", | ||
| 327 | [SWS_UOP_MIN ] = "SWS_UOP_MIN", | ||
| 328 | [SWS_UOP_MAX ] = "SWS_UOP_MAX", | ||
| 329 | [SWS_UOP_SCALE ] = "SWS_UOP_SCALE", | ||
| 330 | [SWS_UOP_LINEAR ] = "SWS_UOP_LINEAR", | ||
| 331 | [SWS_UOP_LINEAR_FMA ] = "SWS_UOP_LINEAR_FMA", | ||
| 332 | [SWS_UOP_DITHER ] = "SWS_UOP_DITHER", | ||
| 333 | }; | ||
| 334 | |||
| 335 | static const char pixel_types[SWS_PIXEL_TYPE_NB][32] = { | ||
| 336 | [SWS_PIXEL_U8 ] = "SWS_PIXEL_U8", | ||
| 337 | [SWS_PIXEL_U16] = "SWS_PIXEL_U16", | ||
| 338 | [SWS_PIXEL_U32] = "SWS_PIXEL_U32", | ||
| 339 | [SWS_PIXEL_F32] = "SWS_PIXEL_F32", | ||
| 340 | }; | ||
| 341 | |||
| 342 | 413 | static void serialize_op(AVBPrint *bp, const SwsAArch64OpImplParams *params) | |
| 343 | { | ||
| 344 | #define FUNC_NAME_WIDTH 45 | ||
| 345 | #define UOP_NAME_WIDTH 21 | ||
| 346 | #define TYPE_NAME_WIDTH 14 | ||
| 347 | |||
| 348 | 413 | const SwsUOpParams *par = ¶ms->par; | |
| 349 | |||
| 350 | char func_name[FUNC_NAME_WIDTH + 2]; | ||
| 351 | 413 | snprintf(func_name, sizeof(func_name), "ff_sws_%s", op_type_names[params->uop]); | |
| 352 |
7/7✓ Branch 0 taken 85 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 43 times.
✓ Branch 4 taken 32 times.
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 169 times.
|
413 | switch (params->uop) { |
| 353 | 85 | case SWS_UOP_PERMUTE: | |
| 354 | case SWS_UOP_COPY: | ||
| 355 | 85 | av_strlcatf(func_name, sizeof(func_name), "_%012" PRIx64, move_to_mask(&par->move)); | |
| 356 | 85 | break; | |
| 357 | 30 | case SWS_UOP_UNPACK: | |
| 358 | case SWS_UOP_PACK: | ||
| 359 | 30 | av_strlcatf(func_name, sizeof(func_name), "_%04x", pack_to_mask(&par->pack)); | |
| 360 | 30 | break; | |
| 361 | 32 | case SWS_UOP_LSHIFT: | |
| 362 | case SWS_UOP_RSHIFT: | ||
| 363 | 32 | av_strlcatf(func_name, sizeof(func_name), "_%u", par->shift.amount); | |
| 364 | 32 | break; | |
| 365 | 43 | case SWS_UOP_CLEAR: | |
| 366 | 43 | av_strlcatf(func_name, sizeof(func_name), "_%04x", clear_to_mask(&par->clear)); | |
| 367 | 43 | break; | |
| 368 | 32 | case SWS_UOP_LINEAR: | |
| 369 | case SWS_UOP_LINEAR_FMA: | ||
| 370 | 32 | av_strlcatf(func_name, sizeof(func_name), "_%010" PRIx64, linear_to_mask(&par->lin)); | |
| 371 | 32 | break; | |
| 372 | 22 | case SWS_UOP_DITHER: | |
| 373 | 22 | av_strlcatf(func_name, sizeof(func_name), "_%04x_%u", dither_to_mask(params, &par->dither), par->dither.size_log2); | |
| 374 | 22 | break; | |
| 375 | } | ||
| 376 | 413 | av_strlcatf(func_name, sizeof(func_name), "_%u_%s_%04x_neon,", | |
| 377 | 413 | params->block_size, pixel_type_names[params->type], nibble_mask(params->mask)); | |
| 378 | |||
| 379 | char uop_name[UOP_NAME_WIDTH + 2]; | ||
| 380 | 413 | snprintf(uop_name, sizeof(uop_name), "%s,", uop_types[params->uop]); | |
| 381 | |||
| 382 | char type_name[TYPE_NAME_WIDTH + 2]; | ||
| 383 | 413 | snprintf(type_name, sizeof(type_name), "%s,", pixel_types[params->type]); | |
| 384 | |||
| 385 | 413 | av_bprintf(bp, "ENTRY(%-*s { .uop = %-*s .block_size = %2u, .type = %-*s .mask = 0x%x", | |
| 386 | FUNC_NAME_WIDTH, func_name, UOP_NAME_WIDTH, uop_name, | ||
| 387 | 413 | params->block_size, TYPE_NAME_WIDTH, type_name, params->mask); | |
| 388 |
7/7✓ Branch 0 taken 85 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 43 times.
✓ Branch 4 taken 32 times.
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 169 times.
|
413 | switch (params->uop) { |
| 389 | 85 | case SWS_UOP_PERMUTE: | |
| 390 | case SWS_UOP_COPY: | ||
| 391 | 85 | av_bprintf(bp, ", .par.move = { .num_moves = %d, .dst = {%d, %d, %d, %d, %d, %d}, .src = {%d, %d, %d, %d, %d, %d} }", | |
| 392 | 85 | par->move.num_moves, | |
| 393 | 85 | par->move.dst[0], par->move.dst[1], par->move.dst[2], | |
| 394 | 85 | par->move.dst[3], par->move.dst[4], par->move.dst[5], | |
| 395 | 85 | par->move.src[0], par->move.src[1], par->move.src[2], | |
| 396 | 85 | par->move.src[3], par->move.src[4], par->move.src[5]); | |
| 397 | 85 | break; | |
| 398 | 30 | case SWS_UOP_UNPACK: | |
| 399 | case SWS_UOP_PACK: | ||
| 400 | 30 | av_bprintf(bp, ", .par.pack = { .pattern = {%d, %d, %d, %d} }", | |
| 401 | 30 | par->pack.pattern[0], par->pack.pattern[1], | |
| 402 | 30 | par->pack.pattern[2], par->pack.pattern[3]); | |
| 403 | 30 | break; | |
| 404 | 32 | case SWS_UOP_LSHIFT: | |
| 405 | case SWS_UOP_RSHIFT: | ||
| 406 | 32 | av_bprintf(bp, ", .par.shift = { .amount = %u }", par->shift.amount); | |
| 407 | 32 | break; | |
| 408 | 43 | case SWS_UOP_CLEAR: | |
| 409 | 43 | av_bprintf(bp, ", .par.clear = { .one = 0x%0x, .zero = 0x%0x }", par->clear.one, par->clear.zero); | |
| 410 | 43 | break; | |
| 411 | 32 | case SWS_UOP_LINEAR: | |
| 412 | case SWS_UOP_LINEAR_FMA: | ||
| 413 | 32 | av_bprintf(bp, ", .par.lin = { .one = 0x%x, .zero = 0x%x }", par->lin.one, par->lin.zero); | |
| 414 | 32 | break; | |
| 415 | 22 | case SWS_UOP_DITHER: | |
| 416 | 22 | av_bprintf(bp, ", .par.dither = { .y_offset = {%u, %u, %u, %u}, .size_log2 = %u }", | |
| 417 | 22 | par->dither.y_offset[0], par->dither.y_offset[1], | |
| 418 | 22 | par->dither.y_offset[2], par->dither.y_offset[3], | |
| 419 | 22 | par->dither.size_log2); | |
| 420 | 22 | break; | |
| 421 | } | ||
| 422 | 413 | av_bprintf(bp, " })"); | |
| 423 | 413 | } | |
| 424 | |||
| 425 | /* Serialize SwsAArch64OpImplParams for one function. */ | ||
| 426 | 413 | static int print_op(void *opaque, void *elem) | |
| 427 | { | ||
| 428 | 413 | SwsAArch64OpImplParams *params = (SwsAArch64OpImplParams *) elem; | |
| 429 | 413 | FILE *fp = (FILE *) opaque; | |
| 430 | |||
| 431 | AVBPrint bp; | ||
| 432 | 413 | av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); | |
| 433 | 413 | serialize_op(&bp, params); | |
| 434 | 413 | fprintf(fp, "%s\n", bp.str); | |
| 435 | 413 | av_bprint_finalize(&bp, NULL); | |
| 436 | |||
| 437 | 413 | av_free(params); | |
| 438 | |||
| 439 | 413 | return 0; | |
| 440 | } | ||
| 441 | |||
| 442 | /*********************************************************************/ | ||
| 443 | 1 | int main(int argc, char *argv[]) | |
| 444 | { | ||
| 445 | 1 | struct AVTreeNode *root = NULL; | |
| 446 | 1 | int ret = 1; | |
| 447 | |||
| 448 | #ifdef _WIN32 | ||
| 449 | _setmode(_fileno(stdout), _O_BINARY); | ||
| 450 | #endif | ||
| 451 | |||
| 452 | 1 | SwsContext *ctx = sws_alloc_context(); | |
| 453 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!ctx) |
| 454 | ✗ | goto fail; | |
| 455 | |||
| 456 | 1 | SwsGraph *graph = ff_sws_graph_alloc(); | |
| 457 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!graph) |
| 458 | ✗ | goto fail; | |
| 459 | |||
| 460 | 1 | graph->ctx = ctx; | |
| 461 | 1 | ctx->opaque = &root; | |
| 462 | |||
| 463 | 1 | ret = ff_sws_enum_op_lists(ctx, graph, NULL, AV_PIX_FMT_NONE, AV_PIX_FMT_NONE, | |
| 464 | register_op); | ||
| 465 | |||
| 466 | /** | ||
| 467 | * Generate a C file with all the unique function parameter entries | ||
| 468 | * collected by aarch64_enum_ops(). | ||
| 469 | */ | ||
| 470 | 1 | printf("/*\n"); | |
| 471 | 1 | printf(" * This file is automatically generated. Do not edit manually.\n"); | |
| 472 | 1 | printf(" * To regenerate, run: make fate-sws-ops-entries-aarch64 GEN=1\n"); | |
| 473 | 1 | printf(" */\n"); | |
| 474 | 1 | printf("\n"); | |
| 475 | 1 | av_tree_enumerate(root, stdout, NULL, print_op); | |
| 476 | |||
| 477 | 1 | ff_sws_graph_free(&graph); | |
| 478 | |||
| 479 | 1 | fail: | |
| 480 | 1 | av_tree_destroy(root); | |
| 481 | 1 | sws_free_context(&ctx); | |
| 482 | 1 | return ret; | |
| 483 | } | ||
| 484 |