You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2026-06-19 19:03:00 +02:00
swscale/ops: generalize SwsReadWriteOp.packed to enum
I want to start adding more data layouts, like semiplanar formats (nv12), or palette formats. I made an effort to distinguish existing checks for rw.packed into "mode != PLANAR" and "mode == PACKED", based on the intent of the surrounding code, in anticipation of these new layouts. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas <git@haasn.dev>
This commit is contained in:
@@ -88,10 +88,12 @@ static int convert_to_aarch64_impl(SwsContext *ctx, const SwsOpList *ops, int n,
|
|||||||
out->op = AARCH64_SWS_OP_READ_NIBBLE;
|
out->op = AARCH64_SWS_OP_READ_NIBBLE;
|
||||||
else if (op->rw.frac == 3)
|
else if (op->rw.frac == 3)
|
||||||
out->op = AARCH64_SWS_OP_READ_BIT;
|
out->op = AARCH64_SWS_OP_READ_BIT;
|
||||||
else if (op->rw.packed && op->rw.elems != 1)
|
else if (op->rw.mode == SWS_RW_PACKED)
|
||||||
out->op = AARCH64_SWS_OP_READ_PACKED;
|
out->op = AARCH64_SWS_OP_READ_PACKED;
|
||||||
else
|
else if (op->rw.mode == SWS_RW_PLANAR)
|
||||||
out->op = AARCH64_SWS_OP_READ_PLANAR;
|
out->op = AARCH64_SWS_OP_READ_PLANAR;
|
||||||
|
else
|
||||||
|
return AVERROR(ENOTSUP);
|
||||||
break;
|
break;
|
||||||
case SWS_OP_WRITE:
|
case SWS_OP_WRITE:
|
||||||
if (op->rw.filter.op)
|
if (op->rw.filter.op)
|
||||||
@@ -104,10 +106,12 @@ static int convert_to_aarch64_impl(SwsContext *ctx, const SwsOpList *ops, int n,
|
|||||||
out->op = AARCH64_SWS_OP_WRITE_NIBBLE;
|
out->op = AARCH64_SWS_OP_WRITE_NIBBLE;
|
||||||
else if (op->rw.frac == 3)
|
else if (op->rw.frac == 3)
|
||||||
out->op = AARCH64_SWS_OP_WRITE_BIT;
|
out->op = AARCH64_SWS_OP_WRITE_BIT;
|
||||||
else if (op->rw.packed && op->rw.elems != 1)
|
else if (op->rw.mode == SWS_RW_PACKED)
|
||||||
out->op = AARCH64_SWS_OP_WRITE_PACKED;
|
out->op = AARCH64_SWS_OP_WRITE_PACKED;
|
||||||
else
|
else if (op->rw.mode == SWS_RW_PLANAR)
|
||||||
out->op = AARCH64_SWS_OP_WRITE_PLANAR;
|
out->op = AARCH64_SWS_OP_WRITE_PLANAR;
|
||||||
|
else
|
||||||
|
return AVERROR(ENOTSUP);
|
||||||
break;
|
break;
|
||||||
case SWS_OP_SWAP_BYTES: out->op = AARCH64_SWS_OP_SWAP_BYTES; break;
|
case SWS_OP_SWAP_BYTES: out->op = AARCH64_SWS_OP_SWAP_BYTES; break;
|
||||||
case SWS_OP_SWIZZLE: out->op = AARCH64_SWS_OP_SWIZZLE; break;
|
case SWS_OP_SWIZZLE: out->op = AARCH64_SWS_OP_SWIZZLE; break;
|
||||||
|
|||||||
+13
-9
@@ -734,20 +734,20 @@ typedef struct FmtInfo {
|
|||||||
int shift;
|
int shift;
|
||||||
} FmtInfo;
|
} FmtInfo;
|
||||||
|
|
||||||
#define BITSTREAM_FMT(SWIZ, FRAC, PACKED, ...) (FmtInfo) { \
|
#define BITSTREAM_FMT(SWIZ, FRAC, MODE, ...) (FmtInfo) { \
|
||||||
.rw = { .elems = 1, .frac = FRAC, .packed = PACKED }, \
|
.rw = { .elems = 1, .frac = FRAC, .mode = MODE }, \
|
||||||
.swizzle = SWIZ, \
|
.swizzle = SWIZ, \
|
||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SUBPACKED_FMT(SWIZ, ...) (FmtInfo) { \
|
#define SUBPACKED_FMT(SWIZ, ...) (FmtInfo) { \
|
||||||
.rw = { .elems = 1, .packed = true }, \
|
.rw = { .elems = 1, .mode = SWS_RW_PACKED }, \
|
||||||
.swizzle = SWIZ, \
|
.swizzle = SWIZ, \
|
||||||
.pack.pattern = {__VA_ARGS__}, \
|
.pack.pattern = {__VA_ARGS__}, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PACKED_FMT(SWIZ, N, ...) (FmtInfo) { \
|
#define PACKED_FMT(SWIZ, N, ...) (FmtInfo) { \
|
||||||
.rw = { .elems = N, .packed = (N) > 1 }, \
|
.rw = { .elems = N, .mode = SWS_RW_PACKED }, \
|
||||||
.swizzle = SWIZ, \
|
.swizzle = SWIZ, \
|
||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
}
|
}
|
||||||
@@ -767,9 +767,9 @@ static FmtInfo fmt_info_irregular(enum AVPixelFormat fmt)
|
|||||||
/* Bitstream formats */
|
/* Bitstream formats */
|
||||||
case AV_PIX_FMT_MONOWHITE:
|
case AV_PIX_FMT_MONOWHITE:
|
||||||
case AV_PIX_FMT_MONOBLACK:
|
case AV_PIX_FMT_MONOBLACK:
|
||||||
return BITSTREAM_FMT(RGBA, 3, false);
|
return BITSTREAM_FMT(RGBA, 3, SWS_RW_PLANAR);
|
||||||
case AV_PIX_FMT_RGB4: return BITSTREAM_FMT(RGBA, 1, true, .pack = {{ 1, 2, 1 }});
|
case AV_PIX_FMT_RGB4: return BITSTREAM_FMT(RGBA, 1, SWS_RW_PACKED, .pack = {{ 1, 2, 1 }});
|
||||||
case AV_PIX_FMT_BGR4: return BITSTREAM_FMT(BGRA, 1, true, .pack = {{ 1, 2, 1 }});
|
case AV_PIX_FMT_BGR4: return BITSTREAM_FMT(BGRA, 1, SWS_RW_PACKED, .pack = {{ 1, 2, 1 }});
|
||||||
|
|
||||||
/* Sub-packed 8-bit aligned formats */
|
/* Sub-packed 8-bit aligned formats */
|
||||||
case AV_PIX_FMT_RGB4_BYTE: return SUBPACKED_FMT(RGBA, 1, 2, 1);
|
case AV_PIX_FMT_RGB4_BYTE: return SUBPACKED_FMT(RGBA, 1, 2, 1);
|
||||||
@@ -865,10 +865,14 @@ static int fmt_analyze_regular(const AVPixFmtDescriptor *desc, SwsReadWriteOp *r
|
|||||||
*swizzle = swiz;
|
*swizzle = swiz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SwsReadWriteMode mode = SWS_RW_PLANAR;
|
||||||
|
if (desc->nb_components > 1 && !(desc->flags & AV_PIX_FMT_FLAG_PLANAR))
|
||||||
|
mode = SWS_RW_PACKED;
|
||||||
|
|
||||||
*shift = (SwsShiftOp) { desc->comp[0].shift };
|
*shift = (SwsShiftOp) { desc->comp[0].shift };
|
||||||
*rw_op = (SwsReadWriteOp) {
|
*rw_op = (SwsReadWriteOp) {
|
||||||
.elems = desc->nb_components,
|
.elems = desc->nb_components,
|
||||||
.packed = desc->nb_components > 1 && !(desc->flags & AV_PIX_FMT_FLAG_PLANAR),
|
.mode = mode,
|
||||||
};
|
};
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-4
@@ -169,7 +169,13 @@ SwsCompMask ff_sws_comp_mask_needed(const SwsOp *op)
|
|||||||
int ff_sws_rw_op_planes(const SwsOp *op)
|
int ff_sws_rw_op_planes(const SwsOp *op)
|
||||||
{
|
{
|
||||||
av_assert2(op->op == SWS_OP_READ || op->op == SWS_OP_WRITE);
|
av_assert2(op->op == SWS_OP_READ || op->op == SWS_OP_WRITE);
|
||||||
return op->rw.packed ? 1 : op->rw.elems;
|
switch (op->rw.mode) {
|
||||||
|
case SWS_RW_PLANAR: return op->rw.elems;
|
||||||
|
case SWS_RW_PACKED: return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
av_unreachable("Invalid read/write mode!");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* biased towards `a` */
|
/* biased towards `a` */
|
||||||
@@ -376,7 +382,12 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
|
|||||||
/* Active components are taken from the user-provided values,
|
/* Active components are taken from the user-provided values,
|
||||||
* other components are explicitly stripped */
|
* other components are explicitly stripped */
|
||||||
for (int i = 0; i < op->rw.elems; i++) {
|
for (int i = 0; i < op->rw.elems; i++) {
|
||||||
const int idx = op->rw.packed ? i : ops->plane_src[i];
|
int idx = 0;
|
||||||
|
switch (op->rw.mode) {
|
||||||
|
case SWS_RW_PACKED: idx = i; break;
|
||||||
|
case SWS_RW_PLANAR: idx = ops->plane_src[i]; break;
|
||||||
|
}
|
||||||
|
|
||||||
av_assert0(!(ops->comps_src.flags[idx] & SWS_COMP_GARBAGE));
|
av_assert0(!(ops->comps_src.flags[idx] & SWS_COMP_GARBAGE));
|
||||||
op->comps.flags[i] = ops->comps_src.flags[idx];
|
op->comps.flags[i] = ops->comps_src.flags[idx];
|
||||||
op->comps.min[i] = ops->comps_src.min[idx];
|
op->comps.min[i] = ops->comps_src.min[idx];
|
||||||
@@ -731,7 +742,7 @@ bool ff_sws_op_list_is_noop(const SwsOpList *ops)
|
|||||||
const SwsOp *write = ff_sws_op_list_output(ops);
|
const SwsOp *write = ff_sws_op_list_output(ops);
|
||||||
if (!read || !write || ops->num_ops > 2 ||
|
if (!read || !write || ops->num_ops > 2 ||
|
||||||
read->type != write->type ||
|
read->type != write->type ||
|
||||||
read->rw.packed != write->rw.packed ||
|
read->rw.mode != write->rw.mode ||
|
||||||
read->rw.elems != write->rw.elems ||
|
read->rw.elems != write->rw.elems ||
|
||||||
read->rw.frac != write->rw.frac)
|
read->rw.frac != write->rw.frac)
|
||||||
return false;
|
return false;
|
||||||
@@ -857,6 +868,11 @@ static void print_q4(AVBPrint *bp, const AVRational q4[4], SwsCompMask mask)
|
|||||||
av_bprintf(bp, "}");
|
av_bprintf(bp, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *const rw_mode_names[] = {
|
||||||
|
[SWS_RW_PLANAR] = "planar",
|
||||||
|
[SWS_RW_PACKED] = "packed",
|
||||||
|
};
|
||||||
|
|
||||||
void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
|
void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
|
||||||
{
|
{
|
||||||
const char *name = ff_sws_op_type_name(op->op);
|
const char *name = ff_sws_op_type_name(op->op);
|
||||||
@@ -870,7 +886,7 @@ void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
|
|||||||
case SWS_OP_READ:
|
case SWS_OP_READ:
|
||||||
case SWS_OP_WRITE:
|
case SWS_OP_WRITE:
|
||||||
av_bprintf(bp, "%-20s: %d elem(s) %s >> %d", name,
|
av_bprintf(bp, "%-20s: %d elem(s) %s >> %d", name,
|
||||||
op->rw.elems, op->rw.packed ? "packed" : "planar",
|
op->rw.elems, rw_mode_names[op->rw.mode],
|
||||||
op->rw.frac);
|
op->rw.frac);
|
||||||
if (!op->rw.filter.op)
|
if (!op->rw.filter.op)
|
||||||
break;
|
break;
|
||||||
|
|||||||
+15
-1
@@ -84,6 +84,20 @@ typedef struct SwsComps {
|
|||||||
AVRational min[4], max[4];
|
AVRational min[4], max[4];
|
||||||
} SwsComps;
|
} SwsComps;
|
||||||
|
|
||||||
|
typedef enum SwsReadWriteMode {
|
||||||
|
/**
|
||||||
|
* Note: 1-component reads are either SWS_RW_PLANAR or SWS_RW_PACKED,
|
||||||
|
* depending on the underlying interpretation. If multiple components are
|
||||||
|
* packed into one element (e.g. rgb10a2 -> u16), they are marked as
|
||||||
|
* SWS_RW_PACKED. Otherwise (e.g. gray16le), they are SWS_RW_PLANAR.
|
||||||
|
*
|
||||||
|
* This is a purely semantic/informative difference; the underlying code
|
||||||
|
* treats 1-components reads/writes the same regardless of mode.
|
||||||
|
*/
|
||||||
|
SWS_RW_PLANAR, /* one plane per component */
|
||||||
|
SWS_RW_PACKED, /* all components on a single plane */
|
||||||
|
} SwsReadWriteMode;
|
||||||
|
|
||||||
typedef struct SwsReadWriteOp {
|
typedef struct SwsReadWriteOp {
|
||||||
/**
|
/**
|
||||||
* Examples:
|
* Examples:
|
||||||
@@ -93,9 +107,9 @@ typedef struct SwsReadWriteOp {
|
|||||||
* monow = 1x u8 (frac 3)
|
* monow = 1x u8 (frac 3)
|
||||||
* rgb4 = 1x u8 (frac 1)
|
* rgb4 = 1x u8 (frac 1)
|
||||||
*/
|
*/
|
||||||
|
SwsReadWriteMode mode; /* how data is laid out in memory */
|
||||||
uint8_t elems; /* number of elements (of type `op.type`) to read/write */
|
uint8_t elems; /* number of elements (of type `op.type`) to read/write */
|
||||||
uint8_t frac; /* fractional pixel step factor (log2) */
|
uint8_t frac; /* fractional pixel step factor (log2) */
|
||||||
bool packed; /* read multiple elements from a single plane */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter kernel to apply to each plane while sampling. Currently, only
|
* Filter kernel to apply to each plane while sampling. Currently, only
|
||||||
|
|||||||
@@ -464,7 +464,12 @@ static void op_pass_run(const SwsFrame *out, const SwsFrame *in, const int y,
|
|||||||
|
|
||||||
static int rw_pixel_bits(const SwsOp *op)
|
static int rw_pixel_bits(const SwsOp *op)
|
||||||
{
|
{
|
||||||
const int elems = op->rw.packed ? op->rw.elems : 1;
|
int elems = 0;
|
||||||
|
switch (op->rw.mode) {
|
||||||
|
case SWS_RW_PLANAR: elems = 1; break;
|
||||||
|
case SWS_RW_PACKED: elems = op->rw.elems; break;
|
||||||
|
}
|
||||||
|
|
||||||
const int size = ff_sws_pixel_type_size(op->type);
|
const int size = ff_sws_pixel_type_size(op->type);
|
||||||
const int bits = 8 >> op->rw.frac;
|
const int bits = 8 >> op->rw.frac;
|
||||||
av_assert1(bits >= 1);
|
av_assert1(bits >= 1);
|
||||||
|
|||||||
@@ -405,7 +405,7 @@ retry:
|
|||||||
switch (op->op) {
|
switch (op->op) {
|
||||||
case SWS_OP_READ:
|
case SWS_OP_READ:
|
||||||
/* "Compress" planar reads where not all components are needed */
|
/* "Compress" planar reads where not all components are needed */
|
||||||
if (!op->rw.packed) {
|
if (op->rw.mode == SWS_RW_PLANAR) {
|
||||||
SwsSwizzleOp swiz = SWS_SWIZZLE(0, 1, 2, 3);
|
SwsSwizzleOp swiz = SWS_SWIZZLE(0, 1, 2, 3);
|
||||||
int nb_planes = 0;
|
int nb_planes = 0;
|
||||||
for (int i = 0; i < op->rw.elems; i++) {
|
for (int i = 0; i < op->rw.elems; i++) {
|
||||||
@@ -529,7 +529,7 @@ retry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Swizzle planes instead of components, if possible */
|
/* Swizzle planes instead of components, if possible */
|
||||||
if (prev->op == SWS_OP_READ && !prev->rw.packed) {
|
if (prev->op == SWS_OP_READ && prev->rw.mode == SWS_RW_PLANAR) {
|
||||||
for (int dst = 0; dst < prev->rw.elems; dst++) {
|
for (int dst = 0; dst < prev->rw.elems; dst++) {
|
||||||
const int src = op->swizzle.in[dst];
|
const int src = op->swizzle.in[dst];
|
||||||
if (src > dst && src < prev->rw.elems) {
|
if (src > dst && src < prev->rw.elems) {
|
||||||
@@ -545,7 +545,7 @@ retry:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next->op == SWS_OP_WRITE && !next->rw.packed) {
|
if (next->op == SWS_OP_WRITE && next->rw.mode == SWS_RW_PLANAR) {
|
||||||
for (int dst = 0; dst < next->rw.elems; dst++) {
|
for (int dst = 0; dst < next->rw.elems; dst++) {
|
||||||
const int src = op->swizzle.in[dst];
|
const int src = op->swizzle.in[dst];
|
||||||
if (src > dst && src < next->rw.elems) {
|
if (src > dst && src < next->rw.elems) {
|
||||||
@@ -748,7 +748,7 @@ retry:
|
|||||||
case SWS_OP_FILTER_V:
|
case SWS_OP_FILTER_V:
|
||||||
/* Merge with prior simple planar read */
|
/* Merge with prior simple planar read */
|
||||||
if (prev->op == SWS_OP_READ && !prev->rw.filter.op &&
|
if (prev->op == SWS_OP_READ && !prev->rw.filter.op &&
|
||||||
!prev->rw.packed && !prev->rw.frac) {
|
prev->rw.mode == SWS_RW_PLANAR && !prev->rw.frac) {
|
||||||
prev->rw.filter.op = op->op;
|
prev->rw.filter.op = op->op;
|
||||||
prev->rw.filter.kernel = av_refstruct_ref(op->filter.kernel);
|
prev->rw.filter.kernel = av_refstruct_ref(op->filter.kernel);
|
||||||
prev->rw.filter.type = op->filter.type;
|
prev->rw.filter.type = op->filter.type;
|
||||||
|
|||||||
+2
-2
@@ -480,7 +480,7 @@ static int translate_rw_op(SwsContext *ctx, SwsUOpList *ops, SwsUOpFlags flags,
|
|||||||
|
|
||||||
const bool is_read = op->op == SWS_OP_READ;
|
const bool is_read = op->op == SWS_OP_READ;
|
||||||
if (op->rw.filter.op) {
|
if (op->rw.filter.op) {
|
||||||
if (op->op == SWS_OP_WRITE || op->rw.frac || op->rw.packed)
|
if (op->op == SWS_OP_WRITE || op->rw.frac || op->rw.mode != SWS_RW_PLANAR)
|
||||||
return AVERROR(ENOTSUP);
|
return AVERROR(ENOTSUP);
|
||||||
uop.par.filter.type = op->rw.filter.type;
|
uop.par.filter.type = op->rw.filter.type;
|
||||||
uop.data.kernel = av_refstruct_ref(op->rw.filter.kernel);
|
uop.data.kernel = av_refstruct_ref(op->rw.filter.kernel);
|
||||||
@@ -491,7 +491,7 @@ static int translate_rw_op(SwsContext *ctx, SwsUOpList *ops, SwsUOpFlags flags,
|
|||||||
} else {
|
} else {
|
||||||
uop.uop = SWS_UOP_READ_PLANAR_FV;
|
uop.uop = SWS_UOP_READ_PLANAR_FV;
|
||||||
}
|
}
|
||||||
} else if (op->rw.packed && op->rw.elems > 1) {
|
} else if (op->rw.mode == SWS_RW_PACKED && op->rw.elems > 1) {
|
||||||
if (op->rw.frac)
|
if (op->rw.frac)
|
||||||
return AVERROR(ENOTSUP);
|
return AVERROR(ENOTSUP);
|
||||||
uop.uop = is_read ? SWS_UOP_READ_PACKED : SWS_UOP_WRITE_PACKED;
|
uop.uop = is_read ? SWS_UOP_READ_PACKED : SWS_UOP_WRITE_PACKED;
|
||||||
|
|||||||
@@ -852,7 +852,7 @@ static int read_filtered(SPICtx *spi, SPIRVIDs *id, const SwsOpList *ops,
|
|||||||
/* Accumulators, initialized to zero */
|
/* Accumulators, initialized to zero */
|
||||||
int acc_s[4] = { id->f32_0, id->f32_0, id->f32_0, id->f32_0 };
|
int acc_s[4] = { id->f32_0, id->f32_0, id->f32_0, id->f32_0 };
|
||||||
int acc_v = id->f32_0;
|
int acc_v = id->f32_0;
|
||||||
if (op->rw.packed)
|
if (op->rw.mode == SWS_RW_PACKED)
|
||||||
acc_v = spi_OpCompositeConstruct(spi, id->f32vec4_type,
|
acc_v = spi_OpCompositeConstruct(spi, id->f32vec4_type,
|
||||||
id->f32_0, id->f32_0,
|
id->f32_0, id->f32_0,
|
||||||
id->f32_0, id->f32_0);
|
id->f32_0, id->f32_0);
|
||||||
@@ -877,7 +877,7 @@ static int read_filtered(SPICtx *spi, SPIRVIDs *id, const SwsOpList *ops,
|
|||||||
spi_OpCompositeConstruct(spi, id->i32vec2_type, c, pos_y) :
|
spi_OpCompositeConstruct(spi, id->i32vec2_type, c, pos_y) :
|
||||||
spi_OpCompositeConstruct(spi, id->i32vec2_type, pos_x, c);
|
spi_OpCompositeConstruct(spi, id->i32vec2_type, pos_x, c);
|
||||||
|
|
||||||
if (op->rw.packed) {
|
if (op->rw.mode == SWS_RW_PACKED) {
|
||||||
int px = spi_OpImageRead(spi, read_vtype,
|
int px = spi_OpImageRead(spi, read_vtype,
|
||||||
in_img[ops->plane_src[0]], coord,
|
in_img[ops->plane_src[0]], coord,
|
||||||
SpvImageOperandsMaskNone);
|
SpvImageOperandsMaskNone);
|
||||||
@@ -902,7 +902,7 @@ static int read_filtered(SPICtx *spi, SPIRVIDs *id, const SwsOpList *ops,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op->rw.packed)
|
if (op->rw.mode == SWS_RW_PACKED)
|
||||||
return acc_v;
|
return acc_v;
|
||||||
return spi_OpCompositeConstruct(spi, id->f32vec4_type,
|
return spi_OpCompositeConstruct(spi, id->f32vec4_type,
|
||||||
acc_s[0], acc_s[1], acc_s[2], acc_s[3]);
|
acc_s[0], acc_s[1], acc_s[2], acc_s[3]);
|
||||||
@@ -1136,7 +1136,7 @@ static int add_ops_spirv(SwsContext *sws, VulkanPriv *p, FFVulkanOpsCtx *s,
|
|||||||
data = read_filtered(spi, id, ops, op,
|
data = read_filtered(spi, id, ops, op,
|
||||||
&id->filt[nb_filter_used++],
|
&id->filt[nb_filter_used++],
|
||||||
in_img, gid, gi2);
|
in_img, gid, gi2);
|
||||||
} else if (op->rw.packed) {
|
} else if (op->rw.mode == SWS_RW_PACKED) {
|
||||||
data = spi_OpImageRead(spi, type_v, in_img[ops->plane_src[0]],
|
data = spi_OpImageRead(spi, type_v, in_img[ops->plane_src[0]],
|
||||||
src_gid, SpvImageOperandsMaskNone);
|
src_gid, SpvImageOperandsMaskNone);
|
||||||
} else {
|
} else {
|
||||||
@@ -1154,7 +1154,7 @@ static int add_ops_spirv(SwsContext *sws, VulkanPriv *p, FFVulkanOpsCtx *s,
|
|||||||
case SWS_OP_WRITE:
|
case SWS_OP_WRITE:
|
||||||
if (op->rw.frac || op->rw.filter.op) {
|
if (op->rw.frac || op->rw.filter.op) {
|
||||||
return AVERROR(ENOTSUP);
|
return AVERROR(ENOTSUP);
|
||||||
} else if (op->rw.packed) {
|
} else if (op->rw.mode == SWS_RW_PACKED) {
|
||||||
spi_OpImageWrite(spi, out_img[ops->plane_dst[0]], dst_gid, data,
|
spi_OpImageWrite(spi, out_img[ops->plane_dst[0]], dst_gid, data,
|
||||||
SpvImageOperandsMaskNone);
|
SpvImageOperandsMaskNone);
|
||||||
} else {
|
} else {
|
||||||
@@ -1332,7 +1332,7 @@ static void read_glsl(const SwsOpList *ops, const SwsOp *op, FFVulkanShader *shd
|
|||||||
wd->filter_size);
|
wd->filter_size);
|
||||||
av_bprintf(&shd->src, " float w = filter_w%i[%s][i];\n",
|
av_bprintf(&shd->src, " float w = filter_w%i[%s][i];\n",
|
||||||
idx, axis);
|
idx, axis);
|
||||||
if (op->rw.packed) {
|
if (op->rw.mode == SWS_RW_PACKED) {
|
||||||
GLSLF(2, tmp += w * %s(imageLoad(src_img[%i], ivec2(%s, %s))); ,
|
GLSLF(2, tmp += w * %s(imageLoad(src_img[%i], ivec2(%s, %s))); ,
|
||||||
type_v, ops->plane_src[0], coord_x, coord_y);
|
type_v, ops->plane_src[0], coord_x, coord_y);
|
||||||
} else {
|
} else {
|
||||||
@@ -1345,7 +1345,7 @@ static void read_glsl(const SwsOpList *ops, const SwsOp *op, FFVulkanShader *shd
|
|||||||
GLSLC(1, f32 = tmp; );
|
GLSLC(1, f32 = tmp; );
|
||||||
} else {
|
} else {
|
||||||
const char *src_pos = interlaced ? "spos" : "pos";
|
const char *src_pos = interlaced ? "spos" : "pos";
|
||||||
if (op->rw.packed) {
|
if (op->rw.mode == SWS_RW_PACKED) {
|
||||||
GLSLF(1, %s = %s(imageLoad(src_img[%i], %s)); ,
|
GLSLF(1, %s = %s(imageLoad(src_img[%i], %s)); ,
|
||||||
type_name, type_v, ops->plane_src[0], src_pos);
|
type_name, type_v, ops->plane_src[0], src_pos);
|
||||||
} else {
|
} else {
|
||||||
@@ -1488,7 +1488,7 @@ static int add_ops_glsl(SwsContext *sws, VulkanPriv *p, FFVulkanOpsCtx *s,
|
|||||||
const char *dst_pos = ops->dst.interlaced ? "dpos" : "pos";
|
const char *dst_pos = ops->dst.interlaced ? "dpos" : "pos";
|
||||||
if (op->rw.frac || op->rw.filter.op) {
|
if (op->rw.frac || op->rw.filter.op) {
|
||||||
return AVERROR(ENOTSUP);
|
return AVERROR(ENOTSUP);
|
||||||
} else if (op->rw.packed) {
|
} else if (op->rw.mode == SWS_RW_PACKED) {
|
||||||
GLSLF(1, imageStore(dst_img[%i], %s, %s(%s)); ,
|
GLSLF(1, imageStore(dst_img[%i], %s, %s(%s)); ,
|
||||||
ops->plane_dst[0], dst_pos, type_v, type_name);
|
ops->plane_dst[0], dst_pos, type_v, type_name);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+27
-4
@@ -56,7 +56,12 @@ static const char *tprintf(char buf[], size_t size, const char *fmt, ...)
|
|||||||
|
|
||||||
static int rw_pixel_bits(const SwsOp *op)
|
static int rw_pixel_bits(const SwsOp *op)
|
||||||
{
|
{
|
||||||
const int elems = op->rw.packed ? op->rw.elems : 1;
|
int elems = 0;
|
||||||
|
switch (op->rw.mode) {
|
||||||
|
case SWS_RW_PLANAR: elems = 1; break;
|
||||||
|
case SWS_RW_PACKED: elems = op->rw.elems; break;
|
||||||
|
}
|
||||||
|
|
||||||
const int size = ff_sws_pixel_type_size(op->type);
|
const int size = ff_sws_pixel_type_size(op->type);
|
||||||
const int bits = 8 >> op->rw.frac;
|
const int bits = 8 >> op->rw.frac;
|
||||||
av_assert1(bits >= 1);
|
av_assert1(bits >= 1);
|
||||||
@@ -233,7 +238,7 @@ static void check_compiled(const char *name,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write_op->rw.packed)
|
if (write_op->rw.mode == SWS_RW_PACKED)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,13 +399,22 @@ static AVRational rndq(SwsPixelType t)
|
|||||||
|
|
||||||
static void check_read(const char *name, const SwsUOp *uop)
|
static void check_read(const char *name, const SwsUOp *uop)
|
||||||
{
|
{
|
||||||
|
SwsReadWriteMode mode;
|
||||||
|
switch (uop->uop) {
|
||||||
|
case SWS_UOP_READ_PACKED:
|
||||||
|
case SWS_UOP_READ_BIT:
|
||||||
|
case SWS_UOP_READ_NIBBLE: mode = SWS_RW_PACKED; break;
|
||||||
|
case SWS_UOP_READ_PLANAR: mode = SWS_RW_PLANAR; break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
const int num = mask_num(uop->mask);
|
const int num = mask_num(uop->mask);
|
||||||
check_ops(name, NULL, (SwsOp[]) {
|
check_ops(name, NULL, (SwsOp[]) {
|
||||||
{
|
{
|
||||||
.op = SWS_OP_READ,
|
.op = SWS_OP_READ,
|
||||||
.type = uop->type,
|
.type = uop->type,
|
||||||
.rw.elems = num,
|
.rw.elems = num,
|
||||||
.rw.packed = uop->uop != SWS_UOP_READ_PLANAR,
|
.rw.mode = mode,
|
||||||
.rw.frac = uop->uop == SWS_UOP_READ_BIT ? 3 :
|
.rw.frac = uop->uop == SWS_UOP_READ_BIT ? 3 :
|
||||||
uop->uop == SWS_UOP_READ_NIBBLE ? 1 : 0,
|
uop->uop == SWS_UOP_READ_NIBBLE ? 1 : 0,
|
||||||
}, {
|
}, {
|
||||||
@@ -413,6 +427,15 @@ static void check_read(const char *name, const SwsUOp *uop)
|
|||||||
|
|
||||||
static void check_write(const char *name, const SwsUOp *uop)
|
static void check_write(const char *name, const SwsUOp *uop)
|
||||||
{
|
{
|
||||||
|
SwsReadWriteMode mode;
|
||||||
|
switch (uop->uop) {
|
||||||
|
case SWS_UOP_WRITE_BIT:
|
||||||
|
case SWS_UOP_WRITE_NIBBLE:
|
||||||
|
case SWS_UOP_READ_PACKED: mode = SWS_RW_PACKED; break;
|
||||||
|
case SWS_UOP_READ_PLANAR: mode = SWS_RW_PLANAR; break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
const int frac = uop->uop == SWS_UOP_WRITE_BIT ? 3 :
|
const int frac = uop->uop == SWS_UOP_WRITE_BIT ? 3 :
|
||||||
uop->uop == SWS_UOP_WRITE_NIBBLE ? 1 : 0;
|
uop->uop == SWS_UOP_WRITE_NIBBLE ? 1 : 0;
|
||||||
const int num = mask_num(uop->mask);
|
const int num = mask_num(uop->mask);
|
||||||
@@ -428,7 +451,7 @@ static void check_write(const char *name, const SwsUOp *uop)
|
|||||||
.op = SWS_OP_WRITE,
|
.op = SWS_OP_WRITE,
|
||||||
.type = uop->type,
|
.type = uop->type,
|
||||||
.rw.elems = num,
|
.rw.elems = num,
|
||||||
.rw.packed = uop->uop != SWS_UOP_WRITE_PLANAR,
|
.rw.mode = mode,
|
||||||
.rw.frac = frac,
|
.rw.frac = frac,
|
||||||
}, {0}
|
}, {0}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user