| 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 | 50590 | static uint16_t clear_to_mask(const SwsClearUOp *clear) | |
| 42 | { | ||
| 43 | 50590 | uint16_t mask = 0; | |
| 44 |
2/2✓ Branch 0 taken 202360 times.
✓ Branch 1 taken 50590 times.
|
252950 | for (int i = 0; i < 4; i++) { |
| 45 |
2/2✓ Branch 0 taken 192619 times.
✓ Branch 1 taken 9741 times.
|
202360 | if (clear->zero & SWS_COMP(i)) { |
| 46 | /* no-op */ | ||
| 47 |
2/2✓ Branch 0 taken 23096 times.
✓ Branch 1 taken 169523 times.
|
192619 | } else if (clear->one & SWS_COMP(i)) { |
| 48 | 23096 | NIBBLE_SET(mask, i, 1); | |
| 49 | } else { | ||
| 50 | 169523 | NIBBLE_SET(mask, i, 0xf); | |
| 51 | } | ||
| 52 | } | ||
| 53 | 50590 | return mask; | |
| 54 | } | ||
| 55 | |||
| 56 | 102956 | static uint64_t move_to_mask(const SwsMoveUOp *move) | |
| 57 | { | ||
| 58 | 102956 | uint64_t mask = 0; | |
| 59 |
2/2✓ Branch 0 taken 313234 times.
✓ Branch 1 taken 102956 times.
|
416190 | for (int i = 0; i < move->num_moves; i++) { |
| 60 |
2/2✓ Branch 0 taken 244950 times.
✓ Branch 1 taken 68284 times.
|
313234 | uint8_t dst = move->dst[i] < 0 ? 0xf : move->dst[i]; |
| 61 |
2/2✓ Branch 0 taken 244950 times.
✓ Branch 1 taken 68284 times.
|
313234 | uint8_t src = move->src[i] < 0 ? 0xf : move->src[i]; |
| 62 | 313234 | uint64_t pair = src | (dst << 4); | |
| 63 | 313234 | mask |= pair << (i * 8); | |
| 64 | } | ||
| 65 | 102956 | return mask; | |
| 66 | } | ||
| 67 | |||
| 68 | 39762 | static uint16_t pack_to_mask(const SwsPackUOp *pack) | |
| 69 | { | ||
| 70 | 39762 | uint16_t mask = 0; | |
| 71 |
2/2✓ Branch 0 taken 159048 times.
✓ Branch 1 taken 39762 times.
|
198810 | for (int i = 0; i < 4; i++) |
| 72 | 159048 | NIBBLE_SET(mask, i, pack->pattern[i]); | |
| 73 | 39762 | return mask; | |
| 74 | } | ||
| 75 | |||
| 76 | 140031 | static uint64_t linear_to_mask(const SwsLinearUOp *linear) | |
| 77 | { | ||
| 78 | 140031 | uint64_t mask = 0; | |
| 79 |
2/2✓ Branch 0 taken 560124 times.
✓ Branch 1 taken 140031 times.
|
700155 | for (int i = 0; i < 4; i++) { |
| 80 |
2/2✓ Branch 0 taken 2800620 times.
✓ Branch 1 taken 560124 times.
|
3360744 | for (int j = 0; j < 5; j++) { |
| 81 |
2/2✓ Branch 0 taken 2240496 times.
✓ Branch 1 taken 560124 times.
|
2800620 | int jj = (j == 0) ? 4 : (j - 1); |
| 82 |
2/2✓ Branch 0 taken 8112 times.
✓ Branch 1 taken 2792508 times.
|
2800620 | if (linear->one & SWS_MASK(i, jj)) |
| 83 | 8112 | mask |= 1ULL << (2 * ((5 * i + j))); | |
| 84 |
2/2✓ Branch 0 taken 966650 times.
✓ Branch 1 taken 1825858 times.
|
2792508 | else if (!(linear->zero & SWS_MASK(i, jj))) |
| 85 | 966650 | mask |= 3ULL << (2 * ((5 * i + j))); | |
| 86 | } | ||
| 87 | } | ||
| 88 | 140031 | return mask; | |
| 89 | } | ||
| 90 | |||
| 91 | 71846 | static uint16_t dither_to_mask(const SwsAArch64OpImplParams *p, const SwsDitherUOp *dither) | |
| 92 | { | ||
| 93 | 71846 | uint16_t mask = 0; | |
| 94 |
2/2✓ Branch 0 taken 287384 times.
✓ Branch 1 taken 71846 times.
|
359230 | for (int i = 0; i < 4; i++) { |
| 95 |
2/2✓ Branch 0 taken 189484 times.
✓ Branch 1 taken 97900 times.
|
287384 | if (p->mask & SWS_COMP(i)) { |
| 96 | 189484 | NIBBLE_SET(mask, i, dither->y_offset[i]); | |
| 97 | } else { | ||
| 98 | 97900 | NIBBLE_SET(mask, i, 0xf); | |
| 99 | } | ||
| 100 | } | ||
| 101 | 71846 | return mask; | |
| 102 | } | ||
| 103 | |||
| 104 | 1105891 | static int aarch64_op_impl_cmp(const void *a, const void *b) | |
| 105 | { | ||
| 106 | 1105891 | const SwsAArch64OpImplParams *pa = (const SwsAArch64OpImplParams *) a; | |
| 107 | 1105891 | const SwsAArch64OpImplParams *pb = (const SwsAArch64OpImplParams *) b; | |
| 108 | 1105891 | const SwsUOpParams *para = &pa->par; | |
| 109 | 1105891 | const SwsUOpParams *parb = &pb->par; | |
| 110 | |||
| 111 |
2/2✓ Branch 0 taken 602077 times.
✓ Branch 1 taken 503814 times.
|
1105891 | if (pa->uop != pb->uop) |
| 112 | 602077 | return (int) pa->uop - pb->uop; | |
| 113 | |||
| 114 |
7/7✓ Branch 0 taken 51435 times.
✓ Branch 1 taken 19866 times.
✓ Branch 2 taken 8180 times.
✓ Branch 3 taken 25270 times.
✓ Branch 4 taken 69994 times.
✓ Branch 5 taken 35912 times.
✓ Branch 6 taken 293157 times.
|
503814 | switch (pa->uop) { |
| 115 | 51435 | case SWS_UOP_PERMUTE: | |
| 116 | case SWS_UOP_COPY: { | ||
| 117 | 51435 | uint64_t ia = move_to_mask(¶->move); | |
| 118 | 51435 | uint64_t ib = move_to_mask(&parb->move); | |
| 119 |
2/2✓ Branch 0 taken 30650 times.
✓ Branch 1 taken 20785 times.
|
51435 | if (ia != ib) |
| 120 |
2/2✓ Branch 0 taken 12502 times.
✓ Branch 1 taken 18148 times.
|
30650 | return (int64_t) (ia - ib) < 0 ? -1 : 1; |
| 121 | 20785 | break; | |
| 122 | } | ||
| 123 | 19866 | case SWS_UOP_UNPACK: | |
| 124 | case SWS_UOP_PACK: { | ||
| 125 | 19866 | uint16_t ia = pack_to_mask(¶->pack); | |
| 126 | 19866 | uint16_t ib = pack_to_mask(&parb->pack); | |
| 127 |
2/2✓ Branch 0 taken 11490 times.
✓ Branch 1 taken 8376 times.
|
19866 | if (ia != ib) |
| 128 | 11490 | return (int) ia - ib; | |
| 129 | 8376 | break; | |
| 130 | } | ||
| 131 | 8180 | case SWS_UOP_LSHIFT: | |
| 132 | case SWS_UOP_RSHIFT: | ||
| 133 |
2/2✓ Branch 0 taken 3132 times.
✓ Branch 1 taken 5048 times.
|
8180 | if (para->shift.amount != parb->shift.amount) |
| 134 | 3132 | return (int) para->shift.amount - parb->shift.amount; | |
| 135 | 5048 | break; | |
| 136 | 25270 | case SWS_UOP_CLEAR: { | |
| 137 | 25270 | uint16_t ia = clear_to_mask(¶->clear); | |
| 138 | 25270 | uint16_t ib = clear_to_mask(&parb->clear); | |
| 139 |
2/2✓ Branch 0 taken 9922 times.
✓ Branch 1 taken 15348 times.
|
25270 | if (ia != ib) |
| 140 | 9922 | return (int) ia - ib; | |
| 141 | 15348 | break; | |
| 142 | } | ||
| 143 | 69994 | case SWS_UOP_LINEAR: | |
| 144 | case SWS_UOP_LINEAR_FMA: { | ||
| 145 | 69994 | uint64_t ia = linear_to_mask(¶->lin); | |
| 146 | 69994 | uint64_t ib = linear_to_mask(&parb->lin); | |
| 147 |
2/2✓ Branch 0 taken 48072 times.
✓ Branch 1 taken 21922 times.
|
69994 | if (ia != ib) |
| 148 |
2/2✓ Branch 0 taken 18704 times.
✓ Branch 1 taken 29368 times.
|
48072 | return (int64_t) (ia - ib) < 0 ? -1 : 1; |
| 149 | 21922 | break; | |
| 150 | } | ||
| 151 | 35912 | case SWS_UOP_DITHER: { | |
| 152 | 35912 | uint16_t ia = dither_to_mask(pa, ¶->dither); | |
| 153 | 35912 | uint16_t ib = dither_to_mask(pb, &parb->dither); | |
| 154 |
2/2✓ Branch 0 taken 27406 times.
✓ Branch 1 taken 8506 times.
|
35912 | if (ia != ib) |
| 155 | 27406 | return (int) ia - ib; | |
| 156 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8506 times.
|
8506 | if (para->dither.size_log2 != parb->dither.size_log2) |
| 157 | ✗ | return (int) para->dither.size_log2 - parb->dither.size_log2; | |
| 158 | 8506 | break; | |
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 |
2/2✓ Branch 0 taken 67781 times.
✓ Branch 1 taken 305361 times.
|
373142 | if (pa->block_size != pb->block_size) |
| 163 | 67781 | return (int) pa->block_size - pb->block_size; | |
| 164 |
2/2✓ Branch 0 taken 64424 times.
✓ Branch 1 taken 240937 times.
|
305361 | if (pa->type != pb->type) |
| 165 | 64424 | return (int) pa->type - pb->type; | |
| 166 |
2/2✓ Branch 0 taken 87827 times.
✓ Branch 1 taken 153110 times.
|
240937 | if (pa->mask != pb->mask) |
| 167 | 87827 | return (int) pa->mask - pb->mask; | |
| 168 | |||
| 169 | 153110 | return 0; | |
| 170 | } | ||
| 171 | |||
| 172 | /*********************************************************************/ | ||
| 173 | /* Insert the SwsAArch64OpImplParams structure into the AVTreeNode. */ | ||
| 174 | 153544 | static int aarch64_collect_op(const SwsAArch64OpImplParams *params, struct AVTreeNode **root) | |
| 175 | { | ||
| 176 | 153544 | int ret = 0; | |
| 177 | |||
| 178 | 153544 | struct AVTreeNode *node = av_tree_node_alloc(); | |
| 179 | 153544 | SwsAArch64OpImplParams *copy = av_memdup(params, sizeof(*params)); | |
| 180 |
2/4✓ Branch 0 taken 153544 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 153544 times.
|
153544 | if (!node || !copy) { |
| 181 | ✗ | ret = AVERROR(ENOMEM); | |
| 182 | ✗ | goto error; | |
| 183 | } | ||
| 184 | 153544 | av_tree_insert(root, copy, aarch64_op_impl_cmp, &node); | |
| 185 |
2/2✓ Branch 0 taken 153110 times.
✓ Branch 1 taken 434 times.
|
153544 | if (!node) |
| 186 | 434 | copy = NULL; | |
| 187 | |||
| 188 | 153110 | error: | |
| 189 | 153544 | av_free(node); | |
| 190 | 153544 | av_free(copy); | |
| 191 | 153544 | return ret; | |
| 192 | } | ||
| 193 | |||
| 194 | 19523 | static int collect_ops_compile(SwsContext *ctx, const SwsOpList *ops, | |
| 195 | SwsCompiledOp *out) | ||
| 196 | { | ||
| 197 | 19523 | struct AVTreeNode **root = (struct AVTreeNode **) ctx->opaque; | |
| 198 | int ret; | ||
| 199 | |||
| 200 | 19523 | SwsUOpList *uops = ff_sws_uop_list_alloc(); | |
| 201 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19523 times.
|
19523 | if (!uops) |
| 202 | ✗ | return AVERROR(ENOMEM); | |
| 203 | |||
| 204 | 19523 | const SwsUOpFlags flags = (ctx->flags & SWS_BITEXACT) ? 0 : SWS_UOP_FLAG_FMA; | |
| 205 | 19523 | ret = ff_sws_ops_translate(ctx, ops, flags, uops); | |
| 206 |
2/2✓ Branch 0 taken 132 times.
✓ Branch 1 taken 19391 times.
|
19523 | if (ret == AVERROR(ENOTSUP)) { |
| 207 | 132 | ret = 0; | |
| 208 | 132 | goto end; | |
| 209 | } | ||
| 210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19391 times.
|
19391 | if (ret < 0) |
| 211 | ✗ | goto end; | |
| 212 | |||
| 213 | /* Use at most two full vregs during the widest precision section */ | ||
| 214 |
2/2✓ Branch 0 taken 15482 times.
✓ Branch 1 taken 3909 times.
|
19391 | int block_size = (uops->pixel_size_max == 4) ? 8 : 16; |
| 215 | |||
| 216 |
2/2✓ Branch 0 taken 143193 times.
✓ Branch 1 taken 19391 times.
|
162584 | for (int i = 0; i < uops->num_ops; i++) { |
| 217 | 143193 | SwsAArch64OpImplParams params = { 0 }; | |
| 218 | 143193 | convert_to_aarch64_impl(&uops->ops[i], block_size, ¶ms); | |
| 219 | 143193 | ret = aarch64_collect_op(¶ms, root); | |
| 220 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 143193 times.
|
143193 | if (ret < 0) |
| 221 | ✗ | goto end; | |
| 222 |
3/4✓ Branch 0 taken 10351 times.
✓ Branch 1 taken 132842 times.
✓ Branch 2 taken 10351 times.
✗ Branch 3 not taken.
|
143193 | if (params.uop == SWS_UOP_LINEAR_FMA && params.type == SWS_PIXEL_F32) { |
| 223 | /** | ||
| 224 | * Generate both sets of linear op functions that do use | ||
| 225 | * and do not use fmla (selected by SWS_BITEXACT). | ||
| 226 | */ | ||
| 227 | 10351 | params.uop = SWS_UOP_LINEAR; | |
| 228 | 10351 | ret = aarch64_collect_op(¶ms, root); | |
| 229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10351 times.
|
10351 | if (ret < 0) |
| 230 | ✗ | goto end; | |
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | 19391 | *out = (SwsCompiledOp) { 0 }; | |
| 235 | 19391 | ret = 0; | |
| 236 | |||
| 237 | 19523 | end: | |
| 238 | 19523 | ff_sws_uop_list_free(&uops); | |
| 239 | 19523 | return ret; | |
| 240 | } | ||
| 241 | |||
| 242 | static const SwsOpBackend backend_collect = { | ||
| 243 | .name = "collect_ops", | ||
| 244 | .compile = collect_ops_compile, | ||
| 245 | }; | ||
| 246 | |||
| 247 | /*********************************************************************/ | ||
| 248 | 70240 | static int register_op(SwsContext *ctx, void *opaque, SwsOpList *ops) | |
| 249 | { | ||
| 250 | /* Skip ops lists which include filtering, since this is still not | ||
| 251 | * supported. */ | ||
| 252 |
2/2✓ Branch 0 taken 277904 times.
✓ Branch 1 taken 17560 times.
|
295464 | for (int i = 0; i < ops->num_ops; i++) { |
| 253 | 277904 | const SwsOp *op = &ops->ops[i]; | |
| 254 |
3/3✓ Branch 0 taken 87800 times.
✓ Branch 1 taken 40008 times.
✓ Branch 2 taken 150096 times.
|
277904 | switch (op->op) { |
| 255 | 87800 | case SWS_OP_READ: | |
| 256 | case SWS_OP_WRITE: | ||
| 257 |
2/2✓ Branch 0 taken 12672 times.
✓ Branch 1 taken 75128 times.
|
87800 | if (op->rw.filter.op) |
| 258 | 12672 | return 0; | |
| 259 | 75128 | break; | |
| 260 | 40008 | case SWS_OP_FILTER_H: | |
| 261 | case SWS_OP_FILTER_V: | ||
| 262 | 40008 | return 0; | |
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | /* ff_sws_compile_pass() takes over ownership of `ops` */ | ||
| 267 | 17560 | SwsOpList *copy = ff_sws_op_list_duplicate(ops); | |
| 268 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17560 times.
|
17560 | if (!copy) |
| 269 | ✗ | return AVERROR(ENOMEM); | |
| 270 | |||
| 271 | 17560 | const int flags = SWS_OP_FLAG_DRY_RUN | SWS_OP_FLAG_SPLIT_MEMCPY; | |
| 272 | 17560 | return ff_sws_compile_pass(opaque, &backend_collect, ©, flags, NULL, NULL); | |
| 273 | } | ||
| 274 | |||
| 275 | /*********************************************************************/ | ||
| 276 | static const char op_type_names[SWS_UOP_TYPE_NB][16] = { | ||
| 277 | [SWS_UOP_READ_BIT ] = "read_bit", | ||
| 278 | [SWS_UOP_READ_NIBBLE ] = "read_nibble", | ||
| 279 | [SWS_UOP_READ_PACKED ] = "read_packed", | ||
| 280 | [SWS_UOP_READ_PLANAR ] = "read_planar", | ||
| 281 | [SWS_UOP_WRITE_BIT ] = "write_bit", | ||
| 282 | [SWS_UOP_WRITE_NIBBLE ] = "write_nibble", | ||
| 283 | [SWS_UOP_WRITE_PACKED ] = "write_packed", | ||
| 284 | [SWS_UOP_WRITE_PLANAR ] = "write_planar", | ||
| 285 | [SWS_UOP_SWAP_BYTES ] = "swap_bytes", | ||
| 286 | [SWS_UOP_PERMUTE ] = "permute", | ||
| 287 | [SWS_UOP_COPY ] = "copy", | ||
| 288 | [SWS_UOP_UNPACK ] = "unpack", | ||
| 289 | [SWS_UOP_PACK ] = "pack", | ||
| 290 | [SWS_UOP_LSHIFT ] = "lshift", | ||
| 291 | [SWS_UOP_RSHIFT ] = "rshift", | ||
| 292 | [SWS_UOP_CLEAR ] = "clear", | ||
| 293 | [SWS_UOP_TO_U8 ] = "to_u8", | ||
| 294 | [SWS_UOP_TO_U16 ] = "to_u16", | ||
| 295 | [SWS_UOP_TO_U32 ] = "to_u32", | ||
| 296 | [SWS_UOP_TO_F32 ] = "to_f32", | ||
| 297 | [SWS_UOP_EXPAND_PAIR ] = "expand_pair", | ||
| 298 | [SWS_UOP_EXPAND_QUAD ] = "expand_quad", | ||
| 299 | [SWS_UOP_MIN ] = "min", | ||
| 300 | [SWS_UOP_MAX ] = "max", | ||
| 301 | [SWS_UOP_SCALE ] = "scale", | ||
| 302 | [SWS_UOP_LINEAR ] = "linear", | ||
| 303 | [SWS_UOP_LINEAR_FMA ] = "linear_fma", | ||
| 304 | [SWS_UOP_DITHER ] = "dither", | ||
| 305 | }; | ||
| 306 | |||
| 307 | static const char pixel_type_names[SWS_PIXEL_TYPE_NB][4] = { | ||
| 308 | [SWS_PIXEL_U8 ] = "u8", | ||
| 309 | [SWS_PIXEL_U16] = "u16", | ||
| 310 | [SWS_PIXEL_U32] = "u32", | ||
| 311 | [SWS_PIXEL_F32] = "f32", | ||
| 312 | }; | ||
| 313 | |||
| 314 | static const char uop_types[SWS_UOP_TYPE_NB][32] = { | ||
| 315 | [SWS_UOP_READ_BIT ] = "SWS_UOP_READ_BIT", | ||
| 316 | [SWS_UOP_READ_NIBBLE ] = "SWS_UOP_READ_NIBBLE", | ||
| 317 | [SWS_UOP_READ_PACKED ] = "SWS_UOP_READ_PACKED", | ||
| 318 | [SWS_UOP_READ_PLANAR ] = "SWS_UOP_READ_PLANAR", | ||
| 319 | [SWS_UOP_WRITE_BIT ] = "SWS_UOP_WRITE_BIT", | ||
| 320 | [SWS_UOP_WRITE_NIBBLE ] = "SWS_UOP_WRITE_NIBBLE", | ||
| 321 | [SWS_UOP_WRITE_PACKED ] = "SWS_UOP_WRITE_PACKED", | ||
| 322 | [SWS_UOP_WRITE_PLANAR ] = "SWS_UOP_WRITE_PLANAR", | ||
| 323 | [SWS_UOP_SWAP_BYTES ] = "SWS_UOP_SWAP_BYTES", | ||
| 324 | [SWS_UOP_PERMUTE ] = "SWS_UOP_PERMUTE", | ||
| 325 | [SWS_UOP_COPY ] = "SWS_UOP_COPY", | ||
| 326 | [SWS_UOP_UNPACK ] = "SWS_UOP_UNPACK", | ||
| 327 | [SWS_UOP_PACK ] = "SWS_UOP_PACK", | ||
| 328 | [SWS_UOP_LSHIFT ] = "SWS_UOP_LSHIFT", | ||
| 329 | [SWS_UOP_RSHIFT ] = "SWS_UOP_RSHIFT", | ||
| 330 | [SWS_UOP_CLEAR ] = "SWS_UOP_CLEAR", | ||
| 331 | [SWS_UOP_TO_U8 ] = "SWS_UOP_TO_U8", | ||
| 332 | [SWS_UOP_TO_U16 ] = "SWS_UOP_TO_U16", | ||
| 333 | [SWS_UOP_TO_U32 ] = "SWS_UOP_TO_U32", | ||
| 334 | [SWS_UOP_TO_F32 ] = "SWS_UOP_TO_F32", | ||
| 335 | [SWS_UOP_EXPAND_PAIR ] = "SWS_UOP_EXPAND_PAIR", | ||
| 336 | [SWS_UOP_EXPAND_QUAD ] = "SWS_UOP_EXPAND_QUAD", | ||
| 337 | [SWS_UOP_MIN ] = "SWS_UOP_MIN", | ||
| 338 | [SWS_UOP_MAX ] = "SWS_UOP_MAX", | ||
| 339 | [SWS_UOP_SCALE ] = "SWS_UOP_SCALE", | ||
| 340 | [SWS_UOP_LINEAR ] = "SWS_UOP_LINEAR", | ||
| 341 | [SWS_UOP_LINEAR_FMA ] = "SWS_UOP_LINEAR_FMA", | ||
| 342 | [SWS_UOP_DITHER ] = "SWS_UOP_DITHER", | ||
| 343 | }; | ||
| 344 | |||
| 345 | static const char pixel_types[SWS_PIXEL_TYPE_NB][32] = { | ||
| 346 | [SWS_PIXEL_U8 ] = "SWS_PIXEL_U8", | ||
| 347 | [SWS_PIXEL_U16] = "SWS_PIXEL_U16", | ||
| 348 | [SWS_PIXEL_U32] = "SWS_PIXEL_U32", | ||
| 349 | [SWS_PIXEL_F32] = "SWS_PIXEL_F32", | ||
| 350 | }; | ||
| 351 | |||
| 352 | 434 | static void serialize_op(AVBPrint *bp, const SwsAArch64OpImplParams *params) | |
| 353 | { | ||
| 354 | #define FUNC_NAME_WIDTH 45 | ||
| 355 | #define UOP_NAME_WIDTH 21 | ||
| 356 | #define TYPE_NAME_WIDTH 14 | ||
| 357 | |||
| 358 | 434 | const SwsUOpParams *par = ¶ms->par; | |
| 359 | |||
| 360 | char func_name[FUNC_NAME_WIDTH + 2]; | ||
| 361 | 434 | snprintf(func_name, sizeof(func_name), "ff_sws_%s", op_type_names[params->uop]); | |
| 362 |
7/7✓ Branch 0 taken 86 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 50 times.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 171 times.
|
434 | switch (params->uop) { |
| 363 | 86 | case SWS_UOP_PERMUTE: | |
| 364 | case SWS_UOP_COPY: | ||
| 365 | 86 | av_strlcatf(func_name, sizeof(func_name), "_%012" PRIx64, move_to_mask(&par->move)); | |
| 366 | 86 | break; | |
| 367 | 30 | case SWS_UOP_UNPACK: | |
| 368 | case SWS_UOP_PACK: | ||
| 369 | 30 | av_strlcatf(func_name, sizeof(func_name), "_%04x", pack_to_mask(&par->pack)); | |
| 370 | 30 | break; | |
| 371 | 32 | case SWS_UOP_LSHIFT: | |
| 372 | case SWS_UOP_RSHIFT: | ||
| 373 | 32 | av_strlcatf(func_name, sizeof(func_name), "_%u", par->shift.amount); | |
| 374 | 32 | break; | |
| 375 | 50 | case SWS_UOP_CLEAR: | |
| 376 | 50 | av_strlcatf(func_name, sizeof(func_name), "_%04x", clear_to_mask(&par->clear)); | |
| 377 | 50 | break; | |
| 378 | 43 | case SWS_UOP_LINEAR: | |
| 379 | case SWS_UOP_LINEAR_FMA: | ||
| 380 | 43 | av_strlcatf(func_name, sizeof(func_name), "_%010" PRIx64, linear_to_mask(&par->lin)); | |
| 381 | 43 | break; | |
| 382 | 22 | case SWS_UOP_DITHER: | |
| 383 | 22 | av_strlcatf(func_name, sizeof(func_name), "_%04x_%u", dither_to_mask(params, &par->dither), par->dither.size_log2); | |
| 384 | 22 | break; | |
| 385 | } | ||
| 386 | 434 | av_strlcatf(func_name, sizeof(func_name), "_%u_%s_%04x_neon,", | |
| 387 | 434 | params->block_size, pixel_type_names[params->type], nibble_mask(params->mask)); | |
| 388 | |||
| 389 | char uop_name[UOP_NAME_WIDTH + 2]; | ||
| 390 | 434 | snprintf(uop_name, sizeof(uop_name), "%s,", uop_types[params->uop]); | |
| 391 | |||
| 392 | char type_name[TYPE_NAME_WIDTH + 2]; | ||
| 393 | 434 | snprintf(type_name, sizeof(type_name), "%s,", pixel_types[params->type]); | |
| 394 | |||
| 395 | 434 | av_bprintf(bp, "ENTRY(%-*s { .uop = %-*s .block_size = %2u, .type = %-*s .mask = 0x%x", | |
| 396 | FUNC_NAME_WIDTH, func_name, UOP_NAME_WIDTH, uop_name, | ||
| 397 | 434 | params->block_size, TYPE_NAME_WIDTH, type_name, params->mask); | |
| 398 |
7/7✓ Branch 0 taken 86 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 50 times.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 171 times.
|
434 | switch (params->uop) { |
| 399 | 86 | case SWS_UOP_PERMUTE: | |
| 400 | case SWS_UOP_COPY: | ||
| 401 | 86 | av_bprintf(bp, ", .par.move = { .num_moves = %d, .dst = {%d, %d, %d, %d, %d, %d}, .src = {%d, %d, %d, %d, %d, %d} }", | |
| 402 | 86 | par->move.num_moves, | |
| 403 | 86 | par->move.dst[0], par->move.dst[1], par->move.dst[2], | |
| 404 | 86 | par->move.dst[3], par->move.dst[4], par->move.dst[5], | |
| 405 | 86 | par->move.src[0], par->move.src[1], par->move.src[2], | |
| 406 | 86 | par->move.src[3], par->move.src[4], par->move.src[5]); | |
| 407 | 86 | break; | |
| 408 | 30 | case SWS_UOP_UNPACK: | |
| 409 | case SWS_UOP_PACK: | ||
| 410 | 30 | av_bprintf(bp, ", .par.pack = { .pattern = {%d, %d, %d, %d} }", | |
| 411 | 30 | par->pack.pattern[0], par->pack.pattern[1], | |
| 412 | 30 | par->pack.pattern[2], par->pack.pattern[3]); | |
| 413 | 30 | break; | |
| 414 | 32 | case SWS_UOP_LSHIFT: | |
| 415 | case SWS_UOP_RSHIFT: | ||
| 416 | 32 | av_bprintf(bp, ", .par.shift = { .amount = %u }", par->shift.amount); | |
| 417 | 32 | break; | |
| 418 | 50 | case SWS_UOP_CLEAR: | |
| 419 | 50 | av_bprintf(bp, ", .par.clear = { .one = 0x%0x, .zero = 0x%0x }", par->clear.one, par->clear.zero); | |
| 420 | 50 | break; | |
| 421 | 43 | case SWS_UOP_LINEAR: | |
| 422 | case SWS_UOP_LINEAR_FMA: | ||
| 423 | 43 | av_bprintf(bp, ", .par.lin = { .one = 0x%x, .zero = 0x%x }", par->lin.one, par->lin.zero); | |
| 424 | 43 | break; | |
| 425 | 22 | case SWS_UOP_DITHER: | |
| 426 | 22 | av_bprintf(bp, ", .par.dither = { .y_offset = {%u, %u, %u, %u}, .size_log2 = %u }", | |
| 427 | 22 | par->dither.y_offset[0], par->dither.y_offset[1], | |
| 428 | 22 | par->dither.y_offset[2], par->dither.y_offset[3], | |
| 429 | 22 | par->dither.size_log2); | |
| 430 | 22 | break; | |
| 431 | } | ||
| 432 | 434 | av_bprintf(bp, " })"); | |
| 433 | 434 | } | |
| 434 | |||
| 435 | /* Serialize SwsAArch64OpImplParams for one function. */ | ||
| 436 | 434 | static int print_op(void *opaque, void *elem) | |
| 437 | { | ||
| 438 | 434 | SwsAArch64OpImplParams *params = (SwsAArch64OpImplParams *) elem; | |
| 439 | 434 | FILE *fp = (FILE *) opaque; | |
| 440 | |||
| 441 | AVBPrint bp; | ||
| 442 | 434 | av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); | |
| 443 | 434 | serialize_op(&bp, params); | |
| 444 | 434 | fprintf(fp, "%s\n", bp.str); | |
| 445 | 434 | av_bprint_finalize(&bp, NULL); | |
| 446 | |||
| 447 | 434 | av_free(params); | |
| 448 | |||
| 449 | 434 | return 0; | |
| 450 | } | ||
| 451 | |||
| 452 | /*********************************************************************/ | ||
| 453 | 1 | int main(int argc, char *argv[]) | |
| 454 | { | ||
| 455 | 1 | struct AVTreeNode *root = NULL; | |
| 456 | 1 | int ret = 1; | |
| 457 | |||
| 458 | #ifdef _WIN32 | ||
| 459 | _setmode(_fileno(stdout), _O_BINARY); | ||
| 460 | #endif | ||
| 461 | |||
| 462 | 1 | SwsContext *ctx = sws_alloc_context(); | |
| 463 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!ctx) |
| 464 | ✗ | goto fail; | |
| 465 | |||
| 466 | 1 | SwsGraph *graph = ff_sws_graph_alloc(); | |
| 467 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!graph) |
| 468 | ✗ | goto fail; | |
| 469 | |||
| 470 | 1 | graph->ctx = ctx; | |
| 471 | 1 | ctx->opaque = &root; | |
| 472 | |||
| 473 | 1 | ret = ff_sws_enum_op_lists(ctx, graph, NULL, AV_PIX_FMT_NONE, AV_PIX_FMT_NONE, | |
| 474 | register_op); | ||
| 475 | |||
| 476 | /** | ||
| 477 | * Generate a C file with all the unique function parameter entries | ||
| 478 | * collected by aarch64_enum_ops(). | ||
| 479 | */ | ||
| 480 | 1 | printf("/*\n"); | |
| 481 | 1 | printf(" * This file is automatically generated. Do not edit manually.\n"); | |
| 482 | 1 | printf(" * To regenerate, run: make fate-sws-ops-entries-aarch64 GEN=1\n"); | |
| 483 | 1 | printf(" */\n"); | |
| 484 | 1 | printf("\n"); | |
| 485 | 1 | av_tree_enumerate(root, stdout, NULL, print_op); | |
| 486 | |||
| 487 | 1 | ff_sws_graph_free(&graph); | |
| 488 | |||
| 489 | 1 | fail: | |
| 490 | 1 | av_tree_destroy(root); | |
| 491 | 1 | sws_free_context(&ctx); | |
| 492 | 1 | return ret; | |
| 493 | } | ||
| 494 |