swscale/aarch64/ops: use SwsLinearUOp for SwsAArch64OpImplParams.linear

This is one more step to eventually replace the parameter fields in
SwsAArch64OpImplParams by generic structs from libswscale/uops.h.

The function names and ordering in ops_entries.c is maintained to
simplify the gradual move to uops.h.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
This commit is contained in:
Ramiro Polla
2026-07-19 15:07:03 +02:00
parent e45e0e7084
commit 4a33d2ce2c
6 changed files with 83 additions and 126 deletions
+8 -6
View File
@@ -79,14 +79,16 @@ static int aarch64_setup_linear(const SwsAArch64OpImplParams *p,
return AVERROR(ENOMEM);
/**
* Copy non-zero coefficients, reordered to match SwsAArch64LinearOpMask.
* The coefficients are packed in sequential order. The same order must
* be followed in asmgen_op_linear().
* Copy non-zero coefficients, packed in sequential order, offset first.
* The same order must be followed in asmgen_op_linear().
*/
int i_coeff = 0;
LOOP_LINEAR_MASK(p, i, j) {
const int jj = linear_index_to_sws_op(j);
coeffs[i_coeff++] = (float) op->lin.m[i][jj].num / op->lin.m[i][jj].den;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
const int jj = (j == 0) ? 4 : (j - 1);
if (!(p->linear.zero & SWS_MASK(i, jj)))
coeffs[i_coeff++] = (float) op->lin.m[i][jj].num / op->lin.m[i][jj].den;
}
}
res->priv.ptr = coeffs;
+9 -9
View File
@@ -1093,10 +1093,10 @@ static void linear_pass(SwsAArch64Context *s, const SwsAArch64OpImplParams *p,
bool first = true;
RasmNode *pre_mul = rasm_get_current_node(r);
for (int j = 0; j < 5; j++) {
if (!LINEAR_MASK_GET(p->linear.mask, i, j))
bool is_offset = (j == 0);
int src_j = is_offset ? 4 : (j - 1);
if (p->linear.zero & SWS_MASK(i, src_j))
continue;
bool is_offset = linear_index_is_offset(j);
int src_j = linear_index_to_vx(j);
RasmOp vsrc = src_vx[src_j];
uint8_t vc_i = i_coeff / 4;
uint8_t vc_j = i_coeff & 3;
@@ -1105,7 +1105,7 @@ static void linear_pass(SwsAArch64Context *s, const SwsAArch64OpImplParams *p,
if (first && is_offset) {
i_dup (r, vx[i], vcoeff); CMTF("v%c[%u] = broadcast(vc[%u][%u]);", cvh, i, vc_i, vc_j);
} else if (first && !is_offset) {
if (LINEAR_MASK_GET(p->linear.mask, i, j) == LINEAR_MASK_1) {
if (p->linear.one & SWS_MASK(i, src_j)) {
i_mov16b(r, vx[i], vsrc); CMTF("v%c[%u] = vsrc[%u];", cvh, i, src_j);
} else {
i_fmul (r, vx[i], vsrc, vcoeff); CMTF("v%c[%u] = vsrc[%u] * vc[%u][%u];", cvh, i, src_j, vc_i, vc_j);
@@ -1125,7 +1125,7 @@ static void linear_pass(SwsAArch64Context *s, const SwsAArch64OpImplParams *p,
* to reduce the dependency chain.
* There is no need to perform multiplications by 1.
*/
if (LINEAR_MASK_GET(p->linear.mask, i, j) != LINEAR_MASK_1) {
if (!(p->linear.one & SWS_MASK(i, src_j))) {
pre_mul = rasm_set_current_node(r, pre_mul);
i_fmul(r, vtmp[vc_j], vsrc, vcoeff); CMTF("vtmp[%u] = vsrc[%u] * vc[%u][%u];", vc_j, src_j, vc_i, vc_j);
pre_mul = rasm_set_current_node(r, pre_mul);
@@ -1165,12 +1165,12 @@ static void asmgen_op_linear(SwsAArch64Context *s, const SwsAArch64OpImplParams
bool overwritten[4] = { false, false, false, false };
LOOP_MASK(p, i) {
for (int j = 0; j < 5; j++) {
if (!LINEAR_MASK_GET(p->linear.mask, i, j))
bool is_offset = (j == 0);
int src_j = is_offset ? 4 : (j - 1);
if (p->linear.zero & SWS_MASK(i, src_j))
continue;
bool is_offset = linear_index_is_offset(j);
int src_j = linear_index_to_vx(j);
if (!is_offset && overwritten[src_j])
MASK_SET(save_mask, j - 1, 1);
MASK_SET(save_mask, src_j, 1);
overwritten[i] = true;
}
}
+32 -32
View File
@@ -358,38 +358,38 @@ ENTRY(ff_sws_clear_ffff_16_u16_0001_neon, { .uop = SWS_UOP_CLEAR, .clear = { .on
ENTRY(ff_sws_clear_ffff_16_u16_0011_neon, { .uop = SWS_UOP_CLEAR, .clear = { .one = 0x0, .zero = 0x0 }, .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x0011 })
ENTRY(ff_sws_clear_ffff_16_u16_0111_neon, { .uop = SWS_UOP_CLEAR, .clear = { .one = 0x0, .zero = 0x0 }, .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x0111 })
ENTRY(ff_sws_clear_ffff_16_u16_1000_neon, { .uop = SWS_UOP_CLEAR, .clear = { .one = 0x0, .zero = 0x0 }, .block_size = 16, .type = SWS_PIXEL_U16, .mask = 0x1000 })
ENTRY(ff_sws_linear_000000000f_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0x000000000fULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_00000000fc_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0x00000000fcULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_00000000ff_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0x00000000ffULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_000000c000_8_f32_0010_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0x000000c000ULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0010 })
ENTRY(ff_sws_linear_000373dcc7_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0x000373dcc7ULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_0003f3fccf_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0x0003f3fccfULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_000c00c00c_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0x000c00c00cULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_000c30cc0f_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0x000c30cc0fULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_000ff3fcfc_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0x000ff3fcfcULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_000ff3fcff_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0x000ff3fcffULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_c000000000_8_f32_1000_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0xc000000000ULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1000 })
ENTRY(ff_sws_linear_c00000000f_8_f32_1001_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0xc00000000fULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1001 })
ENTRY(ff_sws_linear_c0000000fc_8_f32_1001_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0xc0000000fcULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1001 })
ENTRY(ff_sws_linear_c003f3fccf_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0xc003f3fccfULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_linear_c00c00c00c_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0xc00c00c00cULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_linear_c00ff3fcff_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR, .linear.mask = 0xc00ff3fcffULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_linear_fma_000000000f_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0x000000000fULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_fma_00000000fc_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0x00000000fcULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_fma_00000000ff_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0x00000000ffULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_fma_000000c000_8_f32_0010_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0x000000c000ULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0010 })
ENTRY(ff_sws_linear_fma_000373dcc7_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0x000373dcc7ULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_0003f3fccf_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0x0003f3fccfULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_000c00c00c_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0x000c00c00cULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_000c30cc0f_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0x000c30cc0fULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_000ff3fcfc_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0x000ff3fcfcULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_000ff3fcff_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0x000ff3fcffULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_c000000000_8_f32_1000_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0xc000000000ULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1000 })
ENTRY(ff_sws_linear_fma_c00000000f_8_f32_1001_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0xc00000000fULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1001 })
ENTRY(ff_sws_linear_fma_c0000000fc_8_f32_1001_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0xc0000000fcULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1001 })
ENTRY(ff_sws_linear_fma_c003f3fccf_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0xc003f3fccfULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_linear_fma_c00c00c00c_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0xc00c00c00cULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_linear_fma_c00ff3fcff_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear.mask = 0xc00ff3fcffULL, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_linear_000000000f_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xfffee }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_00000000fc_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xffff8 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_00000000ff_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xfffe8 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_000000c000_8_f32_0010_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xfffbf }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0010 })
ENTRY(ff_sws_linear_000373dcc7_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x421, .zero = 0xfb10a }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_0003f3fccf_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xfb10a }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_000c00c00c_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xfefbe }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_000c30cc0f_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xfadae }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_000ff3fcfc_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xfa118 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_000ff3fcff_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xfa108 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_c000000000_8_f32_1000_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xbffff }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1000 })
ENTRY(ff_sws_linear_c00000000f_8_f32_1001_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xbffee }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1001 })
ENTRY(ff_sws_linear_c0000000fc_8_f32_1001_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xbfff8 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1001 })
ENTRY(ff_sws_linear_c003f3fccf_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xbb10a }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_linear_c00c00c00c_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xbefbe }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_linear_c00ff3fcff_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR, .linear = { .one = 0x0, .zero = 0xba108 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_linear_fma_000000000f_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xfffee }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_fma_00000000fc_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xffff8 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_fma_00000000ff_8_f32_0001_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xfffe8 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0001 })
ENTRY(ff_sws_linear_fma_000000c000_8_f32_0010_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xfffbf }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0010 })
ENTRY(ff_sws_linear_fma_000373dcc7_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x421, .zero = 0xfb10a }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_0003f3fccf_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xfb10a }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_000c00c00c_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xfefbe }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_000c30cc0f_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xfadae }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_000ff3fcfc_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xfa118 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_000ff3fcff_8_f32_0111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xfa108 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x0111 })
ENTRY(ff_sws_linear_fma_c000000000_8_f32_1000_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xbffff }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1000 })
ENTRY(ff_sws_linear_fma_c00000000f_8_f32_1001_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xbffee }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1001 })
ENTRY(ff_sws_linear_fma_c0000000fc_8_f32_1001_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xbfff8 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1001 })
ENTRY(ff_sws_linear_fma_c003f3fccf_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xbb10a }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_linear_fma_c00c00c00c_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xbefbe }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_linear_fma_c00ff3fcff_8_f32_1111_neon, { .uop = SWS_UOP_LINEAR_FMA, .linear = { .one = 0x0, .zero = 0xba108 }, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_dither_0325_4_8_f32_1111_neon, { .uop = SWS_UOP_DITHER, .dither.y_offset = 0x0325, .dither.size_log2 = 4, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
ENTRY(ff_sws_dither_032f_4_8_f32_1110_neon, { .uop = SWS_UOP_DITHER, .dither.y_offset = 0x032f, .dither.size_log2 = 4, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1110 })
ENTRY(ff_sws_dither_2305_4_8_f32_1111_neon, { .uop = SWS_UOP_DITHER, .dither.y_offset = 0x2305, .dither.size_log2 = 4, .block_size = 8, .type = SWS_PIXEL_F32, .mask = 0x1111 })
+4 -49
View File
@@ -30,19 +30,6 @@
/* Each nibble in the mask corresponds to one component. */
typedef uint16_t SwsAArch64OpMask;
/**
* Affine coefficient mask for linear op. Packs a 4x5 matrix in execution
* order, where the offset is the first element, with 2 bits per element:
* 00: m[i][j] == 0
* 01: m[i][j] == 1
* 11: m[i][j] is any other coefficient
*/
typedef uint64_t SwsAArch64LinearOpMask;
typedef struct SwsAArch64LinearOp {
SwsAArch64LinearOpMask mask;
} SwsAArch64LinearOp;
typedef struct SwsAArch64DitherOp {
uint16_t y_offset;
uint8_t size_log2;
@@ -63,7 +50,7 @@ typedef struct SwsAArch64OpImplParams {
SwsClearUOp clear;
SwsMoveUOp move;
SwsPackUOp pack;
SwsAArch64LinearOp linear;
SwsLinearUOp linear;
SwsAArch64DitherOp dither;
};
} SwsAArch64OpImplParams;
@@ -83,48 +70,16 @@ typedef struct SwsAArch64OpImplParams {
#define LOOP_MASK(p, idx) LOOP(p->mask, idx)
#define LOOP_MASK_BWD(p, idx) LOOP_BWD(p->mask, idx)
#define LINEAR_MASK_GET(mask, idx, jdx) (((mask) >> (2 * ((5 * (idx) + (jdx))))) & 3)
#define LINEAR_MASK_SET(mask, idx, jdx, val) do { \
(mask) |= ((((SwsAArch64LinearOpMask) (val)) & 3) << (2 * ((5 * (idx) + (jdx))))); \
} while (0)
#define LINEAR_MASK_0 0
#define LINEAR_MASK_1 1
#define LINEAR_MASK_X 3
#define LOOP_LINEAR_MASK(p, idx, jdx) \
LOOP_MASK(p, idx) \
for (int jdx = 0; jdx < 5; jdx++) \
if (LINEAR_MASK_GET(p->linear.mask, idx, jdx))
/* Compute number of vector registers needed to store all coefficients. */
static inline int linear_num_vregs(const SwsAArch64OpImplParams *params)
{
int count = 0;
LOOP_LINEAR_MASK(params, i, j)
count++;
for (int i = 0; i < 4 * 5; i++)
if (!(params->linear.zero & (1ULL << i)))
count++;
return (count + 3) / 4;
}
static inline int linear_index_to_sws_op(int idx)
{
const int reorder_col[5] = { 4, 0, 1, 2, 3 };
return reorder_col[idx];
}
static inline int linear_index_is_offset(int idx)
{
return (idx == 0);
}
static inline int linear_index_to_vx(int idx)
{
/* The offset shouldn't map to any vx, but to please UBSan we map
* it to 0. */
if (linear_index_is_offset(idx))
return 0;
return (idx - 1);
}
/**
* These values will be used by ops_asmgen to access fields inside of
* SwsOpExec and SwsOpImpl. The sizes are checked in aarch64/ops.c when
+7 -25
View File
@@ -29,18 +29,6 @@
#include "ops_impl.h"
/**
* The column index order for SwsLinearOp.mask follows the affine transform
* order, where the offset is the last element. SwsAArch64LinearOpMask, on
* the other hand, follows execution order, where the offset is the first
* element.
*/
static int linear_index_from_sws_op(int idx)
{
const int reorder_col[5] = { 1, 2, 3, 4, 0 };
return reorder_col[idx];
}
static void swizzle_emit(SwsAArch64OpImplParams *out, uint8_t dst, uint8_t src)
{
int idx = out->move.num_moves++;
@@ -277,26 +265,20 @@ static int convert_to_aarch64_impl(SwsContext *ctx, const SwsOpList *ops, int n,
break;
case SWS_UOP_LINEAR:
case SWS_UOP_LINEAR_FMA:
/**
* The out->linear.mask field packs the 4x5 matrix from SwsLinearOp as
* 2 bits per element:
* 00: m[i][j] == 0
* 01: m[i][j] == 1
* 11: m[i][j] is any other coefficient
*/
out->mask = 0;
for (int i = 0; i < 4; i++) {
/* Skip unused or identity rows */
if (!SWS_OP_NEEDED(op, i) || !(op->lin.mask & SWS_MASK_ROW(i)))
if (!SWS_OP_NEEDED(op, i) || !(op->lin.mask & SWS_MASK_ROW(i))) {
for (int j = 0; j < 5; j++)
out->linear.zero |= SWS_MASK(i, j);
continue;
}
MASK_SET(out->mask, i, 1);
for (int j = 0; j < 5; j++) {
const AVRational64 k = op->lin.m[i][j];
int jj = linear_index_from_sws_op(j);
if (j < 4 && k.num == k.den)
LINEAR_MASK_SET(out->linear.mask, i, jj, LINEAR_MASK_1);
else if (k.num != 0)
LINEAR_MASK_SET(out->linear.mask, i, jj, LINEAR_MASK_X);
out->linear.one |= SWS_MASK(i, j);
else if (k.num == 0)
out->linear.zero |= SWS_MASK(i, j);
}
}
break;
+23 -5
View File
@@ -73,6 +73,21 @@ static uint16_t pack_to_mask(const SwsPackUOp *pack)
return mask;
}
static uint64_t linear_to_mask(const SwsLinearUOp *linear)
{
uint64_t mask = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
int jj = (j == 0) ? 4 : (j - 1);
if (linear->one & SWS_MASK(i, jj))
mask |= 1ULL << (2 * ((5 * i + j)));
else if (!(linear->zero & SWS_MASK(i, jj)))
mask |= 3ULL << (2 * ((5 * i + j)));
}
}
return mask;
}
static int aarch64_op_impl_cmp(const void *a, const void *b)
{
const SwsAArch64OpImplParams *pa = (const SwsAArch64OpImplParams *) a;
@@ -111,10 +126,13 @@ static int aarch64_op_impl_cmp(const void *a, const void *b)
break;
}
case SWS_UOP_LINEAR:
case SWS_UOP_LINEAR_FMA:
if (pa->linear.mask != pb->linear.mask)
return (int64_t) (pa->linear.mask - pb->linear.mask) < 0 ? -1 : 1;
case SWS_UOP_LINEAR_FMA: {
uint64_t ia = linear_to_mask(&pa->linear);
uint64_t ib = linear_to_mask(&pb->linear);
if (ia != ib)
return (int64_t) (ia - ib) < 0 ? -1 : 1;
break;
}
case SWS_UOP_DITHER:
if (pa->dither.y_offset != pb->dither.y_offset)
return (int) pa->dither.y_offset - pb->dither.y_offset;
@@ -286,7 +304,7 @@ static void impl_func_name(AVBPrint *bp, const SwsAArch64OpImplParams *params)
break;
case SWS_UOP_LINEAR:
case SWS_UOP_LINEAR_FMA:
av_bprintf(bp, "_%010" PRIx64, params->linear.mask);
av_bprintf(bp, "_%010" PRIx64, linear_to_mask(&params->linear));
break;
case SWS_UOP_DITHER:
av_bprintf(bp, "_%04x_%u", params->dither.y_offset, params->dither.size_log2);
@@ -363,7 +381,7 @@ static void serialize_op(AVBPrint *bp, const SwsAArch64OpImplParams *params)
break;
case SWS_UOP_LINEAR:
case SWS_UOP_LINEAR_FMA:
av_bprintf(bp, ", .linear.mask = 0x%010" PRIx64 "ULL", params->linear.mask);
av_bprintf(bp, ", .linear = { .one = 0x%x, .zero = 0x%x }", params->linear.one, params->linear.zero);
break;
case SWS_UOP_DITHER:
av_bprintf(bp, ", .dither.y_offset = 0x%04x, .dither.size_log2 = %u", params->dither.y_offset, params->dither.size_log2);