diff --git a/libswscale/aarch64/ops.c b/libswscale/aarch64/ops.c index 71c0c38b06..1634cf2e49 100644 --- a/libswscale/aarch64/ops.c +++ b/libswscale/aarch64/ops.c @@ -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; diff --git a/libswscale/aarch64/ops_asmgen.c b/libswscale/aarch64/ops_asmgen.c index 006794a882..95f7dcb551 100644 --- a/libswscale/aarch64/ops_asmgen.c +++ b/libswscale/aarch64/ops_asmgen.c @@ -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; } } diff --git a/libswscale/aarch64/ops_entries.c b/libswscale/aarch64/ops_entries.c index 1a3dd57540..027f6b1ea5 100644 --- a/libswscale/aarch64/ops_entries.c +++ b/libswscale/aarch64/ops_entries.c @@ -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 }) diff --git a/libswscale/aarch64/ops_impl.h b/libswscale/aarch64/ops_impl.h index c15135668d..378ce013d3 100644 --- a/libswscale/aarch64/ops_impl.h +++ b/libswscale/aarch64/ops_impl.h @@ -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 diff --git a/libswscale/aarch64/ops_impl_conv.c b/libswscale/aarch64/ops_impl_conv.c index 6bb51d0a7b..98df0a9c03 100644 --- a/libswscale/aarch64/ops_impl_conv.c +++ b/libswscale/aarch64/ops_impl_conv.c @@ -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; diff --git a/libswscale/tests/sws_ops_aarch64.c b/libswscale/tests/sws_ops_aarch64.c index 829694279b..006e4eb68f 100644 --- a/libswscale/tests/sws_ops_aarch64.c +++ b/libswscale/tests/sws_ops_aarch64.c @@ -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(¶ms->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);