diff --git a/include/libyuv/row.h b/include/libyuv/row.h index ded1995fd..e164a502d 100644 --- a/include/libyuv/row.h +++ b/include/libyuv/row.h @@ -573,6 +573,7 @@ extern "C" { #if !defined(LIBYUV_DISABLE_SVE) && defined(__aarch64__) #define HAS_ABGRTOUVJROW_SVE2 #define HAS_ABGRTOUVROW_SVE2 +#define HAS_ARGBTORGB565ROW_SVE2 #define HAS_ARGBTOUVJROW_SVE2 #define HAS_ARGBTOUVROW_SVE2 #define HAS_BGRATOUVROW_SVE2 @@ -3625,6 +3626,9 @@ void ARGBToRAWRow_NEON(const uint8_t* src_argb, uint8_t* dst_raw, int width); void ARGBToRGB565Row_NEON(const uint8_t* src_argb, uint8_t* dst_rgb565, int width); +void ARGBToRGB565Row_SVE2(const uint8_t* src_argb, + uint8_t* dst_rgb565, + int width); void ARGBToARGB1555Row_NEON(const uint8_t* src_argb, uint8_t* dst_argb1555, int width); diff --git a/source/convert_from_argb.cc b/source/convert_from_argb.cc index 264d73881..daa99505a 100644 --- a/source/convert_from_argb.cc +++ b/source/convert_from_argb.cc @@ -2045,6 +2045,11 @@ int ARGBToRGB565(const uint8_t* src_argb, } } #endif +#if defined(HAS_ARGBTORGB565ROW_SVE2) + if (TestCpuFlag(kCpuHasSVE2)) { + ARGBToRGB565Row = ARGBToRGB565Row_SVE2; + } +#endif #if defined(HAS_ARGBTORGB565ROW_MSA) if (TestCpuFlag(kCpuHasMSA)) { ARGBToRGB565Row = ARGBToRGB565Row_Any_MSA; diff --git a/source/row_sve.cc b/source/row_sve.cc index 3abc3a189..43fc51d70 100644 --- a/source/row_sve.cc +++ b/source/row_sve.cc @@ -499,6 +499,57 @@ void RGBAToUVRow_SVE2(const uint8_t* src_rgba, kRGBAToUVCoefficients); } +#define ARGBTORGB565_SVE \ + /* Inputs: \ + * z0: rrrrrxxxbbbbbxxx \ + * z1: xxxxxxxxggggggxx \ + * z3: 0000000000000011 (3, 0, 3, 0, ...) \ + * z4: 0000011111100000 \ + */ \ + "lsr z0.b, p0/m, z0.b, z3.b \n" \ + "lsl z1.h, z1.h, #3 \n" \ + "bsl z1.d, z1.d, z0.d, z4.d \n" + +void ARGBToRGB565Row_SVE2(const uint8_t* src_argb, + uint8_t* dst_rgb, + int width) { + unsigned bsl_mask = 0x7e0; + uint64_t vl; + width *= 2; + asm("mov z3.h, #3 \n" + "dup z4.h, %w[bsl_mask] \n" + + "cntb %[vl] \n" + "subs %w[width], %w[width], %w[vl] \n" + "b.lt 2f \n" + + "ptrue p0.b \n" + "1: \n" + "ld2b {z0.b, z1.b}, p0/z, [%[src]] \n" // BR, GA + "incb %[src], all, mul #2 \n" + "subs %w[width], %w[width], %w[vl] \n" ARGBTORGB565_SVE + "st1b {z1.b}, p0, [%[dst]] \n" + "incb %[dst] \n" + "b.ge 1b \n" + + "2: \n" + "adds %w[width], %w[width], %w[vl] \n" + "b.eq 99f \n" + + "whilelt p0.b, wzr, %w[width] \n" + "ld2b {z0.b, z1.b}, p0/z, [%[src]] \n" // BR, GA + ARGBTORGB565_SVE + "st1b {z1.b}, p0, [%[dst]] \n" + + "99: \n" + : [src] "+r"(src_argb), // %[src] + [dst] "+r"(dst_rgb), // %[dst] + [width] "+r"(width), // %[width] + [vl] "=&r"(vl) // %[vl] + : [bsl_mask] "r"(bsl_mask) // %[bsl_mask] + : "cc", "memory", "z0", "z1", "z3", "z4", "p0"); +} + #endif // !defined(LIBYUV_DISABLE_SVE) && defined(__aarch64__) #ifdef __cplusplus