From e111db837a1987c52beb1e6d170fbb8f5f5627a1 Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Fri, 28 Aug 2026 15:58:06 -0700 Subject: [PATCH] Add I422ToAR30Row_RVV for RISC-V Vector Bug: none Change-Id: I39f28554b455356c4494c5bea5bdbb04aefff22c TAG=agy CONV=abcd6ba2-e3a4-49ba-a3fc-3b6b55b83509 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8311933 Commit-Queue: Frank Barchard Reviewed-by: Wan-Teh Chang --- include/libyuv/row.h | 7 +++++ source/convert_argb.cc | 5 ++++ source/row_rvv.cc | 67 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/include/libyuv/row.h b/include/libyuv/row.h index 9744ff121..476c0ac4c 100644 --- a/include/libyuv/row.h +++ b/include/libyuv/row.h @@ -885,6 +885,7 @@ extern "C" { #define HAS_COPYROW_RVV #define HAS_HALFROW_16TO8_RVV #define HAS_HALFWIDTHROW_16TO8_RVV +#define HAS_I422TOAR30ROW_RVV #define HAS_INTERPOLATEROW_RVV #define HAS_RGBTOUV444MATRIXROW_RVV #define HAS_RGBTOUVMATRIXROW_RVV @@ -1600,6 +1601,12 @@ void I422ToRGB24Row_RVV(const uint8_t* src_y, uint8_t* dst_rgb24, const struct YuvConstants* yuvconstants, int width); +void I422ToAR30Row_RVV(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_ar30, + const struct YuvConstants* yuvconstants, + int width); void I444ToARGBRow_LSX(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, diff --git a/source/convert_argb.cc b/source/convert_argb.cc index a583dce3e..4f2cc62f5 100644 --- a/source/convert_argb.cc +++ b/source/convert_argb.cc @@ -6556,6 +6556,11 @@ int I420ToAR30Matrix(const uint8_t* src_y, I422ToAR30Row = I422ToAR30Row_SME; } #endif +#if defined(HAS_I422TOAR30ROW_RVV) + if (TestCpuFlag(kCpuHasRVV)) { + I422ToAR30Row = I422ToAR30Row_RVV; + } +#endif for (y = 0; y < height; ++y) { I422ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width); diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 062ab09e2..165b7be4e 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -40,6 +40,18 @@ extern "C" { bg = yuvconst->kRGBCoeffBias[2] - 32; \ br = yuvconst->kRGBCoeffBias[3] + 32; \ } +// Fill YUV -> AR30 conversion constants into vectors +#define YUVTORGB_SETUP_AR30(yuvconst, ub, vr, ug, vg, yg, bb, bg, br) \ + { \ + ub = yuvconst->kUVCoeff[0]; \ + vr = yuvconst->kUVCoeff[1]; \ + ug = yuvconst->kUVCoeff[2]; \ + vg = yuvconst->kUVCoeff[3]; \ + yg = yuvconst->kRGBCoeffBias[0]; \ + bb = yuvconst->kRGBCoeffBias[1] + 24; \ + bg = yuvconst->kRGBCoeffBias[2] - 24; \ + br = yuvconst->kRGBCoeffBias[3] + 24; \ + } #else // Fill YUV -> RGB conversion constants into vectors // NOTE: To match behavior on other platforms, vxrm (fixed-point rounding mode @@ -56,6 +68,19 @@ extern "C" { bg = yuvconst->kRGBCoeffBias[2] - 32; \ br = yuvconst->kRGBCoeffBias[3] + 32; \ } +// Fill YUV -> AR30 conversion constants into vectors +#define YUVTORGB_SETUP_AR30(yuvconst, ub, vr, ug, vg, yg, bb, bg, br) \ + { \ + asm volatile("csrwi vxrm, 0"); \ + ub = yuvconst->kUVCoeff[0]; \ + vr = yuvconst->kUVCoeff[1]; \ + ug = yuvconst->kUVCoeff[2]; \ + vg = yuvconst->kUVCoeff[3]; \ + yg = yuvconst->kRGBCoeffBias[0]; \ + bb = yuvconst->kRGBCoeffBias[1] + 24; \ + bg = yuvconst->kRGBCoeffBias[2] - 24; \ + br = yuvconst->kRGBCoeffBias[3] + 24; \ + } #endif // Read [2*VLEN/8] Y, [VLEN/8] U and [VLEN/8] V from 422 #define READYUV422(vl, w, src_y, src_u, src_v, v_u, v_v, v_y_16) \ @@ -705,6 +730,48 @@ void I422ToRGB24Row_RVV(const uint8_t* src_y, } #endif +#ifdef HAS_I422TOAR30ROW_RVV +void I422ToAR30Row_RVV(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_ar30, + const struct YuvConstants* yuvconstants, + int width) { + size_t vl; + size_t w = (size_t)width; + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + vuint16m4_t v_b_10, v_g_10, v_r_10, v_ra_16; + vuint32m8_t v_ar30, v_ra_32; + YUVTORGB_SETUP_AR30(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + do { + READYUV422(vl, w, src_y, src_u, src_v, v_u, v_v, v_y_16); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); + v_b_10 = + __riscv_vminu_vx_u16m4(__riscv_vsrl_vx_u16m4(v_b_16, 4, vl), 1023, vl); + v_g_10 = + __riscv_vminu_vx_u16m4(__riscv_vsrl_vx_u16m4(v_g_16, 4, vl), 1023, vl); + v_r_10 = + __riscv_vminu_vx_u16m4(__riscv_vsrl_vx_u16m4(v_r_16, 4, vl), 1023, vl); + v_ar30 = __riscv_vwaddu_vx_u32m8(v_b_10, 0, vl); + v_ar30 = __riscv_vwmaccu_vx_u32m8(v_ar30, 1024, v_g_10, vl); + v_ra_16 = __riscv_vor_vx_u16m4(v_r_10, 0x0c00, vl); + v_ra_32 = __riscv_vwaddu_vx_u32m8(v_ra_16, 0, vl); + v_ra_32 = __riscv_vsll_vx_u32m8(v_ra_32, 20, vl); + v_ar30 = __riscv_vor_vv_u32m8(v_ar30, v_ra_32, vl); + __riscv_vse32_v_u32m8((uint32_t*)dst_ar30, v_ar30, vl); + w -= vl; + src_y += vl; + src_u += vl / 2; + src_v += vl / 2; + dst_ar30 += vl * 4; + } while (w > 0); +} +#endif + #ifdef HAS_I400TOARGBROW_RVV #if defined(LIBYUV_RVV_HAS_VXRM_ARG) void I400ToARGBRow_RVV(const uint8_t* src_y,