1
0
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:
Niklas Haas
2026-06-02 14:39:34 +02:00
committed by Niklas Haas
parent 01c007ec4d
commit b488ee5553
9 changed files with 103 additions and 37 deletions
+8 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+6 -1
View File
@@ -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);
+4 -4
View File
@@ -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
View File
@@ -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;
+8 -8
View File
@@ -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
View File
@@ -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}
}); });