swscale/ops_chain: allow implementations to expose over_read/write

And plumb it all the way through to the SwsCompiledOp. This is cleaner than
setting up this metadata up-front in x86/ops.c; and more importantly, it
allows us to determine the amount of over-read programmatically during ops
setup.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
This commit is contained in:
Niklas Haas
2026-03-12 21:41:55 +01:00
committed by Niklas Haas
parent 3aef0213e7
commit 8e3eacd7ad
4 changed files with 16 additions and 5 deletions

View File

@@ -86,6 +86,8 @@ static int compile(SwsContext *ctx, SwsOpList *ops, SwsCompiledOp *out)
.slice_align = 1,
.block_size = SWS_BLOCK_SIZE,
.cpu_flags = chain->cpu_flags,
.over_read = chain->over_read,
.over_write = chain->over_write,
.priv = chain,
.free = ff_sws_op_chain_free_cb,
};

View File

@@ -238,7 +238,6 @@ int ff_sws_op_compile_tables(SwsContext *ctx, const SwsOpTable *const tables[],
return ret;
}
chain->cpu_flags |= best_table->cpu_flags;
ret = ff_sws_op_chain_append(chain, res.func ? res.func : best->func,
res.free, &res.priv);
if (ret < 0) {
@@ -247,6 +246,10 @@ int ff_sws_op_compile_tables(SwsContext *ctx, const SwsOpTable *const tables[],
return ret;
}
chain->cpu_flags |= best_table->cpu_flags;
chain->over_read = FFMAX(chain->over_read, res.over_read);
chain->over_write = FFMAX(chain->over_write, res.over_write);
ops->ops++;
ops->num_ops--;
return ops->num_ops ? AVERROR(EAGAIN) : 0;

View File

@@ -86,7 +86,9 @@ typedef struct SwsOpChain {
SwsOpImpl impl[SWS_MAX_OPS + 1]; /* reserve extra space for the entrypoint */
void (*free[SWS_MAX_OPS + 1])(SwsOpPriv *);
int num_impl;
int cpu_flags; /* set of all used CPU flags */
int cpu_flags; /* set of all used CPU flags */
int over_read; /* chain over-reads input by this many bytes */
int over_write; /* chain over-writes output by this many bytes */
} SwsOpChain;
SwsOpChain *ff_sws_op_chain_alloc(void);
@@ -110,6 +112,8 @@ typedef struct SwsImplResult {
SwsFuncPtr func; /* overrides `SwsOpEntry.func` if non-NULL */
SwsOpPriv priv; /* private data for this implementation instance */
void (*free)(SwsOpPriv *priv); /* free function for `priv` */
int over_read; /* implementation over-reads input by this many bytes */
int over_write; /* implementation over-writes output by this many bytes */
} SwsImplResult;
typedef struct SwsOpEntry {

View File

@@ -710,9 +710,9 @@ static int compile(SwsContext *ctx, SwsOpList *ops, SwsCompiledOp *out)
/* 3-component reads/writes process one extra garbage word */
if (read && read->rw.packed && read->rw.elems == 3)
out->over_read = sizeof(uint32_t);
chain->over_read = sizeof(uint32_t);
if (write->rw.packed && write->rw.elems == 3)
out->over_write = sizeof(uint32_t);
chain->over_write = sizeof(uint32_t);
/* Make on-stack copy of `ops` to iterate over */
@@ -764,7 +764,9 @@ static int compile(SwsContext *ctx, SwsOpList *ops, SwsCompiledOp *out)
return ret;
}
out->cpu_flags = chain->cpu_flags;
out->cpu_flags = chain->cpu_flags;
out->over_read = chain->over_read;
out->over_write = chain->over_write;
return 0;
}